RealTimeClock RTC-8564 library.

Dependents:   LcdClock

Revision:
0:ebc5f6d47cf5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Rtc8564.cpp	Sat Feb 22 23:58:05 2014 +0000
@@ -0,0 +1,108 @@
+#include "Rtc8564.h"
+
+#define RTC_ADDR 0xA2
+
+static uint8_t bcdToUint8(char bcd)
+{
+    uint8_t ret = bcd & 0x0F;
+    ret += ((bcd >> 4) & 0x0F) * 10;
+    return ret;
+}
+
+static char uint8ToBcd(uint8_t uchar)
+{
+    char ret = ((uchar / 10) << 4);
+    ret += (uchar % 10);
+    return ret;
+}
+
+Rtc8564::Rtc8564(I2C& i2c, PinName clockIn, PinMode pull)
+    :m_i2c(i2c),
+     m_clockIn(clockIn),
+     m_clockFp()
+{
+    m_clockIn.mode(pull);
+}
+
+void Rtc8564::initialize()
+{
+    if(checkVoltageLow()) {
+        struct tm dateTime;
+        dateTime.tm_year   = 100; // 2000-01-01
+        dateTime.tm_mon    = 0;
+        dateTime.tm_mday   = 1;
+        dateTime.tm_wday   = 6; // Saturday
+        dateTime.tm_hour   = 0; // 00:00:00
+        dateTime.tm_min    = 0;
+        dateTime.tm_sec    = 0;
+        dateTime.tm_isdst  = -1;
+        setTime(&dateTime);
+    }
+
+    char cmds[2] = {0};
+    cmds[0] = 0x0D;
+    cmds[1] = 0x03;
+    m_i2c.write(RTC_ADDR, cmds, 2);
+
+    m_clockIn.rise(this, &Rtc8564::clockRise);
+
+    cmds[0] = 0x0D;
+    cmds[1] = 0x83;
+    m_i2c.write(RTC_ADDR, cmds, 2);
+}
+
+void Rtc8564::setTime(struct tm* dateTime)
+{
+    char cmds[10] = {0};
+    cmds[0] = 0x00;
+    cmds[1] = 0x20;
+    cmds[2] = 0;
+    cmds[3] = uint8ToBcd(dateTime->tm_sec);        //second
+    cmds[4] = uint8ToBcd(dateTime->tm_min);        //minute
+    cmds[5] = uint8ToBcd(dateTime->tm_hour);       //hour
+    cmds[6] = uint8ToBcd(dateTime->tm_mday);       //day
+    cmds[7] = dateTime->tm_wday;                   //weekday
+    cmds[8] = uint8ToBcd(dateTime->tm_mon + 1);    //month
+    cmds[9] = uint8ToBcd(dateTime->tm_year % 100); //year
+    m_i2c.write(RTC_ADDR, cmds, 10);
+
+    cmds[0] = 0x00;
+    cmds[1] = 0x0;
+    m_i2c.write(RTC_ADDR, cmds, 2);
+}
+
+void Rtc8564::getTime(struct tm* dateTime)
+{
+    char cmds[7] = {0x02};
+
+    m_i2c.write(RTC_ADDR, cmds, 1);
+    m_i2c.read(RTC_ADDR, cmds, 7);
+
+    dateTime->tm_sec  = bcdToUint8(cmds[0] & 0x7F);
+    dateTime->tm_min  = bcdToUint8(cmds[1] & 0x7F);
+    dateTime->tm_hour = bcdToUint8(cmds[2] & 0x3F);
+    dateTime->tm_mday = bcdToUint8(cmds[3] & 0x3F);
+    dateTime->tm_wday = bcdToUint8(cmds[4] & 0x07);
+    dateTime->tm_mon  = bcdToUint8(cmds[5] & 0x1F) - 1;
+    dateTime->tm_year = bcdToUint8(cmds[6]) + 100;
+}
+
+void Rtc8564::clock(void (*fptr)(void))
+{
+    m_clockFp.attach(fptr);
+}
+
+bool Rtc8564::checkVoltageLow()
+{
+    char cmds[1] = {0x02};
+
+    m_i2c.write(RTC_ADDR, cmds, 1);
+    m_i2c.read(RTC_ADDR, cmds, 1);
+
+    return ((cmds[0] & 0x80) != 0);
+}
+
+void Rtc8564::clockRise()
+{
+    m_clockFp.call();
+}