From 7e59d836a1127f660594c2f97046420b0f101450 Mon Sep 17 00:00:00 2001 From: Philipp_EndevourOS Date: Sat, 4 Oct 2025 15:46:30 +0200 Subject: [PATCH] added get date method for rtc --- src/drivers/rtc.rs | 64 +++++++++++++++++++++++++++++++++++++++++++--- src/main.rs | 5 ++-- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/drivers/rtc.rs b/src/drivers/rtc.rs index 1575e4e..ea96a40 100644 --- a/src/drivers/rtc.rs +++ b/src/drivers/rtc.rs @@ -8,13 +8,17 @@ use esp_hal::{ }; use log::{debug, error, info}; -use crate::{FEEDBACK_STATE, drivers, feedback}; +use crate::{FEEDBACK_STATE, drivers, feedback, store::Date}; use chrono::{TimeZone, Utc}; include!(concat!(env!("OUT_DIR"), "/build_time.rs")); const RTC_ADDRESS: u8 = 0x68; +const SECS_PER_DAY: u64 = 86_400; +const UNIX_OFFSET_DAYS: u64 = 719_163; // Days from 0000-03-01 to 1970-01-01 +const UTC_PLUS_ONE: u64 = 3600; + pub struct RTCClock { dev: DS3231>, } @@ -41,8 +45,61 @@ impl RTCClock { } } } + + pub async fn get_date(&mut self) -> Date { + let (year, month, day) = unix_to_ymd_string(self.get_time().await); + + let mut buffer: Date = [0; 10] ; + + // Write YYYY + buffer[0] = b'0' + ((year / 1000) % 10) as u8; + buffer[1] = b'0' + ((year / 100) % 10) as u8; + buffer[2] = b'0' + ((year / 10) % 10) as u8; + buffer[3] = b'0' + (year % 10) as u8; + buffer[4] = b'.'; + + // Write MM + buffer[5] = b'0' + (month / 10) as u8; + buffer[6] = b'0' + (month % 10) as u8; + + buffer[7] = b'.'; + + // Write DD + buffer[8] = b'0' + (day / 10) as u8; + buffer[9] = b'0' + (day % 10) as u8; + + buffer + } + } +fn unix_to_ymd_string(timestamp: u64) -> (u16, u8, u8) { + // Apply UTC+1 offset + let ts = timestamp + UTC_PLUS_ONE; + + // Convert to total days since UNIX epoch + let days_since_epoch = ts / SECS_PER_DAY; + + // Convert to proleptic Gregorian date + civil_from_days(days_since_epoch as i64 + UNIX_OFFSET_DAYS as i64) + } + + // This function returns (year, month, day). + // Based on the algorithm by Howard Hinnant. + fn civil_from_days(z: i64) -> (u16, u8, u8) { + let mut z = z; + z -= 60; // shift epoch for algorithm + let era = (z >= 0).then_some(z).unwrap_or(z - 146096) / 146097; + let doe = z - era * 146097; // [0, 146096] + let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] + let y = yoe + era * 400; + let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] + let mp = (5 * doy + 2) / 153; // [0, 11] + let d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] + let m = mp + (if mp < 10 { 3 } else { -9 }); // [1, 12] + ((y + (m <= 2) as i64) as u16, m as u8, d as u8) + } + pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231> { let mut rtc: DS3231> = DS3231::new(i2c, RTC_ADDRESS); let naive_dt = Utc @@ -62,8 +119,9 @@ pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231> match rtc.configure(&rtc_config).await { Ok(_) => info!("DS3231 configured successfully"), Err(e) => { - info!("Failed to configure DS3231: {:?}", e); - panic!("DS3231 configuration failed"); + error!("Failed to configure DS3231: {:?}", e); + error!("DS3231 configuration failed"); + FEEDBACK_STATE.signal(feedback::FeedbackState::Error); } } diff --git a/src/main.rs b/src/main.rs index 77933ec..c81995e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ use esp_hal::{gpio::InputConfig, peripherals}; use log::{debug, info}; use static_cell::make_static; -use crate::store::{IDStore, TallyID}; +use crate::store::{Date, IDStore, TallyID}; extern crate alloc; @@ -80,7 +80,8 @@ async fn main(mut spawner: Spawner) { Message(msg) => { debug!("Got message: {msg:?}"); - let added = store.add_id(msg).await; + let day: Date = rtc.get_date().await; + let added = store.add_id(msg, day).await; if added { FEEDBACK_STATE.signal(feedback::FeedbackState::Ack);