Hotboards MX / Hotboards_rtcc

Dependents:   Hotboards_rtcc_manual_timedate Hotboards_rtcc_timeSpan Hotboards_rtcc_alarm Hotboards_rtcc_compiler_timedate ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Hotboards_rtcc.cpp Source File

Hotboards_rtcc.cpp

00001 /*
00002   Hotboards_rtcc.cpp - Library to read, write and control the real time clock MCP7941x included in rtc board.
00003   http://hotboards.org
00004   adapted and taken from https://github.com/adafruit/RTClib
00005   Released into the public domain.
00006 */
00007 
00008 #include "Hotboards_rtcc.h"
00009 
00010 
00011 #define RTC_ADDR          (uint8_t)(0xDE)
00012 #define EEPROM_ADDR       (uint8_t)(0xAE)
00013 #define RTC_STARTADDR     (uint8_t)0x00
00014 #define ALARM_STARTADDR   (uint8_t)0x0A
00015 #define CTRL_STARTADDR    (uint8_t)0x07
00016 #define SRAM_SARTADDR     (uint8_t)0x20
00017 #define EEPROM_SARTADDR   (uint8_t)0x00
00018 #define PEEPROM_SARTADDR  (uint8_t)0xF0
00019 
00020 #define SECONDS_FROM_1970_TO_2000 946684800
00021 
00022 const uint8_t daysInMonth[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
00023 
00024 // number of days since 2000/01/01, valid for 2001..2099
00025 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) 
00026 {
00027     if (y >= 2000)
00028         y -= 2000;
00029     uint16_t days = d;
00030     for (uint8_t i = 1; i < m; ++i)
00031         days += daysInMonth[i - 1];
00032     if (m > 2 && y % 4 == 0)
00033         ++days;
00034     return days + 365 * y + (y + 3) / 4 - 1;
00035 }
00036 
00037 static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) 
00038 {
00039     return ((days * 24L + h) * 60 + m) * 60 + s;
00040 }
00041 
00042 static uint8_t conv2d(const char* p) 
00043 {
00044     uint8_t v = 0;
00045     if ('0' <= *p && *p <= '9')
00046         v = *p - '0';
00047     return 10 * v + *++p - '0';
00048 }
00049 
00050 /*
00051  * Constructor that use time in a 32 bit variable
00052  */
00053 DateTime::DateTime( uint32_t t )
00054 {
00055     t -= SECONDS_FROM_1970_TO_2000;    // bring to 2000 timestamp from 1970
00056     ss = t % 60;
00057     t /= 60;
00058     mm = t % 60;
00059     t /= 60;
00060     hh = t % 24;
00061     uint16_t days = t / 24;
00062     uint8_t leap;
00063     for( yOff = 0 ; ; ++yOff ) 
00064     {
00065         leap = yOff % 4 == 0;
00066         if (days < 365 + leap)
00067         {
00068             break;
00069         }
00070         days -= 365 + leap;
00071     }
00072     for (m = 1; ; ++m) 
00073     {
00074         uint8_t daysPerMonth = daysInMonth[m - 1];
00075         if (leap && m == 2)
00076         {
00077             ++daysPerMonth;
00078         }
00079         if (days < daysPerMonth)
00080         {
00081             break;
00082         }
00083         days -= daysPerMonth;
00084     }
00085     d = days + 1;
00086 }
00087         
00088 /*
00089  * Constructor that use time variables for each element in decimal
00090  */
00091 DateTime::DateTime( uint16_t year, uint8_t month, uint8_t day,
00092                   uint8_t hour, uint8_t min, uint8_t sec, uint8_t dweek )
00093 {
00094     if( year >= 2000 )
00095     {
00096         year -= 2000;
00097     }
00098     yOff = year;
00099     m = month;
00100     d = day;
00101     hh = hour;
00102     mm = min;
00103     ss = sec;
00104     dw = dweek;
00105 }
00106         
00107 /*
00108  * Constructor tcreate a copy of DateTime object
00109  */
00110 DateTime::DateTime (const DateTime& copy):
00111   yOff(copy.yOff),
00112   m(copy.m),
00113   d(copy.d),
00114   hh(copy.hh),
00115   mm(copy.mm),
00116   ss(copy.ss)
00117 {}
00118 
00119 
00120 /*
00121  * A convenient constructor for using "the compiler's time":
00122    DateTime now (__DATE__, __TIME__);
00123  */
00124 DateTime::DateTime( const char* date, const char* time ) 
00125 {
00126     // sample input: date = "Dec 26 2009", time = "12:34:56"
00127     yOff = conv2d(date + 9);
00128     // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 
00129     switch( date[0] ) 
00130     {
00131         case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
00132         case 'F': m = 2; break;
00133         case 'A': m = date[2] == 'r' ? 4 : 8; break;
00134         case 'M': m = date[2] == 'r' ? 3 : 5; break;
00135         case 'S': m = 9; break;
00136         case 'O': m = 10; break;
00137         case 'N': m = 11; break;
00138         case 'D': m = 12; break;
00139     }
00140     d  = conv2d( date + 4 );
00141     hh = conv2d( time );
00142     mm = conv2d( time + 3 );
00143     ss = conv2d( time + 6 );
00144 }
00145 
00146 uint8_t DateTime::dayOfTheWeek( void ) const
00147 {    
00148     uint16_t day = date2days( yOff, m, d );
00149     
00150     return ( day + 6 ) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
00151 }
00152 
00153 uint32_t DateTime::unixtime( void ) const
00154 {
00155   uint32_t t;
00156   uint16_t days = date2days( yOff, m, d );
00157   
00158   t = time2long(days, hh, mm, ss);
00159   t += SECONDS_FROM_1970_TO_2000;  // seconds from 1970 to 2000
00160 
00161   return t;
00162 }
00163 
00164 uint32_t DateTime::secondstime( void ) const
00165 {
00166   uint32_t t;
00167   uint16_t days = date2days( yOff, m, d );
00168   
00169   t = time2long( days, hh, mm, ss );
00170   return t;
00171 }
00172 
00173 
00174 
00175 
00176 DateTime DateTime::operator+(const TimeSpan& span) 
00177 {
00178   return DateTime(unixtime()+span.totalseconds());
00179 }
00180 
00181 DateTime DateTime::operator-(const TimeSpan& span) 
00182 {
00183   return DateTime(unixtime()-span.totalseconds());
00184 }
00185 
00186 TimeSpan DateTime::operator-(const DateTime& right) 
00187 {
00188   return TimeSpan(unixtime()-right.unixtime());
00189 }
00190 
00191 
00192 
00193 TimeSpan::TimeSpan (int32_t seconds):
00194   _seconds(seconds)
00195 {}
00196 
00197 TimeSpan::TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds):
00198   _seconds((int32_t)days*86400L + (int32_t)hours*3600 + (int32_t)minutes*60 + seconds)
00199 {}
00200 
00201 TimeSpan::TimeSpan (const TimeSpan& copy):
00202   _seconds(copy._seconds)
00203 {}
00204 
00205 TimeSpan TimeSpan::operator+(const TimeSpan& right) 
00206 {
00207   return TimeSpan(_seconds+right._seconds);
00208 }
00209 
00210 TimeSpan TimeSpan::operator-(const TimeSpan& right) 
00211 {
00212   return TimeSpan(_seconds-right._seconds);
00213 }
00214 
00215 
00216 
00217 Hotboards_rtcc::Hotboards_rtcc( I2C &i2c ) 
00218     : _i2c(i2c) 
00219 {
00220     on_off = 0;
00221 }
00222 /*
00223  * enable internal oscilator if this is disable (start the clock)
00224  */
00225 void Hotboards_rtcc::begin( void )
00226 {
00227     if( isrunning( ) == 0 )
00228     {
00229         writeReg( RTC_STARTADDR, 0x80 );
00230     }
00231 }
00232 
00233 /*
00234  * set a new time and date
00235  */
00236 void Hotboards_rtcc::adjust( const DateTime &dt )
00237 {
00238     char buffer[8]; 
00239      
00240     buffer[0] = RTC_STARTADDR; 
00241     buffer[1] = bin2bcd(dt.second()) | 0x80;
00242     buffer[2] = bin2bcd(dt.minute());
00243     buffer[3] = bin2bcd(dt.hour());
00244     buffer[4] = bin2bcd(dt.dayOfTheWeek()) | on_off;
00245     buffer[5] = bin2bcd(dt.day());
00246     buffer[6] = bin2bcd(dt.month());
00247     buffer[7] = bin2bcd(dt.year() - 2000);
00248     
00249     stop();
00250     _i2c.write( RTC_ADDR, buffer, 8 );
00251 }
00252 
00253 /*
00254  * return an DateTime object with the actual time and date
00255  */
00256 DateTime Hotboards_rtcc::now( void )
00257 {
00258     char buffer[7];
00259     
00260     buffer[0] = RTC_STARTADDR;
00261     _i2c.write(RTC_ADDR, buffer, 1, true);
00262     _i2c.read(RTC_ADDR, buffer, 7, false);
00263     
00264     uint8_t ss = bcd2bin( buffer[0] & 0x7F );
00265     uint8_t mm = bcd2bin( buffer[1] );
00266     uint8_t hh = bcd2bin( buffer[2] );
00267     uint8_t dw = buffer[3] & 0x07;
00268     uint8_t d  = bcd2bin( buffer[4] );
00269     uint8_t m  = bcd2bin( buffer[5] & 0xDF );
00270     uint16_t y = bcd2bin( buffer[6] ) + 2000;
00271     
00272     return DateTime( y, m, d, hh, mm, ss, dw );  
00273 }
00274 
00275 /*
00276  * return a true if the rtcc is running
00277  */
00278 uint8_t Hotboards_rtcc::isrunning( void )
00279 {
00280     uint8_t running = readReg( RTC_STARTADDR + 3 ) & 0x20;
00281     return running >> 5;
00282 }
00283 
00284 /*
00285  * stop the internal rtcc clock
00286  */
00287 void Hotboards_rtcc::stop( void )
00288 {
00289    writeReg( RTC_STARTADDR, 0x00 );
00290    while( isrunning( ) == 1 ); 
00291 }
00292 
00293 void Hotboards_rtcc::setVBAT( uint8_t OnOff )
00294 {
00295     on_off = ( OnOff & 0x01 ) << 3;
00296 }
00297 
00298 void Hotboards_rtcc::setAlarm( const DateTime &dt, uint8_t alarm )
00299 {
00300     char buffer[8]; 
00301      
00302     buffer[0] = ALARM_STARTADDR; 
00303     buffer[1] = bin2bcd(dt.second()) | 0x80;
00304     buffer[2] = bin2bcd(dt.minute());
00305     buffer[3] = bin2bcd(dt.hour());
00306     buffer[4] = bin2bcd(dt.dayOfTheWeek()) | on_off;
00307     buffer[5] = bin2bcd(dt.day());
00308     buffer[6] = bin2bcd(dt.month());
00309     buffer[7] = bin2bcd(dt.year() - 2000);
00310     
00311     _i2c.write( RTC_ADDR, buffer, 8 );    
00312 }
00313 
00314 uint8_t Hotboards_rtcc::getAlarmStatus( uint8_t alarm )
00315 {
00316     uint8_t status = readReg( ALARM_STARTADDR + 3 );
00317     return ( status >> 3 ) & 0x01;
00318 }
00319 
00320 void Hotboards_rtcc::clearAlarm( uint8_t alarm )
00321 {
00322     uint8_t status = readReg( ALARM_STARTADDR + 3 );
00323     writeReg( ALARM_STARTADDR + 3, (status  & 0xF7) );
00324 }
00325 
00326 void Hotboards_rtcc::turnOnAlarm( uint8_t alarm )
00327 {
00328     uint8_t ctrl = readReg( CTRL_STARTADDR );
00329     writeReg( CTRL_STARTADDR, ctrl | 0x10 );
00330 }
00331 
00332 void Hotboards_rtcc::turnOffAlarm( uint8_t alarm )
00333 {
00334     uint8_t ctrl = readReg( CTRL_STARTADDR );
00335     writeReg( CTRL_STARTADDR, ctrl & 0xEF );
00336 }
00337 
00338 uint8_t Hotboards_rtcc::readReg( uint8_t address )
00339 {
00340     char buffer[1];
00341     
00342     buffer[0] = address;
00343     _i2c.write(RTC_ADDR, buffer, 1, true);
00344     _i2c.read(RTC_ADDR, buffer, 1, false);
00345     
00346     return buffer[0];
00347 }
00348 
00349 void Hotboards_rtcc::writeReg( uint8_t address, uint8_t val )
00350 {
00351    char buffer[2]; 
00352      
00353    buffer[0] = address; 
00354    buffer[1] = val;
00355     
00356    _i2c.write( RTC_ADDR, buffer, 2 );     
00357 }
00358       
00359 uint8_t Hotboards_rtcc::bcd2bin( uint8_t val ) 
00360 { 
00361     return val - 6 * ( val >> 4 ); 
00362 }
00363 
00364 uint8_t Hotboards_rtcc::bin2bcd( uint8_t val ) 
00365 { 
00366     return val + 6 * ( val / 10 ); 
00367 
00368 }