Skip to content
Permalink
4435a9949d
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
272 lines (228 sloc) 7.24 KB
#include "mbed.h"
#include "Rtc_Ds1307.h"
#ifndef DEBUG
//#define DEBUG
#endif
#include "debug.h"
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_rtc& time, bool start, bool thm)
{
char buffer[7];
//INFO("reading clock registers to write the new time : %d:%d:%d\n", time.hour, time.min, time.sec);
if (!read(0,buffer,7)) {
//ERR("Failed to read from RTC\n");
return false;
}
// Now update only the time part (saving the existing flags)
if (start) { buffer[0] &= 0x7F; } else { buffer[0] |= 0x80; }
buffer[0] = (buffer[0]&0x80) | (decimalToBcd(time.sec)& 0x7f);
buffer[1] = decimalToBcd(time.min);
if (thm) {
// AM PM format
buffer[2] = (buffer[2]& 196) | (time.hour>12 ? (0x20 | ((decimalToBcd(time.hour-12)))) : decimalToBcd(time.hour));
}
else {
// 24 hours format
buffer[2] = (buffer[2]& 196) | (decimalToBcd(time.hour) & 0x3F);
}
buffer[3] = time.wday;
buffer[4] = decimalToBcd(time.date);
buffer[5] = decimalToBcd(time.mon);
buffer[6] = decimalToBcd(time.year-2000);
//INFO("Writing new time and date data to RTC\n");
if (!write(0, buffer, 7) ) {
//ERR("Failed to write the data to RTC!\n");
return false;
}
return true;
}
bool Rtc_Ds1307::getTime(Time_rtc& time)
{
char buffer[7];
bool thm = false;
//INFO("Getting time from RTC\n");
if (!read(0, buffer, 7) ) {
// Failed to read
//ERR("Failed to read from RTC\n");
return false;
}
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]) + 2000; // plus hundret is because RTC is giving the years since 2000, but std c struct tm needs years since 1900
return true;
}
bool Rtc_Ds1307::startClock()
{
char strtStop;
//INFO ("Reading clock start/stop register value\n");
if (!read(0, &strtStop, 1)) {
//ERR("Failed to read clock start stop register !\n");
return false;
}
strtStop &= 0x7F;
//INFO("Writing back start/stop register value\n");
if (!write(0, &strtStop, 1)) {
//ERR("Failed to write the start stop register !\n");
return false;
}
//INFO("Start/stop register value successfully written\n");
return true;
}
bool Rtc_Ds1307::stopClock()
{
char strtStop;
//INFO ("Reading clock start/stop register value\n");
if (!read(0, &strtStop, 1)) {
//ERR("Failed to read clock start stop register !\n");
return false;
}
strtStop |= 0x80;
//INFO("Writing back start/stop register value\n");
if (!write(0, &strtStop, 1)) {
//ERR("Failed to write the start stop register !\n");
return false;
}
//INFO("Start/stop register value successfully written\n");
return true;
}
bool Rtc_Ds1307::setSquareWaveOutput(bool ena, SqwRateSelect_t rs)
{
char reg;
//INFO("Reading register value first\n");
if (!read(7,&reg, 1)) {
//ERR("Failed to read register value !\n");
return false;
}
//INFO("[Reg:0x07] = %02x\n", reg);
// preserve the OUT control bit while writing the frequency and enable bits
reg = (reg & 0x80) | (ena ? 0x10 : 0) | ((char)rs & 0x03);
//INFO("Writing back register value\n");
//INFO("[Reg:0x07] = %02x\n", reg);
if (!write(7, &reg, 1)) {
//ERR("Failed to write register value !\n");
return false;
}
//INFO("Successfully changed the square wave output.\n");
return true;
}
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;
}
RtcCls::RtcCls(PinName sda, PinName scl, PinName sqw, bool bUseSqw)
: Rtc_Ds1307(sda, scl), m_sqw(sqw), m_bUseSqw(bUseSqw), m_bAlarmEnabled(false), m_alarmfunc(NULL)
{
Time_rtc t;
// query time from device
getTime(t);
// sync the time with MBED RTC
struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
m_time = mktime(&now);
set_time(m_time);
// Only register the callback and start the SQW if requested to do so. Otherwise the system
// will use the MBED built-in RTC.
/*
if (m_bUseSqw) {
// start the wave
setSquareWaveOutput(true, RS1Hz);
// register callback from now on the time will be maintained by the square wave input
m_sqw.rise(this, &RtcCls::_callback);
}
*/
}
void RtcCls::_callback(void)
{
// INFO("Tick!");
// Simply increase the number of seconds
m_time++;
// if (m_bAlarmEnabled && (m_time == m_alarmTime)) {
// if (m_alarmfunc != NULL)
// m_alarmfunc();
// m_bAlarmEnabled = false;
// }
}
time_t RtcCls::getTime()
{
// when not using the HW support, we have to query the RTC chip. Other wise we can just return out stored value
if (!m_bUseSqw) {
Time_rtc t;
getTime(t);
struct tm now = {t.sec, t.min, t.hour, t.date, t.mon-1, t.year-1900};
m_time = mktime(&now);
//INFO("getting time %02d.%02d.%04d %02d:%02d:%02d Ticks=%08lx", t.date, t.mon, t.year, t.hour, t.min, t.sec, m_time);
}
else {
//INFO("getting time Ticks=%08lx", m_time);
}
return m_time;
}
void RtcCls::setTime(time_t t)
{
Time_rtc tim;
struct tm *now;
now = localtime(&t);
tim.sec = now->tm_sec;
tim.min = now->tm_min;
tim.hour = now->tm_hour;
tim.date = now->tm_mday;
tim.mon = now->tm_mon+1;
tim.year = now->tm_year + 1900;
tim.wday = now->tm_wday +1;
setTime( tim, true, true);
set_time(t);
}