From a9467469600d68ce7e386b2ce0a85e2e4c50870a Mon Sep 17 00:00:00 2001 From: BlackMark Date: Sat, 16 May 2020 17:59:38 +0200 Subject: [PATCH] Remove legacy rtc lib --- rtc.cpp | 617 -------------------------------------------------------- rtc.h | 106 ---------- 2 files changed, 723 deletions(-) delete mode 100644 rtc.cpp delete mode 100644 rtc.h diff --git a/rtc.cpp b/rtc.cpp deleted file mode 100644 index f545dd6..0000000 --- a/rtc.cpp +++ /dev/null @@ -1,617 +0,0 @@ -/* - * DS RTC Library: DS1307 and DS3231 driver library - * (C) 2011 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. - * - */ - -/* - * DS1307 register map - * - * 00h-06h: seconds, minutes, hours, day-of-week, date, month, year (all in BCD) - * bit 7 of seconds enables/disables clock - * bit 6 of hours toggles 12/24h mode (1 for 12h, 0 for 24h) - * when 12h mode is selected bit 5 is high for PM, low for AM - * 07h: control - * bit7: OUT - * bit6: 0 - * bit5: 0 - * bit4: SQWE - * bit3: 0 - * bit2: 0 - * bit1: RS0 - * bit0: RS1 - * 08h-3fh: 56 bytes of SRAM - * - * DS3231 register map - * - * 00h-06h: seconds, minutes, hours, day-of-week, date, month, year (all in BCD) - * bit 7 should be set to zero: The DS3231 clock is always running - * 07h: A1M1 Alarm 1 seconds - * 08h: A1M2 Alarm 1 minutes - * 09h: A1M3 Alarm 1 hour (bit6 is am/pm flag in 12h mode) - * 0ah: A1M4 Alarm 1 day/date (bit6: 1 for day, 0 for date) - * 0bh: A2M2 Alarm 2 minutes - * 0ch: A2M3 Alarm 2 hour (bit6 is am/pm flag in 12h mode) - * 0dh: A2M4 Alarm 2 day/data (bit6: 1 for day, 0 for date) - * - * 0eh: control - * bit7: !EOSC - * bit6: BBSQW - * bit5: CONV - * bit4: RS2 - * bit3: RS1 - * bit2: INTCN - * bit1: A2IE - * bit0: A1IE - * 0fh: control/status - * bit7: OSF - * bit6: 0 - * bit5: 0 - * bit4: 0 - * bit3: EN32kHz - * bit2: BSY - * bit1: A2F alarm 2 flag - * bit0: A1F alarm 1 flag - * 10h: aging offset (signed) - * 11h: MSB of temp (signed) - * 12h: LSB of temp in bits 7 and 6 (0.25 degrees for each 00, 01, 10, 11) - * - */ - -#include - -#define TRUE 1 -#define FALSE 0 - -#include "../clock.hpp" - -#include "../i2c/i2c.hpp" -using i2c_t = i2c::I2c>; - -#include "rtc.h" - -#define RTC_ADDR 0x68 // I2C address -#define CH_BIT 7 // clock halt bit - -// statically allocated structure for time value -struct rtc_tm _rtc_tm; - -uint8_t dec2bcd(uint8_t d) -{ - return ((d/10 * 16) + (d % 10)); -} - -uint8_t bcd2dec(uint8_t b) -{ - return ((b/16 * 10) + (b % 16)); -} - -uint8_t rtc_read_byte(uint8_t offset) -{ - i2c_t::start(false); - i2c_t::write(offset); - i2c_t::stop(); - - i2c_t::start(true); - const auto received = i2c_t::read(); - i2c_t::stop(); - - return received; -} - -void rtc_write_byte(uint8_t b, uint8_t offset) -{ - i2c_t::start(false); - i2c_t::write(offset); - i2c_t::write(b); - i2c_t::stop(); -} - -static bool s_is_ds1307 = false; -static bool s_is_ds3231 = false; - -void rtc_init(void) -{ - i2c_t::init(); - - // Attempt autodetection: - // 1) Read and save temperature register - // 2) Write a value to temperature register - // 3) Read back the value - // equal to the one written: DS1307, write back saved value and return - // different from written: DS3231 - - uint8_t temp1 = rtc_read_byte(0x11); - uint8_t temp2 = rtc_read_byte(0x12); - - rtc_write_byte(0xee, 0x11); - rtc_write_byte(0xdd, 0x12); - - if (rtc_read_byte(0x11) == 0xee && rtc_read_byte(0x12) == 0xdd) { - s_is_ds1307 = true; - // restore values - rtc_write_byte(temp1, 0x11); - rtc_write_byte(temp2, 0x12); - } - else { - s_is_ds3231 = true; - } -} - -// Autodetection -bool rtc_is_ds1307(void) { return s_is_ds1307; } -bool rtc_is_ds3231(void) { return s_is_ds3231; } - -// Autodetection override -void rtc_set_ds1307(void) { s_is_ds1307 = true; s_is_ds3231 = false; } -void rtc_set_ds3231(void) { s_is_ds1307 = false; s_is_ds3231 = true; } - -struct rtc_tm* rtc_get_time(void) -{ - uint8_t rtc[9]; - uint8_t century = 0; - - // read 7 bytes starting from register 0 - // sec, min, hour, day-of-week, date, month, year - i2c_t::start(false); - i2c_t::write(0x0); - i2c_t::stop(); - - i2c_t::start(true); - i2c_t::readBytes<7>(rtc); - i2c_t::stop(); - - // Clear clock halt bit from read data - // This starts the clock for a DS1307, and has no effect for a DS3231 - rtc[0] &= ~(_BV(CH_BIT)); // clear bit - - _rtc_tm.sec = bcd2dec(rtc[0]); - _rtc_tm.min = bcd2dec(rtc[1]); - _rtc_tm.hour = bcd2dec(rtc[2]); - _rtc_tm.mday = bcd2dec(rtc[4]); - _rtc_tm.mon = bcd2dec(rtc[5] & 0x1F); // returns 1-12 - century = (rtc[5] & 0x80) >> 7; - _rtc_tm.year = century == 1 ? 2000 + bcd2dec(rtc[6]) : 1900 + bcd2dec(rtc[6]); // year 0-99 - _rtc_tm.wday = bcd2dec(rtc[3]); // returns 1-7 - - if (_rtc_tm.hour == 0) { - _rtc_tm.twelveHour = 0; - _rtc_tm.am = 1; - } else if (_rtc_tm.hour < 12) { - _rtc_tm.twelveHour = _rtc_tm.hour; - _rtc_tm.am = 1; - } else { - _rtc_tm.twelveHour = _rtc_tm.hour - 12; - _rtc_tm.am = 0; - } - - return &_rtc_tm; -} - -void rtc_get_time_s(uint8_t* hour, uint8_t* min, uint8_t* sec) -{ - uint8_t rtc[9]; - - // read 7 bytes starting from register 0 - // sec, min, hour, day-of-week, date, month, year - i2c_t::start(false); - i2c_t::write(0x0); - i2c_t::stop(); - - i2c_t::start(true); - i2c_t::readBytes<7>(rtc); - i2c_t::stop(); - - if (sec) *sec = bcd2dec(rtc[0]); - if (min) *min = bcd2dec(rtc[1]); - if (hour) *hour = bcd2dec(rtc[2]); -} - -// fixme: support 12-hour mode for setting time -void rtc_set_time(struct rtc_tm* tm_) -{ - i2c_t::start(false); - i2c_t::write(0x0); - - uint8_t century; - if (tm_->year > 2000) { - century = 0x80; - tm_->year = tm_->year - 2000; - } else { - century = 0; - tm_->year = tm_->year - 1900; - } - - // clock halt bit is 7th bit of seconds: this is always cleared to start the clock - i2c_t::write(dec2bcd(tm_->sec)); // seconds - i2c_t::write(dec2bcd(tm_->min)); // minutes - i2c_t::write(dec2bcd(tm_->hour)); // hours - i2c_t::write(dec2bcd(tm_->wday)); // day of week - i2c_t::write(dec2bcd(tm_->mday)); // day - i2c_t::write(dec2bcd(tm_->mon) + century); // month - i2c_t::write(dec2bcd(tm_->year)); // year - - i2c_t::stop(); -} - -void rtc_set_time_s(uint8_t hour, uint8_t min, uint8_t sec) -{ - i2c_t::start(false); - i2c_t::write(0x0); - - // clock halt bit is 7th bit of seconds: this is always cleared to start the clock - i2c_t::write(dec2bcd(sec)); // seconds - i2c_t::write(dec2bcd(min)); // minutes - i2c_t::write(dec2bcd(hour)); // hours - - i2c_t::stop(); -} - -// DS1307 only (has no effect when run on DS3231) -// halt/start the clock -// 7th bit of register 0 (second register) -// 0 = clock is running -// 1 = clock is not running -void rtc_run_clock(bool run) -{ - if (s_is_ds3231) return; - - uint8_t b = rtc_read_byte(0x0); - - if (run) - b &= ~(_BV(CH_BIT)); // clear bit - else - b |= _BV(CH_BIT); // set bit - - rtc_write_byte(b, 0x0); -} - -// DS1307 only -// Returns true if the clock is running, false otherwise -// For DS3231, it always returns true -bool rtc_is_clock_running(void) -{ - if (s_is_ds3231) return true; - - uint8_t b = rtc_read_byte(0x0); - - if (b & _BV(CH_BIT)) return false; - return true; -} - -void ds3231_get_temp_int(int8_t* i, uint8_t* f) -{ - uint8_t msb, lsb; - - *i = 0; - *f = 0; - - if (s_is_ds1307) return; // only valid on DS3231 - - i2c_t::start(false); - // temp registers 0x11 and 0x12 - i2c_t::write(0x11); - i2c_t::stop(); - - i2c_t::start(true); - msb = i2c_t::read(); // integer part (in twos complement) - lsb = i2c_t::read(); // fraction part - - // integer part in entire byte - *i = msb; - // fractional part in top two bits (increments of 0.25) - *f = (lsb >> 6) * 25; - - // float value can be read like so: - // float temp = ((((short)msb << 8) | (short)lsb) >> 6) / 4.0f; -} - -void rtc_force_temp_conversion(uint8_t block) -{ - if (s_is_ds1307) return; // only valid on DS3231 - - // read control register (0x0E) - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::stop(); - - i2c_t::start(true); - uint8_t ctrl = i2c_t::read(); - i2c_t::stop(); - - ctrl |= 0b00100000; // Set CONV bit - - // write new control register value - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::write(ctrl); - i2c_t::stop(); - - if (!block) return; - - // Temp conversion is ready when control register becomes 0 - do { - // Block until CONV is 0 - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::stop(); - - i2c_t::start(true); - // HACK: Missing stop after read, might still work though - } while ((i2c_t::read() & 0b00100000) != 0); -} - - -#define DS1307_SRAM_ADDR 0x08 - -// SRAM: 56 bytes from address 0x08 to 0x3f (DS1307-only) -void rtc_get_sram(uint8_t* data) -{ - // cannot receive 56 bytes in one go, because of the TWI library buffer limit - // so just receive one at a time for simplicity - for(int i=0;i<56;i++) - data[i] = rtc_get_sram_byte(i); -} - -void rtc_set_sram(uint8_t *data) -{ - // cannot send 56 bytes in one go, because of the TWI library buffer limit - // so just send one at a time for simplicity - for(int i=0;i<56;i++) - rtc_set_sram_byte(data[i], i); -} - -uint8_t rtc_get_sram_byte(uint8_t offset) -{ - i2c_t::start(false); - i2c_t::write(DS1307_SRAM_ADDR + offset); - i2c_t::stop(); - - i2c_t::start(true); - const auto received = i2c_t::read(); - i2c_t::stop(); - return received; -} - -void rtc_set_sram_byte(uint8_t b, uint8_t offset) -{ - i2c_t::start(false); - i2c_t::write(DS1307_SRAM_ADDR + offset); - i2c_t::write(b); - i2c_t::stop(); -} - -void rtc_SQW_enable(bool enable) -{ - if (s_is_ds1307) { - i2c_t::start(false); - i2c_t::write(0x07); - i2c_t::stop(); - - // read control - i2c_t::start(true); - uint8_t control = i2c_t::read(); - i2c_t::stop(); - - if (enable) - control |= 0b00010000; // set SQWE to 1 - else - control &= ~0b00010000; // set SQWE to 0 - - // write control back - i2c_t::start(false); - i2c_t::write(0x07); - i2c_t::write(control); - i2c_t::stop(); - - } - else { // DS3231 - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::stop(); - - // read control - i2c_t::start(true); - uint8_t control = i2c_t::read(); - i2c_t::stop(); - - if (enable) { - control |= 0b01000000; // set BBSQW to 1 - control &= ~0b00000100; // set INTCN to 0 - } - else { - control &= ~0b01000000; // set BBSQW to 0 - } - - // write control back - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::write(control); - i2c_t::stop(); - } -} - -void rtc_SQW_set_freq(enum RTC_SQW_FREQ freq) -{ - if (s_is_ds1307) { - i2c_t::start(false); - i2c_t::write(0x07); - i2c_t::stop(); - - // read control (uses bits 0 and 1) - i2c_t::start(true); - uint8_t control = i2c_t::read(); - i2c_t::stop(); - - control &= ~0b00000011; // Set to 0 - control |= freq; // Set freq bitmask - - // write control back - i2c_t::start(false); - i2c_t::write(0x07); - i2c_t::write(control); - i2c_t::stop(); - - } - else { // DS3231 - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::stop(); - - // read control (uses bits 3 and 4) - i2c_t::start(true); - uint8_t control = i2c_t::read(); - i2c_t::stop(); - - control &= ~0b00011000; // Set to 0 - control |= (freq << 4); // Set freq bitmask - - // write control back - i2c_t::start(false); - i2c_t::write(0x0E); - i2c_t::write(control); - i2c_t::stop(); - } -} - -void rtc_osc32kHz_enable(bool enable) -{ - if (!s_is_ds3231) return; - - i2c_t::start(false); - i2c_t::write(0x0F); - i2c_t::stop(); - - // read status - i2c_t::start(true); - uint8_t status = i2c_t::read(); - i2c_t::stop(); - - if (enable) - status |= 0b00001000; // set to 1 - else - status &= ~0b00001000; // Set to 0 - - // write status back - i2c_t::start(false); - i2c_t::write(0x0F); - i2c_t::write(status); - i2c_t::stop(); -} - -// Alarm functionality -// fixme: should decide if "alarm disabled" mode should be available, or if alarm should always be enabled -// at 00:00:00. Currently, "alarm disabled" only works for ds3231 -void rtc_reset_alarm(void) -{ - if (s_is_ds1307) { - rtc_set_sram_byte(0, 0); // hour - rtc_set_sram_byte(0, 1); // minute - rtc_set_sram_byte(0, 2); // second - } - else { - // writing 0 to bit 7 of all four alarm 1 registers disables alarm - rtc_write_byte(0, 0x07); // second - rtc_write_byte(0, 0x08); // minute - rtc_write_byte(0, 0x09); // hour - rtc_write_byte(0, 0x0a); // day - } -} - -// fixme: add an option to set whether or not the INTCN and Interrupt Enable flag is set when setting the alarm -void rtc_set_alarm_s(uint8_t hour, uint8_t min, uint8_t sec) -{ - if (hour > 23) return; - if (min > 59) return; - if (sec > 59) return; - - if (s_is_ds1307) { - rtc_set_sram_byte(hour, 0); // hour - rtc_set_sram_byte(min, 1); // minute - rtc_set_sram_byte(sec, 2); // second - } - else { - /* - * 07h: A1M1:0 Alarm 1 seconds - * 08h: A1M2:0 Alarm 1 minutes - * 09h: A1M3:0 Alarm 1 hour (bit6 is am/pm flag in 12h mode) - * 0ah: A1M4:1 Alarm 1 day/date (bit6: 1 for day, 0 for date) - * Sets alarm to fire when hour, minute and second matches - */ - rtc_write_byte(dec2bcd(sec), 0x07); // second - rtc_write_byte(dec2bcd(min), 0x08); // minute - rtc_write_byte(dec2bcd(hour), 0x09); // hour - rtc_write_byte(0b10000001, 0x0a); // day (upper bit must be set) - - // clear alarm flag - uint8_t val = rtc_read_byte(0x0f); - rtc_write_byte(val & ~0b00000001, 0x0f); - } -} - -void rtc_set_alarm(struct rtc_tm* tm_) -{ - if (!tm_) return; - rtc_set_alarm_s(tm_->hour, tm_->min, tm_->sec); -} - -void rtc_get_alarm_s(uint8_t* hour, uint8_t* min, uint8_t* sec) -{ - if (s_is_ds1307) { - if (hour) *hour = rtc_get_sram_byte(0); - if (min) *min = rtc_get_sram_byte(1); - if (sec) *sec = rtc_get_sram_byte(2); - } - else { - *sec = bcd2dec(rtc_read_byte(0x07) & ~0b10000000); - *min = bcd2dec(rtc_read_byte(0x08) & ~0b10000000); - *hour = bcd2dec(rtc_read_byte(0x09) & ~0b10000000); - } -} - -struct rtc_tm* rtc_get_alarm(void) -{ - uint8_t hour, min, sec; - - rtc_get_alarm_s(&hour, &min, &sec); - _rtc_tm.hour = hour; - _rtc_tm.min = min; - _rtc_tm.sec = sec; - return &_rtc_tm; -} - -bool rtc_check_alarm(void) -{ - if (s_is_ds1307) { - uint8_t hour = rtc_get_sram_byte(0); - uint8_t min = rtc_get_sram_byte(1); - uint8_t sec = rtc_get_sram_byte(2); - - uint8_t cur_hour, cur_min, cur_sec; - rtc_get_time_s(&cur_hour, &cur_min, &cur_sec); - - if (cur_hour == hour && cur_min == min && cur_sec == sec) - return true; - return false; - } - else { - // Alarm 1 flag (A1F) in bit 0 - uint8_t val = rtc_read_byte(0x0f); - - // clear flag when set - if (val & 1) - rtc_write_byte(val & ~0b00000001, 0x0f); - - return val & 1 ? 1 : 0; - } -} diff --git a/rtc.h b/rtc.h deleted file mode 100644 index 32890af..0000000 --- a/rtc.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * DS RTC Library: DS1307 and DS3231 driver library - * (C) 2011 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. - * - */ - -#ifndef DS1307_H -#define DS1307_H - -#include -#include - -#define DS1307_SLAVE_ADDR 0b11010000 - -/** Time structure - * - * Both 24-hour and 12-hour time is stored, and is always updated when rtc_get_time is called. - * - * When setting time and alarm, 24-hour mode is always used. - * - * If you run your clock in 12-hour mode: - * - set time hour to store in twelveHour and set am to true or false. - * - call rtc_12h_translate (this will put the correct value in hour, so you don't have to - * calculate it yourself. - * - call rtc_set_alarm or rtc_set_clock - * - * Note that rtc_set_clock_s, rtc_set_alarm_s, rtc_get_time_s, rtc_set_alarm_s always operate in 24-hour mode - * and translation has to be done manually (you can call rtc_24h_to_12h to perform the calculation) - * - */ -struct rtc_tm { - int sec; // 0 to 59 - int min; // 0 to 59 - int hour; // 0 to 23 - int mday; // 1 to 31 - int mon; // 1 to 12 - int year; // year-99 - int wday; // 1-7 - - // 12-hour clock data - bool am; // true for AM, false for PM - int twelveHour; // 12 hour clock time -}; - -// statically allocated -extern struct rtc_tm _rtc_tm; - -// Initialize the RTC and autodetect type (DS1307 or DS3231) -void rtc_init(void); - -// Autodetection -bool rtc_is_ds1307(void); -bool rtc_is_ds3231(void); - -void rtc_set_ds1307(void); -void rtc_set_ds3231(void); - -// Get/set time -// Gets the time: Supports both 24-hour and 12-hour mode -struct rtc_tm* rtc_get_time(void); -// Gets the time: 24-hour mode only -void rtc_get_time_s(uint8_t* hour, uint8_t* min, uint8_t* sec); -// Sets the time: Supports both 24-hour and 12-hour mode -void rtc_set_time(struct rtc_tm* tm_); -// Sets the time: Supports 12-hour mode only -void rtc_set_time_s(uint8_t hour, uint8_t min, uint8_t sec); - -// start/stop clock running (DS1307 only) -void rtc_run_clock(bool run); -bool rtc_is_clock_running(void); - -// Read Temperature (DS3231 only) -void ds3231_get_temp_int(int8_t* i, uint8_t* f); -void rtc_force_temp_conversion(uint8_t block); - -// SRAM read/write DS1307 only -void rtc_get_sram(uint8_t* data); -void rtc_set_sram(uint8_t *data); -uint8_t rtc_get_sram_byte(uint8_t offset); -void rtc_set_sram_byte(uint8_t b, uint8_t offset); - - // Auxillary functions -enum RTC_SQW_FREQ { FREQ_1 = 0, FREQ_1024, FREQ_4096, FREQ_8192 }; - -void rtc_SQW_enable(bool enable); -void rtc_SQW_set_freq(enum RTC_SQW_FREQ freq); -void rtc_osc32kHz_enable(bool enable); - -// Alarm functionality -void rtc_reset_alarm(void); -void rtc_set_alarm(struct rtc_tm* tm_); -void rtc_set_alarm_s(uint8_t hour, uint8_t min, uint8_t sec); -struct rtc_tm* rtc_get_alarm(void); -void rtc_get_alarm_s(uint8_t* hour, uint8_t* min, uint8_t* sec); -bool rtc_check_alarm(void); - -#endif