Alejandro Lara / DS3231
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RTClib.cpp Source File

RTClib.cpp

Go to the documentation of this file.
00001 /**************************************************************************/
00002 /*!
00003   @file     RTClib.cpp
00004 
00005   @mainpage Adafruit RTClib
00006 
00007   @section intro Introduction
00008 
00009   This is a fork of JeeLab's fantastic real time clock library for Arduino.
00010 
00011   For details on using this library with an RTC module like the DS1307, PCF8523, or DS3231,
00012   see the guide at: https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview
00013 
00014   Adafruit invests time and resources providing this open source code,
00015   please support Adafruit and open-source hardware by purchasing
00016   products from Adafruit!
00017 
00018   @section classes Available classes
00019 
00020   This library provides the following classes:
00021 
00022   - Classes for manipulating dates, times and durations:
00023     - DateTime represents a specific point in time; this is the data
00024       type used for setting and reading the supported RTCs
00025     - TimeSpan represents the length of a time interval
00026   - Interfacing specific RTC chips:
00027     - RTC_DS1307
00028     - RTC_DS3231
00029     - RTC_PCF8523
00030   - RTC emulated in software; do not expect much accuracy out of these:
00031     - RTC_Millis is based on `millis()`
00032     - RTC_Micros is based on `micros()`; its drift rate can be tuned by
00033       the user
00034 
00035   @section license License
00036 
00037   Original library by JeeLabs http://news.jeelabs.org/code/, released to the public domain.
00038 
00039   This version: MIT (see LICENSE)
00040 */
00041 /**************************************************************************/
00042 
00043 #include "mbed.h"
00044 #include <string>
00045 //using namespace std;
00046 #include "RTClib.h "
00047 
00048 /**************************************************************************/
00049 /*!
00050     @brief  Read a uint8_t from an I2C register
00051     @param addr I2C address
00052     @param reg Register address
00053     @return Register value
00054 */
00055 /**************************************************************************/
00056 uint8_t RTC_DS3231::read_i2c_register(uint8_t addr, uint8_t reg)
00057 {
00058 
00059     char cmdData[1] = { (char)reg };
00060     char value;
00061 
00062     (*_i2c).write(DS3231_ADDRESS, cmdData, sizeof(cmdData));
00063 
00064     (*_i2c).read(DS3231_ADDRESS, &value, 1);
00065 
00066     return value;
00067 }
00068 
00069 /**************************************************************************/
00070 /*!
00071     @brief  Write a uint8_t to an I2C register
00072     @param addr I2C address
00073     @param reg Register address
00074     @param val Value to write
00075 */
00076 /**************************************************************************/
00077 void RTC_DS3231::write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val)
00078 {
00079     char cmdData[2] = { (char)reg, val };
00080 
00081     (*_i2c).write(DS3231_ADDRESS, cmdData, sizeof(cmdData));
00082 
00083 }
00084 
00085 
00086 /**************************************************************************/
00087 // utility code, some of this could be exposed in the DateTime API if needed
00088 /**************************************************************************/
00089 
00090 /**
00091   Number of days in each month, from January to November. December is not
00092   needed. Omitting it avoids an incompatibility with Paul Stoffregen's Time
00093   library. C.f. https://github.com/adafruit/RTClib/issues/114
00094 */
00095 const uint8_t daysInMonth [] = { 31,28,31,30,31,30,31,31,30,31,30 };
00096 
00097 /**************************************************************************/
00098 /*!
00099     @brief  Given a date, return number of days since 2000/01/01, valid for 2001..2099
00100     @param y Year
00101     @param m Month
00102     @param d Day
00103     @return Number of days
00104 */
00105 /**************************************************************************/
00106 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d)
00107 {
00108     if (y >= 2000)
00109         y -= 2000;
00110     uint16_t days = d;
00111     for (uint8_t i = 1; i < m; ++i)
00112         days += daysInMonth [i - 1];
00113     if (m > 2 && y % 4 == 0)
00114         ++days;
00115     return days + 365 * y + (y + 3) / 4 - 1;
00116 }
00117 
00118 /**************************************************************************/
00119 /*!
00120     @brief  Given a number of days, hours, minutes, and seconds, return the total seconds
00121     @param days Days
00122     @param h Hours
00123     @param m Minutes
00124     @param s Seconds
00125     @return Number of seconds total
00126 */
00127 /**************************************************************************/
00128 static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s)
00129 {
00130     return ((days * 24L + h) * 60 + m) * 60 + s;
00131 }
00132 
00133 
00134 
00135 /**************************************************************************/
00136 /*!
00137     @brief  DateTime constructor from unixtime
00138     @param t Initial time in seconds since Jan 1, 1970 (Unix time)
00139 */
00140 /**************************************************************************/
00141 DateTime::DateTime (uint32_t t)
00142 {
00143     t -= SECONDS_FROM_1970_TO_2000;    // bring to 2000 timestamp from 1970
00144 
00145     ss = t % 60;
00146     t /= 60;
00147     mm = t % 60;
00148     t /= 60;
00149     hh = t % 24;
00150     uint16_t days = t / 24;
00151     uint8_t leap;
00152     for (yOff = 0; ; ++yOff) {
00153         leap = yOff % 4 == 0;
00154         if (days < 365 + leap)
00155             break;
00156         days -= 365 + leap;
00157     }
00158     for (m = 1; m < 12; ++m) {
00159         uint8_t daysPerMonth = daysInMonth [m - 1];
00160         if (leap && m == 2)
00161             ++daysPerMonth;
00162         if (days < daysPerMonth)
00163             break;
00164         days -= daysPerMonth;
00165     }
00166     d = days + 1;
00167 }
00168 
00169 /**************************************************************************/
00170 /*!
00171     @brief  DateTime constructor from Y-M-D H:M:S
00172     @param year Year, 2 or 4 digits (year 2000 or higher)
00173     @param month Month 1-12
00174     @param day Day 1-31
00175     @param hour 0-23
00176     @param min 0-59
00177     @param sec 0-59
00178 */
00179 /**************************************************************************/
00180 DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
00181 {
00182     if (year >= 2000)
00183         year -= 2000;
00184     yOff = year;
00185     m = month;
00186     d = day;
00187     hh = hour;
00188     mm = min;
00189     ss = sec;
00190 }
00191 
00192 /**************************************************************************/
00193 /*!
00194     @brief  DateTime copy constructor using a member initializer list
00195     @param copy DateTime object to copy
00196 */
00197 /**************************************************************************/
00198 DateTime::DateTime (const DateTime& copy):
00199     yOff(copy.yOff),
00200     m(copy.m),
00201     d(copy.d),
00202     hh(copy.hh),
00203     mm(copy.mm),
00204     ss(copy.ss)
00205 {}
00206 
00207 /**************************************************************************/
00208 /*!
00209     @brief  Convert a string containing two digits to uint8_t, e.g. "09" returns 9
00210     @param p Pointer to a string containing two digits
00211 */
00212 /**************************************************************************/
00213 static uint8_t conv2d(const char* p)
00214 {
00215     uint8_t v = 0;
00216     if ('0' <= *p && *p <= '9')
00217         v = *p - '0';
00218     return 10 * v + *++p - '0';
00219 }
00220 
00221 /**************************************************************************/
00222 /*!
00223     @brief  A convenient constructor for using "the compiler's time":
00224             DateTime now (__DATE__, __TIME__);
00225             NOTE: using F() would further reduce the RAM footprint, see below.
00226     @param date Date string, e.g. "Dec 26 2009"
00227     @param time Time string, e.g. "12:34:56"
00228 */
00229 /**************************************************************************/
00230 DateTime::DateTime (const char* date, const char* time)
00231 {
00232     // sample input: date = "Dec 26 2009", time = "12:34:56"
00233     yOff = conv2d(date + 9);
00234     // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
00235     switch (date[0]) {
00236         case 'J':
00237             m = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7);
00238             break;
00239         case 'F':
00240             m = 2;
00241             break;
00242         case 'A':
00243             m = date[2] == 'r' ? 4 : 8;
00244             break;
00245         case 'M':
00246             m = date[2] == 'r' ? 3 : 5;
00247             break;
00248         case 'S':
00249             m = 9;
00250             break;
00251         case 'O':
00252             m = 10;
00253             break;
00254         case 'N':
00255             m = 11;
00256             break;
00257         case 'D':
00258             m = 12;
00259             break;
00260     }
00261     d = conv2d(date + 4);
00262     hh = conv2d(time);
00263     mm = conv2d(time + 3);
00264     ss = conv2d(time + 6);
00265 }
00266 
00267 /**************************************************************************/
00268 /*!
00269     @brief  A convenient constructor for using "the compiler's time":
00270             This version will save RAM by using PROGMEM to store it by using the F macro.
00271             DateTime now (F(__DATE__), F(__TIME__));
00272     @param date Date string, e.g. "Dec 26 2009"
00273     @param time Time string, e.g. "12:34:56"
00274 */
00275 /**************************************************************************/
00276 /*DateTime::DateTime (const __FlashstringHelper* date, const __FlashstringHelper* time) {
00277     // sample input: date = "Dec 26 2009", time = "12:34:56"
00278     char buff[11];
00279     memcpy_P(buff, date, 11);
00280     yOff = conv2d(buff + 9);
00281     // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
00282     switch (buff[0]) {
00283         case 'J': m = (buff[1] == 'a') ? 1 : ((buff[2] == 'n') ? 6 : 7); break;
00284         case 'F': m = 2; break;
00285         case 'A': m = buff[2] == 'r' ? 4 : 8; break;
00286         case 'M': m = buff[2] == 'r' ? 3 : 5; break;
00287         case 'S': m = 9; break;
00288         case 'O': m = 10; break;
00289         case 'N': m = 11; break;
00290         case 'D': m = 12; break;
00291     }
00292     d = conv2d(buff + 4);
00293     memcpy_P(buff, time, 8);
00294     hh = conv2d(buff);
00295     mm = conv2d(buff + 3);
00296     ss = conv2d(buff + 6);
00297 }*/
00298 
00299 /**************************************************************************/
00300 /*!
00301     @brief  Return DateTime in based on user defined format.
00302     @param buffer: array of char for holding the format description and the formatted DateTime.
00303                    Before calling this method, the buffer should be initialized by the user with
00304                    a format string, e.g. "YYYY-MM-DD hh:mm:ss". The method will overwrite
00305                    the buffer with the formatted date and/or time.
00306     @return a pointer to the provided buffer. This is returned for convenience,
00307             in order to enable idioms such as Serial.println(now.tostring(buffer));
00308 */
00309 /**************************************************************************/
00310 
00311 char* DateTime::tostring(char* buffer)
00312 {
00313     for(int i=0; i<strlen(buffer)-1; i++) {
00314         if(buffer[i] == 'h' && buffer[i+1] == 'h') {
00315             buffer[i] = '0'+hh/10;
00316             buffer[i+1] = '0'+hh%10;
00317         }
00318         if(buffer[i] == 'm' && buffer[i+1] == 'm') {
00319             buffer[i] = '0'+mm/10;
00320             buffer[i+1] = '0'+mm%10;
00321         }
00322         if(buffer[i] == 's' && buffer[i+1] == 's') {
00323             buffer[i] = '0'+ss/10;
00324             buffer[i+1] = '0'+ss%10;
00325         }
00326         if(buffer[i] == 'D' && buffer[i+1] =='D' && buffer[i+2] =='D') {
00327             static const char day_names[] = "SunMonTueWedThuFriSat";
00328             const uint8_t p = 3*dayOfTheWeek();
00329             buffer[i] = day_names[p];
00330             buffer[i+1] = day_names[p+1];
00331             buffer[i+2] = day_names[p+2];
00332         } else if(buffer[i] == 'D' && buffer[i+1] == 'D') {
00333             buffer[i] = '0'+d/10;
00334             buffer[i+1] = '0'+d%10;
00335         }
00336         if(buffer[i] == 'M' && buffer[i+1] =='M' && buffer[i+2] =='M') {
00337             static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
00338             const uint8_t p = 3*(m-1);
00339             buffer[i] = month_names[p];
00340             buffer[i+1] = month_names[p+1];
00341             buffer[i+2] = month_names[p+2];
00342         } else if(buffer[i] == 'M' && buffer[i+1] == 'M') {
00343             buffer[i] = '0'+m/10;
00344             buffer[i+1] = '0'+m%10;
00345         }
00346         if(buffer[i] == 'Y'&& buffer[i+1] == 'Y'&& buffer[i+2] == 'Y'&& buffer[i+3] == 'Y') {
00347             buffer[i] = '2';
00348             buffer[i+1] = '0';
00349             buffer[i+2] = '0'+(yOff/10)%10;
00350             buffer[i+3] = '0'+yOff%10;
00351         } else if(buffer[i] == 'Y'&& buffer[i+1] == 'Y') {
00352             buffer[i] = '0'+(yOff/10)%10;
00353             buffer[i+1] = '0'+yOff%10;
00354         }
00355 
00356     }
00357     return buffer;
00358 }
00359 
00360 /**************************************************************************/
00361 /*!
00362     @brief  Return the day of the week for this object, from 0-6.
00363     @return Day of week 0-6 starting with Sunday, e.g. Sunday = 0, Saturday = 6
00364 */
00365 /**************************************************************************/
00366 uint8_t DateTime::dayOfTheWeek() const
00367 {
00368     uint16_t day = date2days(yOff, m, d);
00369     return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
00370 }
00371 
00372 /**************************************************************************/
00373 /*!
00374     @brief  Return unix time, seconds since Jan 1, 1970.
00375     @return Number of seconds since Jan 1, 1970
00376 */
00377 /**************************************************************************/
00378 uint32_t DateTime::unixtime(void) const
00379 {
00380     uint32_t t;
00381     uint16_t days = date2days(yOff, m, d);
00382     t = time2long(days, hh, mm, ss);
00383     t += SECONDS_FROM_1970_TO_2000;  // seconds from 1970 to 2000
00384 
00385     return t;
00386 }
00387 
00388 /**************************************************************************/
00389 /*!
00390     @brief  Convert the DateTime to seconds
00391     @return The object as seconds since 2000-01-01
00392 */
00393 /**************************************************************************/
00394 long DateTime::secondstime(void) const
00395 {
00396     long t;
00397     uint16_t days = date2days(yOff, m, d);
00398     t = time2long(days, hh, mm, ss);
00399     return t;
00400 }
00401 
00402 /**************************************************************************/
00403 /*!
00404     @brief  Add a TimeSpan to the DateTime object
00405     @param span TimeSpan object
00406     @return new DateTime object with span added to it
00407 */
00408 /**************************************************************************/
00409 DateTime DateTime::operator+(const TimeSpan& span)
00410 {
00411     return DateTime(unixtime()+span.totalseconds());
00412 }
00413 
00414 /**************************************************************************/
00415 /*!
00416     @brief  Subtract a TimeSpan from the DateTime object
00417     @param span TimeSpan object
00418     @return new DateTime object with span subtracted from it
00419 */
00420 /**************************************************************************/
00421 DateTime DateTime::operator-(const TimeSpan& span)
00422 {
00423     return DateTime(unixtime()-span.totalseconds());
00424 }
00425 
00426 /**************************************************************************/
00427 /*!
00428     @brief  Subtract one DateTime from another
00429     @param right The DateTime object to subtract from self (the left object)
00430     @return TimeSpan of the difference between DateTimes
00431 */
00432 /**************************************************************************/
00433 TimeSpan DateTime::operator-(const DateTime& right)
00434 {
00435     return TimeSpan(unixtime()-right.unixtime());
00436 }
00437 
00438 /**************************************************************************/
00439 /*!
00440     @brief  Is one DateTime object less than (older) than the other?
00441     @param right Comparison DateTime object
00442     @return True if the left object is older than the right object
00443 */
00444 /**************************************************************************/
00445 bool DateTime::operator<(const DateTime& right) const
00446 {
00447     return unixtime() < right.unixtime();
00448 }
00449 
00450 /**************************************************************************/
00451 /*!
00452     @brief  Is one DateTime object equal to the other?
00453     @param right Comparison DateTime object
00454     @return True if both DateTime objects are the same
00455 */
00456 /**************************************************************************/
00457 bool DateTime::operator==(const DateTime& right) const
00458 {
00459     return unixtime() == right.unixtime();
00460 }
00461 
00462 /**************************************************************************/
00463 /*!
00464     @brief  ISO 8601 Timestamp
00465     @param opt Format of the timestamp
00466     @return Timestamp string, e.g. "2000-01-01T12:34:56"
00467 */
00468 /**************************************************************************/
00469 string DateTime::timestamp(timestampOpt opt)
00470 {
00471     char buffer[20];
00472 
00473     //Generate timestamp according to opt
00474     switch(opt) {
00475         case TIMESTAMP_TIME:
00476             //Only time
00477             sprintf(buffer, "%02d:%02d:%02d", hh, mm, ss);
00478             break;
00479         case TIMESTAMP_DATE:
00480             //Only date
00481             sprintf(buffer, "%d-%02d-%02d", 2000+yOff, m, d);
00482             break;
00483         default:
00484             //Full
00485             sprintf(buffer, "%d-%02d-%02dT%02d:%02d:%02d", 2000+yOff, m, d, hh, mm, ss);
00486     }
00487     return string(buffer);
00488 }
00489 
00490 
00491 
00492 /**************************************************************************/
00493 /*!
00494     @brief  Create a new TimeSpan object in seconds
00495     @param seconds Number of seconds
00496 */
00497 /**************************************************************************/
00498 TimeSpan::TimeSpan (int32_t seconds):
00499     _seconds(seconds)
00500 {}
00501 
00502 /**************************************************************************/
00503 /*!
00504     @brief  Create a new TimeSpan object using a number of days/hours/minutes/seconds
00505             e.g. Make a TimeSpan of 3 hours and 45 minutes: new TimeSpan(0, 3, 45, 0);
00506     @param days Number of days
00507     @param hours Number of hours
00508     @param minutes Number of minutes
00509     @param seconds Number of seconds
00510 */
00511 /**************************************************************************/
00512 TimeSpan::TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds):
00513     _seconds((int32_t)days*86400L + (int32_t)hours*3600 + (int32_t)minutes*60 + seconds)
00514 {}
00515 
00516 /**************************************************************************/
00517 /*!
00518     @brief  Copy constructor, make a new TimeSpan using an existing one
00519     @param copy The TimeSpan to copy
00520 */
00521 /**************************************************************************/
00522 TimeSpan::TimeSpan (const TimeSpan& copy):
00523     _seconds(copy._seconds)
00524 {}
00525 
00526 /**************************************************************************/
00527 /*!
00528     @brief  Add two TimeSpans
00529     @param right TimeSpan to add
00530     @return New TimeSpan object, sum of left and right
00531 */
00532 /**************************************************************************/
00533 TimeSpan TimeSpan::operator+(const TimeSpan& right)
00534 {
00535     return TimeSpan(_seconds+right._seconds);
00536 }
00537 
00538 /**************************************************************************/
00539 /*!
00540     @brief  Subtract a TimeSpan
00541     @param right TimeSpan to subtract
00542     @return New TimeSpan object, right subtracted from left
00543 */
00544 /**************************************************************************/
00545 TimeSpan TimeSpan::operator-(const TimeSpan& right)
00546 {
00547     return TimeSpan(_seconds-right._seconds);
00548 }
00549 
00550 
00551 
00552 /**************************************************************************/
00553 /*!
00554     @brief  Convert a binary coded decimal value to binary. RTC stores time/date values as BCD.
00555     @param val BCD value
00556     @return Binary value
00557 */
00558 /**************************************************************************/
00559 static uint8_t bcd2bin (uint8_t val)
00560 {
00561     return val - 6 * (val >> 4);
00562 }
00563 
00564 /**************************************************************************/
00565 /*!
00566     @brief  Convert a binary value to BCD format for the RTC registers
00567     @param val Binary value
00568     @return BCD value
00569 */
00570 /**************************************************************************/
00571 static uint8_t bin2bcd (uint8_t val)
00572 {
00573     return val + 6 * (val / 10);
00574 }
00575 
00576 
00577 /**************************************************************************/
00578 /*!
00579     @brief  Start I2C for the DS3231 and test succesful connection
00580     @return True if Wire can find DS3231 or false otherwise.
00581 */
00582 /**************************************************************************/
00583 bool RTC_DS3231::begin(void)
00584 {
00585 
00586     (*_i2c).frequency(100000);
00587     char cmdData[1] = { (char)0x00 };
00588 
00589     if ((*_i2c).write(DS3231_ADDRESS, cmdData, sizeof(cmdData)) == 0) return true;
00590     return false;
00591 }
00592 
00593 /**************************************************************************/
00594 /*!
00595     @brief  Check the status register Oscillator Stop Flag to see if the DS3231 stopped due to power loss
00596     @return True if the bit is set (oscillator stopped) or false if it is running
00597 */
00598 /**************************************************************************/
00599 bool RTC_DS3231::lostPower(void)
00600 {
00601     return (read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG) >> 7);
00602 }
00603 
00604 /**************************************************************************/
00605 /*!
00606     @brief  Set the date and flip the Oscillator Stop Flag
00607     @param dt DateTime object containing the date/time to set
00608 */
00609 /**************************************************************************/
00610 void RTC_DS3231::adjust(const DateTime& dt)
00611 {
00612 
00613     char cmdData[8] = { (uint8_t)0,bin2bcd(dt.second()),bin2bcd(dt.minute()),bin2bcd(dt.hour()),bin2bcd(0),bin2bcd(dt.day()),bin2bcd(dt.month()),bin2bcd(dt.year() - 2000) };
00614     (*_i2c).write(DS3231_ADDRESS, cmdData, sizeof(cmdData));
00615     /*(*_i2c).write(bin2bcd(dt.second()));
00616     (*_i2c).write(bin2bcd(dt.minute()));
00617     (*_i2c).write(bin2bcd(dt.hour()));
00618     (*_i2c).write(bin2bcd(0));
00619     (*_i2c).write(bin2bcd(dt.day()));
00620     (*_i2c).write(bin2bcd(dt.month()));
00621     (*_i2c).write(bin2bcd(dt.year() - 2000));*/
00622 
00623     uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
00624     statreg &= ~0x80; // flip OSF bit
00625     write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg);
00626 }
00627 
00628 /**************************************************************************/
00629 /*!
00630     @brief  Get the current date/time
00631     @return DateTime object with the current date/time
00632 */
00633 /**************************************************************************/
00634 DateTime RTC_DS3231::now()
00635 {
00636 
00637     uint8_t ss = bcd2bin(read_i2c_register(DS3231_ADDRESS, DS3231_SECONDS) & 0x7F);
00638     uint8_t mm = bcd2bin(read_i2c_register(DS3231_ADDRESS, DS3231_MINUTES));
00639     uint8_t hh = bcd2bin(read_i2c_register(DS3231_ADDRESS, DS3231_HOURS));
00640     read_i2c_register(DS3231_ADDRESS, DS3231_DAY);
00641     uint8_t d = bcd2bin(read_i2c_register(DS3231_ADDRESS, DS3231_DATE));
00642     uint8_t m = bcd2bin(read_i2c_register(DS3231_ADDRESS, DS3231_MONTH));
00643     uint16_t y = bcd2bin(read_i2c_register(DS3231_ADDRESS, DS3231_YEAR)) + 2000;
00644 
00645     return DateTime (y, m, d, hh, mm, ss);
00646 }
00647 
00648 /**************************************************************************/
00649 /*!
00650     @brief  Read the SQW pin mode
00651     @return Pin mode, see Ds3231SqwPinMode enum
00652 */
00653 /**************************************************************************/
00654 Ds3231SqwPinMode RTC_DS3231::readSqwPinMode()
00655 {
00656     int mode;
00657 
00658     mode = read_i2c_register(DS3231_ADDRESS, DS3231_SECONDS);
00659 
00660     mode &= 0x93;
00661     return static_cast<Ds3231SqwPinMode>(mode);
00662 }
00663 
00664 /**************************************************************************/
00665 /*!
00666     @brief  Set the SQW pin mode
00667     @param mode Desired mode, see Ds3231SqwPinMode enum
00668 */
00669 /**************************************************************************/
00670 void RTC_DS3231::writeSqwPinMode(Ds3231SqwPinMode mode)
00671 {
00672     uint8_t ctrl;
00673     ctrl = read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL);
00674 
00675     ctrl &= ~0x04; // turn off INTCON
00676     ctrl &= ~0x18; // set freq bits to 0
00677 
00678     if (mode == DS3231_OFF) {
00679         ctrl |= 0x04; // turn on INTCN
00680     } else {
00681         ctrl |= mode;
00682     }
00683     write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
00684 
00685     //Serial.println( read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), HEX);
00686 }
00687 
00688 /**************************************************************************/
00689 /*!
00690     @brief  Get the current temperature from the DS3231's temperature sensor
00691     @return Current temperature (float)
00692 */
00693 /**************************************************************************/
00694 float RTC_DS3231::getTemperature()
00695 {
00696     uint8_t msb, lsb;
00697 
00698     msb = read_i2c_register(DS3231_ADDRESS, DS3231_TEMPREG1);
00699     lsb = read_i2c_register(DS3231_ADDRESS, DS3231_TEMPREG2);
00700 
00701 //  Serial.print("msb=");
00702 //  Serial.print(msb,HEX);
00703 //  Serial.print(", lsb=");
00704 //  Serial.println(lsb,HEX);
00705 
00706     return (float) msb + (lsb >> 6) * 0.25f;
00707 }
00708 
00709 //******************************************************************************
00710 RTC_DS3231::RTC_DS3231(I2C *i2c): _i2c(i2c)
00711 {
00712 }
00713 
00714 //******************************************************************************
00715 RTC_DS3231::~RTC_DS3231()
00716 {
00717 }