Justin Howard / RTclock

Dependents:   AdaFruit_RGBLCD

Committer:
vtraveller
Date:
Thu Oct 09 14:04:25 2014 +0000
Revision:
16:f7e4b4cbfb9e
Parent:
15:1645f55bd0ee
Child:
17:bdc15c054ac1
Fixed midnight bug.; Fixed minutes going beyond 59.

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 13:1ccadbd4c1bd 4 RTclock::RTclock(I2C & in_cI2C, uint8_t in_nAddress, EClockType in_eClockType)
vtraveller 10:e5eabd3a1ca6 5 : m_bTwelveHour(false)
vtraveller 10:e5eabd3a1ca6 6 , m_cI2C(in_cI2C)
vtraveller 13:1ccadbd4c1bd 7 , m_nAddress(in_nAddress)
vtraveller 9:3a0ba8364ef2 8 , m_eClockType(in_eClockType)
vtraveller 0:98b84d9c8c96 9 {
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 15:1645f55bd0ee 40 out_sTM.tm_hour = bcdToDecimal(aBuffer[2] & 0x1f);
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 16:f7e4b4cbfb9e 44 if (!bPM && 12 == out_sTM.tm_hour) out_sTM.tm_hour = 0;
vtraveller 0:98b84d9c8c96 45 }
vtraveller 0:98b84d9c8c96 46 else
vtraveller 0:98b84d9c8c96 47 {
vtraveller 7:3621025e7949 48 out_sTM.tm_hour = bcdToDecimal(aBuffer[2] & 0x3f);
vtraveller 0:98b84d9c8c96 49 }
vtraveller 0:98b84d9c8c96 50
vtraveller 7:3621025e7949 51 out_sTM.tm_wday = aBuffer[3] % 7;
vtraveller 7:3621025e7949 52 out_sTM.tm_mday = bcdToDecimal(aBuffer[4]);
vtraveller 7:3621025e7949 53 out_sTM.tm_mon = bcdToDecimal(aBuffer[5]);
vtraveller 7:3621025e7949 54 out_sTM.tm_year = (bcdToDecimal(aBuffer[6]) + 2000) - 1900; // Returns from 2000, need form 1900 for time function
vtraveller 1:8952befe5d36 55 out_sTM.tm_isdst = 0;
vtraveller 0:98b84d9c8c96 56
vtraveller 0:98b84d9c8c96 57 return true;
vtraveller 0:98b84d9c8c96 58 }
vtraveller 0:98b84d9c8c96 59
vtraveller 7:3621025e7949 60 bool RTclock::isTwelveHour()
vtraveller 5:d71d6e5a7eee 61 {
vtraveller 5:d71d6e5a7eee 62 return m_bTwelveHour;
vtraveller 5:d71d6e5a7eee 63 }
vtraveller 5:d71d6e5a7eee 64
vtraveller 7:3621025e7949 65 bool RTclock::mapTime()
vtraveller 0:98b84d9c8c96 66 {
vtraveller 0:98b84d9c8c96 67 tm sTM;
vtraveller 7:3621025e7949 68 if (!getTime(sTM)) return false;
vtraveller 0:98b84d9c8c96 69
vtraveller 0:98b84d9c8c96 70 // Convert and set internal time
vtraveller 0:98b84d9c8c96 71 time_t nTime = ::mktime(&sTM);
vtraveller 0:98b84d9c8c96 72 ::set_time(nTime);
vtraveller 0:98b84d9c8c96 73
vtraveller 0:98b84d9c8c96 74 return true;
vtraveller 0:98b84d9c8c96 75 }
vtraveller 0:98b84d9c8c96 76
vtraveller 11:49b987f6ae26 77 bool RTclock::read(uint8_t in_nAddress, char * out_pBuffer, int in_nLength)
vtraveller 1:8952befe5d36 78 {
vtraveller 13:1ccadbd4c1bd 79 if (0 != m_cI2C.write(m_nAddress, (char *)&in_nAddress, 1)) return false;
vtraveller 13:1ccadbd4c1bd 80 if (0 != m_cI2C.read(m_nAddress, 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 7:3621025e7949 85 bool RTclock::setTime(const tm & in_sTM, bool in_bTwelveHour)
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 5:d71d6e5a7eee 92 m_bTwelveHour = in_bTwelveHour;
vtraveller 5:d71d6e5a7eee 93
vtraveller 5:d71d6e5a7eee 94 // We always have tm in 24hr form - so adjut if 12hr clock
vtraveller 5:d71d6e5a7eee 95 int nHour = in_sTM.tm_hour;
vtraveller 5:d71d6e5a7eee 96 if (in_bTwelveHour) nHour %= 12;
vtraveller 5:d71d6e5a7eee 97
vtraveller 9:3a0ba8364ef2 98 switch (m_eClockType)
vtraveller 5:d71d6e5a7eee 99 {
vtraveller 9:3a0ba8364ef2 100 case eDS1311:
vtraveller 9:3a0ba8364ef2 101 aBuffer[0] &= 0x7f;
vtraveller 9:3a0ba8364ef2 102 aBuffer[0] = (aBuffer[0] & 0x80) | (decimalToBcd(in_sTM.tm_sec)& 0x7f);
vtraveller 9:3a0ba8364ef2 103 aBuffer[1] = decimalToBcd(in_sTM.tm_min);
vtraveller 9:3a0ba8364ef2 104 aBuffer[2] = (aBuffer[2] & 0xc4) | (decimalToBcd(nHour) & 0x3f);
vtraveller 9:3a0ba8364ef2 105 aBuffer[3] = in_sTM.tm_wday;
vtraveller 9:3a0ba8364ef2 106 aBuffer[4] = decimalToBcd(in_sTM.tm_mday);
vtraveller 9:3a0ba8364ef2 107 aBuffer[5] = decimalToBcd(in_sTM.tm_mon);
vtraveller 9:3a0ba8364ef2 108 aBuffer[6] = decimalToBcd(in_sTM.tm_year + 1900 - 2000);
vtraveller 5:d71d6e5a7eee 109
vtraveller 9:3a0ba8364ef2 110 // Handle the 12hr clock bits
vtraveller 9:3a0ba8364ef2 111 if (in_bTwelveHour)
vtraveller 9:3a0ba8364ef2 112 {
vtraveller 9:3a0ba8364ef2 113 // Turn on 12hr clock
vtraveller 9:3a0ba8364ef2 114 aBuffer[2] |= 0x40;
vtraveller 9:3a0ba8364ef2 115
vtraveller 9:3a0ba8364ef2 116 // Set am/pm bit based on hours
vtraveller 9:3a0ba8364ef2 117 if (in_sTM.tm_hour >= 12) aBuffer[2] |= 0x20; else aBuffer[2] &= ~0x20;
vtraveller 9:3a0ba8364ef2 118 }
vtraveller 9:3a0ba8364ef2 119 else
vtraveller 9:3a0ba8364ef2 120 {
vtraveller 9:3a0ba8364ef2 121 aBuffer[2] &= ~64;
vtraveller 9:3a0ba8364ef2 122 }
vtraveller 9:3a0ba8364ef2 123 break;
vtraveller 9:3a0ba8364ef2 124
vtraveller 9:3a0ba8364ef2 125 case eDS3231:
vtraveller 9:3a0ba8364ef2 126 aBuffer[0] = decimalToBcd(in_sTM.tm_sec) & 0x7f;
vtraveller 9:3a0ba8364ef2 127 aBuffer[1] = decimalToBcd(in_sTM.tm_min) & 0x7f;
vtraveller 9:3a0ba8364ef2 128 aBuffer[2] = decimalToBcd(nHour) & (m_bTwelveHour ? 0x1f : 0x3f);
vtraveller 9:3a0ba8364ef2 129 aBuffer[3] = in_sTM.tm_wday;
vtraveller 9:3a0ba8364ef2 130 aBuffer[4] = decimalToBcd(in_sTM.tm_mday);
vtraveller 14:d5b47ff12d17 131 aBuffer[5] = decimalToBcd(in_sTM.tm_mon) & ~0x80 /* 2000+ */;
vtraveller 9:3a0ba8364ef2 132 aBuffer[6] = decimalToBcd(in_sTM.tm_year + 1900 - 2000);
vtraveller 9:3a0ba8364ef2 133
vtraveller 9:3a0ba8364ef2 134 // Handle the 12hr clock bits
vtraveller 9:3a0ba8364ef2 135 if (in_bTwelveHour)
vtraveller 9:3a0ba8364ef2 136 {
vtraveller 9:3a0ba8364ef2 137 // Turn on 12hr clock
vtraveller 9:3a0ba8364ef2 138 aBuffer[2] |= 0x40;
vtraveller 9:3a0ba8364ef2 139
vtraveller 9:3a0ba8364ef2 140 // Set am/pm bit based on hours
vtraveller 9:3a0ba8364ef2 141 if (in_sTM.tm_hour >= 12) aBuffer[2] |= 0x20;
vtraveller 9:3a0ba8364ef2 142 }
vtraveller 9:3a0ba8364ef2 143 break;
vtraveller 9:3a0ba8364ef2 144 }
vtraveller 5:d71d6e5a7eee 145
vtraveller 0:98b84d9c8c96 146 // Write new date and time
vtraveller 7:3621025e7949 147 setRunning(false);
vtraveller 0:98b84d9c8c96 148
vtraveller 0:98b84d9c8c96 149 bool bSuccess = write(0, aBuffer, 7);
vtraveller 0:98b84d9c8c96 150
vtraveller 7:3621025e7949 151 if (bSuccess) setRunning(true);
vtraveller 0:98b84d9c8c96 152
vtraveller 0:98b84d9c8c96 153 return bSuccess;
vtraveller 0:98b84d9c8c96 154 }
vtraveller 0:98b84d9c8c96 155
vtraveller 7:3621025e7949 156 bool RTclock::setRunning(bool in_bEnable)
vtraveller 0:98b84d9c8c96 157 {
vtraveller 0:98b84d9c8c96 158 char nRunning;
vtraveller 0:98b84d9c8c96 159
vtraveller 0:98b84d9c8c96 160 if (!read(0, &nRunning, 1)) return false;
vtraveller 0:98b84d9c8c96 161
vtraveller 0:98b84d9c8c96 162 // Set running
vtraveller 0:98b84d9c8c96 163 if (in_bEnable)
vtraveller 0:98b84d9c8c96 164 {
vtraveller 0:98b84d9c8c96 165 nRunning &= 0x7F;
vtraveller 0:98b84d9c8c96 166 }
vtraveller 0:98b84d9c8c96 167 else
vtraveller 0:98b84d9c8c96 168 {
vtraveller 0:98b84d9c8c96 169 nRunning |= 0x80;
vtraveller 0:98b84d9c8c96 170 }
vtraveller 0:98b84d9c8c96 171
vtraveller 0:98b84d9c8c96 172 return write(0, &nRunning, 1);
vtraveller 0:98b84d9c8c96 173 }
vtraveller 0:98b84d9c8c96 174
vtraveller 7:3621025e7949 175 bool RTclock::setSquareWaveOutput
vtraveller 0:98b84d9c8c96 176 (
vtraveller 0:98b84d9c8c96 177 bool in_bEnable,
vtraveller 0:98b84d9c8c96 178 ESquareWaveRates in_nRateSelect
vtraveller 0:98b84d9c8c96 179 )
vtraveller 0:98b84d9c8c96 180 {
vtraveller 0:98b84d9c8c96 181 char nValue;
vtraveller 0:98b84d9c8c96 182
vtraveller 0:98b84d9c8c96 183 // Read register
vtraveller 0:98b84d9c8c96 184 if (!read(7, &nValue, 1)) return false;
vtraveller 0:98b84d9c8c96 185
vtraveller 0:98b84d9c8c96 186 // Protect control bits
vtraveller 0:98b84d9c8c96 187 nValue = (nValue & 0x80) | (in_bEnable ? 0x10 : 0) | ((char)in_nRateSelect & 0x03);
vtraveller 0:98b84d9c8c96 188
vtraveller 0:98b84d9c8c96 189 return write(7, &nValue, 1);
vtraveller 0:98b84d9c8c96 190 }
vtraveller 0:98b84d9c8c96 191
vtraveller 11:49b987f6ae26 192 bool RTclock::write(uint8_t in_nAddress, const char * in_pBuffer, int in_nLength)
vtraveller 0:98b84d9c8c96 193 {
vtraveller 0:98b84d9c8c96 194 char aBuffer[10];
vtraveller 0:98b84d9c8c96 195
vtraveller 0:98b84d9c8c96 196 aBuffer[0] = in_nAddress & 0xff;
vtraveller 0:98b84d9c8c96 197
vtraveller 0:98b84d9c8c96 198 for (size_t i = 0 ; i < in_nLength; i++)
vtraveller 0:98b84d9c8c96 199 aBuffer[i + 1] = in_pBuffer[i];
vtraveller 0:98b84d9c8c96 200
vtraveller 13:1ccadbd4c1bd 201 return m_cI2C.write(m_nAddress, aBuffer, in_nLength + 1);
vtraveller 0:98b84d9c8c96 202 }