Working Version of the Real Time Clock module DS1307.
Fork of RTC-DS1307 by
Rtc_Ds1307.cpp@8:d0e66fa78e79, 2013-06-23 (annotated)
- Committer:
- leihen
- Date:
- Sun Jun 23 19:24:57 2013 +0000
- Revision:
- 8:d0e66fa78e79
- Parent:
- 7:dca20be3ef38
- Child:
- 9:5627b407e097
Totally working now. Will set the MBED RTC once the class has been created. Can use the Ds1307 clock to Keep the System time up to date.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
leihen | 5:30531f2121a2 | 1 | #include "mbed.h" |
leihen | 0:3940f0ad2ca5 | 2 | #include "Rtc_Ds1307.h" |
leihen | 7:dca20be3ef38 | 3 | |
leihen | 5:30531f2121a2 | 4 | #ifndef DEBUG |
leihen | 8:d0e66fa78e79 | 5 | #define DEBUG |
leihen | 5:30531f2121a2 | 6 | #endif |
leihen | 3:e89d63f3342e | 7 | #include "debug.h" |
leihen | 0:3940f0ad2ca5 | 8 | |
leihen | 1:64274190e842 | 9 | const char *Rtc_Ds1307::m_weekDays[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }; |
leihen | 0:3940f0ad2ca5 | 10 | |
leihen | 0:3940f0ad2ca5 | 11 | |
leihen | 0:3940f0ad2ca5 | 12 | Rtc_Ds1307::Rtc_Ds1307(PinName sda, PinName scl) |
leihen | 0:3940f0ad2ca5 | 13 | { |
leihen | 0:3940f0ad2ca5 | 14 | // Create a new I2C object |
leihen | 0:3940f0ad2ca5 | 15 | m_rtc = new I2C(sda, scl); |
leihen | 0:3940f0ad2ca5 | 16 | if (m_rtc == NULL) |
leihen | 0:3940f0ad2ca5 | 17 | error("Rtc_Ds1307"); |
leihen | 1:64274190e842 | 18 | |
leihen | 1:64274190e842 | 19 | // Set the frequency to standard 100kHz |
leihen | 1:64274190e842 | 20 | m_rtc->frequency(100000); |
leihen | 0:3940f0ad2ca5 | 21 | } |
leihen | 0:3940f0ad2ca5 | 22 | |
leihen | 0:3940f0ad2ca5 | 23 | Rtc_Ds1307::~Rtc_Ds1307() |
leihen | 0:3940f0ad2ca5 | 24 | { |
leihen | 0:3940f0ad2ca5 | 25 | if (m_rtc != NULL) |
leihen | 0:3940f0ad2ca5 | 26 | delete m_rtc; |
leihen | 0:3940f0ad2ca5 | 27 | } |
leihen | 0:3940f0ad2ca5 | 28 | |
leihen | 5:30531f2121a2 | 29 | bool Rtc_Ds1307::setTime(Time_rtc& time, bool start, bool thm) |
leihen | 0:3940f0ad2ca5 | 30 | { |
leihen | 2:ee81f2c5a706 | 31 | char buffer[7]; |
leihen | 2:ee81f2c5a706 | 32 | INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour, time.min, time.sec); |
leihen | 2:ee81f2c5a706 | 33 | if (!read(0,buffer,7)) { |
leihen | 2:ee81f2c5a706 | 34 | ERR("Failed to read from RTC\n"); |
leihen | 2:ee81f2c5a706 | 35 | return false; |
leihen | 2:ee81f2c5a706 | 36 | } |
leihen | 2:ee81f2c5a706 | 37 | // Now update only the time part (saving the existing flags) |
leihen | 2:ee81f2c5a706 | 38 | if (start) { buffer[0] &= 0x7F; } else { buffer[0] |= 0x80; } |
leihen | 2:ee81f2c5a706 | 39 | buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)& 0x7f); |
leihen | 2:ee81f2c5a706 | 40 | buffer[1] = decimalToBcd(time.min); |
leihen | 2:ee81f2c5a706 | 41 | if (thm) { |
leihen | 2:ee81f2c5a706 | 42 | // AM PM format |
leihen | 2:ee81f2c5a706 | 43 | buffer[2] = (buffer[2]& 196) | (time.hour>12 ? (0x20 | ((decimalToBcd(time.hour-12)))) : decimalToBcd(time.hour)); |
leihen | 2:ee81f2c5a706 | 44 | } |
leihen | 2:ee81f2c5a706 | 45 | else { |
leihen | 2:ee81f2c5a706 | 46 | // 24 hours format |
leihen | 2:ee81f2c5a706 | 47 | buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour) & 0x3F); |
leihen | 2:ee81f2c5a706 | 48 | } |
leihen | 2:ee81f2c5a706 | 49 | buffer[3] = time.wday; |
leihen | 2:ee81f2c5a706 | 50 | buffer[4] = decimalToBcd(time.date); |
leihen | 2:ee81f2c5a706 | 51 | buffer[5] = decimalToBcd(time.mon); |
leihen | 2:ee81f2c5a706 | 52 | buffer[6] = decimalToBcd(time.year-2000); |
leihen | 2:ee81f2c5a706 | 53 | INFO("Writing new time and date data to RTC\n"); |
leihen | 2:ee81f2c5a706 | 54 | if (!write(0, buffer, 7) ) { |
leihen | 2:ee81f2c5a706 | 55 | ERR("Failed to write the data to RTC!\n"); |
leihen | 2:ee81f2c5a706 | 56 | return false; |
leihen | 2:ee81f2c5a706 | 57 | } |
leihen | 0:3940f0ad2ca5 | 58 | return true; |
leihen | 0:3940f0ad2ca5 | 59 | } |
leihen | 0:3940f0ad2ca5 | 60 | |
leihen | 5:30531f2121a2 | 61 | bool Rtc_Ds1307::getTime(Time_rtc& time) |
leihen | 0:3940f0ad2ca5 | 62 | { |
leihen | 1:64274190e842 | 63 | char buffer[7]; |
leihen | 1:64274190e842 | 64 | bool thm = false; |
leihen | 1:64274190e842 | 65 | |
leihen | 1:64274190e842 | 66 | INFO("Getting time from RTC\n"); |
leihen | 2:ee81f2c5a706 | 67 | if (!read(0, buffer, 7) ) { |
leihen | 1:64274190e842 | 68 | // Failed to read |
leihen | 1:64274190e842 | 69 | ERR("Failed to read from RTC\n"); |
leihen | 1:64274190e842 | 70 | return false; |
leihen | 1:64274190e842 | 71 | } |
leihen | 1:64274190e842 | 72 | thm = ((buffer[2] & 64) == 64); |
leihen | 1:64274190e842 | 73 | time.sec = bcdToDecimal(buffer[0]&0x7F); |
leihen | 1:64274190e842 | 74 | time.min = bcdToDecimal(buffer[1]); |
leihen | 1:64274190e842 | 75 | if (thm) { |
leihen | 1:64274190e842 | 76 | // in 12-hour-mode, we need to add 12 hours if PM bit is set |
leihen | 1:64274190e842 | 77 | time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 31 ); |
leihen | 1:64274190e842 | 78 | if ((buffer[2] & 32) == 32) |
leihen | 1:64274190e842 | 79 | time.hour += 12; |
leihen | 1:64274190e842 | 80 | } |
leihen | 1:64274190e842 | 81 | else { |
leihen | 1:64274190e842 | 82 | time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 63 ); |
leihen | 1:64274190e842 | 83 | } |
leihen | 1:64274190e842 | 84 | time.wday = buffer[3]; |
leihen | 1:64274190e842 | 85 | time.date = Rtc_Ds1307::bcdToDecimal( buffer[4]); |
leihen | 1:64274190e842 | 86 | time.mon = Rtc_Ds1307::bcdToDecimal( buffer[5]); |
leihen | 2:ee81f2c5a706 | 87 | time.year = Rtc_Ds1307::bcdToDecimal(buffer[6]) + 2000; // plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900 |
leihen | 2:ee81f2c5a706 | 88 | |
leihen | 2:ee81f2c5a706 | 89 | return true; |
leihen | 2:ee81f2c5a706 | 90 | } |
leihen | 2:ee81f2c5a706 | 91 | |
leihen | 2:ee81f2c5a706 | 92 | |
leihen | 2:ee81f2c5a706 | 93 | bool Rtc_Ds1307::startClock() |
leihen | 2:ee81f2c5a706 | 94 | { |
leihen | 2:ee81f2c5a706 | 95 | char strtStop; |
leihen | 2:ee81f2c5a706 | 96 | |
leihen | 2:ee81f2c5a706 | 97 | INFO ("Reading clock start/stop register value\n"); |
leihen | 2:ee81f2c5a706 | 98 | if (!read(0, &strtStop, 1)) { |
leihen | 2:ee81f2c5a706 | 99 | ERR("Failed to read clock start stop register !\n"); |
leihen | 2:ee81f2c5a706 | 100 | return false; |
leihen | 2:ee81f2c5a706 | 101 | } |
leihen | 2:ee81f2c5a706 | 102 | |
leihen | 2:ee81f2c5a706 | 103 | strtStop &= 0x7F; |
leihen | 2:ee81f2c5a706 | 104 | |
leihen | 2:ee81f2c5a706 | 105 | INFO("Writing back start/stop register value\n"); |
leihen | 2:ee81f2c5a706 | 106 | if (!write(0, &strtStop, 1)) { |
leihen | 2:ee81f2c5a706 | 107 | ERR("Failed to write the start stop register !\n"); |
leihen | 2:ee81f2c5a706 | 108 | return false; |
leihen | 2:ee81f2c5a706 | 109 | } |
leihen | 2:ee81f2c5a706 | 110 | |
leihen | 2:ee81f2c5a706 | 111 | INFO("Start/stop register value successfully written\n"); |
leihen | 2:ee81f2c5a706 | 112 | return true; |
leihen | 2:ee81f2c5a706 | 113 | } |
leihen | 2:ee81f2c5a706 | 114 | |
leihen | 2:ee81f2c5a706 | 115 | bool Rtc_Ds1307::stopClock() |
leihen | 2:ee81f2c5a706 | 116 | { |
leihen | 2:ee81f2c5a706 | 117 | char strtStop; |
leihen | 2:ee81f2c5a706 | 118 | |
leihen | 2:ee81f2c5a706 | 119 | INFO ("Reading clock start/stop register value\n"); |
leihen | 2:ee81f2c5a706 | 120 | if (!read(0, &strtStop, 1)) { |
leihen | 2:ee81f2c5a706 | 121 | ERR("Failed to read clock start stop register !\n"); |
leihen | 2:ee81f2c5a706 | 122 | return false; |
leihen | 2:ee81f2c5a706 | 123 | } |
leihen | 1:64274190e842 | 124 | |
leihen | 2:ee81f2c5a706 | 125 | strtStop |= 0x80; |
leihen | 2:ee81f2c5a706 | 126 | |
leihen | 2:ee81f2c5a706 | 127 | INFO("Writing back start/stop register value\n"); |
leihen | 2:ee81f2c5a706 | 128 | if (!write(0, &strtStop, 1)) { |
leihen | 2:ee81f2c5a706 | 129 | ERR("Failed to write the start stop register !\n"); |
leihen | 2:ee81f2c5a706 | 130 | return false; |
leihen | 2:ee81f2c5a706 | 131 | } |
leihen | 2:ee81f2c5a706 | 132 | |
leihen | 2:ee81f2c5a706 | 133 | INFO("Start/stop register value successfully written\n"); |
leihen | 2:ee81f2c5a706 | 134 | return true; |
leihen | 0:3940f0ad2ca5 | 135 | } |
leihen | 1:64274190e842 | 136 | |
leihen | 5:30531f2121a2 | 137 | bool Rtc_Ds1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs) |
leihen | 2:ee81f2c5a706 | 138 | { |
leihen | 2:ee81f2c5a706 | 139 | char reg; |
leihen | 2:ee81f2c5a706 | 140 | INFO("Reading register value first\n"); |
leihen | 2:ee81f2c5a706 | 141 | |
leihen | 2:ee81f2c5a706 | 142 | if (!read(7,®, 1)) { |
leihen | 2:ee81f2c5a706 | 143 | ERR("Failed to read register value !\n"); |
leihen | 2:ee81f2c5a706 | 144 | return false; |
leihen | 2:ee81f2c5a706 | 145 | } |
leihen | 2:ee81f2c5a706 | 146 | INFO("[Reg:0x07] = %02x\n", reg); |
leihen | 2:ee81f2c5a706 | 147 | |
leihen | 2:ee81f2c5a706 | 148 | // preserve the OUT control bit while writing the frequency and enable bits |
leihen | 2:ee81f2c5a706 | 149 | reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03); |
leihen | 2:ee81f2c5a706 | 150 | |
leihen | 2:ee81f2c5a706 | 151 | INFO("Writing back register value\n"); |
leihen | 2:ee81f2c5a706 | 152 | INFO("[Reg:0x07] = %02x\n", reg); |
leihen | 2:ee81f2c5a706 | 153 | |
leihen | 2:ee81f2c5a706 | 154 | if (!write(7, ®, 1)) { |
leihen | 2:ee81f2c5a706 | 155 | ERR("Failed to write register value !\n"); |
leihen | 2:ee81f2c5a706 | 156 | return false; |
leihen | 2:ee81f2c5a706 | 157 | } |
leihen | 2:ee81f2c5a706 | 158 | |
leihen | 2:ee81f2c5a706 | 159 | INFO("Successfully changed the square wave output.\n"); |
leihen | 2:ee81f2c5a706 | 160 | return true; |
leihen | 2:ee81f2c5a706 | 161 | } |
leihen | 2:ee81f2c5a706 | 162 | |
leihen | 2:ee81f2c5a706 | 163 | |
leihen | 1:64274190e842 | 164 | |
leihen | 1:64274190e842 | 165 | bool Rtc_Ds1307::read(int address, char *buffer, int len) |
leihen | 1:64274190e842 | 166 | { |
leihen | 1:64274190e842 | 167 | char buffer2[2] = {(char)address, 0}; |
leihen | 1:64274190e842 | 168 | |
leihen | 2:ee81f2c5a706 | 169 | // m_rtc->start(); |
leihen | 1:64274190e842 | 170 | if (m_rtc->write(0xd0, buffer2, 1) != 0) { |
leihen | 1:64274190e842 | 171 | ERR("Failed to write register address on rtv!\n"); |
leihen | 1:64274190e842 | 172 | m_rtc->stop(); |
leihen | 1:64274190e842 | 173 | return false; |
leihen | 1:64274190e842 | 174 | } |
leihen | 1:64274190e842 | 175 | if (m_rtc->read(0xd0, buffer, len) != 0) { |
leihen | 1:64274190e842 | 176 | ERR("Failed to read register !\n"); |
leihen | 1:64274190e842 | 177 | return false; |
leihen | 1:64274190e842 | 178 | } |
leihen | 1:64274190e842 | 179 | m_rtc->stop(); |
leihen | 1:64274190e842 | 180 | |
leihen | 1:64274190e842 | 181 | INFO("Successfully read %d registers from RTC\n", len); |
leihen | 1:64274190e842 | 182 | return true; |
leihen | 1:64274190e842 | 183 | } |
leihen | 1:64274190e842 | 184 | |
leihen | 1:64274190e842 | 185 | bool Rtc_Ds1307::write(int address, char *buffer, int len) |
leihen | 1:64274190e842 | 186 | { |
leihen | 1:64274190e842 | 187 | char buffer2[10]; |
leihen | 1:64274190e842 | 188 | buffer2[0] = address&0xFF; |
leihen | 1:64274190e842 | 189 | for (int i = 0 ; i < len ; i++) |
leihen | 1:64274190e842 | 190 | buffer2[i+1] = buffer[i]; |
leihen | 1:64274190e842 | 191 | |
leihen | 2:ee81f2c5a706 | 192 | // m_rtc->start(); |
leihen | 1:64274190e842 | 193 | if (m_rtc->write(0xd0, buffer2, len+1) != 0) { |
leihen | 1:64274190e842 | 194 | ERR("Failed to write data to rtc\n"); |
leihen | 1:64274190e842 | 195 | m_rtc->stop(); |
leihen | 1:64274190e842 | 196 | return false; |
leihen | 1:64274190e842 | 197 | } |
leihen | 1:64274190e842 | 198 | m_rtc->stop(); |
leihen | 1:64274190e842 | 199 | return true; |
leihen | 7:dca20be3ef38 | 200 | } |
leihen | 7:dca20be3ef38 | 201 | |
leihen | 7:dca20be3ef38 | 202 | |
leihen | 7:dca20be3ef38 | 203 | |
leihen | 7:dca20be3ef38 | 204 | |
leihen | 7:dca20be3ef38 | 205 | RtcCls::RtcCls(PinName sda, PinName scl, PinName sqw, bool bUseSqw) |
leihen | 7:dca20be3ef38 | 206 | : Rtc_Ds1307(sda, scl), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL) |
leihen | 7:dca20be3ef38 | 207 | { |
leihen | 7:dca20be3ef38 | 208 | // Only register the callback and start the SQW if requested to do so. Otherwise the system |
leihen | 7:dca20be3ef38 | 209 | // will use the MBED built-in RTC. |
leihen | 7:dca20be3ef38 | 210 | if (m_bUseSqw) { |
leihen | 7:dca20be3ef38 | 211 | Time_rtc t; |
leihen | 7:dca20be3ef38 | 212 | // start the wave |
leihen | 7:dca20be3ef38 | 213 | setSquareWaveOutput(true, RS1Hz); |
leihen | 7:dca20be3ef38 | 214 | // query time |
leihen | 7:dca20be3ef38 | 215 | getTime(t); |
leihen | 8:d0e66fa78e79 | 216 | struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; |
leihen | 7:dca20be3ef38 | 217 | m_time = mktime(&now); |
leihen | 8:d0e66fa78e79 | 218 | set_time(m_time); |
leihen | 7:dca20be3ef38 | 219 | // register callback from now on the time will be maintained by the square wave input |
leihen | 7:dca20be3ef38 | 220 | m_sqw.rise(this, &RtcCls::_callback); |
leihen | 7:dca20be3ef38 | 221 | } |
leihen | 7:dca20be3ef38 | 222 | } |
leihen | 7:dca20be3ef38 | 223 | |
leihen | 7:dca20be3ef38 | 224 | void RtcCls::_callback(void) |
leihen | 7:dca20be3ef38 | 225 | { |
leihen | 8:d0e66fa78e79 | 226 | // INFO("Tick!"); |
leihen | 7:dca20be3ef38 | 227 | // Simply increase the number of seconds |
leihen | 7:dca20be3ef38 | 228 | m_time++; |
leihen | 8:d0e66fa78e79 | 229 | // if (m_bAlarmEnabled && (m_time == m_alarmTime)) { |
leihen | 8:d0e66fa78e79 | 230 | // if (m_alarmfunc != NULL) |
leihen | 8:d0e66fa78e79 | 231 | // m_alarmfunc(); |
leihen | 8:d0e66fa78e79 | 232 | // m_bAlarmEnabled = false; |
leihen | 8:d0e66fa78e79 | 233 | // } |
leihen | 7:dca20be3ef38 | 234 | } |
leihen | 7:dca20be3ef38 | 235 | |
leihen | 7:dca20be3ef38 | 236 | time_t RtcCls::getTime() |
leihen | 7:dca20be3ef38 | 237 | { |
leihen | 7:dca20be3ef38 | 238 | // when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value |
leihen | 7:dca20be3ef38 | 239 | if (!m_bUseSqw) { |
leihen | 7:dca20be3ef38 | 240 | Time_rtc t; |
leihen | 7:dca20be3ef38 | 241 | getTime(t); |
leihen | 8:d0e66fa78e79 | 242 | struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900}; |
leihen | 7:dca20be3ef38 | 243 | m_time = mktime(&now); |
leihen | 8:d0e66fa78e79 | 244 | INFO("getting time %02d.%02d.%04d %02d:%02d:%02d Ticks=%08lx", t.date, t.mon, t.year, t.hour, t.min, t.sec, m_time); |
leihen | 8:d0e66fa78e79 | 245 | } |
leihen | 8:d0e66fa78e79 | 246 | else { |
leihen | 8:d0e66fa78e79 | 247 | INFO("getting time Ticks=%08lx", m_time); |
leihen | 7:dca20be3ef38 | 248 | } |
leihen | 7:dca20be3ef38 | 249 | return m_time; |
leihen | 7:dca20be3ef38 | 250 | } |
leihen | 7:dca20be3ef38 | 251 | |
leihen | 7:dca20be3ef38 | 252 | void RtcCls::setTime(time_t t) |
leihen | 7:dca20be3ef38 | 253 | { |
leihen | 7:dca20be3ef38 | 254 | Time_rtc tim; |
leihen | 7:dca20be3ef38 | 255 | struct tm *now; |
leihen | 7:dca20be3ef38 | 256 | now = localtime(&t); |
leihen | 7:dca20be3ef38 | 257 | |
leihen | 7:dca20be3ef38 | 258 | tim.sec = now->tm_sec; |
leihen | 7:dca20be3ef38 | 259 | tim.min = now->tm_min; |
leihen | 7:dca20be3ef38 | 260 | tim.hour = now->tm_hour; |
leihen | 7:dca20be3ef38 | 261 | tim.date = now->tm_mday; |
leihen | 8:d0e66fa78e79 | 262 | tim.mon = now->tm_mon+1; |
leihen | 7:dca20be3ef38 | 263 | tim.year = now->tm_year + 1900; |
leihen | 7:dca20be3ef38 | 264 | tim.wday = now->tm_wday +1; |
leihen | 7:dca20be3ef38 | 265 | |
leihen | 7:dca20be3ef38 | 266 | setTime( tim, true, true); |
leihen | 8:d0e66fa78e79 | 267 | set_time(t); |
leihen | 7:dca20be3ef38 | 268 | } |