Working Version of the Real Time Clock module DS1307.

Dependents:   Rtc_Ds1307_Sample TAREA_5_PROCESADORES Rtc_Ds1307_lcd_alarma Rtc_Ds1307_Reloj_con_alarma_aplazable ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Rtc_Ds1307.cpp Source File

Rtc_Ds1307.cpp

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