*Rewritten working version of* Working Version of the Real Time Clock module DS1307.
Fork of RTC-DS1307 by
Revision 10:8c0c306cee03, committed 2018-01-31
- Comitter:
- amateusz
- Date:
- Wed Jan 31 11:50:07 2018 +0000
- Parent:
- 9:5627b407e097
- Commit message:
- Oh yeah, I changed something. The idea behind was it to be more uniform or something.. Sorry. I'm hoping this commit is my private as I only want to publish a program.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DS1307.cpp Wed Jan 31 11:50:07 2018 +0000 @@ -0,0 +1,278 @@ +#include "mbed.h" +#include "DS1307.h" + +#ifndef DEBUG +//#define DEBUG +#endif +//#include "debug.h" + +const char *DS1307::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }; + + +DS1307::DS1307(I2C * i2c) +{ + // Create a new I2C object + m_rtc = i2c; + if (m_rtc == NULL) + error("Rtc_Ds1307"); + + // Set the frequency to standard 100kHz + m_rtc->frequency(100000); +} + +DS1307::~DS1307() +{ +// if (m_rtc != NULL) +// delete m_rtc; +} + +bool DS1307::setTime(Time_rtc& time, bool start, bool thm) +{ + char buffer[7]; +// INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour, time.min, time.sec); + if (!read(0,buffer,7)) { +// ERR("Failed to read from RTC\n"); + return false; + } + // Now update only the time part (saving the existing flags) + if (start) { + buffer[0] &= 0x7F; + } else { + buffer[0] |= 0x80; + } + buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)& 0x7f); + buffer[1] = decimalToBcd(time.min); + if (thm) { + // AM PM format + buffer[2] = (buffer[2]& 196) | (time.hour>12 ? (0x20 | ((decimalToBcd(time.hour-12)))) : decimalToBcd(time.hour)); + } else { + // 24 hours format + buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour) & 0x3F); + } + buffer[3] = time.wday; + buffer[4] = decimalToBcd(time.date); + buffer[5] = decimalToBcd(time.mon); + buffer[6] = decimalToBcd(time.year-2000); +// INFO("Writing new time and date data to RTC\n"); + if (!write(0, buffer, 7) ) { +// ERR("Failed to write the data to RTC!\n"); + return false; + } + return true; +} + +bool DS1307::getTime(Time_rtc& time) +{ + char buffer[7]; + bool thm = false; + +// INFO("Getting time from RTC\n"); + if (!read(0, buffer, 7) ) { + // Failed to read +// ERR("Failed to read from RTC\n"); + return false; + } + thm = ((buffer[2] & 64) == 64); + time.sec = bcdToDecimal(buffer[0]&0x7F); + time.min = bcdToDecimal(buffer[1]); + if (thm) { + // in 12-hour-mode, we need to add 12 hours if PM bit is set + time.hour = DS1307::bcdToDecimal( buffer[2] & 31 ); + if ((buffer[2] & 32) == 32) + time.hour += 12; + } else { + time.hour = DS1307::bcdToDecimal( buffer[2] & 63 ); + } + time.wday = buffer[3]; + time.date = DS1307::bcdToDecimal( buffer[4]); + time.mon = DS1307::bcdToDecimal( buffer[5]); + time.year = DS1307::bcdToDecimal(buffer[6]) + 2000; // plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900 + + return true; +} + + +bool DS1307::startClock() +{ + char strtStop; + +// INFO ("Reading clock start/stop register value\n"); + if (!read(0, &strtStop, 1)) { +// ERR("Failed to read clock start stop register !\n"); + return false; + } + + strtStop &= 0x7F; + +// INFO("Writing back start/stop register value\n"); + if (!write(0, &strtStop, 1)) { +// ERR("Failed to write the start stop register !\n"); + return false; + } + +// INFO("Start/stop register value successfully written\n"); + return true; +} + +bool DS1307::stopClock() +{ + char strtStop; + +// INFO ("Reading clock start/stop register value\n"); + if (!read(0, &strtStop, 1)) { +// ERR("Failed to read clock start stop register !\n"); + return false; + } + + strtStop |= 0x80; + +// INFO("Writing back start/stop register value\n"); + if (!write(0, &strtStop, 1)) { +// ERR("Failed to write the start stop register !\n"); + return false; + } + +// INFO("Start/stop register value successfully written\n"); + return true; +} + +bool DS1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs) +{ + char reg; +// INFO("Reading register value first\n"); + + if (!read(7,®, 1)) { +// ERR("Failed to read register value !\n"); + return false; + } +// INFO("[Reg:0x07] = %02x\n", reg); + + // preserve the OUT control bit while writing the frequency and enable bits + reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03); + +// INFO("Writing back register value\n"); +// INFO("[Reg:0x07] = %02x\n", reg); + + if (!write(7, ®, 1)) { +// ERR("Failed to write register value !\n"); + return false; + } + +// INFO("Successfully changed the square wave output.\n"); + return true; +} + +void DS1307::setLocalTime() +{ + Time_rtc t; // query time from device + getTime(t); // sync the time with MBED RTC + struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; + time_t epoch = mktime(&now); + set_time(epoch); +} + +bool DS1307::read(int address, char *buffer, int len) +{ + char buffer2[2] = {(char)address, 0}; + +// m_rtc->start(); + if (m_rtc->write(0xd0, buffer2, 1) != 0) { +// ERR("Failed to write register address on rtv!\n"); + m_rtc->stop(); + return false; + } + if (m_rtc->read(0xd0, buffer, len) != 0) { +// ERR("Failed to read register !\n"); + return false; + } + m_rtc->stop(); + +// INFO("Successfully read %d registers from RTC\n", len); + return true; +} + +bool DS1307::write(int address, char *buffer, int len) +{ + char buffer2[10]; + buffer2[0] = address&0xFF; + for (int i = 0 ; i < len ; i++) + buffer2[i+1] = buffer[i]; + +// m_rtc->start(); + if (m_rtc->write(0xd0, buffer2, len+1) != 0) { +// ERR("Failed to write data to rtc\n"); + m_rtc->stop(); + return false; + } + m_rtc->stop(); + return true; +} + + + + +RtcCls::RtcCls(I2C * i2c, PinName sqw, bool bUseSqw) + : DS1307(i2c), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL) +{ + Time_rtc t; + // query time from device + getTime(t); + // sync the time with MBED RTC + struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; + m_time = mktime(&now); + set_time(m_time); + + // Only register the callback and start the SQW if requested to do so. Otherwise the system + // will use the MBED built-in RTC. + if (m_bUseSqw) { + // start the wave + setSquareWaveOutput(true, RS1Hz); + // register callback from now on the time will be maintained by the square wave input + m_sqw.rise(this, &RtcCls::_callback); + } +} + +void RtcCls::_callback(void) +{ +// INFO("Tick!"); + // Simply increase the number of seconds + m_time++; +// if (m_bAlarmEnabled && (m_time == m_alarmTime)) { +// if (m_alarmfunc != NULL) +// m_alarmfunc(); +// m_bAlarmEnabled = false; +// } +} + +time_t RtcCls::getTime() +{ + // when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value + if (!m_bUseSqw) { + Time_rtc t; + getTime(t); + struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; + m_time = mktime(&now); +// INFO("getting time %02d.%02d.%04d %02d:%02d:%02d Ticks=%08lx", t.date, t.mon, t.year, t.hour, t.min, t.sec, m_time); + } else { +// INFO("getting time Ticks=%08lx", m_time); + } + return m_time; +} + +void RtcCls::setTime(time_t t) +{ + Time_rtc tim; + struct tm *now; + now = localtime(&t); + + tim.sec = now->tm_sec; + tim.min = now->tm_min; + tim.hour = now->tm_hour; + tim.date = now->tm_mday; + tim.mon = now->tm_mon+1; + tim.year = now->tm_year + 1900; + tim.wday = now->tm_wday +1; + + setTime( tim, true, true); + set_time(t); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DS1307.h Wed Jan 31 11:50:07 2018 +0000 @@ -0,0 +1,187 @@ +/* Rtc_Ds1307.h */ +/* +Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#include "mbed.h" + +#ifndef __DS1307_H__ +#define __DS1307_H__ + + + +/** Class Rtc_Ds1307 implements the real time clock module DS1307 + * + * You can read the clock and set a new time and date. + * It is also possible to start and stop the clock. + * Rtc_Ds1307 allows you to display the time in a 12h or 24h format + */ +class DS1307 +{ +public: + /** Structure which is used to exchange the time and date + */ + typedef struct { + int sec; /*!< seconds [0..59] */ + int min; /*!< minutes {0..59] */ + int hour; /*!< hours [0..23] */ + int wday; /*!< weekday [1..7, where 1 = sunday, 2 = monday, ... */ + int date; /*!< day of month [0..31] */ + int mon; /*!< month of year [1..12] */ + int year; /*!< year [2000..2255] */ + } Time_rtc; + + + /** RateSelect specifies the valid frequency values for the square wave output + */ + typedef enum { + RS1Hz = 0, + RS4kHz = 1, + RS8kHz = 2, + RS32kHz = 3 + } SqwRateSelect_t; + +protected: + I2C * m_rtc; + + static const char *m_weekDays[]; + +public: + /** public constructor which creates the real time clock object + * + * @param sda : specifies the pin for the SDA communication line. + * + * @param scl : the pin for the serial clock + * + */ + DS1307(I2C * ); + + ~DS1307(); + + /** Read the current time from RTC chip + * + * @param time : reference to a struct tm which will be filled with the time from rtc + * + * @returns true if successful, otherwise an acknowledge error occured + */ + virtual bool getTime(Time_rtc& time); + + /** Write the given time onto the RTC chip + * + * @param time : refereence to a struct which contains valid date and time information + * + * @param start : contains true if the clock shall start (or keep on running). + * + * @param thm : 12-hour-mode if set to true, otherwise 24-hour-mode will be set. + * + * @returns true if successful, otherwise an acknowledge error occured + */ + virtual bool setTime(Time_rtc& time, bool start, bool thm); + + /** Start the clock. Please note that the seconds register need to be read and + * written in order to start or stop the clock. This can lead to an error + * in the time value. The recommended way of starting and stoping the clock is + * to write the actual date and time and set the start bit accordingly. + * + * @returns true if the clock was started, false if a communication error occured + */ + bool startClock(); + + /** Stop the clock. Please note that the seconds register need to be read and + * written in order to start or stop the clock. This can lead to an error + * in the time value. The recommended way of starting and stoping the clock is + * to write the actual date and time and set the start bit accordingly. + * + * @returns true if the clock was stopped, false if a communication error occured + */ + bool stopClock(); + + /** Service function to convert a weekday into a string representation + * + * @param wday : day of week to convert (starting with sunday = 1, monday = 2, ..., saturday = 7 + * + * @returns the corresponding string representation + */ + const char* weekdayToString( int wday ) { + return m_weekDays[wday%7]; + } + + /** Enable Square Wave output. The function enables or disables the square wave output + * of the module and sets the desired frequency. + * + * @param ena : if set to true, the square wave output is enabled. + * + * @param rs : rate select, can be either one of the four values defined by type /c RateSelect_t + * + * @return true if the operation was successful or false otherwise + */ + bool setSquareWaveOutput(bool ena, SqwRateSelect_t rs); + + void setLocalTime(); + +private: + bool read(int address, char* buffer, int len); + bool write(int address, char* buffer, int len); + + static int bcdToDecimal(int bcd) { + return ((bcd&0xF0)>>4)*10 + (bcd&0x0F); + } + + static int decimalToBcd(int dec) { + return (dec%10) + ((dec/10)<<4); + } +}; + + + +typedef void (*RtcCallback_t) (void); + + +class RtcCls : public DS1307 +{ +protected: + InterruptIn m_sqw; + bool m_bUseSqw; + time_t m_time; // Only used in case SQW is used + + bool m_bAlarmEnabled; + RtcCallback_t m_alarmfunc; + time_t m_alarmTime; + +public: + RtcCls(I2C * i2c, PinName sqw, bool bUseSqw); + +protected: + void _callback(void); + +public: + time_t getTime(); + virtual bool getTime(Time_rtc& time) { return DS1307::getTime(time); } + void setTime(time_t time); + virtual bool setTime(Time_rtc& time, bool start, bool thm) { return DS1307::setTime(time, start, thm); } +public: + void setAlarm(int nSeconds, RtcCallback_t alarmfunc) { + m_alarmfunc = alarmfunc; + m_alarmTime = m_time + nSeconds; + m_bAlarmEnabled = (alarmfunc == NULL) ? false : true; + } +}; + +#endif // __DS1307_H__ \ No newline at end of file
--- a/Rtc_Ds1307.cpp Wed Jun 26 21:05:46 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ -#include "mbed.h" -#include "Rtc_Ds1307.h" - -#ifndef DEBUG -//#define DEBUG -#endif -#include "debug.h" - -const char *Rtc_Ds1307::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }; - - -Rtc_Ds1307::Rtc_Ds1307(PinName sda, PinName scl) -{ - // Create a new I2C object - m_rtc = new I2C(sda, scl); - if (m_rtc == NULL) - error("Rtc_Ds1307"); - - // Set the frequency to standard 100kHz - m_rtc->frequency(100000); -} - -Rtc_Ds1307::~Rtc_Ds1307() -{ - if (m_rtc != NULL) - delete m_rtc; -} - -bool Rtc_Ds1307::setTime(Time_rtc& time, bool start, bool thm) -{ - char buffer[7]; - INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour, time.min, time.sec); - if (!read(0,buffer,7)) { - ERR("Failed to read from RTC\n"); - return false; - } - // Now update only the time part (saving the existing flags) - if (start) { buffer[0] &= 0x7F; } else { buffer[0] |= 0x80; } - buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)& 0x7f); - buffer[1] = decimalToBcd(time.min); - if (thm) { - // AM PM format - buffer[2] = (buffer[2]& 196) | (time.hour>12 ? (0x20 | ((decimalToBcd(time.hour-12)))) : decimalToBcd(time.hour)); - } - else { - // 24 hours format - buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour) & 0x3F); - } - buffer[3] = time.wday; - buffer[4] = decimalToBcd(time.date); - buffer[5] = decimalToBcd(time.mon); - buffer[6] = decimalToBcd(time.year-2000); - INFO("Writing new time and date data to RTC\n"); - if (!write(0, buffer, 7) ) { - ERR("Failed to write the data to RTC!\n"); - return false; - } - return true; -} - -bool Rtc_Ds1307::getTime(Time_rtc& time) -{ - char buffer[7]; - bool thm = false; - - INFO("Getting time from RTC\n"); - if (!read(0, buffer, 7) ) { - // Failed to read - ERR("Failed to read from RTC\n"); - return false; - } - thm = ((buffer[2] & 64) == 64); - time.sec = bcdToDecimal(buffer[0]&0x7F); - time.min = bcdToDecimal(buffer[1]); - if (thm) { - // in 12-hour-mode, we need to add 12 hours if PM bit is set - time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 31 ); - if ((buffer[2] & 32) == 32) - time.hour += 12; - } - else { - time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 63 ); - } - time.wday = buffer[3]; - time.date = Rtc_Ds1307::bcdToDecimal( buffer[4]); - time.mon = Rtc_Ds1307::bcdToDecimal( buffer[5]); - time.year = Rtc_Ds1307::bcdToDecimal(buffer[6]) + 2000; // plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900 - - return true; -} - - -bool Rtc_Ds1307::startClock() -{ - char strtStop; - - INFO ("Reading clock start/stop register value\n"); - if (!read(0, &strtStop, 1)) { - ERR("Failed to read clock start stop register !\n"); - return false; - } - - strtStop &= 0x7F; - - INFO("Writing back start/stop register value\n"); - if (!write(0, &strtStop, 1)) { - ERR("Failed to write the start stop register !\n"); - return false; - } - - INFO("Start/stop register value successfully written\n"); - return true; -} - -bool Rtc_Ds1307::stopClock() -{ - char strtStop; - - INFO ("Reading clock start/stop register value\n"); - if (!read(0, &strtStop, 1)) { - ERR("Failed to read clock start stop register !\n"); - return false; - } - - strtStop |= 0x80; - - INFO("Writing back start/stop register value\n"); - if (!write(0, &strtStop, 1)) { - ERR("Failed to write the start stop register !\n"); - return false; - } - - INFO("Start/stop register value successfully written\n"); - return true; -} - -bool Rtc_Ds1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs) -{ - char reg; - INFO("Reading register value first\n"); - - if (!read(7,®, 1)) { - ERR("Failed to read register value !\n"); - return false; - } - INFO("[Reg:0x07] = %02x\n", reg); - - // preserve the OUT control bit while writing the frequency and enable bits - reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03); - - INFO("Writing back register value\n"); - INFO("[Reg:0x07] = %02x\n", reg); - - if (!write(7, ®, 1)) { - ERR("Failed to write register value !\n"); - return false; - } - - INFO("Successfully changed the square wave output.\n"); - return true; -} - - - -bool Rtc_Ds1307::read(int address, char *buffer, int len) -{ - char buffer2[2] = {(char)address, 0}; - -// m_rtc->start(); - if (m_rtc->write(0xd0, buffer2, 1) != 0) { - ERR("Failed to write register address on rtv!\n"); - m_rtc->stop(); - return false; - } - if (m_rtc->read(0xd0, buffer, len) != 0) { - ERR("Failed to read register !\n"); - return false; - } - m_rtc->stop(); - - INFO("Successfully read %d registers from RTC\n", len); - return true; -} - -bool Rtc_Ds1307::write(int address, char *buffer, int len) -{ - char buffer2[10]; - buffer2[0] = address&0xFF; - for (int i = 0 ; i < len ; i++) - buffer2[i+1] = buffer[i]; - -// m_rtc->start(); - if (m_rtc->write(0xd0, buffer2, len+1) != 0) { - ERR("Failed to write data to rtc\n"); - m_rtc->stop(); - return false; - } - m_rtc->stop(); - return true; -} - - - - -RtcCls::RtcCls(PinName sda, PinName scl, PinName sqw, bool bUseSqw) - : Rtc_Ds1307(sda, scl), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL) -{ - Time_rtc t; - // query time from device - getTime(t); - // sync the time with MBED RTC - struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; - m_time = mktime(&now); - set_time(m_time); - - // Only register the callback and start the SQW if requested to do so. Otherwise the system - // will use the MBED built-in RTC. - if (m_bUseSqw) { - // start the wave - setSquareWaveOutput(true, RS1Hz); - // register callback from now on the time will be maintained by the square wave input - m_sqw.rise(this, &RtcCls::_callback); - } -} - -void RtcCls::_callback(void) -{ -// INFO("Tick!"); - // Simply increase the number of seconds - m_time++; -// if (m_bAlarmEnabled && (m_time == m_alarmTime)) { -// if (m_alarmfunc != NULL) -// m_alarmfunc(); -// m_bAlarmEnabled = false; -// } -} - -time_t RtcCls::getTime() -{ - // when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value - if (!m_bUseSqw) { - Time_rtc t; - getTime(t); - struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; - m_time = mktime(&now); - INFO("getting time %02d.%02d.%04d %02d:%02d:%02d Ticks=%08lx", t.date, t.mon, t.year, t.hour, t.min, t.sec, m_time); - } - else { - INFO("getting time Ticks=%08lx", m_time); - } - return m_time; -} - -void RtcCls::setTime(time_t t) -{ - Time_rtc tim; - struct tm *now; - now = localtime(&t); - - tim.sec = now->tm_sec; - tim.min = now->tm_min; - tim.hour = now->tm_hour; - tim.date = now->tm_mday; - tim.mon = now->tm_mon+1; - tim.year = now->tm_year + 1900; - tim.wday = now->tm_wday +1; - - setTime( tim, true, true); - set_time(t); -}
--- a/Rtc_Ds1307.h Wed Jun 26 21:05:46 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* Rtc_Ds1307.h */ -/* -Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#ifndef __RTC_DS1307_H__ -#define __RTC_DS1307_H__ - - - -/** Class Rtc_Ds1307 implements the real time clock module DS1307 - * - * You can read the clock and set a new time and date. - * It is also possible to start and stop the clock. - * Rtc_Ds1307 allows you to display the time in a 12h or 24h format - */ -class Rtc_Ds1307 -{ -public: - /** Structure which is used to exchange the time and date - */ - typedef struct { - int sec; /*!< seconds [0..59] */ - int min; /*!< minutes {0..59] */ - int hour; /*!< hours [0..23] */ - int wday; /*!< weekday [1..7, where 1 = sunday, 2 = monday, ... */ - int date; /*!< day of month [0..31] */ - int mon; /*!< month of year [1..12] */ - int year; /*!< year [2000..2255] */ - } Time_rtc; - - - /** RateSelect specifies the valid frequency values for the square wave output - */ - typedef enum { - RS1Hz = 0, - RS4kHz = 1, - RS8kHz = 2, - RS32kHz = 3 - } SqwRateSelect_t; - -protected: - I2C* m_rtc; - - static const char *m_weekDays[]; - -public: - /** public constructor which creates the real time clock object - * - * @param sda : specifies the pin for the SDA communication line. - * - * @param scl : the pin for the serial clock - * - */ - Rtc_Ds1307(PinName sda, PinName scl); - - ~Rtc_Ds1307(); - - /** Read the current time from RTC chip - * - * @param time : reference to a struct tm which will be filled with the time from rtc - * - * @returns true if successful, otherwise an acknowledge error occured - */ - virtual bool getTime(Time_rtc& time); - - /** Write the given time onto the RTC chip - * - * @param time : refereence to a struct which contains valid date and time information - * - * @param start : contains true if the clock shall start (or keep on running). - * - * @param thm : 12-hour-mode if set to true, otherwise 24-hour-mode will be set. - * - * @returns true if successful, otherwise an acknowledge error occured - */ - virtual bool setTime(Time_rtc& time, bool start, bool thm); - - /** Start the clock. Please note that the seconds register need to be read and - * written in order to start or stop the clock. This can lead to an error - * in the time value. The recommended way of starting and stoping the clock is - * to write the actual date and time and set the start bit accordingly. - * - * @returns true if the clock was started, false if a communication error occured - */ - bool startClock(); - - /** Stop the clock. Please note that the seconds register need to be read and - * written in order to start or stop the clock. This can lead to an error - * in the time value. The recommended way of starting and stoping the clock is - * to write the actual date and time and set the start bit accordingly. - * - * @returns true if the clock was stopped, false if a communication error occured - */ - bool stopClock(); - - /** Service function to convert a weekday into a string representation - * - * @param wday : day of week to convert (starting with sunday = 1, monday = 2, ..., saturday = 7 - * - * @returns the corresponding string representation - */ - const char* weekdayToString( int wday ) { - return m_weekDays[wday%7]; - } - - /** Enable Square Wave output. The function enables or disables the square wave output - * of the module and sets the desired frequency. - * - * @param ena : if set to true, the square wave output is enabled. - * - * @param rs : rate select, can be either one of the four values defined by type /c RateSelect_t - * - * @return true if the operation was successful or false otherwise - */ - bool setSquareWaveOutput(bool ena, SqwRateSelect_t rs); - -private: - bool read(int address, char* buffer, int len); - bool write(int address, char* buffer, int len); - - static int bcdToDecimal(int bcd) { - return ((bcd&0xF0)>>4)*10 + (bcd&0x0F); - } - - static int decimalToBcd(int dec) { - return (dec%10) + ((dec/10)<<4); - } -}; - - - -typedef void (*RtcCallback_t) (void); - - -class RtcCls : public Rtc_Ds1307 -{ -protected: - InterruptIn m_sqw; - bool m_bUseSqw; - time_t m_time; // Only used in case SQW is used - - bool m_bAlarmEnabled; - RtcCallback_t m_alarmfunc; - time_t m_alarmTime; - -public: - RtcCls(PinName sda, PinName scl, PinName sqw, bool bUseSqw); - -protected: - void _callback(void); - -public: - time_t getTime(); - virtual bool getTime(Time_rtc& time) { return Rtc_Ds1307::getTime(time); } - void setTime(time_t time); - virtual bool setTime(Time_rtc& time, bool start, bool thm) { return Rtc_Ds1307::setTime(time, start, thm); } -public: - void setAlarm(int nSeconds, RtcCallback_t alarmfunc) { - m_alarmfunc = alarmfunc; - m_alarmTime = m_time + nSeconds; - m_bAlarmEnabled = (alarmfunc == NULL) ? false : true; - } -}; - -#endif // __RTC_DS1307_H__ \ No newline at end of file