Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RTclock.cpp@16:f7e4b4cbfb9e, 2014-10-09 (annotated)
- 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?
User | Revision | Line number | New 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 | } |