/* * ds1302.c: * Real Time clock * * Copyright (c) 2013 Gordon Henderson. *********************************************************************** * This file is part of wiringPi: * https://projects.drogon.net/raspberry-pi/wiringpi/ * * wiringPi is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wiringPi is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wiringPi. If not, see . *********************************************************************** */ #include #include #include #include #include #include "ds1302.h" // Register defines #define RTC_SECS 0 #define RTC_MINS 1 #define RTC_HOURS 2 #define RTC_DATE 3 #define RTC_MONTH 4 #define RTC_DAY 5 #define RTC_YEAR 6 #define RTC_WP 7 #define RTC_TC 8 #define RTC_BM 31 // Locals static int dPin, cPin, sPin ; /* * dsShiftIn: * Shift a number in from the chip, LSB first. Note that the data is * sampled on the trailing edge of the last clock, so it's valid immediately. ********************************************************************************* */ static unsigned int dsShiftIn (void) { uint8_t value = 0 ; int i ; pinMode (dPin, INPUT) ; delayMicroseconds (1) ; for (i = 0 ; i < 8 ; ++i) { value |= (digitalRead (dPin) << i) ; digitalWrite (cPin, HIGH) ; delayMicroseconds (1) ; digitalWrite (cPin, LOW) ; delayMicroseconds (1) ; } return value; } /* * dsShiftOut: * A normal LSB-first shift-out, just slowed down a bit - the Pi is * a bit faster than the chip can handle. ********************************************************************************* */ static void dsShiftOut (unsigned int data) { int i ; pinMode (dPin, OUTPUT) ; for (i = 0 ; i < 8 ; ++i) { digitalWrite (dPin, data & (1 << i)) ; delayMicroseconds (1) ; digitalWrite (cPin, HIGH) ; delayMicroseconds (1) ; digitalWrite (cPin, LOW) ; delayMicroseconds (1) ; } } /* * ds1302regRead: ds1302regWrite: * Read/Write a value to an RTC Register or RAM location on the chip ********************************************************************************* */ static unsigned int ds1302regRead (const int reg) { unsigned int data ; digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; dsShiftOut (reg) ; data = dsShiftIn () ; digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; return data ; } static void ds1302regWrite (const int reg, const unsigned int data) { digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; dsShiftOut (reg) ; dsShiftOut (data) ; digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; } /* * ds1302rtcWrite: ds1302rtcRead: * Writes/Reads the data to/from the RTC register ********************************************************************************* */ unsigned int ds1302rtcRead (const int reg) { return ds1302regRead (0x81 | ((reg & 0x1F) << 1)) ; } void ds1302rtcWrite (int reg, unsigned int data) { ds1302regWrite (0x80 | ((reg & 0x1F) << 1), data) ; } /* * ds1302ramWrite: ds1302ramRead: * Writes/Reads the data to/from the RTC register ********************************************************************************* */ unsigned int ds1302ramRead (const int addr) { return ds1302regRead (0xC1 | ((addr & 0x1F) << 1)) ; } void ds1302ramWrite (const int addr, const unsigned int data) { ds1302regWrite ( 0xC0 | ((addr & 0x1F) << 1), data) ; } /* * ds1302clockRead: * Read all 8 bytes of the clock in a single operation ********************************************************************************* */ void ds1302clockRead (int clockData [8]) { int i ; unsigned int regVal = 0x81 | ((RTC_BM & 0x1F) << 1) ; digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; dsShiftOut (regVal) ; for (i = 0 ; i < 8 ; ++i) clockData [i] = dsShiftIn () ; digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; } /* * ds1302clockWrite: * Write all 8 bytes of the clock in a single operation ********************************************************************************* */ void ds1302clockWrite (const int clockData [8]) { int i ; unsigned int regVal = 0x80 | ((RTC_BM & 0x1F) << 1) ; digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ; dsShiftOut (regVal) ; for (i = 0 ; i < 8 ; ++i) dsShiftOut (clockData [i]) ; digitalWrite (sPin, LOW) ; delayMicroseconds (1) ; } /* * ds1302trickleCharge: * Set the bits on the trickle charger. * Probably best left alone... ********************************************************************************* */ void ds1302trickleCharge (const int diodes, const int resistors) { if (diodes + resistors == 0) ds1302rtcWrite (RTC_TC, 0x5C) ; // Disabled else ds1302rtcWrite (RTC_TC, 0xA0 | ((diodes & 3) << 2) | (resistors & 3)) ; } /* * ds1302setup: * Initialise the chip & remember the pins we're using ********************************************************************************* */ void ds1302setup (const int clockPin, const int dataPin, const int csPin) { dPin = dataPin ; cPin = clockPin ; sPin = csPin ; digitalWrite (dPin, LOW) ; digitalWrite (cPin, LOW) ; digitalWrite (sPin, LOW) ; pinMode (dPin, OUTPUT) ; pinMode (cPin, OUTPUT) ; pinMode (sPin, OUTPUT) ; ds1302rtcWrite (RTC_WP, 0) ; // Remove write-protect }