/* xdrv_56_BM8563_RTC.ino - BM8563 RTC Copyright (C) 2021 Stephan Hadinger and Theo Arends 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 3 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. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef USE_I2C #ifdef USE_BM8563 /*********************************************************************************************\ * BM8563 - Real Time Clock * * I2C Address: 0x51 (Fixed in library as BM8563_ADRESS) \*********************************************************************************************/ #define XDRV_56 56 #define XI2C_59 59 // See I2CDEVICES.md #include "BM8563.h" struct { BM8563 Rtc; bool rtc_ready = false; bool ntp_time_ok = false; } bm8563_driver; uint32_t BM8563GetUtc(void) { RTC_TimeTypeDef RTCtime; // 1. read has errors ??? bm8563_driver.Rtc.GetTime(&RTCtime); // core2_globs.Rtc.GetTime(&RTCtime); RTC_DateTypeDef RTCdate; bm8563_driver.Rtc.GetDate(&RTCdate); TIME_T tm; tm.second = RTCtime.Seconds; tm.minute = RTCtime.Minutes; tm.hour = RTCtime.Hours; tm.day_of_week = RTCdate.WeekDay; tm.day_of_month = RTCdate.Date; tm.month = RTCdate.Month; tm.year = RTCdate.Year - 1970; return MakeTime(tm); } void BM8563SetUtc(uint32_t epoch_time) { TIME_T tm; BreakTime(epoch_time, tm); RTC_TimeTypeDef RTCtime; RTCtime.Hours = tm.hour; RTCtime.Minutes = tm.minute; RTCtime.Seconds = tm.second; bm8563_driver.Rtc.SetTime(&RTCtime); RTC_DateTypeDef RTCdate; RTCdate.WeekDay = tm.day_of_week; RTCdate.Month = tm.month; RTCdate.Date = tm.day_of_month; RTCdate.Year = tm.year + 1970; bm8563_driver.Rtc.SetDate(&RTCdate); } /*********************************************************************************************/ void BM8563Detect(void) { #ifdef ESP32 if (!I2cSetDevice(BM8563_ADRESS, 0)) { if (!I2cSetDevice(BM8563_ADRESS, 1)) { return; } // check on bus 1 bm8563_driver.Rtc.setBus(1); // switch to bus 1 I2cSetActiveFound(BM8563_ADRESS, "BM8563", 1); } else { I2cSetActiveFound(BM8563_ADRESS, "BM8563", 0); } #else if (!I2cSetDevice(BM8563_ADRESS)) { return; } I2cSetActiveFound(BM8563_ADRESS, "BM8563"); #endif bm8563_driver.Rtc.begin(); bm8563_driver.rtc_ready = true; if (Rtc.utc_time < START_VALID_TIME) { // Not sync with NTP/GPS (time not valid), so read time uint32_t time = BM8563GetUtc(); // Read UTC TIME if (time > START_VALID_TIME) { Rtc.utc_time = time; RtcSync("BM8563"); } } } void BM8563TimeSynced(void) { if ((Rtc.utc_time > START_VALID_TIME) && // Valid UTC time (abs((int32_t)(Rtc.utc_time - BM8563GetUtc())) > 2)) { // Time has drifted from RTC more than 2 seconds BM8563SetUtc(Rtc.utc_time); // Update time AddLog(LOG_LEVEL_DEBUG, PSTR("BM8: Re-synced (" D_UTC_TIME ") %s"), GetDateAndTime(DT_UTC).c_str()); } } /*********************************************************************************************\ * Interface \*********************************************************************************************/ bool Xdrv56(uint8_t function) { if (!I2cEnabled(XI2C_59)) { return false; } bool result = false; if (FUNC_INIT == function) { BM8563Detect(); } else if (bm8563_driver.rtc_ready) { switch (function) { case FUNC_TIME_SYNCED: BM8563TimeSynced(); break; } } return result; } #endif // USE_BM8563 #endif // USE_I2C