mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 20:09:17 +00:00
fix RTC and time display
This commit is contained in:
@@ -124,27 +124,34 @@ static bool rtc_probe(uint32_t *epoch_out)
|
||||
continue; /* no ACK => chip absent */
|
||||
}
|
||||
|
||||
/* Mask off flag/century bits, then require the block to be valid
|
||||
* BCD. This is what proves a real RTC lives here (vs. an unrelated
|
||||
* chip sharing the address) — only then is it safe to adopt and
|
||||
* later WRITE to. A factory-fresh RTC reads a clean 2000-01-01,
|
||||
* which is valid BCD (just stale), so it's still adopted. */
|
||||
/* Mask off flag/century bits. We trust this is a real RTC (vs. an
|
||||
* unrelated chip sharing the address) if EITHER the block is valid
|
||||
* BCD, OR the chip's power-loss flag is set — the latter is itself
|
||||
* proof it's an RTC that lost power and whose time registers may be
|
||||
* garbage. Adopting in the power-loss case is essential: otherwise a
|
||||
* battery-depleted RTC (garbage registers, VL/OSF/PORF latched) would
|
||||
* never become the write-back target, so a sync could never
|
||||
* re-initialise it and the clock would stay blank forever. */
|
||||
uint8_t sb = blk[0] & 0x7F, mb = blk[1] & 0x7F, hb = blk[2] & 0x3F;
|
||||
uint8_t db = blk[d->date_index] & 0x3F, ob = blk[5] & 0x1F, yb = blk[6];
|
||||
|
||||
if (!bcd_field_ok(sb, 59) || !bcd_field_ok(mb, 59) ||
|
||||
!bcd_field_ok(hb, 23) || !bcd_field_ok(db, 31) ||
|
||||
!bcd_field_ok(ob, 12) || !bcd_field_ok(yb, 99) ||
|
||||
BCD2BIN(db) < 1 || BCD2BIN(ob) < 1) {
|
||||
continue; /* not a real RTC at this address — do not adopt */
|
||||
bool bcd_ok = bcd_field_ok(sb, 59) && bcd_field_ok(mb, 59) &&
|
||||
bcd_field_ok(hb, 23) && bcd_field_ok(db, 31) &&
|
||||
bcd_field_ok(ob, 12) && bcd_field_ok(yb, 99) &&
|
||||
BCD2BIN(db) >= 1 && BCD2BIN(ob) >= 1;
|
||||
bool unreliable = rtc_time_unreliable(d, blk);
|
||||
|
||||
if (!bcd_ok && !unreliable) {
|
||||
continue; /* neither valid time nor a lost-power RTC => skip */
|
||||
}
|
||||
|
||||
if (s_active == NULL) {
|
||||
s_active = d; /* confirmed RTC => our write-back target */
|
||||
s_active = d; /* RTC => our write-back target */
|
||||
}
|
||||
|
||||
if (rtc_time_unreliable(d, blk)) {
|
||||
LOG_WRN("%s present but time flagged unreliable", d->name);
|
||||
if (unreliable) {
|
||||
LOG_WRN("%s present, power-loss flag set — clock will be set "
|
||||
"on the next GPS/app/CLI sync", d->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <time_sync.h>
|
||||
#include <adapters/gps/ZephyrGPSManager.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
static enum time_sync_source s_last = TIME_SYNC_NONE;
|
||||
@@ -22,6 +23,16 @@ void time_sync_report(enum time_sync_source src)
|
||||
|
||||
enum time_sync_source time_sync_get_source(void)
|
||||
{
|
||||
/* Live GPS hold is authoritative and uses the SAME signal that blocks
|
||||
* phone time-sync (gps_has_time_sync(), expires 2h after the last fix),
|
||||
* so the tag can never disagree with that policy: while GPS holds the
|
||||
* clock the tag is G regardless of the freshness window below. After a
|
||||
* reboot the flag is reset, so this returns false and we fall through to
|
||||
* the local/freshness logic (→ L until something re-syncs). */
|
||||
if (gps_has_time_sync()) {
|
||||
return TIME_SYNC_GPS;
|
||||
}
|
||||
|
||||
/* Local/manual (CLI) and "never synced" are both just local time. */
|
||||
if (s_last == TIME_SYNC_NONE || s_last == TIME_SYNC_CLI) {
|
||||
return TIME_SYNC_CLI;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "ui_task.h"
|
||||
#include "ui_pages.h"
|
||||
#include <time_sync.h>
|
||||
|
||||
#ifdef CONFIG_ZEPHCORE_UI_BUZZER
|
||||
#include "buzzer.h"
|
||||
@@ -909,8 +910,28 @@ void ui_set_battery(uint16_t mv, uint8_t pct)
|
||||
void ui_set_clock(uint32_t epoch)
|
||||
{
|
||||
struct ui_state *s = get_state();
|
||||
static enum time_sync_source last_src = TIME_SYNC_NONE;
|
||||
|
||||
/* 1735689600 = 2025-01-01: the same "time is set" threshold the top-bar
|
||||
* renderer uses. The clock only becomes visible once epoch crosses it. */
|
||||
bool was_valid = s->rtc_epoch > 1735689600;
|
||||
bool now_valid = epoch > 1735689600;
|
||||
|
||||
s->rtc_epoch = epoch;
|
||||
|
||||
/* Repaint the EPD (which only redraws on demand) when the visible top-bar
|
||||
* clock/source-tag changes, so the user never has to change pages to see
|
||||
* an update. Both transitions are picked up on the next housekeeping tick:
|
||||
* - clock first becomes valid → boot RTC restore / first sync
|
||||
* - source tag changes → L→A (app), →G (GPS fix), A→L (12h expiry)
|
||||
* Steady state triggers nothing (epoch valid + source unchanged). */
|
||||
enum time_sync_source src = time_sync_get_source();
|
||||
bool source_changed = (src != last_src);
|
||||
last_src = src;
|
||||
|
||||
if (now_valid && (!was_valid || source_changed)) {
|
||||
schedule_render();
|
||||
}
|
||||
}
|
||||
|
||||
void ui_add_recent(const char *name, int16_t rssi, uint32_t age_s)
|
||||
|
||||
Reference in New Issue
Block a user