Mateusz Grzywacz / DS1307

Dependents:   Nucleo_praktyki

Fork of RTC-DS1307 by Henry Leinen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS1307.cpp Source File

DS1307.cpp

00001 #include "mbed.h"
00002 #include "DS1307.h"
00003 
00004 #ifndef DEBUG
00005 //#define DEBUG
00006 #endif
00007 //#include "debug.h"
00008 
00009 const char *DS1307::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
00010 
00011 
00012 DS1307::DS1307(I2C * i2c)
00013 {
00014     //  Create a new I2C object
00015     m_rtc = i2c;
00016     if (m_rtc == NULL)
00017         error("Rtc_Ds1307");
00018 
00019     // Set the frequency to standard 100kHz
00020     m_rtc->frequency(100000);
00021 }
00022 
00023 DS1307::~DS1307()
00024 {
00025 //    if (m_rtc != NULL)
00026 //        delete m_rtc;
00027 }
00028 
00029 bool DS1307::setTime(Time_rtc& time, bool start, bool thm)
00030 {
00031     char buffer[7];
00032 //    INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour, time.min, time.sec);
00033     if (!read(0,buffer,7)) {
00034 //        ERR("Failed to read from RTC\n");
00035         return false;
00036     }
00037     //  Now update only the time part (saving the existing flags)
00038     if (start) {
00039         buffer[0] &= 0x7F;
00040     } else {
00041         buffer[0] |= 0x80;
00042     }
00043     buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec )& 0x7f);
00044     buffer[1] = decimalToBcd(time.min );
00045     if (thm) {
00046         //  AM PM format
00047         buffer[2] = (buffer[2]& 196) | (time.hour >12 ? (0x20 | ((decimalToBcd(time.hour -12)))) : decimalToBcd(time.hour ));
00048     } else {
00049         // 24 hours format
00050         buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour ) & 0x3F);
00051     }
00052     buffer[3] = time.wday ;
00053     buffer[4] = decimalToBcd(time.date );
00054     buffer[5] = decimalToBcd(time.mon );
00055     buffer[6] = decimalToBcd(time.year -2000);
00056 //    INFO("Writing new time and date data to RTC\n");
00057     if (!write(0, buffer, 7) ) {
00058 //        ERR("Failed to write the data to RTC!\n");
00059         return false;
00060     }
00061     return true;
00062 }
00063 
00064 bool DS1307::getTime(Time_rtc& time)
00065 {
00066     char buffer[7];
00067     bool thm = false;
00068 
00069 //    INFO("Getting time from RTC\n");
00070     if (!read(0, buffer, 7) ) {
00071         //  Failed to read
00072 //        ERR("Failed to read from RTC\n");
00073         return false;
00074     }
00075     thm = ((buffer[2] & 64) == 64);
00076     time.sec  = bcdToDecimal(buffer[0]&0x7F);
00077     time.min  = bcdToDecimal(buffer[1]);
00078     if (thm) {
00079         // in 12-hour-mode, we need to add 12 hours if PM bit is set
00080         time.hour  = DS1307::bcdToDecimal( buffer[2] & 31 );
00081         if ((buffer[2] & 32) == 32)
00082             time.hour  += 12;
00083     } else {
00084         time.hour  = DS1307::bcdToDecimal( buffer[2] & 63 );
00085     }
00086     time.wday  = buffer[3];
00087     time.date  = DS1307::bcdToDecimal( buffer[4]);
00088     time.mon  = DS1307::bcdToDecimal( buffer[5]);
00089     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
00090 
00091     return true;
00092 }
00093 
00094 
00095 bool DS1307::startClock()
00096 {
00097     char strtStop;
00098 
00099 //    INFO ("Reading clock start/stop register value\n");
00100     if (!read(0, &strtStop, 1)) {
00101 //        ERR("Failed to read clock start stop register !\n");
00102         return false;
00103     }
00104 
00105     strtStop &= 0x7F;
00106 
00107 //    INFO("Writing back start/stop register value\n");
00108     if (!write(0, &strtStop, 1)) {
00109 //        ERR("Failed to write the start stop register !\n");
00110         return false;
00111     }
00112 
00113 //    INFO("Start/stop register value successfully written\n");
00114     return true;
00115 }
00116 
00117 bool DS1307::stopClock()
00118 {
00119     char strtStop;
00120 
00121 //    INFO ("Reading clock start/stop register value\n");
00122     if (!read(0, &strtStop, 1)) {
00123 //        ERR("Failed to read clock start stop register !\n");
00124         return false;
00125     }
00126 
00127     strtStop |= 0x80;
00128 
00129 //    INFO("Writing back start/stop register value\n");
00130     if (!write(0, &strtStop, 1)) {
00131 //        ERR("Failed to write the start stop register !\n");
00132         return false;
00133     }
00134 
00135 //    INFO("Start/stop register value successfully written\n");
00136     return true;
00137 }
00138 
00139 bool DS1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs)
00140 {
00141     char reg;
00142 //    INFO("Reading register value first\n");
00143 
00144     if (!read(7,&reg, 1)) {
00145 //        ERR("Failed to read register value !\n");
00146         return false;
00147     }
00148 //    INFO("[Reg:0x07] = %02x\n", reg);
00149 
00150     //  preserve the OUT control bit while writing the frequency and enable bits
00151     reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03);
00152 
00153 //    INFO("Writing back register value\n");
00154 //    INFO("[Reg:0x07] = %02x\n", reg);
00155 
00156     if (!write(7, &reg, 1)) {
00157 //        ERR("Failed to write register value !\n");
00158         return false;
00159     }
00160 
00161 //    INFO("Successfully changed the square wave output.\n");
00162     return true;
00163 }
00164 
00165 void DS1307::setLocalTime()
00166 {
00167     Time_rtc t;   //  query time from device
00168     getTime(t);   //  sync the time with MBED RTC
00169     struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
00170     time_t epoch = mktime(&now);
00171     set_time(epoch);
00172 }
00173 
00174 bool DS1307::read(int address, char *buffer, int len)
00175 {
00176     char buffer2[2] = {(char)address, 0};
00177 
00178 //    m_rtc->start();
00179     if (m_rtc->write(0xd0, buffer2, 1) != 0) {
00180 //        ERR("Failed to write register address on rtv!\n");
00181         m_rtc->stop();
00182         return false;
00183     }
00184     if (m_rtc->read(0xd0, buffer, len) != 0) {
00185 //        ERR("Failed to read register !\n");
00186         return false;
00187     }
00188     m_rtc->stop();
00189 
00190 //    INFO("Successfully read %d registers from RTC\n", len);
00191     return true;
00192 }
00193 
00194 bool DS1307::write(int address, char *buffer, int len)
00195 {
00196     char buffer2[10];
00197     buffer2[0] = address&0xFF;
00198     for (int i = 0 ; i < len ; i++)
00199         buffer2[i+1] = buffer[i];
00200 
00201 //    m_rtc->start();
00202     if (m_rtc->write(0xd0, buffer2, len+1) != 0) {
00203 //        ERR("Failed to write data to rtc\n");
00204         m_rtc->stop();
00205         return false;
00206     }
00207     m_rtc->stop();
00208     return true;
00209 }
00210 
00211 
00212 
00213 
00214 RtcCls::RtcCls(I2C * i2c, PinName sqw, bool bUseSqw)
00215     : DS1307(i2c), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL)
00216 {
00217     Time_rtc t;
00218     //  query time from device
00219     getTime(t);
00220     //  sync the time with MBED RTC
00221     struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
00222     m_time = mktime(&now);
00223     set_time(m_time);
00224 
00225     //  Only register the callback and start the SQW if requested to do so. Otherwise the system
00226     //  will use the MBED built-in RTC.
00227     if (m_bUseSqw) {
00228         //  start the wave
00229         setSquareWaveOutput(true, RS1Hz);
00230         //  register callback from now on the time will be maintained by the square wave input
00231         m_sqw.rise(this, &RtcCls::_callback);
00232     }
00233 }
00234 
00235 void RtcCls::_callback(void)
00236 {
00237 //    INFO("Tick!");
00238     //  Simply increase the number of seconds
00239     m_time++;
00240 //    if (m_bAlarmEnabled && (m_time == m_alarmTime)) {
00241 //        if (m_alarmfunc != NULL)
00242 //            m_alarmfunc();
00243 //        m_bAlarmEnabled = false;
00244 //    }
00245 }
00246 
00247 time_t RtcCls::getTime()
00248 {
00249     //  when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value
00250     if (!m_bUseSqw) {
00251         Time_rtc t;
00252         getTime(t);
00253         struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
00254         m_time = mktime(&now);
00255 //        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);
00256     } else {
00257 //        INFO("getting time Ticks=%08lx", m_time);
00258     }
00259     return m_time;
00260 }
00261 
00262 void RtcCls::setTime(time_t t)
00263 {
00264     Time_rtc tim;
00265     struct tm *now;
00266     now = localtime(&t);
00267 
00268     tim.sec = now->tm_sec;
00269     tim.min = now->tm_min;
00270     tim.hour = now->tm_hour;
00271     tim.date = now->tm_mday;
00272     tim.mon = now->tm_mon+1;
00273     tim.year = now->tm_year + 1900;
00274     tim.wday = now->tm_wday +1;
00275 
00276     setTime( tim, true, true);
00277     set_time(t);
00278 }