APS_SO

Dependencies:   mbed

Committer:
ianwillianb
Date:
Fri Dec 15 20:07:49 2017 +0000
Revision:
2:27a7a42b2bae
Parent:
0:f603fa86c646
finalizado;

Who changed what in which revision?

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