Izvorne datoteke za TinyRTC DS1307 sa I2C komunikacijom.

Dependents:   Detektor_Pokreta Dino_Martic_Programski

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