RealTimeClock RTC-8564 library.

Dependents:   LcdClock

Rtc8564.cpp

Committer:
togayan
Date:
2014-02-22
Revision:
0:ebc5f6d47cf5

File content as of revision 0:ebc5f6d47cf5:

#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();
}