Library for DS3231 RTC

Dependents:   ard2pmod DS3231demo DS3231demo_COM_Port_Output MAXREFDES99_RTC_Display ... more

DS3231 Component Page

Revision:
2:4e6e761c60f2
Parent:
1:c814af60fdbf
Child:
3:312589d8185c
--- a/ds3231.cpp	Wed Nov 19 04:16:33 2014 +0000
+++ b/ds3231.cpp	Thu Nov 20 00:03:27 2014 +0000
@@ -76,6 +76,8 @@
 
 /**********************************************************//**
 * Sets the time on DS3231
+* Struct data is in integrer format, not BCD.  Fx will convert
+* to BCD for you.
 *
 * On Entry:
 *     @param[in] time - struct cotaining time data; 
@@ -99,8 +101,42 @@
 **************************************************************/
 uint16_t Ds3231::set_time(ds3231_time_t time)
 {
+    uint8_t data[] = {0,0,0,0};
+    uint8_t data_length = 0;
+    uint8_t max_hour = 24;
     
-    return 0;
+    data[data_length++] = SECONDS;
+    data[data_length++] = uchar_2_bcd(time.seconds);
+    data[data_length++] = uchar_2_bcd(time.minutes);
+    
+    //format Hours register
+    data[data_length] = uchar_2_bcd(time.hours);
+    if(time.mode)
+    {
+        max_hour = max_hour/2;
+        
+        data[data_length] |= MODE;
+        if(time.am_pm)
+        {
+            data[data_length] |= AM_PM;
+        }
+        
+    }
+    else
+    {
+        max_hour = max_hour - 1;
+    }
+    data_length++;
+    
+    //Test for good data.
+    if((time.seconds > 59) || (time.minutes > 59) || (time.hours > max_hour))
+    {
+        return(1);
+    }
+    else
+    {
+        return(write(w_adrs,(const char*) data, data_length));
+    }
 }
 
 
@@ -130,8 +166,17 @@
 **************************************************************/
 uint16_t Ds3231::set_calendar(ds3231_calendar_t calendar)
 {
+    uint8_t data[] = {0,0,0,0,0};
+    uint8_t data_length = 0;
+    
+    data[data_length++] = DAY;
+    data[data_length++] = uchar_2_bcd(calendar.day);
+    data[data_length++] = uchar_2_bcd(calendar.date);
+    data[data_length++] = uchar_2_bcd(calendar.month);
+    data[data_length++] = uchar_2_bcd(calendar.year);
 
-    return 0;
+    //users responsibility to make sure calendar is logical
+    return(write(w_adrs,(const char*) data, data_length));
 }
 
 
@@ -164,8 +209,128 @@
 **************************************************************/
 uint16_t Ds3231::set_alarm(ds3231_alrm_t alarm, bool one_r_two)
 {
-
-    return 0;    
+    uint8_t data[] = {0,0,0,0,0};
+    uint8_t data_length = 0;
+    uint8_t max_hour = 24;
+    uint8_t mask_var = 0;
+    
+    //setting alarm 1 or 2?
+    if(one_r_two)
+    {
+        data[data_length++] = ALRM1_SECONDS;
+        
+        //config seconds register
+        if(alarm.am1)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        data[data_length++] =  (mask_var | uchar_2_bcd(alarm.seconds));
+        mask_var = 0;
+        
+        //config minutes register
+        if(alarm.am2)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        data[data_length++] =  (mask_var | uchar_2_bcd(alarm.minutes));
+        mask_var = 0;
+        
+        //config hours register
+        if(alarm.am3)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        if(alarm.mode)
+        {
+            max_hour = max_hour/2;
+            mask_var |= MODE;
+            if(alarm.am_pm)
+            {
+                mask_var |= AM_PM;
+            }
+        } 
+        else
+        {
+            max_hour = max_hour - 1;
+        }
+        data[data_length++] =  (mask_var | uchar_2_bcd(alarm.hours));
+        mask_var = 0;
+        
+        //config day/date register
+        if(alarm.am4)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        if(alarm.dy_dt)
+        {
+            mask_var |= DY_DT;
+            data[data_length++] =  (mask_var | uchar_2_bcd(alarm.day));
+        } 
+        else
+        {
+            data[data_length++] =  (mask_var | uchar_2_bcd(alarm.date));
+        }
+        mask_var = 0;
+    }
+    else
+    {
+        data[data_length++] = ALRM2_MINUTES;
+        
+        //config minutes register
+        if(alarm.am2)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        data[data_length++] =  (mask_var | uchar_2_bcd(alarm.minutes));
+        mask_var = 0;
+        
+        //config hours register
+        if(alarm.am3)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        if(alarm.mode)
+        {
+            max_hour = max_hour/2;
+            mask_var |= MODE;
+            if(alarm.am_pm)
+            {
+                mask_var |= AM_PM;
+            }
+        } 
+        else
+        {
+            max_hour = max_hour - 1;
+        }
+        data[data_length++] =  (mask_var | uchar_2_bcd(alarm.hours));
+        mask_var = 0;
+        
+        //config day/date register
+        if(alarm.am4)
+        {
+           mask_var |= ALRM_MASK;
+        }
+        if(alarm.dy_dt)
+        {
+            mask_var |= DY_DT;
+            data[data_length++] =  (mask_var | uchar_2_bcd(alarm.day));
+        } 
+        else
+        {
+            data[data_length++] =  (mask_var | uchar_2_bcd(alarm.date));
+        }
+        mask_var = 0;
+    }  
+    
+    //Test for good data.
+    if((alarm.seconds > 59) || (alarm.minutes > 59) || (alarm.hours > max_hour) || (alarm.day > 7) || (alarm.date > 31))
+    {
+        return(1);
+    }
+    else
+    {
+        return(write(w_adrs,(const char*) data, data_length));
+    }
 }
 
 
@@ -194,8 +359,15 @@
 **************************************************************/
 uint16_t Ds3231::set_cntl_stat_reg(ds3231_cntl_stat_t data)
 {
+    uint8_t local_data[] = {0,0,0};
+    uint8_t data_length = 0;
+    
+    local_data[data_length++] = CONTROL;
+    local_data[data_length++] = data.control;
+    local_data[data_length++] = data.status;
 
-    return 0;
+    //users responsibility to make sure data is logical
+    return(write(w_adrs,(const char*) local_data, data_length));
 }
 
 
@@ -203,11 +375,12 @@
 * Gets the time on DS3231
 *
 * On Entry:
-*     @param[in] time - struct for storing time data; 
-*                       seconds, minutes and hours
+*     @param[in] time - pointer to struct for storing time 
+*                       data; seconds, minutes and hours
 *
 * On Exit:
-*     @param[out] time - contains current rtc time data
+*     @param[out] time - contains current integrer rtc time 
+*                        data
 *     @return return value = 0 on success, non-0 on failure
 *
 * Example:
@@ -223,10 +396,24 @@
 *
 * @endcode
 **************************************************************/
-uint16_t Ds3231::get_time(ds3231_time_t time)
+uint16_t Ds3231::get_time(ds3231_time_t* time)
 {
-
-    return 0;
+    uint16_t rtn_val = 1;
+    uint8_t data[3];
+    
+    data[0] = SECONDS;
+    rtn_val = write(w_adrs, (const char*) data, 1);
+    
+    if(!rtn_val)
+    {
+        rtn_val = read(r_adrs,(char *) data, 3);
+        
+        time->seconds = bcd_2_uchar(data[0]);
+        time->minutes = bcd_2_uchar(data[1]);
+        time->hours = bcd_2_uchar((data[2]&0x1F));
+    } 
+  
+    return(rtn_val);
 }
 
 
@@ -234,11 +421,13 @@
 * Gets the calendar on DS3231
 *
 * On Entry:
-*     @param[in] calendar - struct for storing calendar data; 
+*     @param[in] calendar - pointer to struct for storing 
+*                           calendar data; 
 *                           day, date, month, year
 *
 * On Exit:
-*     @param[out] calendar - contains current rtc calendar
+*     @param[out] calendar - contains current integer rtc 
+*                            calendar data
 *     @return return value = 0 on success, non-0 on failure
 *
 * Example:
@@ -255,10 +444,25 @@
 *
 * @endcode
 **************************************************************/
-uint16_t Ds3231::get_calendar(ds3231_calendar_t calendar)
+uint16_t Ds3231::get_calendar(ds3231_calendar_t* calendar)
 {
-
-    return 0;
+    uint16_t rtn_val = 1;
+    uint8_t data[4];
+    
+    data[0] = DAY;
+    rtn_val = write(w_adrs, (const char*) data, 1);
+    
+    if(!rtn_val)
+    {
+        rtn_val = read(r_adrs,(char *) data, 4);
+        
+        calendar->day = bcd_2_uchar(data[0]);
+        calendar->date = bcd_2_uchar(data[1]);
+        calendar->month = bcd_2_uchar((data[2]&0x1F));
+        calendar->year = bcd_2_uchar(data[3]);
+    } 
+  
+    return(rtn_val);
 }
 
 
@@ -266,14 +470,16 @@
 * Get either Alarm1 or Alarm2 of DS3231
 *
 * On Entry:
-*     @param[in] alarm - struct for storing alarm data 
+*     @param[in] alarm - pointer to struct for storing alarm 
+*                        data; 
 *                        seconds, minutes, hours, day, date
 *                        seconds used on Alarm1 only
+*
 *     @param[in] one_r_two - TRUE for Alarm1 and FALSE for 
 *                            Alarm2
 *
 * On Exit:
-*     @param[out] alarm - contains alarm register data
+*     @param[out] alarm - contains integer alarm data
 *     @return return value = 0 on success, non-0 on failure
 *
 * Example:
@@ -290,10 +496,58 @@
 *
 * @endcode
 **************************************************************/
-uint16_t Ds3231::get_alarm(ds3231_alrm_t alarm, bool one_r_two)
+uint16_t Ds3231::get_alarm(ds3231_alrm_t* alarm, bool one_r_two)
 {
-
-    return 0;
+    uint16_t rtn_val = 1;
+    uint8_t data[4];
+    
+    if(one_r_two)
+    {
+        data[0] = ALRM1_SECONDS;
+        rtn_val = write(w_adrs, (const char*) data, 1);
+        
+        if(!rtn_val)
+        {
+            rtn_val = read(r_adrs,(char *) data, 4);
+            
+            alarm->seconds = bcd_2_uchar(data[0]&0x7F);
+            alarm->minutes = bcd_2_uchar(data[1]&0x7F);
+            alarm->hours = bcd_2_uchar(data[2]&0x1F);
+            
+            if(data[3] & DY_DT)
+            {
+                alarm->day = bcd_2_uchar(data[3]&0x0F);
+            }
+            else
+            {
+                alarm->date = bcd_2_uchar(data[3]&0x3F);
+            }
+        } 
+    }
+    else
+    {
+        data[0] = ALRM2_MINUTES;
+        rtn_val = write(w_adrs, (const char*) data, 1);
+        
+        if(!rtn_val)
+        {
+            rtn_val = read(r_adrs,(char *) data, 4);
+            
+            alarm->minutes = bcd_2_uchar(data[0]&0x7F);
+            alarm->hours = bcd_2_uchar(data[1]&0x1F);
+            
+            if(data[3] & DY_DT)
+            {
+                alarm->day = bcd_2_uchar(data[2]&0x0F);
+            }
+            else
+            {
+                alarm->date = bcd_2_uchar(data[2]&0x3F);
+            }
+        } 
+    }
+    
+    return(rtn_val);
 }
 
 
@@ -301,8 +555,8 @@
 * Get control and status registers of DS3231
 *
 * On Entry:
-*     @param[in] data - Struct for storing control and status 
-*                       register data
+*     @param[in] data - pointer to struct for storing control 
+*                       nd status register data
 *
 * On Exit:
 *     @param[out] data - contains control and status registers
@@ -322,10 +576,23 @@
 *
 * @endcode
 **************************************************************/
-uint16_t Ds3231::get_cntl_stat_reg(ds3231_cntl_stat_t data)
+uint16_t Ds3231::get_cntl_stat_reg(ds3231_cntl_stat_t* data)
 {
-
-    return 0;
+    uint16_t rtn_val = 1;
+    uint8_t local_data[2];
+    
+    local_data[0] = CONTROL;
+    rtn_val = write(w_adrs, (const char*) local_data, 1);
+    
+    if(!rtn_val)
+    {
+        rtn_val = read(r_adrs,(char *) local_data, 2);
+        
+        data->control = local_data[0];
+        data->status = local_data[1];
+    } 
+  
+    return(rtn_val);
 }
 
 
@@ -333,11 +600,9 @@
 * Get temperature data of DS3231
 *
 * On Entry:
-*     @param[in] temp - Integer for storing temperature data
 *
 * On Exit:
-*     @param[out] temp - contains temperature data
-*     @return return value = 0 on success, non-0 on failure
+*     @return return value = raw temperature data
 *
 * Example:
 * @code
@@ -345,16 +610,79 @@
 * //instantiate rtc object
 * Ds3231 rtc(D14, D15); 
 * 
-* //do not use 0xAA, see datasheet for appropriate data 
 * uint16_t temp; 
 *
-* rtn_val = rtc.get_temperature(temp);
+* temp = rtc.get_temperature();
 *
 * @endcode
 **************************************************************/
-uint16_t Ds3231::get_temperature(uint16_t temp)
+uint16_t Ds3231::get_temperature(void)
 {
-
-    return 0;    
+    uint16_t rtn_val = 1;
+    uint8_t data[2];
+    
+    data[0] = MSB_TEMP;
+    rtn_val = write(w_adrs, (const char*) data, 1);
+    
+    if(!rtn_val)
+    {
+        read(r_adrs,(char *) data, 2);
+        
+        rtn_val = data[0] << 8;
+        rtn_val |= data[1];
+    } 
+  
+    return(rtn_val);    
 }
 
+
+/**********************************************************//**
+* Private mmber fx, converts unsigned char to BCD
+*
+* On Entry:
+*     @param[in] data - 0-255
+*
+* On Exit:
+*     @return bcd_result = BCD representation of data
+*
+**************************************************************/
+uint16_t Ds3231::uchar_2_bcd(uint8_t data)
+{
+   uint16_t bcd_result = 0;
+   
+   //Get hundreds
+   bcd_result |= ((data/100) << 8);
+   data = (data - (data/100)*100);
+   
+   //Get tens
+   bcd_result |= ((data/10) << 4);
+   data = (data - (data/10)*10);
+   
+   //Get ones
+   bcd_result |= data;
+   
+   return(bcd_result);   
+}
+
+
+/**********************************************************//**
+* Private mmber fx, converts BCD to a uint8_t
+*
+* On Entry:
+*     @param[in] bcd - 0-99
+*
+* On Exit:
+*     @return rtn_val = integer rep. of BCD
+*
+**************************************************************/
+uint8_t Ds3231::bcd_2_uchar(uint8_t bcd)
+{
+    uint8_t rtn_val = 0;
+
+    rtn_val += ((bcd&0xf0)>>4)*10;
+    rtn_val += (bcd&0x000f);   
+
+    return rtn_val;
+}
+
+