Files
TEF6686_ESP32/src/rtc.cpp

130 lines
3.6 KiB
C++

#include "rtc.hpp"
// the hardware rtc driver was made with the support of Wh1teRabbitHU's implementation
bool rtcset;
bool NTPupdated;
ESP32Time rtc(0);
bool rx_rtc_avail = false;
inline int16_t readFromModule(byte address) {
Wire.beginTransmission(RX8010SJ_ADDRESS);
Wire.write(address);
if (Wire.endTransmission() != 0) return -1;
if (Wire.requestFrom(RX8010SJ_ADDRESS, 1) != 1) return -1;
if (Wire.available()) return Wire.read();
return -1;
}
inline void writeToModule(byte address, byte data) {
Wire.beginTransmission(RX8010SJ_ADDRESS);
Wire.write(address);
Wire.write(data);
Wire.endTransmission();
}
inline byte toBCD(byte val) {
return ((val / 10) << 4) | (val % 10);
}
inline byte sumValueFromBinary(byte binary, byte length) {
byte sum = 0;
for (byte i = 0; i < length; i++) {
byte value;
if (i < 4 ) value = 1 << i;
else value = 10 * (1 << (i - 4));
sum += ((binary >> i) & 1) == 1 ? value : 0;
}
return sum;
}
void sync_from_rx_rtc(int32_t offset = 0) {
if(!rx_rtc_avail) return;
struct tm timeinfo;
memset(&timeinfo, 0, sizeof(timeinfo));
Wire.beginTransmission(RX8010SJ_ADDRESS);
Wire.write(0x10);
Wire.endTransmission();
if (Wire.requestFrom(RX8010SJ_ADDRESS, 7) == 7) {
timeinfo.tm_sec = sumValueFromBinary(Wire.read(), 7);
timeinfo.tm_min = sumValueFromBinary(Wire.read(), 7);
timeinfo.tm_hour = sumValueFromBinary(Wire.read(), 6);
auto dayOfWeekBin = Wire.read();
for (int i = 0; i < 7; i++) {
if (dayOfWeekBin & (1u << i)) {
timeinfo.tm_wday = i;
break;
}
}
timeinfo.tm_mday = sumValueFromBinary(Wire.read(), 6);
timeinfo.tm_mon = sumValueFromBinary(Wire.read(), 5) - 1;
timeinfo.tm_year = sumValueFromBinary(Wire.read(), 8) + 100;
rtc.setTime(mktime(&timeinfo) + offset);
}
}
bool init_rtc() {
rtc.setTime(0);
if(!rx_rtc_avail) return false;
auto flagregister = readFromModule(0x1E);
if(flagregister < 0) {
rx_rtc_avail = false;
return false;
}
if((flagregister >> 1) & 1) {
while((flagregister >> 1) & 1) {
writeToModule(0x1E, 0); // clear VLF
flagregister = readFromModule(0x1E);
}
writeToModule(0x17, 216); // Reserved register
writeToModule(0x1F, 64); // Control register, stop bit set
Wire.beginTransmission(RX8010SJ_ADDRESS);
Wire.write(0x31);
Wire.write(8); // Reserved register
Wire.write(0); // IRQ control register
Wire.endTransmission();
Wire.beginTransmission(RX8010SJ_ADDRESS);
Wire.write(0x10);
Wire.write(0);
Wire.write(0);
Wire.write(toBCD(12));
Wire.write(1 << 2);
Wire.write(toBCD(14));
Wire.write(1);
Wire.write(toBCD(26));
Wire.endTransmission();
writeToModule(0x1F, 0); // Unset stop bit
return true;
}
sync_from_rx_rtc();
return false;
}
void set_time(time_t time) {
rtc.setTime(time);
if(!rx_rtc_avail) return;
struct tm* timeinfo = gmtime(&time);
writeToModule(0x1F, 64);
Wire.beginTransmission(RX8010SJ_ADDRESS);
Wire.write(0x10);
Wire.write(toBCD(timeinfo->tm_sec));
Wire.write(toBCD(timeinfo->tm_min));
Wire.write(toBCD(timeinfo->tm_hour));
Wire.write(1 << timeinfo->tm_wday);
Wire.write(toBCD(timeinfo->tm_mday));
Wire.write(toBCD(timeinfo->tm_mon + 1));
Wire.write(toBCD((1900 + timeinfo->tm_year) % 100));
Wire.endTransmission();
writeToModule(0x1F, 0);
}