Working Version of the Real Time Clock module DS1307.

Dependents:   Rtc_Ds1307_Sample TAREA_5_PROCESADORES Rtc_Ds1307_lcd_alarma Rtc_Ds1307_Reloj_con_alarma_aplazable ... more

This is my implementation of the DS1307.

I plan to add functionality which will make use of the OSC Input and which will increment the time continuously. A query to the module will then only have to be made when the MBED has been powered down.

Rtc_Ds1307.cpp

Committer:
leihen
Date:
2013-06-02
Revision:
1:64274190e842
Parent:
0:3940f0ad2ca5
Child:
2:ee81f2c5a706

File content as of revision 1:64274190e842:

/* Rtc_Ds1307.cpp */

#include "Rtc_Ds1307.h"

#define _DEBUG 1


#if (_DEBUG && !defined(TARGET_LPC11U24))
#define INFO(x, ...) std::printf("[Rtc_Ds1307 : INFO]"x"\r\n", ##__VA_ARGS__);
#define WARN(x, ...) std::printf("[Rtc_Ds1307 : WARN]"x"\r\n", ##__VA_ARGS__);
#define ERR(x, ...) std::printf("[Rtc_Ds1307 : ERR]"x"\r\n", ##__VA_ARGS__);
#else
#define INFO(x, ...)
#define WARN(x, ...)
#define ERR(x, ...)
#endif

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


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

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

bool Rtc_Ds1307::setTime(Time& time, bool start, bool thm)
{
    INFO("Setting new time : %d:%d:%d\n", time.hour, time.min, time.sec);
    
    return true;
}

bool Rtc_Ds1307::getTime(Time& time)
{
    char buffer[7];
    bool bClock_halt = false;
    bool thm = false;
    
    INFO("Getting time from RTC\n");
    if (read(0, buffer, 7) != 0) {
        //  Failed to read
        ERR("Failed to read from RTC\n");
        return false;
    }
    bClock_halt = ((buffer[0] & 128) == 128);
    thm = ((buffer[2] & 64) == 64);
    time.sec = bcdToDecimal(buffer[0]&0x7F);
    time.min = bcdToDecimal(buffer[1]);
    if (thm) {
        // in 12-hour-mode, we need to add 12 hours if PM bit is set
        time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 31 );
        if ((buffer[2] & 32) == 32)
            time.hour += 12;
    }
    else {
        time.hour = Rtc_Ds1307::bcdToDecimal( buffer[2] & 63 );
    }  
    time.wday = buffer[3]; 
    time.date = Rtc_Ds1307::bcdToDecimal( buffer[4]);
    time.mon = Rtc_Ds1307::bcdToDecimal( buffer[5]);
    time.year = Rtc_Ds1307::bcdToDecimal(buffer[6]) + 100;   //  plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900
    
    INFO("Clock is %s\n", bClock_halt ? "halted" : "running");
    return false;
}


bool Rtc_Ds1307::read(int address, char *buffer, int len)
{
    char buffer2[2] = {(char)address, 0};
    
    m_rtc->start();
    if (m_rtc->write(0xd0, buffer2, 1) != 0) {
        ERR("Failed to write register address on rtv!\n");
        m_rtc->stop();
        return false;
    }
    if (m_rtc->read(0xd0, buffer, len) != 0) {
        ERR("Failed to read register !\n");
        return false;
    }
    m_rtc->stop();
    
    INFO("Successfully read %d registers from RTC\n", len);
    return true;
}

bool Rtc_Ds1307::write(int address, char *buffer, int len)
{
    char buffer2[10];
    buffer2[0] = address&0xFF;
    for (int i = 0 ; i < len ; i++)
        buffer2[i+1] = buffer[i];

    m_rtc->start();        
    if (m_rtc->write(0xd0, buffer2, len+1) != 0) {
        ERR("Failed to write data to rtc\n");
        m_rtc->stop();
        return false;
    }
    m_rtc->stop();
    return true;
}