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

Committer:
vtraveller
Date:
Sat Aug 09 11:46:08 2014 +0000
Revision:
4:04a51e4dbf4c
Parent:
3:ed1628b05d37
Child:
5:d71d6e5a7eee
Fix for 12 hour clock past midday.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vtraveller 0:98b84d9c8c96 1 #include "mbed.h"
vtraveller 0:98b84d9c8c96 2 #include "RTclock.h"
vtraveller 0:98b84d9c8c96 3
vtraveller 3:ed1628b05d37 4 const char * RTclock::m_aWeekDays[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
vtraveller 0:98b84d9c8c96 5
vtraveller 0:98b84d9c8c96 6 RTclock::RTclock(PinName in_nSDA, PinName in_nSCL, bool in_bHiSpeed)
vtraveller 0:98b84d9c8c96 7 : RTclock_parent(in_nSDA,in_nSCL)
vtraveller 0:98b84d9c8c96 8 {
vtraveller 0:98b84d9c8c96 9 // Frequency depends on chip - most are 100KHz
vtraveller 0:98b84d9c8c96 10 frequency(in_bHiSpeed ? 400000 : 100000);
vtraveller 0:98b84d9c8c96 11 }
vtraveller 0:98b84d9c8c96 12
vtraveller 0:98b84d9c8c96 13 RTclock::~RTclock()
vtraveller 0:98b84d9c8c96 14 {
vtraveller 0:98b84d9c8c96 15 }
vtraveller 0:98b84d9c8c96 16
vtraveller 0:98b84d9c8c96 17 int RTclock::BcdToDecimal(int in_nBCD)
vtraveller 0:98b84d9c8c96 18 {
vtraveller 0:98b84d9c8c96 19 return ((in_nBCD & 0xF0) >> 4) * 10 + (in_nBCD & 0x0F);
vtraveller 0:98b84d9c8c96 20 }
vtraveller 0:98b84d9c8c96 21
vtraveller 0:98b84d9c8c96 22 int RTclock::DecimalToBcd(int in_nDecimal)
vtraveller 0:98b84d9c8c96 23 {
vtraveller 0:98b84d9c8c96 24 return (in_nDecimal % 10) + ((in_nDecimal / 10) << 4);
vtraveller 0:98b84d9c8c96 25 }
vtraveller 0:98b84d9c8c96 26
vtraveller 0:98b84d9c8c96 27 bool RTclock::GetTime(tm & out_sTM)
vtraveller 0:98b84d9c8c96 28 {
vtraveller 0:98b84d9c8c96 29 char aBuffer[7];
vtraveller 0:98b84d9c8c96 30 bool b12hour = false;
vtraveller 0:98b84d9c8c96 31
vtraveller 0:98b84d9c8c96 32 if (!read(0, aBuffer, 7)) return false;
vtraveller 0:98b84d9c8c96 33
vtraveller 0:98b84d9c8c96 34 b12hour = ((aBuffer[2] & 64) == 64);
vtraveller 4:04a51e4dbf4c 35
vtraveller 0:98b84d9c8c96 36 out_sTM.tm_sec = BcdToDecimal(aBuffer[0] & 0x7F);
vtraveller 0:98b84d9c8c96 37 out_sTM.tm_min = BcdToDecimal(aBuffer[1]);
vtraveller 0:98b84d9c8c96 38
vtraveller 0:98b84d9c8c96 39 if (b12hour)
vtraveller 0:98b84d9c8c96 40 {
vtraveller 4:04a51e4dbf4c 41 // remove 12 hours if PM bit is set and past midday
vtraveller 0:98b84d9c8c96 42 out_sTM.tm_hour = BcdToDecimal(aBuffer[2] & 31);
vtraveller 4:04a51e4dbf4c 43 if ((aBuffer[2] & 32) && out_sTM.tm_hour > 12) out_sTM.tm_hour -= 12;
vtraveller 0:98b84d9c8c96 44 }
vtraveller 0:98b84d9c8c96 45 else
vtraveller 0:98b84d9c8c96 46 {
vtraveller 0:98b84d9c8c96 47 out_sTM.tm_hour = BcdToDecimal(aBuffer[2] & 63);
vtraveller 0:98b84d9c8c96 48 }
vtraveller 0:98b84d9c8c96 49
vtraveller 0:98b84d9c8c96 50 out_sTM.tm_wday = aBuffer[3];
vtraveller 0:98b84d9c8c96 51 out_sTM.tm_mday = BcdToDecimal(aBuffer[4]);
vtraveller 0:98b84d9c8c96 52 out_sTM.tm_mon = BcdToDecimal(aBuffer[5]);
vtraveller 1:8952befe5d36 53 out_sTM.tm_year = (BcdToDecimal(aBuffer[6]) + 2000) - 1900; // Returns from 2000, need form 1900 for time function
vtraveller 1:8952befe5d36 54 out_sTM.tm_isdst = 0;
vtraveller 0:98b84d9c8c96 55
vtraveller 0:98b84d9c8c96 56 return true;
vtraveller 0:98b84d9c8c96 57 }
vtraveller 0:98b84d9c8c96 58
vtraveller 0:98b84d9c8c96 59 const char * RTclock::GetWeekday(int in_nWeekDay)
vtraveller 0:98b84d9c8c96 60 {
vtraveller 0:98b84d9c8c96 61 return m_aWeekDays[in_nWeekDay];
vtraveller 0:98b84d9c8c96 62 }
vtraveller 0:98b84d9c8c96 63
vtraveller 0:98b84d9c8c96 64 bool RTclock::MapTime()
vtraveller 0:98b84d9c8c96 65 {
vtraveller 0:98b84d9c8c96 66 tm sTM;
vtraveller 0:98b84d9c8c96 67 if (!GetTime(sTM)) return false;
vtraveller 0:98b84d9c8c96 68
vtraveller 0:98b84d9c8c96 69 // Convert and set internal time
vtraveller 0:98b84d9c8c96 70 time_t nTime = ::mktime(&sTM);
vtraveller 0:98b84d9c8c96 71 ::set_time(nTime);
vtraveller 0:98b84d9c8c96 72
vtraveller 0:98b84d9c8c96 73 return true;
vtraveller 0:98b84d9c8c96 74 }
vtraveller 0:98b84d9c8c96 75
vtraveller 1:8952befe5d36 76 bool RTclock::read(int in_nAddress, char * out_pBuffer, int in_nLength)
vtraveller 1:8952befe5d36 77 {
vtraveller 1:8952befe5d36 78 char aBuffer[2] = { (char)in_nAddress, 0 };
vtraveller 1:8952befe5d36 79
vtraveller 1:8952befe5d36 80 if (0 != RTclock_parent::write(0xd0, aBuffer, 1)) return false;
vtraveller 1:8952befe5d36 81 if (0 != RTclock_parent::read(0xd0, out_pBuffer, in_nLength)) return false;
vtraveller 1:8952befe5d36 82
vtraveller 1:8952befe5d36 83 return true;
vtraveller 1:8952befe5d36 84 }
vtraveller 1:8952befe5d36 85
vtraveller 0:98b84d9c8c96 86 bool RTclock::SetTime(const tm & in_sTM)
vtraveller 0:98b84d9c8c96 87 {
vtraveller 0:98b84d9c8c96 88 char aBuffer[7];
vtraveller 0:98b84d9c8c96 89
vtraveller 0:98b84d9c8c96 90 // Preserve flags that were in register
vtraveller 0:98b84d9c8c96 91 if (!read(0,aBuffer,7)) return false;
vtraveller 0:98b84d9c8c96 92
vtraveller 0:98b84d9c8c96 93 aBuffer[0] &= 0x7F;
vtraveller 0:98b84d9c8c96 94 aBuffer[0] = (aBuffer[0] & 0x80) | (DecimalToBcd(in_sTM.tm_sec)& 0x7f);
vtraveller 0:98b84d9c8c96 95 aBuffer[1] = DecimalToBcd(in_sTM.tm_min);
vtraveller 0:98b84d9c8c96 96 aBuffer[2] = (aBuffer[2] & 196) | (DecimalToBcd(in_sTM.tm_hour) & 0x3F);
vtraveller 0:98b84d9c8c96 97 aBuffer[3] = in_sTM.tm_wday;
vtraveller 0:98b84d9c8c96 98 aBuffer[4] = DecimalToBcd(in_sTM.tm_mday);
vtraveller 0:98b84d9c8c96 99 aBuffer[5] = DecimalToBcd(in_sTM.tm_mon);
vtraveller 2:3dc63e48cb5d 100 aBuffer[6] = DecimalToBcd(in_sTM.tm_year + 1900 -2000);
vtraveller 0:98b84d9c8c96 101
vtraveller 0:98b84d9c8c96 102 // Write new date and time
vtraveller 0:98b84d9c8c96 103 SetRunning(false);
vtraveller 0:98b84d9c8c96 104
vtraveller 0:98b84d9c8c96 105 bool bSuccess = write(0, aBuffer, 7);
vtraveller 0:98b84d9c8c96 106
vtraveller 0:98b84d9c8c96 107 if (bSuccess) SetRunning(true);
vtraveller 0:98b84d9c8c96 108
vtraveller 0:98b84d9c8c96 109 return bSuccess;
vtraveller 0:98b84d9c8c96 110 }
vtraveller 0:98b84d9c8c96 111
vtraveller 0:98b84d9c8c96 112 bool RTclock::SetRunning(bool in_bEnable)
vtraveller 0:98b84d9c8c96 113 {
vtraveller 0:98b84d9c8c96 114 char nRunning;
vtraveller 0:98b84d9c8c96 115
vtraveller 0:98b84d9c8c96 116 if (!read(0, &nRunning, 1)) return false;
vtraveller 0:98b84d9c8c96 117
vtraveller 0:98b84d9c8c96 118 // Set running
vtraveller 0:98b84d9c8c96 119 if (in_bEnable)
vtraveller 0:98b84d9c8c96 120 {
vtraveller 0:98b84d9c8c96 121 nRunning &= 0x7F;
vtraveller 0:98b84d9c8c96 122 }
vtraveller 0:98b84d9c8c96 123 else
vtraveller 0:98b84d9c8c96 124 {
vtraveller 0:98b84d9c8c96 125 nRunning |= 0x80;
vtraveller 0:98b84d9c8c96 126 }
vtraveller 0:98b84d9c8c96 127
vtraveller 0:98b84d9c8c96 128 return write(0, &nRunning, 1);
vtraveller 0:98b84d9c8c96 129 }
vtraveller 0:98b84d9c8c96 130
vtraveller 0:98b84d9c8c96 131 bool RTclock::SetSquareWaveOutput
vtraveller 0:98b84d9c8c96 132 (
vtraveller 0:98b84d9c8c96 133 bool in_bEnable,
vtraveller 0:98b84d9c8c96 134 ESquareWaveRates in_nRateSelect
vtraveller 0:98b84d9c8c96 135 )
vtraveller 0:98b84d9c8c96 136 {
vtraveller 0:98b84d9c8c96 137 char nValue;
vtraveller 0:98b84d9c8c96 138
vtraveller 0:98b84d9c8c96 139 // Read register
vtraveller 0:98b84d9c8c96 140 if (!read(7, &nValue, 1)) return false;
vtraveller 0:98b84d9c8c96 141
vtraveller 0:98b84d9c8c96 142 // Protect control bits
vtraveller 0:98b84d9c8c96 143 nValue = (nValue & 0x80) | (in_bEnable ? 0x10 : 0) | ((char)in_nRateSelect & 0x03);
vtraveller 0:98b84d9c8c96 144
vtraveller 0:98b84d9c8c96 145 return write(7, &nValue, 1);
vtraveller 0:98b84d9c8c96 146 }
vtraveller 0:98b84d9c8c96 147
vtraveller 0:98b84d9c8c96 148 bool RTclock::write(int in_nAddress, const char * in_pBuffer, int in_nLength)
vtraveller 0:98b84d9c8c96 149 {
vtraveller 0:98b84d9c8c96 150 char aBuffer[10];
vtraveller 0:98b84d9c8c96 151
vtraveller 0:98b84d9c8c96 152 aBuffer[0] = in_nAddress & 0xff;
vtraveller 0:98b84d9c8c96 153
vtraveller 0:98b84d9c8c96 154 for (size_t i = 0 ; i < in_nLength; i++)
vtraveller 0:98b84d9c8c96 155 aBuffer[i + 1] = in_pBuffer[i];
vtraveller 0:98b84d9c8c96 156
vtraveller 0:98b84d9c8c96 157 return RTclock_parent::write(0xd0, aBuffer, in_nLength + 1);
vtraveller 0:98b84d9c8c96 158 }