This is a class for using the DS1307 Real Time Clock chip from Dallas Semiconductor. This class uses mbeds i2c class to talk to the chip. I have tested this currently on the LPC1768 mbed device with the Spark fun breakout board from http://www.sparkfun.com/products/99

Dependents:   Mbell Astromed_build20121123 Raymon_pub_ver CCRMonitor12_sp07_120ver ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ds1307.cpp Source File

ds1307.cpp

00001 #include "ds1307.h"
00002 
00003 DS1307::DS1307(PinName sda, PinName scl ) : ds1307i2c(sda,scl) {
00004     ds1307i2c.frequency(DS1307_freq);
00005 }
00006 
00007 DS1307::~DS1307() {
00008 }
00009 
00010 int DS1307::read( int addr, int quantity, char *data) {
00011     // note the char array at data must contain 63 locations or unpredictable behavior will happen
00012     // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
00013     // quantity must be 1 - 63 as the 64th ram location is clobered in this method of access
00014     int test = 0 ;
00015     char temp_data[65];
00016 
00017     if (addr > DS1307_lastram) return (1);  // fail because address greater then what chip has to read from
00018     if (addr < 0 ) return (1);     // fail because address less then 0 is not available
00019     if (quantity > DS1307_lastreg) return (1);  // fail because quantity greater then what can be read
00020     if ((addr + quantity) > DS1307_lastreg ) return (1);    // fail because cant read past reg 63
00021     if ( quantity == 0 ) return (1);    // fail because zero quantity wanted
00022     temp_data[0] = DS1307_lastreg ;  // note this ram location is used to set the addressing pointer in DS1307
00023     temp_data[1] = 0;    // just junk to clober this address with
00024     test = ds1307i2c.write(DS1307_addr,temp_data,2);
00025     if (test == 1) return (1);  // the write operation failed
00026     ds1307i2c.stop();   // now the DS1307 is pointing to the first register
00027     if ( addr != 0 ) test = ds1307i2c.read(DS1307_addr,temp_data,addr);  // now the DS1307 address pointer is pointing to correct address
00028     if (test == 1) return (1);  // the read operation failed
00029     test = ds1307i2c.read(DS1307_addr,data,quantity);   // read the DS1307 registers now
00030     if (test == 1) return (1);  // read operation failed
00031     return(0);  // looks like the data read was good
00032 }
00033 
00034 int DS1307::read(int addr, int *data) {
00035     // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
00036     int test = 0;
00037     char temp_data[65];
00038     test = DS1307::read(addr, 1, &temp_data[0]);
00039     if (test == 1) return(1);   // fail because read to DS1307 failed
00040     *data = (int)temp_data[0];      // returing the read data by pointer
00041     return (0);                     // the single read is successfull
00042 }
00043 
00044 int DS1307::write( int addr, int quantity, char *data) {
00045     // note the char array at data must contain 63 locations or unpredictable behavior will happen
00046     // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
00047     // quantity must be 1 - 63 as the 64th ram location is clobered in this method of access
00048     int test = 0 ;
00049     char temp_data[65] ;
00050     int loop = 0;
00051 
00052     if (addr > DS1307_lastram) return (1);      // fail because address greater then what chip has to read from
00053     if (addr < 0 ) return (1);      // fail because address less then 0 is not available
00054     if (quantity > DS1307_lastreg) return (1);  // fail because quantity greater then what can be read
00055     if (quantity == 0) return (1);  // fail because zero quantity is wanted
00056     if ((addr + quantity) > DS1307_lastreg ) return (1);    // fail because cant read past reg 63
00057 
00058     temp_data[0] = (char)addr;
00059     for ( ; loop < quantity ; loop++ ) {
00060         temp_data[loop+1] = *(data + loop);
00061     }
00062     test = ds1307i2c.write(DS1307_addr, temp_data, (quantity + 1));
00063     ds1307i2c.stop();
00064     return(test);   // 0 for success 1 for failure to write
00065 }
00066 
00067 int DS1307::write( int addr, int data ) {
00068     // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
00069     int test = 0 ;
00070     char temp_data[2] ;
00071 
00072     temp_data[0] = (char)addr;
00073     temp_data[1] = (char)data;
00074     if (addr > DS1307_lastram) return (1);      // fail because address greater then what chip has to read from
00075     if (addr < 0 ) return (1);      // fail because address less then 0 is not available
00076     test = ds1307i2c.write(DS1307_addr, temp_data, 2);
00077     ds1307i2c.stop();
00078     return(test);
00079 }
00080 
00081 int DS1307::start_clock(void) {           // start the clock
00082     int test = 0;
00083     int junk = 0;
00084 
00085     test = DS1307::read(DS1307_sec, &junk);
00086     if (test == 1) return(1);       // fail because read to DS1307 failed
00087     junk = ( 0x7F & junk);              // basicaly i mask bit 8 to set it to zero
00088     test = DS1307::write(DS1307_sec,junk);        // now write the seconds back to register and because bit 8 is zero this starts clock.
00089     if (test == 1) return(1);        // fail because read to DS1307 failed
00090     return(test);                        //
00091 }
00092 
00093 int DS1307::stop_clock(void) {           // stop clock
00094     int test = 0;
00095     int junk = 0;
00096 
00097     test = DS1307::read(DS1307_sec, &junk);
00098     if (test == 1) return(1);        // fail because read to DS1307 failed
00099     junk = ( 0x7F & junk);              // basicaly i mask bit 8 to set it to zero but keep all other bits
00100     junk = ( 0x80 | junk);              // basicaly i mask bit 8 to set it to one
00101     test = DS1307::write(DS1307_sec,junk);        // now write the seconds back to register and because bit 8 is one this starts clock.
00102     if (test == 1) return(1);        // fail because read to DS1307 failed
00103     return(test);                        //
00104 }
00105 
00106 int DS1307::twelve_hour(void) {           // set 12 hour mode
00107     int test = 0;
00108     int junk = 0;
00109 
00110     test = DS1307::read(DS1307_hour, &junk);
00111     if (test == 1) return(1);       // fail because read to DS1307 failed
00112     if ((junk & 0x40) == 0x40) return(0);         // return because 12 mode is active now all done!
00113 
00114     junk = ( junk & 0x3F);              // only use 24 hour time values
00115     if (junk == 0x00)
00116         junk = 0x12;
00117     else if (junk >= 0x13)
00118         if (junk < 0x20) {
00119             junk = junk - 0x12;
00120             junk = (junk | 0x20);   // add back the pm indicator
00121         } else
00122             switch (junk) {
00123                 case 0x20:
00124                     junk = 0x28;
00125                     break;
00126                 case 0x21:
00127                     junk = 0x29;
00128                     break;
00129                 case 0x22:
00130                     junk = 0x30;
00131                     break;
00132                 case 0x23:
00133                     junk = 0x31;
00134                     break;
00135             }
00136 
00137     test = DS1307::write(DS1307_hour,(0x40 | junk));    // set bit 6 with the new 12 hour time converted from the 24 hour time
00138     if (test == 1) return(1);       // fail because read to DS1307 failed
00139 
00140     return(0);
00141 }
00142 
00143 int DS1307::twentyfour_hour(void) {     // set 24 hour mode
00144     int test = 0;
00145     int junk = 0;
00146 
00147     test = DS1307::read(DS1307_hour, &junk);
00148     if (test == 1) return(1);       // fail because read to DS1307 failed
00149     if ((junk & 0x40) == 0) return(0);         // return because 24 mode is active now all done!
00150 
00151     junk = (junk &  0xBF);              // get value bits and am/pm indicator bit but drop 12/24 hour bit
00152 
00153     if (junk > 0x12)
00154         if ( junk <= 0x27 )
00155             junk = junk - 0x0E;
00156         else
00157             junk = junk - 0x08;
00158 
00159     test = DS1307::write(DS1307_hour,( 0xBF & junk));   // clear bit 6 and set the new 24 hour time converted from 12 hour time
00160     if (test == 1) return(1);       // fail because read to DS1307 failed
00161 
00162     return(0);
00163 }
00164 
00165 int DS1307::settime(int sec, int min, int hour, int day, int date, int month, int year) {        // to set the current time and start clock
00166     // sec = 0 to 59, min = 0 to 59, hours = 0 to 23 ( 24 hour mode only ), day = 1 to 7 ( day of week ), date = 1 to 31, month = 1 to 12, year 0 to 99 ( this is for 2000 to 2099)
00167     DS1307::stop_clock();
00168 
00169     if (1 == DS1307::hilow_check( 59, 0, sec)) {
00170         return(1);    // failed because recieved value is not in bounds
00171     } else {
00172         if (1 == (DS1307::write(DS1307_sec,DS1307::dectobcd(sec)))) return(1);    // failed to write for some reason
00173     }
00174 
00175     if (1 == DS1307::hilow_check( 59, 0, min)) {
00176         return(1);    // failed because recieved value is not in bounds
00177     } else {
00178         if (1 == (DS1307::write(DS1307_min,DS1307::dectobcd(min)))) return(1);    // failed to write for some reason
00179     }
00180 
00181     if (1 == DS1307::twentyfour_hour()) return(1);                                      // failed to set 24 hour format
00182     if (1 == DS1307::hilow_check( 23, 0, hour)) {                                       // note setting 24 hour mode befor and after writing the hour value ensures 24 hour mode is set
00183         return(1);    // failed because recieved value is not in bounds
00184     } else {
00185         if (1 == (DS1307::write(DS1307_hour,DS1307::dectobcd(hour)))) return(1);    // failed to write for some reason
00186     }
00187     if (1 == DS1307::twentyfour_hour()) return(1);                                      // failed to set 24 hour format
00188 
00189     if (1 == DS1307::hilow_check( 7, 1, day)) {
00190         return(1);    // failed because recieved value is not in bounds
00191     } else {
00192         if (1 == (DS1307::write(DS1307_day,DS1307::dectobcd(day)))) return(1);    // failed to write for some reason
00193     }
00194 
00195     if (1 == DS1307::hilow_check( 31, 1, date)) {
00196         return(1);    // failed because recieved value is not in bounds
00197     } else {
00198         if (1 == (DS1307::write(DS1307_date,DS1307::dectobcd(date)))) return(1);    // failed to write for some reason
00199     }
00200 
00201     if (1 == DS1307::hilow_check( 12, 1, month)) {
00202         return(1);    // failed because recieved value is not in bounds
00203     } else {
00204         if (1 == (DS1307::write(DS1307_month,DS1307::dectobcd(month)))) return(1);    // failed to write for some reason
00205     }
00206 
00207     if (1 == DS1307::hilow_check( 99, 0, year)) {
00208         return(1);    // failed because recieved value is not in bounds
00209     } else {
00210         if (1 == (DS1307::write(DS1307_year,DS1307::dectobcd(year)))) return(1);    // failed to write for some reason
00211     }
00212 
00213     DS1307::start_clock();
00214     return (0);             // time is now set
00215 }
00216 
00217 int DS1307::gettime(int *sec, int *min, int *hour, int *day, int *date, int *month, int *year) { // to get the current time information
00218     // sec = 0 to 59, min = 0 to 59, hours = 0 to 23 ( 24 hour mode only ), day = 1 to 7 ( day of week ), date = 1 to 31, month = 1 to 12, year 0 to 99 ( this is for 2000 to 2099)
00219     if (1 == DS1307::read(DS1307_sec,sec)) return(1);       // failed to read for some reason
00220     *sec = (*sec & 0x7F );                                  // drop the clock start stop bit
00221     *sec = DS1307::bcdtodec( *sec);                         // bcd is now dec value
00222 
00223     if (1 == DS1307::read(DS1307_min,min)) return(1);       // failed to read for some reason
00224     *min = (*min & 0x7F );                                  // drop bit 7 because it should be 0 anyways
00225     *min = DS1307::bcdtodec( *min);                         // bcd is now dec value
00226 
00227     if (1 == DS1307::read(DS1307_hour,hour)) return(1);     // failed to read for some reason
00228     if ((*hour & 0x40) == 0x40) {                           // if true then 12 hour mode is set currently  so change to 24 hour, read value, and return to 12 hour mode
00229         if (1 == DS1307::twentyfour_hour()) return(1);          // failed to set 24 hour mode for some reason
00230         if (1 == DS1307::read(DS1307_hour,hour)) return(1);     // failed to read for some reason
00231         *hour = (*hour & 0x3F );                                // drop bit 7 & 6 they are not used for 24 hour mode reading
00232         *hour = DS1307::bcdtodec( *hour);                       // bcd is now dec value
00233         if (1 == DS1307::twelve_hour()) return(1);              // failed to return to 12 hour mode for some reason
00234     } else {                                                     // in 24 hour mode already so just read the hour value
00235         if (1 == DS1307::read(DS1307_hour,hour)) return(1);    // failed to read for some reason
00236         *hour = (*hour & 0x3F );                                // drop bit 7 & 6 they are not used for 24 hour mode reading
00237         *hour = DS1307::bcdtodec( *hour);                       // bcd is now dec value
00238     }
00239 
00240     if (1 == DS1307::read(DS1307_day,day)) return(1);       // failed to read for some reason
00241     *day = (*day & 0x07 );                                  // drop the non used bits
00242     *day = DS1307::bcdtodec( *day);                         // bcd is now dec value
00243 
00244     if (1 == DS1307::read(DS1307_date,date)) return(1);     // failed to read for some reason
00245     *date = (*date & 0x3F );                                // drop bit 6 and 7 not used for date value
00246     *date = DS1307::bcdtodec( *date);                       // bcd is now dec value
00247 
00248     if (1 == DS1307::read(DS1307_month,month)) return(1);   // failed to read for some reason
00249     *month = (*month & 0x1F );                              // drop bit 5, 6 and 7 not used for month value
00250     *month = DS1307::bcdtodec( *month);                     // bcd is now dec value
00251 
00252     if (1 == DS1307::read(DS1307_year,year)) return(1);     // failed to read for some reason
00253     *year = DS1307::bcdtodec( *year);                       // bcd is now dec value
00254 
00255     return (0);                                             // data returned is valid
00256 }
00257 
00258 
00259 int DS1307::dectobcd( int dec) {
00260     int low = 0;
00261     int high = 0;
00262 
00263     high = dec / 10;                // this gives the high nibble value
00264     low = dec - (high * 10);        // this gives the lower nibble value
00265     return ((high *16) + low);      // this is the final bcd value but in interger format
00266 }
00267 
00268 int DS1307::bcdtodec( int bcd) {
00269     int low = 0;
00270     int high = 0;
00271 
00272     high = bcd / 16;
00273     low = bcd - (high * 16);
00274     return ((high * 10) + low);
00275 
00276 }
00277 
00278 int DS1307::hilow_check( int hi, int low, int value) {
00279     if ((value >= low)&(value <= hi))
00280         return(0);              // value is equal to or inbetween hi and low
00281     else
00282         return(1);              // value is not equal to or inbetween hi and low
00283 }
00284 
00285 
00286 
00287