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:18:38 2014 +0000
Revision:
0:98b84d9c8c96
Child:
1:8952befe5d36
First version.  Normalised version of DS1307 I2C control.  Designed to map into the internal time.h functions using MapTime.

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