Akafugu / RTC

Dependents:   vfd_modular_clock_mbed

Revision:
0:1602fdac44ec
diff -r 000000000000 -r 1602fdac44ec ds1307.cpp
--- /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);
+}