Update

Dependents:   16A_Autopancakemaker

Files at this revision

API Documentation at this revision

Comitter:
pruek
Date:
Sat Dec 12 07:35:54 2015 +0000
Commit message:
A

Changed in this revision

ds1307.cpp Show annotated file Show diff for this revision Revisions of this file
ds1307.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 9570e313fcba ds1307.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ds1307.cpp	Sat Dec 12 07:35:54 2015 +0000
@@ -0,0 +1,286 @@
+#include "ds1307.h"
+ 
+DS1307::DS1307(PinName sda, PinName scl ) : ds1307i2c(sda,scl) {
+    ds1307i2c.frequency(DS1307_freq);
+}
+ 
+DS1307::~DS1307() {
+}
+ 
+int DS1307::read( int addr, int quantity, char *data) {
+    // note the char array at data must contain 63 locations or unpredictable behavior will happen
+    // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
+    // quantity must be 1 - 63 as the 64th ram location is clobered in this method of access
+    int test = 0 ;
+    char temp_data[65];
+ 
+    if (addr > DS1307_lastram) return (1);  // fail because address greater then what chip has to read from
+    if (addr < 0 ) return (1);     // fail because address less then 0 is not available
+    if (quantity > DS1307_lastreg) return (1);  // fail because quantity greater then what can be read
+    if ((addr + quantity) > DS1307_lastreg ) return (1);    // fail because cant read past reg 63
+    if ( quantity == 0 ) return (1);    // fail because zero quantity wanted
+    temp_data[0] = DS1307_lastreg ;  // note this ram location is used to set the addressing pointer in DS1307
+    temp_data[1] = 0;    // just junk to clober this address with
+    test = ds1307i2c.write(DS1307_addr,temp_data,2);
+    if (test == 1) return (1);  // the write operation failed
+    ds1307i2c.stop();   // now the DS1307 is pointing to the first register
+    if ( addr != 0 ) test = ds1307i2c.read(DS1307_addr,temp_data,addr);  // now the DS1307 address pointer is pointing to correct address
+    if (test == 1) return (1);  // the read operation failed
+    test = ds1307i2c.read(DS1307_addr,data,quantity);   // read the DS1307 registers now
+    if (test == 1) return (1);  // read operation failed
+    return(0);  // looks like the data read was good
+}
+ 
+int DS1307::read(int addr, int *data) {
+    // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
+    int test = 0;
+    char temp_data[65];
+    test = DS1307::read(addr, 1, &temp_data[0]);
+    if (test == 1) return(1);   // fail because read to DS1307 failed
+    *data = (int)temp_data[0];      // returing the read data by pointer
+    return (0);                     // the single read is successfull
+}
+ 
+int DS1307::write( int addr, int quantity, char *data) {
+    // note the char array at data must contain 63 locations or unpredictable behavior will happen
+    // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
+    // quantity must be 1 - 63 as the 64th ram location is clobered in this method of access
+    int test = 0 ;
+    char temp_data[65] ;
+    int loop = 0;
+ 
+    if (addr > DS1307_lastram) return (1);      // fail because address greater then what chip has to read from
+    if (addr < 0 ) return (1);      // fail because address less then 0 is not available
+    if (quantity > DS1307_lastreg) return (1);  // fail because quantity greater then what can be read
+    if (quantity == 0) return (1);  // fail because zero quantity is wanted
+    if ((addr + quantity) > DS1307_lastreg ) return (1);    // fail because cant read past reg 63
+ 
+    temp_data[0] = (char)addr;
+    for ( ; loop < quantity ; loop++ ) {
+        temp_data[loop+1] = *(data + loop);
+    }
+    test = ds1307i2c.write(DS1307_addr, temp_data, (quantity + 1));
+    ds1307i2c.stop();
+    return(test);   // 0 for success 1 for failure to write
+}
+ 
+int DS1307::write( int addr, int data ) {
+    // addr must be 0 - 62 as the 64th(or 63rd as indexed from 0) ram location is clobered in this method of access
+    int test = 0 ;
+    char temp_data[2] ;
+ 
+    temp_data[0] = (char)addr;
+    temp_data[1] = (char)data;
+    if (addr > DS1307_lastram) return (1);      // fail because address greater then what chip has to read from
+    if (addr < 0 ) return (1);      // fail because address less then 0 is not available
+    test = ds1307i2c.write(DS1307_addr, temp_data, 2);
+    ds1307i2c.stop();
+    return(test);
+}
+ 
+int DS1307::start_clock(void) {           // start the clock
+    int test = 0;
+    int junk = 0;
+ 
+    test = DS1307::read(DS1307_sec, &junk);
+    if (test == 1) return(1);       // fail because read to DS1307 failed
+    junk = ( 0x7F & junk);              // basicaly i mask bit 8 to set it to zero
+    test = DS1307::write(DS1307_sec,junk);        // now write the seconds back to register and because bit 8 is zero this starts clock.
+    if (test == 1) return(1);        // fail because read to DS1307 failed
+    return(test);                        //
+}
+ 
+int DS1307::stop_clock(void) {           // stop clock
+    int test = 0;
+    int junk = 0;
+ 
+    test = DS1307::read(DS1307_sec, &junk);
+    if (test == 1) return(1);        // fail because read to DS1307 failed
+    junk = ( 0x7F & junk);              // basicaly i mask bit 8 to set it to zero but keep all other bits
+    junk = ( 0x80 | junk);              // basicaly i mask bit 8 to set it to one
+    test = DS1307::write(DS1307_sec,junk);        // now write the seconds back to register and because bit 8 is one this starts clock.
+    if (test == 1) return(1);        // fail because read to DS1307 failed
+    return(test);                        //
+}
+ 
+int DS1307::twelve_hour(void) {           // set 12 hour mode
+    int test = 0;
+    int junk = 0;
+ 
+    test = DS1307::read(DS1307_hour, &junk);
+    if (test == 1) return(1);       // fail because read to DS1307 failed
+    if ((junk & 0x40) == 0x40) return(0);         // return because 12 mode is active now all done!
+ 
+    junk = ( junk & 0x3F);              // only use 24 hour time values
+    if (junk == 0x00)
+        junk = 0x12;
+    else if (junk >= 0x13)
+        if (junk < 0x20) {
+            junk = junk - 0x12;
+            junk = (junk | 0x20);   // add back the pm indicator
+        } else
+            switch (junk) {
+                case 0x20:
+                    junk = 0x28;
+                    break;
+                case 0x21:
+                    junk = 0x29;
+                    break;
+                case 0x22:
+                    junk = 0x30;
+                    break;
+                case 0x23:
+                    junk = 0x31;
+                    break;
+            }
+ 
+    test = DS1307::write(DS1307_hour,(0x40 | junk));    // set bit 6 with the new 12 hour time converted from the 24 hour time
+    if (test == 1) return(1);       // fail because read to DS1307 failed
+ 
+    return(0);
+}
+ 
+int DS1307::twentyfour_hour(void) {     // set 24 hour mode
+    int test = 0;
+    int junk = 0;
+ 
+    test = DS1307::read(DS1307_hour, &junk);
+    if (test == 1) return(1);       // fail because read to DS1307 failed
+    if ((junk & 0x40) == 0) return(0);         // return because 24 mode is active now all done!
+ 
+    junk = (junk &  0xBF);              // get value bits and am/pm indicator bit but drop 12/24 hour bit
+ 
+    if (junk > 0x12)
+        if ( junk <= 0x27 )
+            junk = junk - 0x0E;
+        else
+            junk = junk - 0x08;
+ 
+    test = DS1307::write(DS1307_hour,( 0xBF & junk));   // clear bit 6 and set the new 24 hour time converted from 12 hour time
+    if (test == 1) return(1);       // fail because read to DS1307 failed
+ 
+    return(0);
+}
+ 
+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
+    // 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)
+    DS1307::stop_clock();
+ 
+    if (1 == DS1307::hilow_check( 59, 0, sec)) {
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_sec,DS1307::dectobcd(sec)))) return(1);    // failed to write for some reason
+    }
+ 
+    if (1 == DS1307::hilow_check( 59, 0, min)) {
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_min,DS1307::dectobcd(min)))) return(1);    // failed to write for some reason
+    }
+ 
+    if (1 == DS1307::twentyfour_hour()) return(1);                                      // failed to set 24 hour format
+    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
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_hour,DS1307::dectobcd(hour)))) return(1);    // failed to write for some reason
+    }
+    if (1 == DS1307::twentyfour_hour()) return(1);                                      // failed to set 24 hour format
+ 
+    if (1 == DS1307::hilow_check( 7, 1, day)) {
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_day,DS1307::dectobcd(day)))) return(1);    // failed to write for some reason
+    }
+ 
+    if (1 == DS1307::hilow_check( 31, 1, date)) {
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_date,DS1307::dectobcd(date)))) return(1);    // failed to write for some reason
+    }
+ 
+    if (1 == DS1307::hilow_check( 12, 1, month)) {
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_month,DS1307::dectobcd(month)))) return(1);    // failed to write for some reason
+    }
+ 
+    if (1 == DS1307::hilow_check( 99, 0, year)) {
+        return(1);    // failed because recieved value is not in bounds
+    } else {
+        if (1 == (DS1307::write(DS1307_year,DS1307::dectobcd(year)))) return(1);    // failed to write for some reason
+    }
+ 
+    DS1307::start_clock();
+    return (0);             // time is now set
+}
+ 
+int DS1307::gettime(int *sec, int *min, int *hour, int *day, int *date, int *month, int *year) { // to get the current time information
+    // 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)
+    if (1 == DS1307::read(DS1307_sec,sec)) return(1);       // failed to read for some reason
+    *sec = (*sec & 0x7F );                                  // drop the clock start stop bit
+    *sec = DS1307::bcdtodec( *sec);                         // bcd is now dec value
+ 
+    if (1 == DS1307::read(DS1307_min,min)) return(1);       // failed to read for some reason
+    *min = (*min & 0x7F );                                  // drop bit 7 because it should be 0 anyways
+    *min = DS1307::bcdtodec( *min);                         // bcd is now dec value
+ 
+    if (1 == DS1307::read(DS1307_hour,hour)) return(1);     // failed to read for some reason
+    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
+        if (1 == DS1307::twentyfour_hour()) return(1);          // failed to set 24 hour mode for some reason
+        if (1 == DS1307::read(DS1307_hour,hour)) return(1);     // failed to read for some reason
+        *hour = (*hour & 0x3F );                                // drop bit 7 & 6 they are not used for 24 hour mode reading
+        *hour = DS1307::bcdtodec( *hour);                       // bcd is now dec value
+        if (1 == DS1307::twelve_hour()) return(1);              // failed to return to 12 hour mode for some reason
+    } else {                                                     // in 24 hour mode already so just read the hour value
+        if (1 == DS1307::read(DS1307_hour,hour)) return(1);    // failed to read for some reason
+        *hour = (*hour & 0x3F );                                // drop bit 7 & 6 they are not used for 24 hour mode reading
+        *hour = DS1307::bcdtodec( *hour);                       // bcd is now dec value
+    }
+ 
+    if (1 == DS1307::read(DS1307_day,day)) return(1);       // failed to read for some reason
+    *day = (*day & 0x07 );                                  // drop the non used bits
+    *day = DS1307::bcdtodec( *day);                         // bcd is now dec value
+ 
+    if (1 == DS1307::read(DS1307_date,date)) return(1);     // failed to read for some reason
+    *date = (*date & 0x3F );                                // drop bit 6 and 7 not used for date value
+    *date = DS1307::bcdtodec( *date);                       // bcd is now dec value
+ 
+    if (1 == DS1307::read(DS1307_month,month)) return(1);   // failed to read for some reason
+    *month = (*month & 0x1F );                              // drop bit 5, 6 and 7 not used for month value
+    *month = DS1307::bcdtodec( *month);                     // bcd is now dec value
+ 
+    if (1 == DS1307::read(DS1307_year,year)) return(1);     // failed to read for some reason
+    *year = DS1307::bcdtodec( *year);                       // bcd is now dec value
+ 
+    return (0);                                             // data returned is valid
+}
+ 
+ 
+int DS1307::dectobcd( int dec) {
+    int low = 0;
+    int high = 0;
+ 
+    high = dec / 10;                // this gives the high nibble value
+    low = dec - (high * 10);        // this gives the lower nibble value
+    return ((high *16) + low);      // this is the final bcd value but in interger format
+}
+ 
+int DS1307::bcdtodec( int bcd) {
+    int low = 0;
+    int high = 0;
+ 
+    high = bcd / 16;
+    low = bcd - (high * 16);
+    return ((high * 10) + low);
+ 
+}
+ 
+int DS1307::hilow_check( int hi, int low, int value) {
+    if ((value >= low)&(value <= hi))
+        return(0);              // value is equal to or inbetween hi and low
+    else
+        return(1);              // value is not equal to or inbetween hi and low
+}
+ 
+ 
+ 
\ No newline at end of file
diff -r 000000000000 -r 9570e313fcba ds1307.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ds1307.h	Sat Dec 12 07:35:54 2015 +0000
@@ -0,0 +1,44 @@
+#ifndef DS1307_H
+#define DS1307_H
+#include "mbed.h"
+ 
+#define DS1307_addr 0xD0    // this is fixed by Dallas
+#define DS1307_freq 100000  // this is the Dallas spec for operating i2c for this device
+#define DS1307_sec 0x00     // seconds
+#define DS1307_min  0x01    // min
+#define DS1307_hour 0x02    // hours
+#define DS1307_day  0x03    // day
+#define DS1307_date 0x04    // date
+#define DS1307_month 0x05   // month
+#define DS1307_year 0x06    // year
+#define DS1307_sqrout 0x07  // square output register
+#define DS1307_ramstart 0x08    // register address that ram starts at
+#define DS1307_lastreg 0x3F // this is the last register in the device (note also this register is used to address everything so it gets clobbered)
+#define DS1307_lastram 0x3E // last usable ram by this class as the lastreg is clobbered by code for normal operation
+ class DS1307 {
+public:
+DS1307( PinName sda, PinName slc) ;                 // constructor
+ 
+    ~DS1307();                                          // destructor
+  int read( int addr, int quantity, char *data);      // to read some of the 63 bytes from DS1307
+ int read(int addr, int *data);
+ int write( int addr, int quantity, char *data); 
+ int write( int addr, int data );                    // to write one byte only
+ int start_clock(void);    
+  int stop_clock(void);                               // stop clock
+ int twelve_hour(void);    
+ int twentyfour_hour(void);   
+ int settime(int sec, int min, int hour, int day, int date, int month, int year); 
+ int gettime(int *sec, int *min, int *hour, int *day, int *date, int *month, int *year);  // to get the current time information
+ 
+ 
+protected:
+    I2C ds1307i2c;
+    int dectobcd( int );
+    int bcdtodec( int );
+    int hilow_check( int, int, int);
+ 
+};
+ 
+#endif
+            
\ No newline at end of file