Browse Source

Implement RTC tick

Kevin Lee 2 years ago
parent
commit
a0ed1ae17f
2 changed files with 102 additions and 12 deletions
  1. 10 6
      Nixie_Firmware_Rust/src/main.rs
  2. 92 6
      Nixie_Firmware_Rust/src/nixie.rs

+ 10 - 6
Nixie_Firmware_Rust/src/main.rs

@@ -9,7 +9,7 @@
 #[cfg(not(test))]
 use core::panic::PanicInfo;
 
-use core::{cell::RefCell, ops::DerefMut};
+use core::{borrow::Borrow, cell::RefCell, ops::DerefMut};
 use cortex_m::{asm, interrupt::free, interrupt::Mutex, peripheral::NVIC};
 use cortex_m_rt::entry;
 // use cortex_m_semihosting::hprintln;
@@ -244,12 +244,16 @@ fn set_fault_led(state: State) {
 fn EXTI9_5() {
     free(|cs| {
         let mut rtc_int_ref = RTC_INT.borrow(cs).borrow_mut();
+        let mut i2c_int_ref = I2C.borrow(cs).borrow_mut();
         if let Some(ref mut rtc_int) = rtc_int_ref.deref_mut() {
-            if rtc_int.check_interrupt() {
-                rtc_int.clear_interrupt_pending_bit();
-                set_fault_led(State::High);
-                asm::delay(8_000_000);
-                set_fault_led(State::Low);
+            if let Some(ref mut i2c) = i2c_int_ref.deref_mut() {
+                if rtc_int.check_interrupt() {
+                    rtc_int.clear_interrupt_pending_bit();
+                    nixie::rtc_tick(i2c);
+                    // set_fault_led(State::High);
+                    // asm::delay(8_000_000);
+                    // set_fault_led(State::Low);
+                }
             }
         }
     });

+ 92 - 6
Nixie_Firmware_Rust/src/nixie.rs

@@ -1,4 +1,9 @@
-use core::future::pending;
+use stm32l4xx_hal::prelude::{
+    _embedded_hal_blocking_i2c_Read, _embedded_hal_blocking_i2c_Write,
+    _embedded_hal_blocking_i2c_WriteRead,
+};
+
+use crate::ds3231;
 
 pub const DS3231_ADDR: u8 = 0x68;
 pub const TUSB322_ADDR: u8 = 0x47;
@@ -362,7 +367,7 @@ pub fn refresh_frame() {
                         }
                         d.updated = true;
                         pending_refresh = true;
-                    },
+                    }
                     DigitState::Decrementing => {
                         d.value = d.value.saturating_sub(steps);
                         if d.value <= DIGIT_MIN_BRIGHTNESS {
@@ -371,8 +376,7 @@ pub fn refresh_frame() {
                         }
                         d.updated = true;
                         pending_refresh = true;
-
-                    },
+                    }
                     DigitState::Idle => (),
                 }
             }
@@ -388,7 +392,7 @@ pub fn refresh_frame() {
                 }
                 CLOCK.dot.updated = true;
                 pending_refresh = true;
-            },
+            }
             DigitState::Decrementing => {
                 CLOCK.dot.value = CLOCK.dot.value.saturating_sub(steps);
                 if CLOCK.dot.value >= DIGIT_MIN_BRIGHTNESS {
@@ -397,7 +401,7 @@ pub fn refresh_frame() {
                 }
                 CLOCK.dot.updated = true;
                 pending_refresh = true;
-            },
+            }
             DigitState::Idle => (),
         }
     }
@@ -406,3 +410,85 @@ pub fn refresh_frame() {
         // TODO! trigger refresh timer
     }
 }
+
+pub fn rtc_tick<T>(i2c: &mut T)
+where
+    T: _embedded_hal_blocking_i2c_WriteRead
+        + _embedded_hal_blocking_i2c_Read
+        + _embedded_hal_blocking_i2c_Write,
+{
+    static mut STARTUP: bool = true;
+    static mut PREV_MINUTE: u32 = 0;
+    static mut PREV_HOUR: u32 = 0;
+
+    let (second, minute, hour) = ds3231::get_time(DS3231_ADDR, i2c);
+    let (weekday, day, month, _, _) = ds3231::get_date(DS3231_ADDR, i2c);
+
+    let hour = if ds3231::in_dst(weekday, day, month, hour) {
+        (hour + 1) % 12
+    } else {
+        hour % 12
+    };
+    let hour = if hour == 0 { 12 } else { hour };
+
+    unsafe {
+        if STARTUP || PREV_HOUR / 10 != hour / 10 {
+            fade_in_out_digit(
+                0,
+                if hour / 10 != 0 {
+                    Some((hour / 10) as usize)
+                } else {
+                    None
+                },
+                DIGIT_FADE_DURATION_US,
+                false,
+            )
+        }
+        if STARTUP || PREV_HOUR % 10 != hour % 10 {
+            fade_in_out_digit(1, Some((hour % 10) as usize), DIGIT_FADE_DURATION_US, false);
+        }
+        if STARTUP || PREV_MINUTE / 10 != minute / 10 {
+            fade_in_out_digit(
+                2,
+                Some((minute / 10) as usize),
+                DIGIT_FADE_DURATION_US,
+                false,
+            );
+        }
+        if STARTUP || PREV_MINUTE % 10 != minute % 10 {
+            fade_in_out_digit(
+                3,
+                Some((minute % 10) as usize),
+                DIGIT_FADE_DURATION_US,
+                false,
+            );
+        }
+
+        CLOCK.dot.current_state = match second % 2 {
+            0 => DigitState::Incrementing,
+            1 => DigitState::Decrementing,
+            _ => DigitState::Idle,
+        };
+
+        PREV_MINUTE = minute;
+        PREV_HOUR = hour;
+
+        STARTUP = false;
+    }
+}
+
+pub fn refresh_tick<T>(i2c: &mut T)
+where
+    T: _embedded_hal_blocking_i2c_WriteRead
+        + _embedded_hal_blocking_i2c_Read
+        + _embedded_hal_blocking_i2c_Write,
+{
+}
+
+pub fn rng_tick<T>(i2c: &mut T)
+where
+    T: _embedded_hal_blocking_i2c_WriteRead
+        + _embedded_hal_blocking_i2c_Read
+        + _embedded_hal_blocking_i2c_Write,
+{
+}