Library for Real Time Clock module MCP97410 based on Library for DS1307

Fork of RTC-DS1307 by Henry Leinen

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?

UserRevisionLine numberNew 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,&reg, 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, &reg, 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 }