From 9e97fac25206577c5404bcb4368b2c1a97e54c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Wed, 27 Apr 2022 11:05:08 +0200 Subject: [PATCH] - implement generic support for on-device battery powered RTC Modules. - implement support for I2C RV-3028 based RTC modules like the RAK12002 - pretty print some debug timestamps --- src/RedirectablePrint.cpp | 2 +- src/configuration.h | 4 +++ src/debug/i2cScan.h | 13 +++++++-- src/gps/NMEAGPS.cpp | 2 +- src/gps/RTC.cpp | 40 ++++++++++++++++++++++---- src/gps/RTC.h | 10 +++++-- src/graphics/Screen.cpp | 2 +- src/main.cpp | 3 ++ src/main.h | 1 + variants/rak4631/platformio.ini | 1 + variants/rak4631/variant.h | 3 ++ variants/rak4631_epaper/platformio.ini | 1 + variants/rak4631_epaper/variant.h | 3 ++ 13 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index dc0f3b958..a2f048f8e 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -72,7 +72,7 @@ size_t RedirectablePrint::logDebug(const char *format, ...) // If we are the first message on a report, include the header if (!isContinuationMessage) { - uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityFromNet); + uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; // hms += tz.tz_dsttime * SEC_PER_HOUR; diff --git a/src/configuration.h b/src/configuration.h index 628cd0bf1..60cf7512b 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -25,6 +25,10 @@ along with this program. If not, see . #pragma once #include +#ifdef RV3028_RTC + #include "Melopero_RV3028.h" +#endif + // ----------------------------------------------------------------------------- // Version // ----------------------------------------------------------------------------- diff --git a/src/debug/i2cScan.h b/src/debug/i2cScan.h index 4279a5122..ae6384fbc 100644 --- a/src/debug/i2cScan.h +++ b/src/debug/i2cScan.h @@ -54,7 +54,16 @@ void scanI2Cdevice(void) DEBUG_MSG("unknown display found\n"); } } - +#ifdef RV3028_RTC + if (addr == RV3028_RTC){ + rtc_found = addr; + DEBUG_MSG("RV3028 RTC found\n"); + Melopero_RV3028 rtc; + rtc.initI2C(); + rtc.writeToRegister(0x35,0x07); // no Clkout + rtc.writeToRegister(0x37,0xB4); + } +#endif if (addr == CARDKB_ADDR) { cardkb_found = addr; DEBUG_MSG("m5 cardKB found\n"); @@ -81,7 +90,7 @@ void scanI2Cdevice(void) if (nDevices == 0) DEBUG_MSG("No I2C devices found\n"); else - DEBUG_MSG("done\n"); + DEBUG_MSG("%i I2C devices found\n",nDevices); } #else void scanI2Cdevice(void) {} diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp index 7560c0b30..8a8181f3b 100644 --- a/src/gps/NMEAGPS.cpp +++ b/src/gps/NMEAGPS.cpp @@ -65,7 +65,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s t.tm_year = d.year() - 1900; t.tm_isdst = false; if (t.tm_mon > -1){ - DEBUG_MSG("NMEA GPS time %d-%d-%d %d:%d:%d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); + DEBUG_MSG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); perhapsSetRTC(RTCQualityGPS, t); return true; } else diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index bc7e816cb..e717f97ba 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -1,5 +1,6 @@ #include "RTC.h" #include "configuration.h" +#include "main.h" #include #include @@ -18,14 +19,35 @@ static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only upda void readFromRTC() { struct timeval tv; /* btw settimeofday() is helpfull here too*/ - +#ifdef RV3028_RTC + if(rtc_found == RV3028_RTC) { + uint32_t now = millis(); + Melopero_RV3028 rtc; + rtc.initI2C(); + tm t; + t.tm_year = rtc.getYear() - 1900; + t.tm_mon = rtc.getMonth() - 1; + t.tm_mday = rtc.getDate(); + t.tm_hour = rtc.getHour(); + t.tm_min = rtc.getMinute(); + t.tm_sec = rtc.getSecond(); + tv.tv_sec = mktime(&t); + tv.tv_usec = 0; + DEBUG_MSG("Read RTC time from RV3028 as %ld\n", tv.tv_sec); + timeStartMsec = now; + zeroOffsetSecs = tv.tv_sec; + if (currentQuality == RTCQualityNone) { + currentQuality = RTCQualityDevice; + } + } +#else if (!gettimeofday(&tv, NULL)) { uint32_t now = millis(); - - DEBUG_MSG("Read RTC time as %ld (cur millis %u) quality=%d\n", tv.tv_sec, now, currentQuality); + DEBUG_MSG("Read RTC time as %ld\n", tv.tv_sec); timeStartMsec = now; zeroOffsetSecs = tv.tv_sec; } +#endif } /// If we haven't yet set our RTC this boot, set it from a GPS derived time @@ -55,12 +77,20 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) zeroOffsetSecs = tv->tv_sec; // If this platform has a setable RTC, set it -#ifndef NO_ESP32 +#ifdef RV3028_RTC + if(rtc_found == RV3028_RTC) { + Melopero_RV3028 rtc; + rtc.initI2C(); + tm *t = localtime(&tv->tv_sec); + rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + DEBUG_MSG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec); + } +#elif !defined(NO_ESP32) settimeofday(tv, NULL); #endif // nrf52 doesn't have a readable RTC (yet - software not written) -#if defined(PORTDUINO) || !defined(NO_ESP32) +#if defined(PORTDUINO) || !defined(NO_ESP32) || defined(RV3028_RTC) readFromRTC(); #endif diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 730d1914e..f2df3c757 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -5,17 +5,21 @@ #include enum RTCQuality { + /// We haven't had our RTC set yet RTCQualityNone = 0, + /// We got time from an onboard peripheral after boot. + RTCQualityDevice = 1, + /// Some other node gave us a time we can use - RTCQualityFromNet = 1, + RTCQualityFromNet = 2, /// Our time is based on NTP - RTCQualityNTP= 2, + RTCQualityNTP= 3, /// Our time is based on our own GPS - RTCQualityGPS = 3 + RTCQualityGPS = 4 }; RTCQuality getRTCQuality(); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index edb3ebc45..136964006 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1557,7 +1557,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat else uptime += String(seconds) + "s "; - uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityFromNet); + uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; // hms += tz.tz_dsttime * SEC_PER_HOUR; diff --git a/src/main.cpp b/src/main.cpp index afb162cee..00963e224 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,6 +79,9 @@ uint8_t cardkb_found; // The I2C address of the Faces Keyboard (if found) uint8_t faceskb_found; +// The I2C address of the RTC Module (if found) +uint8_t rtc_found; + bool eink_found = true; uint32_t serialSinceMsec; diff --git a/src/main.h b/src/main.h index fc91f396a..de79435bb 100644 --- a/src/main.h +++ b/src/main.h @@ -9,6 +9,7 @@ extern uint8_t screen_found; extern uint8_t screen_model; extern uint8_t cardkb_found; extern uint8_t faceskb_found; +extern uint8_t rtc_found; extern bool eink_found; extern bool axp192_found; diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 6e0563598..fd9fbcd89 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -6,6 +6,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631 src_filter = ${nrf52_base.src_filter} +<../variants/rak4631> lib_deps = ${nrf52840_base.lib_deps} + melopero/Melopero RV3028@^1.1.0 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink \ No newline at end of file diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index c211ec4a1..bae5d957a 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -198,6 +198,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define GPS_RX_PIN PIN_SERIAL1_RX #define GPS_TX_PIN PIN_SERIAL1_TX +// RAK12002 RTC Module +#define RV3028_RTC (uint8_t) 0b1010010 + // Battery // The battery sense is hooked to pin A0 (5) #define BATTERY_PIN PIN_A0 diff --git a/variants/rak4631_epaper/platformio.ini b/variants/rak4631_epaper/platformio.ini index fc65ac2c8..55f799e25 100644 --- a/variants/rak4631_epaper/platformio.ini +++ b/variants/rak4631_epaper/platformio.ini @@ -7,6 +7,7 @@ src_filter = ${nrf52_base.src_filter} +<../variants/rak4631_epaper> lib_deps = ${nrf52840_base.lib_deps} https://github.com/ZinggJM/GxEPD2.git + melopero/Melopero RV3028@^1.1.0 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink \ No newline at end of file diff --git a/variants/rak4631_epaper/variant.h b/variants/rak4631_epaper/variant.h index 071c659e1..12f379d06 100644 --- a/variants/rak4631_epaper/variant.h +++ b/variants/rak4631_epaper/variant.h @@ -198,6 +198,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define GPS_RX_PIN PIN_SERIAL1_RX #define GPS_TX_PIN PIN_SERIAL1_TX +// RAK12002 RTC Module +#define RV3028_RTC (uint8_t) 0b1010010 + // Battery // The battery sense is hooked to pin A0 (5) #define BATTERY_PIN PIN_A0