00001
00002
00003
00004
00005
00006 #include "RTC.h"
00007
00008 extern "C"
00009 {
00010 #include <inttypes.h>
00011 #include "WConstants.h"
00012 #include "TWI.h"
00013 }
00014
00015
00026
00033
00034 RTC::RTC() {
00035
00036 };
00037
00038 #define _rtc_reg_p_(reg) (reg <= RTC_LAST_REG ? 1 : 0)
00039
00048 char RTC::write_reg(unsigned char reg, unsigned char v) {
00049 if (!_rtc_reg_p_(reg)) return(-1);
00050 _buf[0] = _i2c_wr_address;
00051 _buf[1] = reg;
00052 _buf[2] = v;
00053 twi_transmit(_buf, 3);
00054 return(0);
00055 }
00056
00066 char RTC::write_regs(unsigned char reg, unsigned char *v, unsigned char n) {
00067 unsigned char *p;
00068 unsigned char i;
00069 if (!_rtc_reg_p_(reg)) return(-1);
00070 if (n > 16) return(-1);
00071 _buf[0] = _i2c_wr_address;
00072 _buf[1] = reg;
00073 p = v;
00074 for (i = 0; i < n; i++) _buf[i + 2] = *p++;
00075 twi_transmit(_buf, n + 2);
00076 return(0);
00077 }
00078
00086
00087 char RTC::write_reg_ptr(unsigned char reg) {
00088 if (!_rtc_reg_p_(reg)) return(-1);
00089 _buf[0] = _i2c_wr_address;
00090 _buf[1] = reg;
00091 twi_transmit(_buf, 2);
00092 return(0);
00093 }
00094
00100
00101 char RTC::read_regs() {
00102 unsigned char i;
00103 write_reg_ptr(0);
00104 _buf[0] = _i2c_rd_address;
00105 twi_transmit(_buf, 17);
00106 delay(10);
00107 while(twi_busy_p());
00108
00109 if (!twi_status_reg.last_trans_ok) return(-1);
00110 twi_get_data(_regs.reg_array, 17);
00111 return(0);
00112 }
00113
00114
00121
00122 unsigned char RTC::read_reg(unsigned char reg) {
00123 unsigned char i;
00124 unsigned char data[1];
00125 if (!_rtc_reg_p_(reg)) return(-2);
00126 write_reg_ptr(reg);
00127 _buf[0] = _i2c_rd_address;
00128 _buf[1] = reg;
00129 delay(10);
00130 twi_transmit(_buf, 2);
00131 while(twi_busy_p());
00132
00133 if (!twi_status_reg.last_trans_ok) return(-1);
00134 twi_get_data(data, 2);
00135 return(data[1]);
00136 }
00137
00138
00139 #define PM_BIT 0x02
00140 #define _rb_(name) (_regs.reg_bits.name)
00141 #define _digit_(name) (_rb_(name) + '0')
00142 #define _hours_10_ ( _rb_(hour12) ? (_rb_(hours_10) & 0x01) : _rb_(hours_10))
00143 #define _hours_ ( _rb_(hours) )
00144 #define _pm_p_ (_rb_(hours_10) & PM_BIT)
00145
00149 unsigned char RTC::get_secs() { return(_rb_(secs_10) * 10 + _rb_(secs)); }
00153 unsigned char RTC::get_mins() { return(_rb_(mins_10) * 10 + _rb_(mins)); }
00157 unsigned char RTC::get_hours() { return(_hours_10_ * 10 + _hours_); }
00161 unsigned char RTC::get_day() { return(_rb_(day_10) * 10 + _rb_(day)); }
00165 unsigned char RTC::get_month() { return(_rb_(month_10) * 10 + _rb_(month)); }
00169 unsigned int RTC::get_year() { return(2000 + _rb_(year_10) * 10 + _rb_(year)); }
00170
00171
00172
00173 #define _break_(x, x10, x1) { x1 = x % 10; x10 = (unsigned char)((x - x1) / 10); }
00174
00175
00179 #define valid_year_p(y) (((y > 2099) || (y < 2000)) ? 0 : 1)
00180 #define valid_month_p(m) (((m > 12) || (m < 1)) ? 0 : 1)
00181 #define valid_day_p(d) (((d > 31) || (d < 1)) ? 0 : 1)
00182
00183
00190 unsigned char RTC::set_year(unsigned int year) {
00191 unsigned char y10;
00192 unsigned char y1;
00193 if (year > 2099) return(-1);
00194 if (year < 2000) return(-1);
00195 year -= 2000;
00196 _break_(year, y10, y1);
00197 write_reg(RTC_REG_YEAR, (y10 << 4) | y1);
00198 return(0);
00199 }
00200
00207 unsigned char RTC::set_month(unsigned char month) {
00208 unsigned char m10, m1;
00209 if (month > 12) return(-1);
00210 if (month < 1) return(-1);
00211 _break_(month, m10, m1);
00212 write_reg(RTC_REG_MONTH, (m10 << 4) | m1);
00213 return(0);
00214 }
00215
00222 unsigned char RTC::set_day(unsigned char day) {
00223 unsigned char d10, d1;
00224 if (day > 31) return(-1);
00225 if (day < 1) return(-1);
00226 _break_(day, d10, d1);
00227 write_reg(RTC_REG_DAY, (d10 << 4) | d1);
00228 return(0);
00229 }
00230
00240 unsigned char RTC::set_date(unsigned int year, unsigned char month,
00241 unsigned char day) {
00242 if (set_year(year)) return(-1);
00243 if (set_month(month)) return(-1);
00244 if (set_day(day)) return(-1);
00245 return(0);
00246 }
00247
00248
00255 unsigned char RTC::set_secs(unsigned char secs) {
00256 unsigned char s10, s1;
00257 if (secs > 59) return(-1);
00258 _break_(secs, s10, s1);
00259 write_reg(RTC_REG_SECS, (s10 << 4) | s1);
00260 return(0);
00261 }
00262
00269 unsigned char RTC::set_mins(unsigned char mins) {
00270 unsigned char m10, m1;
00271 if (mins > 59) return(-1);
00272 _break_(mins, m10, m1);
00273 write_reg(RTC_REG_MINS, (m10 << 4) | m1);
00274 return(0);
00275 }
00276
00278 union hours_reg {
00279 struct {
00280 unsigned hours : 4;
00281 unsigned hours_10 : 1;
00282 unsigned pm : 1;
00283 unsigned hour12 : 1;
00284 unsigned UNUSED : 1;
00285 } _bits12;
00286 struct {
00287 unsigned hours : 4;
00288 unsigned hours_10 : 2;
00289 unsigned hour12 : 1;
00290 unsigned UNUSED : 1;
00291 } _bits24;
00292 unsigned char _byte;
00293 };
00294
00296
00300
00306
00307 unsigned char RTC::set_hours12(unsigned char hours, unsigned char pm_p) {
00308 union hours_reg reg;
00309 if (hours > 12) return(-1);
00310 reg._bits12.hour12 = 1;
00311 reg._bits12.pm = pm_p ? 1 : 0;
00312 _break_(hours, reg._bits12.hours_10, reg._bits12.hours);
00313 write_reg(RTC_REG_HOURS, reg._byte);
00314 return(0);
00315 }
00316
00322
00323 unsigned char RTC::set_hours(unsigned char hours) {
00324 union hours_reg reg;
00325 if (hours > 23) return(-1);
00326 reg._bits24.hour12 = 0;
00327 _break_(hours, reg._bits24.hours_10, reg._bits24.hours);
00328 write_reg(RTC_REG_HOURS, reg._byte);
00329 return(0);
00330 }
00331
00335
00336 unsigned char RTC::set_time(unsigned char hours, unsigned char mins,
00337 unsigned char secs) {
00338 if (set_hours(hours)) return(-1);
00339 if (set_mins(mins)) return(-1);
00340 if (set_secs(secs)) return(-1);
00341 return(0);
00342 }
00343
00351
00352 unsigned char RTC::set_time12(unsigned char hours,
00353 unsigned char mins,
00354 unsigned char secs,
00355 unsigned char pm_p) {
00356 if (set_hours12(hours, pm_p)) return(-1);
00357 if (set_mins(mins)) return(-1);
00358 if (set_secs(secs)) return(-1);
00359 return(0);
00360 }
00361
00362 #define _ar_(n) alarm_reg._bits.n
00363 #define _a1_bits_(dy, m4, m3, m2, m1) { _ar_(a1_dy) = dy; \
00364 _ar_(a1m4) = m4; _ar_(a1m3) = m3; \
00365 _ar_(a1m2) = m2; _ar_(a1m1) = m1; }
00366
00367
00390 unsigned char RTC::set_alarm1(unsigned char mode, unsigned char day_or_dow,
00391 unsigned char hours, unsigned char mins,
00392 unsigned char secs) {
00393 union {
00394 struct {
00395 unsigned a1_secs : 4;
00396 unsigned a1_secs_10 : 3;
00397 unsigned a1m1 : 1;
00398
00399 unsigned a1_mins : 4;
00400 unsigned a1_mins_10 : 3;
00401 unsigned a1m2 : 1;
00402
00403 unsigned a1_hours : 4;
00404 unsigned a1_hours_10 : 2;
00405 unsigned a1_hour12 : 1;
00406 unsigned a1m3 : 1;
00407
00408 unsigned a1_day : 4;
00409 unsigned a1_day_10 : 2;
00410 unsigned a1_dy : 1;
00411 unsigned a1m4 : 1;
00412 } _bits;
00413 unsigned char _bytes[3];
00414 } alarm_reg = { 0, 0, 0, 0 };
00415 switch(mode) {
00416 case RTC_ALARM1_MODE1: _a1_bits_(0, 1, 1, 1, 1); break;
00417 case RTC_ALARM1_MODE2: _a1_bits_(0, 1, 1, 1, 0); break;
00418 case RTC_ALARM1_MODE3: _a1_bits_(0, 1, 1, 0, 0); break;
00419 case RTC_ALARM1_MODE4: _a1_bits_(0, 1, 0, 0, 0); break;
00420 case RTC_ALARM1_MODE5: _a1_bits_(0, 0, 0, 0, 0); break;
00421 case RTC_ALARM1_MODE6: _a1_bits_(1, 0, 0, 0, 0); break;
00422 default: _a1_bits_(0, 0, 0, 0, 0); break;
00423 }
00424 _break_(secs, alarm_reg._bits.a1_secs_10, alarm_reg._bits.a1_secs);
00425 _break_(mins, alarm_reg._bits.a1_mins_10, alarm_reg._bits.a1_mins);
00426 _break_(hours, alarm_reg._bits.a1_hours_10, alarm_reg._bits.a1_hours);
00427 _break_(day_or_dow, alarm_reg._bits.a1_day_10, alarm_reg._bits.a1_day);
00428
00429 write_regs(RTC_REG_A1SECS, alarm_reg._bytes, 4);
00430
00431 return(0);
00432 }
00433
00438 unsigned char RTC::clear_alarm1(void) {
00439 unsigned char reg_value;
00440 reg_value = read_reg(RTC_REG_STATUS);
00441 reg_value &= ~RTC_A1F;
00442 write_reg(RTC_REG_STATUS, reg_value);
00443 return(0);
00444 }
00445
00450 unsigned char RTC::enable_alarm1(void) {
00451 unsigned char reg_value;
00452 clear_alarm1();
00453 reg_value = read_reg(RTC_REG_CONTROL);
00454 reg_value |= RTC_A1IE;
00455 write_reg(RTC_REG_CONTROL, reg_value);
00456 return(0);
00457 }
00458
00459
00460 #define _substr_(str) { *p++ = _digit_(str##_10); *p++ = _digit_(str); }
00461
00470
00471 void RTC::localtime(char *str) {
00472 char *p;
00473 p = str;
00474 *p++ = '2';
00475 *p++ = '0';
00476 _substr_(year); *p++ = '-';
00477 _substr_(month); *p++ = '-';
00478 _substr_(day); *p++ = ' ';
00479 *p++ = _hours_10_ + '0';
00480 *p++ = _hours_ + '0';
00481 *p++ = ':';
00482 _substr_(mins); *p++ = ':';
00483 _substr_(secs);
00484 if (_rb_(hour12)) {
00485 *p++ = ' ';
00486 *p++ = _pm_p_ ? 'P' : 'A';
00487 *p++ = 'M';
00488 }
00489 *p = '\0';
00490 }
00491
00497 unsigned char RTC::get_reg(unsigned char reg) {
00498 if (reg > RTC_LAST_REG) return(0xFF);
00499 return(_regs.reg_array[reg + 1]);
00500 }
00501