Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: vfd_modular_clock_mbed
Diff: ds1307.cpp
- Revision:
- 0:1602fdac44ec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ds1307.cpp Wed Feb 11 05:30:48 2015 +0000 @@ -0,0 +1,230 @@ +/* + * RTC library - mbed + * (C) 2011-15 Akafugu Corporation + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + */ + +#include "ds1307.h" + +#define DS1307_SLAVE_ADDR 0xD0 + +DS1307::DS1307(I2C& i2c) + : RTC() + , m_i2c(i2c) +{ + //m_i2c.frequency(100000); +} + +void DS1307::begin() +{ +} + + +time_t DS1307::time() +{ + return m_time; +} + +struct tm* DS1307::getTime() +{ + char rtc[7]; + + rtc[0] = 0; // second register, 0 + int w = m_i2c.write(DS1307_SLAVE_ADDR, rtc, 1); + int r = m_i2c.read(DS1307_SLAVE_ADDR, rtc, 7); + + // Clear clock halt bit from read data + //rtc[0] &= ~(_BV(CH_BIT)); + + m_tm.tm_sec = bcd2dec(rtc[0]); + m_tm.tm_min = bcd2dec(rtc[1]); + m_tm.tm_hour = bcd2dec(rtc[2]); + m_tm.tm_wday = bcd2dec(rtc[3])-1; + m_tm.tm_mday = bcd2dec(rtc[4]); + m_tm.tm_mon = bcd2dec(rtc[5])-1; // tm_mon is 0-11 + m_tm.tm_year = bcd2dec(rtc[6]); + + return &m_tm; +} + +void DS1307::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + char rtc[3]; + + rtc[0] = 0; // second register, 0 + int w = m_i2c.write(DS1307_SLAVE_ADDR, rtc, 1); + int r = m_i2c.read(DS1307_SLAVE_ADDR, rtc, 3); + + // Clear clock halt bit from read data + //rtc[0] &= ~(_BV(CH_BIT)); + + if (sec) *sec = bcd2dec(rtc[0]); + if (min) *min = bcd2dec(rtc[1]); + if (hour) *hour = bcd2dec(rtc[2]); +} + +void DS1307::setTime(time_t t) +{ + struct tm * timeinfo; + timeinfo = localtime (&t); + setTime(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); +} + +void DS1307::setTime(uint8_t hour, uint8_t min, uint8_t sec) +{ + write_byte(dec2bcd(sec), 0); + write_byte(dec2bcd(min), 1); + write_byte(dec2bcd(hour), 2); +} + +void DS1307::setTime(struct tm* tm) +{ + write_byte(dec2bcd(tm->tm_sec), 0); + write_byte(dec2bcd(tm->tm_min), 1); + write_byte(dec2bcd(tm->tm_hour), 2); + write_byte(dec2bcd(tm->tm_wday+1), 3); + write_byte(dec2bcd(tm->tm_mday), 4); + write_byte(dec2bcd(tm->tm_mon+1), 5); + write_byte(dec2bcd(tm->tm_year), 6); +} + +void DS1307::setAlarm(time_t t) +{ + struct tm * timeinfo; + timeinfo = localtime (&t); + setAlarm(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); +} + +void DS1307::setAlarm(uint8_t hour, uint8_t min, uint8_t sec) +{ + writeRam(0, hour); // hour + writeRam(1, min); // minute + writeRam(2, sec); // sec +} + +struct tm* DS1307::getAlarm(void) +{ + struct tm * timeinfo = getTime(); + uint8_t hour, min, sec; + + getAlarm(&hour, &min, &sec); + timeinfo->tm_hour = hour; + timeinfo->tm_min = min; + timeinfo->tm_sec = sec; + return timeinfo; +} + +void DS1307::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + if (hour) *hour = readRam(0); + if (min) *min = readRam(1); + if (sec) *sec = readRam(2); +} + +bool DS1307::checkAlarm(void) +{ + uint8_t hour = readRam(0); + uint8_t min = readRam(1); + uint8_t sec = readRam(2); + + uint8_t cur_hour, cur_min, cur_sec; + getTime(&cur_hour, &cur_min, &cur_sec); + + if (cur_hour == hour && cur_min == min && cur_sec == sec) + return true; + return false; +} + +void DS1307::SQWEnable(bool enable) +{ + uint8_t offset = 0x07; + uint8_t control = read_byte(offset); // read control register + if (enable) + control |= 0x10; // set SQWE to 1 + else + control &= ~0x10; // set SQWE to 0 + + // write control back + write_byte(control, offset); +} + +void DS1307::SQWSetFreq(enum RTC_SQW_FREQ freq) +{ + uint8_t offset = 0x07; + uint8_t control = read_byte(offset); // read control register + + control &= ~0x03; // Set to 0 + control |= freq; // Set freq bitmask + + // write control back + write_byte(control, offset); +} + +#define CH_BIT (1 << 7) // clock halt bit + +void DS1307::runClock(bool run) +{ + uint8_t b = read_byte(0x0); + + if (run) + b &= ~(CH_BIT); // clear bit + else + b |= CH_BIT; // set bit + + write_byte(b, 0x0); +} + +bool DS1307::isClockRunning(void) +{ + uint8_t b = read_byte(0x0); + + if (b & CH_BIT) return false; + return true; +} + +// --------- // + + +uint8_t DS1307::read_byte(uint8_t offset) +{ + char buf[1]; + buf[0] = offset; + + int w = m_i2c.write(DS1307_SLAVE_ADDR, buf, 1); + int r = m_i2c.read(DS1307_SLAVE_ADDR, buf, 1); + //error = ((w!=0) || (r!=0)); + + return buf[0]; +} + +void DS1307::write_byte(uint8_t b, uint8_t offset) +{ + char buf[2]; + buf[0] = offset; + buf[1] = b; + + int w = m_i2c.write(DS1307_SLAVE_ADDR, buf, 2); + //error=(w!=0); +} + + +#define DS1307_SRAM_ADDR 0x08 + +void DS1307::writeRam(uint8_t addr, uint8_t data) +{ + write_byte(data, DS1307_SRAM_ADDR + addr); +} + +uint8_t DS1307::readRam(uint8_t addr) +{ + return read_byte(DS1307_SRAM_ADDR + addr); +}