M41T62 is a serial real-time clock (RTC) made by STMicroelectronics.

Dependents:   LPC1114_data_logger Check_external_RTC LPC1114_barometer_with_data_logging

Revision:
1:9d7702a887d3
Parent:
0:2919f8bd90f3
Child:
3:41c351da2fdf
diff -r 2919f8bd90f3 -r 9d7702a887d3 m41t62_rtc.cpp
--- a/m41t62_rtc.cpp	Sat Jun 21 04:37:56 2014 +0000
+++ b/m41t62_rtc.cpp	Sun Jun 22 01:45:49 2014 +0000
@@ -6,7 +6,7 @@
  *  http://www.page.sannet.ne.jp/kenjia/index.html
  *  http://mbed.org/users/kenjiArai/
  *      Created: June      21st, 2014
- *      Revised: June      21st, 2014
+ *      Revised: June      22nd, 2014
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
@@ -17,12 +17,12 @@
 /*
  *---------------- REFERENCE ----------------------------------------------------------------------
  *  http://www.st-japan.co.jp/web/jp/catalog/sense_power/FM151/CL1410/SC403/PF82507
+ *  http://strawberry-linux.com/catalog/items?code=12062
  */
 
 #include "mbed.h"
 #include "m41t62_rtc.h"
 
-
 // Register definition
 #define M41T62_REG_SSEC 0
 #define M41T62_REG_SEC  1
@@ -37,17 +37,52 @@
 #define M41T62_REG_ALARM_HOUR   0xc
 #define M41T62_REG_ALARM_MIN    0xd
 #define M41T62_REG_ALARM_SEC    0xe
-#define M41T62_REG_FLAGS    0xf
+#define M41T62_REG_FLAGS        0xf
 
-M41T62::M41T62 (PinName p_sda, PinName p_scl) : i2c(p_sda, p_scl) {
+M41T62::M41T62 (PinName p_sda, PinName p_scl) : i2c(p_sda, p_scl){
+    M41T62_addr = M41T62ADDR;
+}
+
+M41T62::M41T62 (I2C& p_i2c) : i2c(p_i2c){ 
     M41T62_addr = M41T62ADDR;
 }
 
-M41T62::M41T62 (I2C& p_i2c) : i2c(p_i2c) { 
-    M41T62_addr = M41T62ADDR;
+void M41T62::read_rtc_std (tm *t){
+rtc_time time;
+
+    read_rtc_direct(&time);
+    t->tm_sec  = time.rtc_seconds;
+    t->tm_min  = time.rtc_minutes;
+    t->tm_hour = time.rtc_hours;
+    t->tm_mday = time.rtc_date;
+    if ( time.rtc_weekday == RTC_Wk_Sunday){
+        t->tm_wday = 0; // Sun is not 7 but 0
+    } else {
+        t->tm_wday = time.rtc_weekday;
+    }
+    t->tm_mon  = time.rtc_month - 1;
+    t->tm_year = time.rtc_year_raw + 100;
+    t->tm_isdst= 0;
 }
 
-void M41T62::read_rtc (rtc_time *tm) {
+void M41T62::write_rtc_std (tm *t){
+rtc_time time;
+  
+    time.rtc_seconds  = t->tm_sec;
+    time.rtc_minutes  = t->tm_min;
+    time.rtc_hours    = t->tm_hour;
+    time.rtc_date     = t->tm_mday;
+    if ( t->tm_wday == 0){
+        time.rtc_weekday = RTC_Wk_Sunday;
+    } else {
+        time.rtc_weekday = t->tm_wday;
+    }
+    time.rtc_month    = t->tm_mon + 1;
+    time.rtc_year_raw = t->tm_year - 100;
+    write_rtc_direct(&time);
+}
+
+void M41T62::read_rtc_direct (rtc_time *tm){
 uint8_t eep_dt;
 
     eep_dt = M41T62_REG_SSEC;
@@ -59,10 +94,11 @@
     tm->rtc_date    = bcd2bin(rtc_buf[M41T62_REG_DAY]  & 0x3f);
     tm->rtc_weekday = rtc_buf[M41T62_REG_WDAY] & 0x07;
     tm->rtc_month   = bcd2bin(rtc_buf[M41T62_REG_MON]  & 0x1f);
-    tm->rtc_year    = bcd2bin(rtc_buf[M41T62_REG_YEAR]) + 100 + 1900;
+    tm->rtc_year_raw= bcd2bin(rtc_buf[M41T62_REG_YEAR]);
+    tm->rtc_year = tm->rtc_year_raw + 100 + 1900;
 }
 
-void M41T62::write_rtc (rtc_time *tm) {
+void M41T62::write_rtc_direct (rtc_time *tm){
 uint8_t eep_dt;
 
     eep_dt = M41T62_REG_SSEC;
@@ -70,7 +106,7 @@
     i2c_read_n_bytes((int)M41T62_addr, (char *)rtc_buf, 8);  
     rtc_buf[0] = M41T62_REG_SSEC;
     rtc_buf[M41T62_REG_SSEC + 1] = 0;
-    rtc_buf[M41T62_REG_YEAR + 1] = bin2bcd((uint8_t)(tm->rtc_year % 100)); 
+    rtc_buf[M41T62_REG_YEAR + 1] = bin2bcd(tm->rtc_year_raw); 
     rtc_buf[M41T62_REG_MON  + 1] = bin2bcd(tm->rtc_month)   | (rtc_buf[M41T62_REG_MON]  & ~0x1f);
     rtc_buf[M41T62_REG_DAY  + 1] = bin2bcd(tm->rtc_date)    | (rtc_buf[M41T62_REG_DAY]  & ~0x3f);
     rtc_buf[M41T62_REG_WDAY + 1] = (tm->rtc_weekday & 0x07) | (rtc_buf[M41T62_REG_WDAY] & ~0x07);
@@ -80,29 +116,44 @@
     i2c_write_n_bytes((int)M41T62_addr, (char *)rtc_buf, 9);
 }
 
-void M41T62::set_sq_wave (uint8_t sqw_dt) {
+void M41T62::set_sq_wave (uint8_t sqw_dt){
 uint8_t eep_dt[2];
 
+    // set SQW frequency
     eep_dt[0] = M41T62_REG_WDAY;
     i2c_write_n_bytes((int)M41T62_addr, (char *)eep_dt, 1);
     i2c_read_n_bytes((int)M41T62_addr, (char *)eep_dt, 1);
     eep_dt[1] = (eep_dt[0] & 0x07) | (sqw_dt << 4);
     eep_dt[0] = M41T62_REG_WDAY;
     i2c_write_n_bytes((int)M41T62_addr, (char *)rtc_buf, 2);
+    // set or clear SQWE
+    eep_dt[0] = M41T62_REG_ALARM_MON;
+    i2c_write_n_bytes((int)M41T62_addr, (char *)eep_dt, 1);
+    i2c_read_n_bytes((int)M41T62_addr, (char *)eep_dt, 1);
+    eep_dt[1] = (eep_dt[0] & 0x07) | (sqw_dt << 4);
+    eep_dt[0] = M41T62_REG_WDAY;
+    i2c_write_n_bytes((int)M41T62_addr, (char *)rtc_buf, 2);
+    if (sqw_dt == RTC_SQW_NONE){    // Clear SQWE
+        eep_dt[1] = eep_dt[0] & 0xbf;
+    } else {                        // Set SQWE
+        eep_dt[1] = eep_dt[0] | 0x40;
+    }
+    eep_dt[0] = M41T62_REG_ALARM_MON;
+    i2c_write_n_bytes((int)M41T62_addr, (char *)rtc_buf, 2);
 }
 
-void M41T62::i2c_read_n_bytes (int addr, char *dt, int n) {
+void M41T62::i2c_read_n_bytes (int addr, char *dt, int n){
     i2c.read(addr, dt, n);
 }
 
-void M41T62::i2c_write_n_bytes (int addr, char *dt, int n) {
+void M41T62::i2c_write_n_bytes (int addr, char *dt, int n){
     i2c.write(addr, dt, n);
 }
 
 uint8_t M41T62::bin2bcd (uint8_t dt){
 uint8_t bcdhigh = 0;
   
-    while (dt >= 10)  {
+    while (dt >= 10){
         bcdhigh++;
         dt -= 10;
     }