00001
00002
00003
00004
00005
00006 #include "RTC.h"
00007 #if defined(ARDUINO) && (ARDUINO >= 100)
00008 #include "Arduino.h"
00009 #else
00010 #endif
00011
00012 extern "C"
00013 {
00014 #if defined(ARDUINO) && (ARDUINO >= 100)
00015 #else
00016 #include <inttypes.h>
00017 #include "WConstants.h"
00018 #endif
00019 #include "TWI.h"
00020 }
00021
00032
00039
00040 RTC::RTC() {
00041
00042 };
00043
00044 #define _rtc_reg_p_(reg) (reg <= RTC_LAST_REG ? 1 : 0)
00045
00054 char RTC::write_reg(unsigned char reg, unsigned char v) {
00055 if (!_rtc_reg_p_(reg)) return(-1);
00056 _buf[0] = _i2c_wr_address;
00057 _buf[1] = reg;
00058 _buf[2] = v;
00059 twi_transmit(_buf, 3);
00060 return(0);
00061 }
00062
00072 char RTC::write_regs(unsigned char reg, unsigned char *v, unsigned char n) {
00073 unsigned char *p;
00074 unsigned char i;
00075 if (!_rtc_reg_p_(reg)) return(-1);
00076 if (n > 16) return(-1);
00077 _buf[0] = _i2c_wr_address;
00078 _buf[1] = reg;
00079 p = v;
00080 for (i = 0; i < n; i++) _buf[i + 2] = *p++;
00081 twi_transmit(_buf, n + 2);
00082 return(0);
00083 }
00084
00092
00093 char RTC::write_reg_ptr(unsigned char reg) {
00094 if (!_rtc_reg_p_(reg)) return(-1);
00095 _buf[0] = _i2c_wr_address;
00096 _buf[1] = reg;
00097 twi_transmit(_buf, 2);
00098 return(0);
00099 }
00100
00106
00107 char RTC::read_regs() {
00108 unsigned char i;
00109 write_reg_ptr(0);
00110 _buf[0] = _i2c_rd_address;
00111 twi_transmit(_buf, 17);
00112 delay(10);
00113 while(twi_busy_p());
00114
00115 if (!twi_status_reg.last_trans_ok) return(-1);
00116 twi_get_data(_regs.reg_array, 17);
00117 return(0);
00118 }
00119
00120
00127
00128 unsigned char RTC::read_reg(unsigned char reg) {
00129 unsigned char i;
00130 unsigned char data[1];
00131 if (!_rtc_reg_p_(reg)) return(-2);
00132 write_reg_ptr(reg);
00133 _buf[0] = _i2c_rd_address;
00134 _buf[1] = reg;
00135 delay(10);
00136 twi_transmit(_buf, 2);
00137 while(twi_busy_p());
00138
00139 if (!twi_status_reg.last_trans_ok) return(-1);
00140 twi_get_data(data, 2);
00141 return(data[1]);
00142 }
00143
00144
00145 #define PM_BIT 0x02
00146 #define _rb_(name) (_regs.reg_bits.name) ///< register bits for <B>name</B>
00147 #define _digit_(name) (_rb_(name) + '0') ///< ASCII digit
00148 #define _hours_10_ ( _rb_(hour12) ? (_rb_(hours_10) & 0x01) : _rb_(hours_10)) ///< left digit of hours
00149 #define _hours_ ( _rb_(hours) )
00150 #define _pm_p_ (_rb_(hours_10) & PM_BIT)
00151
00155 unsigned char RTC::get_secs() { return(_rb_(secs_10) * 10 + _rb_(secs)); }
00159 unsigned char RTC::get_mins() { return(_rb_(mins_10) * 10 + _rb_(mins)); }
00163 unsigned char RTC::get_hours() { return(_hours_10_ * 10 + _hours_); }
00167 unsigned char RTC::get_day() { return(_rb_(day_10) * 10 + _rb_(day)); }
00171 unsigned char RTC::get_month() { return(_rb_(month_10) * 10 + _rb_(month)); }
00175 unsigned int RTC::get_year() { return(2000 + _rb_(year_10) * 10 + _rb_(year)); }
00176
00177
00178
00179 #define _break_(x, x10, x1) { x1 = x % 10; x10 = (unsigned char)((x - x1) / 10); }
00180
00181
00185 #define valid_year_p(y) (((y > 2099) || (y < 2000)) ? 0 : 1)
00186 #define valid_month_p(m) (((m > 12) || (m < 1)) ? 0 : 1)
00187 #define valid_day_p(d) (((d > 31) || (d < 1)) ? 0 : 1)
00188
00189
00196 unsigned char RTC::set_year(unsigned int year) {
00197 unsigned char y10;
00198 unsigned char y1;
00199 if (year > 2099) return(-1);
00200 if (year < 2000) return(-1);
00201 year -= 2000;
00202 _break_(year, y10, y1);
00203 write_reg(RTC_REG_YEAR, (y10 << 4) | y1);
00204 return(0);
00205 }
00206
00213 unsigned char RTC::set_month(unsigned char month) {
00214 unsigned char m10, m1;
00215 if (month > 12) return(-1);
00216 if (month < 1) return(-1);
00217 _break_(month, m10, m1);
00218 write_reg(RTC_REG_MONTH, (m10 << 4) | m1);
00219 return(0);
00220 }
00221
00228 unsigned char RTC::set_day(unsigned char day) {
00229 unsigned char d10, d1;
00230 if (day > 31) return(-1);
00231 if (day < 1) return(-1);
00232 _break_(day, d10, d1);
00233 write_reg(RTC_REG_DAY, (d10 << 4) | d1);
00234 return(0);
00235 }
00236
00246 unsigned char RTC::set_date(unsigned int year, unsigned char month,
00247 unsigned char day) {
00248 if (set_year(year)) return(-1);
00249 if (set_month(month)) return(-1);
00250 if (set_day(day)) return(-1);
00251 return(0);
00252 }
00253
00254
00261 unsigned char RTC::set_secs(unsigned char secs) {
00262 unsigned char s10, s1;
00263 if (secs > 59) return(-1);
00264 _break_(secs, s10, s1);
00265 write_reg(RTC_REG_SECS, (s10 << 4) | s1);
00266 return(0);
00267 }
00268
00275 unsigned char RTC::set_mins(unsigned char mins) {
00276 unsigned char m10, m1;
00277 if (mins > 59) return(-1);
00278 _break_(mins, m10, m1);
00279 write_reg(RTC_REG_MINS, (m10 << 4) | m1);
00280 return(0);
00281 }
00282
00284 union hours_reg {
00285 struct {
00286 unsigned hours : 4;
00287 unsigned hours_10 : 1;
00288 unsigned pm : 1;
00289 unsigned hour12 : 1;
00290 unsigned UNUSED : 1;
00291 } _bits12;
00292 struct {
00293 unsigned hours : 4;
00294 unsigned hours_10 : 2;
00295 unsigned hour12 : 1;
00296 unsigned UNUSED : 1;
00297 } _bits24;
00298 unsigned char _byte;
00299 };
00300
00302
00306
00312
00313 unsigned char RTC::set_hours12(unsigned char hours, unsigned char pm_p) {
00314 union hours_reg reg;
00315 if (hours > 12) return(-1);
00316 reg._bits12.hour12 = 1;
00317 reg._bits12.pm = pm_p ? 1 : 0;
00318 _break_(hours, reg._bits12.hours_10, reg._bits12.hours);
00319 write_reg(RTC_REG_HOURS, reg._byte);
00320 return(0);
00321 }
00322
00328
00329 unsigned char RTC::set_hours(unsigned char hours) {
00330 union hours_reg reg;
00331 if (hours > 23) return(-1);
00332 reg._bits24.hour12 = 0;
00333 _break_(hours, reg._bits24.hours_10, reg._bits24.hours);
00334 write_reg(RTC_REG_HOURS, reg._byte);
00335 return(0);
00336 }
00337
00341
00342 unsigned char RTC::set_time(unsigned char hours, unsigned char mins,
00343 unsigned char secs) {
00344 if (set_hours(hours)) return(-1);
00345 if (set_mins(mins)) return(-1);
00346 if (set_secs(secs)) return(-1);
00347 return(0);
00348 }
00349
00357
00358 unsigned char RTC::set_time12(unsigned char hours,
00359 unsigned char mins,
00360 unsigned char secs,
00361 unsigned char pm_p) {
00362 if (set_hours12(hours, pm_p)) return(-1);
00363 if (set_mins(mins)) return(-1);
00364 if (set_secs(secs)) return(-1);
00365 return(0);
00366 }
00367
00368 #define _ar_(n) alarm_reg._bits.n
00369 #define _a1_bits_(dy, m4, m3, m2, m1) { _ar_(a1_dy) = dy; \
00370 _ar_(a1m4) = m4; _ar_(a1m3) = m3; \
00371 _ar_(a1m2) = m2; _ar_(a1m1) = m1; }
00372
00373
00396 unsigned char RTC::set_alarm1(unsigned char mode, unsigned char day_or_dow,
00397 unsigned char hours, unsigned char mins,
00398 unsigned char secs) {
00399 union {
00400 struct {
00401 unsigned a1_secs : 4;
00402 unsigned a1_secs_10 : 3;
00403 unsigned a1m1 : 1;
00404
00405 unsigned a1_mins : 4;
00406 unsigned a1_mins_10 : 3;
00407 unsigned a1m2 : 1;
00408
00409 unsigned a1_hours : 4;
00410 unsigned a1_hours_10 : 2;
00411 unsigned a1_hour12 : 1;
00412 unsigned a1m3 : 1;
00413
00414 unsigned a1_day : 4;
00415 unsigned a1_day_10 : 2;
00416 unsigned a1_dy : 1;
00417 unsigned a1m4 : 1;
00418 } _bits;
00419 unsigned char _bytes[4];
00420 } alarm_reg = { 0, 0, 0, 0 };
00421 switch(mode) {
00422 case RTC_ALARM1_MODE1: _a1_bits_(0, 1, 1, 1, 1); break;
00423 case RTC_ALARM1_MODE2: _a1_bits_(0, 1, 1, 1, 0); break;
00424 case RTC_ALARM1_MODE3: _a1_bits_(0, 1, 1, 0, 0); break;
00425 case RTC_ALARM1_MODE4: _a1_bits_(0, 1, 0, 0, 0); break;
00426 case RTC_ALARM1_MODE5: _a1_bits_(0, 0, 0, 0, 0); break;
00427 case RTC_ALARM1_MODE6: _a1_bits_(1, 0, 0, 0, 0); break;
00428 default: _a1_bits_(0, 0, 0, 0, 0); break;
00429 }
00430 _break_(secs, alarm_reg._bits.a1_secs_10, alarm_reg._bits.a1_secs);
00431 _break_(mins, alarm_reg._bits.a1_mins_10, alarm_reg._bits.a1_mins);
00432 _break_(hours, alarm_reg._bits.a1_hours_10, alarm_reg._bits.a1_hours);
00433 _break_(day_or_dow, alarm_reg._bits.a1_day_10, alarm_reg._bits.a1_day);
00434
00435 write_regs(RTC_REG_A1SECS, alarm_reg._bytes, 4);
00436
00437 return(0);
00438 }
00439
00444 unsigned char RTC::clear_alarm1(void) {
00445 unsigned char reg_value;
00446 reg_value = read_reg(RTC_REG_STATUS);
00447 reg_value &= ~RTC_A1F;
00448 write_reg(RTC_REG_STATUS, reg_value);
00449 return(0);
00450 }
00451
00456 unsigned char RTC::enable_alarm1(void) {
00457 unsigned char reg_value;
00458 clear_alarm1();
00459 reg_value = read_reg(RTC_REG_CONTROL);
00460 reg_value |= RTC_A1IE;
00461 write_reg(RTC_REG_CONTROL, reg_value);
00462 return(0);
00463 }
00464
00465
00466 #define _substr_(str) { *p++ = _digit_(str##_10); *p++ = _digit_(str); }
00467
00476
00477 void RTC::localtime(char *str) {
00478 char *p;
00479 p = str;
00480 *p++ = '2';
00481 *p++ = '0';
00482 _substr_(year); *p++ = '-';
00483 _substr_(month); *p++ = '-';
00484 _substr_(day); *p++ = ' ';
00485 *p++ = _hours_10_ + '0';
00486 *p++ = _hours_ + '0';
00487 *p++ = ':';
00488 _substr_(mins); *p++ = ':';
00489 _substr_(secs);
00490 if (_rb_(hour12)) {
00491 *p++ = ' ';
00492 *p++ = _pm_p_ ? 'P' : 'A';
00493 *p++ = 'M';
00494 }
00495 *p = '\0';
00496 }
00497
00503 unsigned char RTC::get_reg(unsigned char reg) {
00504 if (reg > RTC_LAST_REG) return(0xFF);
00505 return(_regs.reg_array[reg + 1]);
00506 }
00507