Dallas DS1307 real-time clock minimalistic driver

Dependents:   testing_RTC_OneWire EMIRv2

DS1307.cpp

Committer:
alpov
Date:
2014-04-25
Revision:
0:f29e45a25cba
Child:
1:60383faa35a9

File content as of revision 0:f29e45a25cba:

#include "mbed.h"
#include "DS1307.h"


const char *DS1307::m_weekDays[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

#define DS1307_ADDR 0xd0


DS1307::DS1307(PinName sda, PinName scl)
{
    // create a new I2C object
    m_rtc = new I2C(sda, scl);
    if (m_rtc == NULL) error("DS1307");
        
    // set the frequency to standard 100kHz
    m_rtc->frequency(100000);
}


DS1307::~DS1307()
{
    if (m_rtc != NULL) delete m_rtc;
}


bool DS1307::read(int address, char *buffer, int len)
{
    char data[1] = { (char)address };

    if (m_rtc->write(DS1307_ADDR, data, 1) != 0) return false;
    if (m_rtc->read(DS1307_ADDR, buffer, len) != 0) return false;

    return true;
}


bool DS1307::write(int address, char *buffer, int len)
{
    char data[9] = { (char)address };

    if (len > 8) return false;
    memcpy(&data[1], buffer, len);

    if (m_rtc->write(DS1307_ADDR, data, len + 1) != 0) return false;
    
    return true;
}


time_t DS1307::getNow()
{
    struct tm now;
    char buffer[7];
    
    if (!read(0, buffer, 7)) return 0;
    if (!(buffer[2] & 0x40)) return 0; // 12-hour format not supported
    now.tm_sec = bcdToDecimal(buffer[0] & 0x7F);
    now.tm_min = bcdToDecimal(buffer[1]);
    now.tm_hour = bcdToDecimal(buffer[2] & 0x3F);
    now.tm_wday = buffer[3]; 
    now.tm_mday = bcdToDecimal(buffer[4]);
    now.tm_mon = bcdToDecimal(buffer[5]) - 1;
    now.tm_year = bcdToDecimal(buffer[6]) + 2000 - 1900;
    
    return mktime(&now);
}


bool DS1307::setNow(time_t t)
{
    struct tm *now;
    char buffer[8];

    now = localtime(&t);

    buffer[0] = decimalToBcd(now->tm_sec) & 0x7f; // CH = 0
    buffer[1] = decimalToBcd(now->tm_min);
    buffer[2] = 0x40 | (decimalToBcd(now->tm_hour) & 0x3F); // 24-hour format
    buffer[3] = now->tm_wday + 1;
    buffer[4] = decimalToBcd(now->tm_mday);
    buffer[5] = decimalToBcd(now->tm_mon+1);
    buffer[6] = decimalToBcd(now->tm_year + 1900 - 2000);
    buffer[7] = 0x00; // OUT = 0
    if (!write(0, buffer, 8)) return false;

    return true;
}