Wiblocks --- RTC

RTC/RTC.cpp

00001 // RTC clock library for the NB1A
00002 
00003 // DS1337 IC
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); // 16 register bytes + ADDR
00106   delay(10);
00107   while(twi_busy_p());
00108   // retrieve the data bytes from the twi buffer
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); // addr + reg
00131   while(twi_busy_p());
00132   // retrieve the data bytes from the twi buffer
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 // breaks a binary value into two BCD digits
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 

Generated on Sun Dec 13 16:47:17 2009 by  doxygen 1.6.1