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 09:54:36 2014 +0000
Revision:
2:3dc63e48cb5d
Parent:
1:8952befe5d36
Child:
3:ed1628b05d37
Fixed setting of the year (RTC is from 2000, struct tm time is from 1900).

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