Simple RTC class based on DS1307. Emphasis on simple. Allows you to run at 100k or 400k Hz (for newer DS1307 capable devices). MapTime() allows you to set the time() service to the same as the RTC. Uses struct tm throughout so you can use traditional time functions for manipulation.

Dependents:   AdaFruit_RGBLCD

Revision:
5:d71d6e5a7eee
Parent:
4:04a51e4dbf4c
Child:
7:3621025e7949
--- a/RTclock.cpp	Sat Aug 09 11:46:08 2014 +0000
+++ b/RTclock.cpp	Sat Aug 09 17:02:40 2014 +0000
@@ -5,6 +5,7 @@
 
 RTclock::RTclock(PinName in_nSDA, PinName in_nSCL, bool in_bHiSpeed)
     : RTclock_parent(in_nSDA,in_nSCL)
+    , m_bTwelveHour(false)
 {        
     // Frequency depends on chip - most are 100KHz
     frequency(in_bHiSpeed ? 400000 : 100000);
@@ -27,24 +28,25 @@
 bool RTclock::GetTime(tm & out_sTM)
 {
     char aBuffer[7];
-    bool b12hour = false;
     
     if (!read(0, aBuffer, 7)) return false;
 
-    b12hour = ((aBuffer[2] & 64) == 64);
+    m_bTwelveHour = ((aBuffer[2] & 0x40) == 0x40);
     
-    out_sTM.tm_sec = BcdToDecimal(aBuffer[0] & 0x7F);
+    out_sTM.tm_sec = BcdToDecimal(aBuffer[0] & 0x7f);
     out_sTM.tm_min = BcdToDecimal(aBuffer[1]);
     
-    if (b12hour)
+    if (m_bTwelveHour)
     {
-        // remove 12 hours if PM bit is set and past midday
+        // add 12 hours if PM bit is set and past midday
         out_sTM.tm_hour = BcdToDecimal(aBuffer[2] & 31);
-        if ((aBuffer[2] & 32) && out_sTM.tm_hour > 12) out_sTM.tm_hour -= 12;
+        
+        bool bPM = (0 != (aBuffer[2] & 0x20));
+        if (bPM && 12 != out_sTM.tm_hour) out_sTM.tm_hour += 12;
     }
     else
     {
-        out_sTM.tm_hour = BcdToDecimal(aBuffer[2] & 63);
+        out_sTM.tm_hour = BcdToDecimal(aBuffer[2] & 0x3f);
     }
     
     out_sTM.tm_wday = aBuffer[3]; 
@@ -61,6 +63,11 @@
     return m_aWeekDays[in_nWeekDay];
 }
 
+ bool RTclock::IsTwelveHour()
+{
+    return m_bTwelveHour;
+}
+
 bool RTclock::MapTime()
 {
     tm sTM;
@@ -83,22 +90,42 @@
     return true;
 }
 
-bool RTclock::SetTime(const tm  & in_sTM)
+bool RTclock::SetTime(const tm  & in_sTM, bool in_bTwelveHour)
 {
     char aBuffer[7];
 
     // Preserve flags that were in register
     if (!read(0,aBuffer,7)) return false;
     
-    aBuffer[0] &= 0x7F;
+    m_bTwelveHour = in_bTwelveHour;
+    
+    // We always have tm in 24hr form - so adjut if 12hr clock
+    int nHour = in_sTM.tm_hour;
+    if (in_bTwelveHour) nHour %= 12;
+    
+    aBuffer[0] &= 0x7f;
     aBuffer[0] = (aBuffer[0] & 0x80) | (DecimalToBcd(in_sTM.tm_sec)& 0x7f);
     aBuffer[1] = DecimalToBcd(in_sTM.tm_min);    
-    aBuffer[2] = (aBuffer[2] & 196) | (DecimalToBcd(in_sTM.tm_hour) & 0x3F);
+    aBuffer[2] = (aBuffer[2] & 0xc4) | (DecimalToBcd(nHour) & 0x3f);
     aBuffer[3] = in_sTM.tm_wday;
     aBuffer[4] = DecimalToBcd(in_sTM.tm_mday);
     aBuffer[5] = DecimalToBcd(in_sTM.tm_mon);
-    aBuffer[6] = DecimalToBcd(in_sTM.tm_year + 1900 -2000);
+    aBuffer[6] = DecimalToBcd(in_sTM.tm_year + 1900 - 2000);
 
+    // Handle the 12hr clock bits
+    if (in_bTwelveHour)
+    {
+        // Turn on 12hr clock
+        aBuffer[2] |= 0x40;
+        
+        // Set am/pm bit based on hours
+        if (in_sTM.tm_hour >= 12) aBuffer[2] |= 0x20; else aBuffer[2] &= ~0x20;        
+    }
+    else
+    {
+        aBuffer[2] &= ~64;
+    }
+    
     // Write new date and time
     SetRunning(false);