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:
Sun Aug 10 12:34:32 2014 +0000
Revision:
7:3621025e7949
Parent:
5:d71d6e5a7eee
Child:
9:3a0ba8364ef2
Removed weekday support as not useful in a generic class.; Renamed members to patch coding style of other modules.

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 RTclock::RTclock(PinName in_nSDA, PinName in_nSCL, bool in_bHiSpeed)
vtraveller 0:98b84d9c8c96 5 : RTclock_parent(in_nSDA,in_nSCL)
vtraveller 5:d71d6e5a7eee 6 , m_bTwelveHour(false)
vtraveller 0:98b84d9c8c96 7 {
vtraveller 0:98b84d9c8c96 8 // Frequency depends on chip - most are 100KHz
vtraveller 0:98b84d9c8c96 9 frequency(in_bHiSpeed ? 400000 : 100000);
vtraveller 0:98b84d9c8c96 10 }
vtraveller 0:98b84d9c8c96 11
vtraveller 0:98b84d9c8c96 12 RTclock::~RTclock()
vtraveller 0:98b84d9c8c96 13 {
vtraveller 0:98b84d9c8c96 14 }
vtraveller 0:98b84d9c8c96 15
vtraveller 7:3621025e7949 16 int RTclock::bcdToDecimal(int in_nBCD)
vtraveller 0:98b84d9c8c96 17 {
vtraveller 0:98b84d9c8c96 18 return ((in_nBCD & 0xF0) >> 4) * 10 + (in_nBCD & 0x0F);
vtraveller 0:98b84d9c8c96 19 }
vtraveller 0:98b84d9c8c96 20
vtraveller 7:3621025e7949 21 int RTclock::decimalToBcd(int in_nDecimal)
vtraveller 0:98b84d9c8c96 22 {
vtraveller 0:98b84d9c8c96 23 return (in_nDecimal % 10) + ((in_nDecimal / 10) << 4);
vtraveller 0:98b84d9c8c96 24 }
vtraveller 0:98b84d9c8c96 25
vtraveller 7:3621025e7949 26 bool RTclock::getTime(tm & out_sTM)
vtraveller 0:98b84d9c8c96 27 {
vtraveller 0:98b84d9c8c96 28 char aBuffer[7];
vtraveller 0:98b84d9c8c96 29
vtraveller 0:98b84d9c8c96 30 if (!read(0, aBuffer, 7)) return false;
vtraveller 0:98b84d9c8c96 31
vtraveller 5:d71d6e5a7eee 32 m_bTwelveHour = ((aBuffer[2] & 0x40) == 0x40);
vtraveller 4:04a51e4dbf4c 33
vtraveller 7:3621025e7949 34 out_sTM.tm_sec = bcdToDecimal(aBuffer[0] & 0x7f);
vtraveller 7:3621025e7949 35 out_sTM.tm_min = bcdToDecimal(aBuffer[1]);
vtraveller 0:98b84d9c8c96 36
vtraveller 5:d71d6e5a7eee 37 if (m_bTwelveHour)
vtraveller 0:98b84d9c8c96 38 {
vtraveller 5:d71d6e5a7eee 39 // add 12 hours if PM bit is set and past midday
vtraveller 7:3621025e7949 40 out_sTM.tm_hour = bcdToDecimal(aBuffer[2] & 31);
vtraveller 5:d71d6e5a7eee 41
vtraveller 5:d71d6e5a7eee 42 bool bPM = (0 != (aBuffer[2] & 0x20));
vtraveller 5:d71d6e5a7eee 43 if (bPM && 12 != out_sTM.tm_hour) out_sTM.tm_hour += 12;
vtraveller 0:98b84d9c8c96 44 }
vtraveller 0:98b84d9c8c96 45 else
vtraveller 0:98b84d9c8c96 46 {
vtraveller 7:3621025e7949 47 out_sTM.tm_hour = bcdToDecimal(aBuffer[2] & 0x3f);
vtraveller 0:98b84d9c8c96 48 }
vtraveller 0:98b84d9c8c96 49
vtraveller 7:3621025e7949 50 out_sTM.tm_wday = aBuffer[3] % 7;
vtraveller 7:3621025e7949 51 out_sTM.tm_mday = bcdToDecimal(aBuffer[4]);
vtraveller 7:3621025e7949 52 out_sTM.tm_mon = bcdToDecimal(aBuffer[5]);
vtraveller 7:3621025e7949 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 7:3621025e7949 59 bool RTclock::isTwelveHour()
vtraveller 5:d71d6e5a7eee 60 {
vtraveller 5:d71d6e5a7eee 61 return m_bTwelveHour;
vtraveller 5:d71d6e5a7eee 62 }
vtraveller 5:d71d6e5a7eee 63
vtraveller 7:3621025e7949 64 bool RTclock::mapTime()
vtraveller 0:98b84d9c8c96 65 {
vtraveller 0:98b84d9c8c96 66 tm sTM;
vtraveller 7:3621025e7949 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 7:3621025e7949 86 bool RTclock::setTime(const tm & in_sTM, bool in_bTwelveHour)
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 5:d71d6e5a7eee 93 m_bTwelveHour = in_bTwelveHour;
vtraveller 5:d71d6e5a7eee 94
vtraveller 5:d71d6e5a7eee 95 // We always have tm in 24hr form - so adjut if 12hr clock
vtraveller 5:d71d6e5a7eee 96 int nHour = in_sTM.tm_hour;
vtraveller 5:d71d6e5a7eee 97 if (in_bTwelveHour) nHour %= 12;
vtraveller 5:d71d6e5a7eee 98
vtraveller 5:d71d6e5a7eee 99 aBuffer[0] &= 0x7f;
vtraveller 7:3621025e7949 100 aBuffer[0] = (aBuffer[0] & 0x80) | (decimalToBcd(in_sTM.tm_sec)& 0x7f);
vtraveller 7:3621025e7949 101 aBuffer[1] = decimalToBcd(in_sTM.tm_min);
vtraveller 7:3621025e7949 102 aBuffer[2] = (aBuffer[2] & 0xc4) | (decimalToBcd(nHour) & 0x3f);
vtraveller 0:98b84d9c8c96 103 aBuffer[3] = in_sTM.tm_wday;
vtraveller 7:3621025e7949 104 aBuffer[4] = decimalToBcd(in_sTM.tm_mday);
vtraveller 7:3621025e7949 105 aBuffer[5] = decimalToBcd(in_sTM.tm_mon);
vtraveller 7:3621025e7949 106 aBuffer[6] = decimalToBcd(in_sTM.tm_year + 1900 - 2000);
vtraveller 0:98b84d9c8c96 107
vtraveller 5:d71d6e5a7eee 108 // Handle the 12hr clock bits
vtraveller 5:d71d6e5a7eee 109 if (in_bTwelveHour)
vtraveller 5:d71d6e5a7eee 110 {
vtraveller 5:d71d6e5a7eee 111 // Turn on 12hr clock
vtraveller 5:d71d6e5a7eee 112 aBuffer[2] |= 0x40;
vtraveller 5:d71d6e5a7eee 113
vtraveller 5:d71d6e5a7eee 114 // Set am/pm bit based on hours
vtraveller 5:d71d6e5a7eee 115 if (in_sTM.tm_hour >= 12) aBuffer[2] |= 0x20; else aBuffer[2] &= ~0x20;
vtraveller 5:d71d6e5a7eee 116 }
vtraveller 5:d71d6e5a7eee 117 else
vtraveller 5:d71d6e5a7eee 118 {
vtraveller 5:d71d6e5a7eee 119 aBuffer[2] &= ~64;
vtraveller 5:d71d6e5a7eee 120 }
vtraveller 5:d71d6e5a7eee 121
vtraveller 0:98b84d9c8c96 122 // Write new date and time
vtraveller 7:3621025e7949 123 setRunning(false);
vtraveller 0:98b84d9c8c96 124
vtraveller 0:98b84d9c8c96 125 bool bSuccess = write(0, aBuffer, 7);
vtraveller 0:98b84d9c8c96 126
vtraveller 7:3621025e7949 127 if (bSuccess) setRunning(true);
vtraveller 0:98b84d9c8c96 128
vtraveller 0:98b84d9c8c96 129 return bSuccess;
vtraveller 0:98b84d9c8c96 130 }
vtraveller 0:98b84d9c8c96 131
vtraveller 7:3621025e7949 132 bool RTclock::setRunning(bool in_bEnable)
vtraveller 0:98b84d9c8c96 133 {
vtraveller 0:98b84d9c8c96 134 char nRunning;
vtraveller 0:98b84d9c8c96 135
vtraveller 0:98b84d9c8c96 136 if (!read(0, &nRunning, 1)) return false;
vtraveller 0:98b84d9c8c96 137
vtraveller 0:98b84d9c8c96 138 // Set running
vtraveller 0:98b84d9c8c96 139 if (in_bEnable)
vtraveller 0:98b84d9c8c96 140 {
vtraveller 0:98b84d9c8c96 141 nRunning &= 0x7F;
vtraveller 0:98b84d9c8c96 142 }
vtraveller 0:98b84d9c8c96 143 else
vtraveller 0:98b84d9c8c96 144 {
vtraveller 0:98b84d9c8c96 145 nRunning |= 0x80;
vtraveller 0:98b84d9c8c96 146 }
vtraveller 0:98b84d9c8c96 147
vtraveller 0:98b84d9c8c96 148 return write(0, &nRunning, 1);
vtraveller 0:98b84d9c8c96 149 }
vtraveller 0:98b84d9c8c96 150
vtraveller 7:3621025e7949 151 bool RTclock::setSquareWaveOutput
vtraveller 0:98b84d9c8c96 152 (
vtraveller 0:98b84d9c8c96 153 bool in_bEnable,
vtraveller 0:98b84d9c8c96 154 ESquareWaveRates in_nRateSelect
vtraveller 0:98b84d9c8c96 155 )
vtraveller 0:98b84d9c8c96 156 {
vtraveller 0:98b84d9c8c96 157 char nValue;
vtraveller 0:98b84d9c8c96 158
vtraveller 0:98b84d9c8c96 159 // Read register
vtraveller 0:98b84d9c8c96 160 if (!read(7, &nValue, 1)) return false;
vtraveller 0:98b84d9c8c96 161
vtraveller 0:98b84d9c8c96 162 // Protect control bits
vtraveller 0:98b84d9c8c96 163 nValue = (nValue & 0x80) | (in_bEnable ? 0x10 : 0) | ((char)in_nRateSelect & 0x03);
vtraveller 0:98b84d9c8c96 164
vtraveller 0:98b84d9c8c96 165 return write(7, &nValue, 1);
vtraveller 0:98b84d9c8c96 166 }
vtraveller 0:98b84d9c8c96 167
vtraveller 0:98b84d9c8c96 168 bool RTclock::write(int in_nAddress, const char * in_pBuffer, int in_nLength)
vtraveller 0:98b84d9c8c96 169 {
vtraveller 0:98b84d9c8c96 170 char aBuffer[10];
vtraveller 0:98b84d9c8c96 171
vtraveller 0:98b84d9c8c96 172 aBuffer[0] = in_nAddress & 0xff;
vtraveller 0:98b84d9c8c96 173
vtraveller 0:98b84d9c8c96 174 for (size_t i = 0 ; i < in_nLength; i++)
vtraveller 0:98b84d9c8c96 175 aBuffer[i + 1] = in_pBuffer[i];
vtraveller 0:98b84d9c8c96 176
vtraveller 0:98b84d9c8c96 177 return RTclock_parent::write(0xd0, aBuffer, in_nLength + 1);
vtraveller 0:98b84d9c8c96 178 }