|
@@ -1,6 +1,6 @@
|
|
|
-use core::{cell::RefCell, ops::DerefMut};
|
|
|
+use core::ops::DerefMut;
|
|
|
|
|
|
-use cortex_m::interrupt::{free, Mutex};
|
|
|
+use cortex_m::interrupt::free;
|
|
|
use stm32l4xx_hal::{
|
|
|
prelude::{
|
|
|
_embedded_hal_blocking_i2c_Read, _embedded_hal_blocking_i2c_Write,
|
|
@@ -9,7 +9,7 @@ use stm32l4xx_hal::{
|
|
|
timer::Event,
|
|
|
};
|
|
|
|
|
|
-use crate::{ds3231, pca9685};
|
|
|
+use crate::pca9685;
|
|
|
|
|
|
pub const DS3231_ADDR: u8 = 0x68;
|
|
|
pub const TUSB322_ADDR: u8 = 0x47;
|
|
@@ -208,9 +208,7 @@ impl Tube {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static CLOCK: Mutex<RefCell<Clock>> = Mutex::new(RefCell::new(Clock::default()));
|
|
|
-
|
|
|
-struct Clock {
|
|
|
+pub struct Clock {
|
|
|
tubes: [Tube; NUM_TUBES],
|
|
|
dot: Digit,
|
|
|
minute: Option<u32>,
|
|
@@ -218,7 +216,7 @@ struct Clock {
|
|
|
}
|
|
|
|
|
|
impl Clock {
|
|
|
- const fn default() -> Self {
|
|
|
+ pub const fn default() -> Self {
|
|
|
const TUBE_INIT: Tube = Tube::default();
|
|
|
Self {
|
|
|
tubes: [TUBE_INIT; NUM_TUBES],
|
|
@@ -416,6 +414,16 @@ impl Clock {
|
|
|
cycle_ended
|
|
|
}
|
|
|
|
|
|
+ // Start cycling sequence for the given tube to prevent long term damage from cathode poisoning
|
|
|
+ pub fn cycle_start(&mut self, tube: usize) {
|
|
|
+ self.tubes[tube].cycle = Some(CycleSettings {
|
|
|
+ last_digit: self.tubes[tube].last_digit,
|
|
|
+ next_digit: 0,
|
|
|
+ iteration: CYCLE_ITERATIONS,
|
|
|
+ last_fade_duration: DIGIT_FADE_DURATION_MS,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
// Writes updated PWM values to each PCA9685
|
|
|
pub fn write_i2c<T>(&mut self, i2c: &mut T)
|
|
|
where
|
|
@@ -532,96 +540,6 @@ impl Clock {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// Periodically called to update the display with a new time
|
|
|
-pub fn rtc_interrupt<T>(i2c: &mut T)
|
|
|
-where
|
|
|
- T: _embedded_hal_blocking_i2c_WriteRead
|
|
|
- + _embedded_hal_blocking_i2c_Read
|
|
|
- + _embedded_hal_blocking_i2c_Write,
|
|
|
-{
|
|
|
- // Read new time from DS3231
|
|
|
- let (second, minute, hour) = ds3231::get_time(DS3231_ADDR, i2c);
|
|
|
- let (weekday, day, month, _, _) = ds3231::get_date(DS3231_ADDR, i2c);
|
|
|
-
|
|
|
- // Calculate new values and account for DST
|
|
|
- let hour = if ds3231::in_dst(weekday, day, month, hour) { (hour + 1) % 12 } else { hour % 12 };
|
|
|
- let hour = if hour == 0 { 12 } else { hour };
|
|
|
-
|
|
|
- free(|cs| {
|
|
|
- let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
|
|
|
- let clock = clock_ref.deref_mut();
|
|
|
- clock.rtc_tick(second, minute, hour);
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-// Periodically called to trigger a display refresh
|
|
|
-pub fn fps_interrupt<T>(i2c: &mut T)
|
|
|
-where
|
|
|
- T: _embedded_hal_blocking_i2c_WriteRead
|
|
|
- + _embedded_hal_blocking_i2c_Read
|
|
|
- + _embedded_hal_blocking_i2c_Write,
|
|
|
-{
|
|
|
- free(|cs| {
|
|
|
- let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
|
|
|
- let clock = clock_ref.deref_mut();
|
|
|
-
|
|
|
- // Compute updates for non-static digits
|
|
|
- let updated = clock.fps_tick();
|
|
|
-
|
|
|
- // Write new values if values have changed, otherwise disable the refresh timer
|
|
|
- if updated {
|
|
|
- clock.write_i2c(i2c);
|
|
|
- free(|cs| {
|
|
|
- let mut timer_ref = super::FPS_TIMER.borrow(cs).borrow_mut();
|
|
|
- if let Some(ref mut timer) = timer_ref.deref_mut() {
|
|
|
- timer.clear_interrupt(Event::TimeOut);
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- free(|cs| {
|
|
|
- let mut timer_ref = super::FPS_TIMER.borrow(cs).borrow_mut();
|
|
|
- if let Some(ref mut timer) = timer_ref.deref_mut() {
|
|
|
- timer.unlisten(Event::TimeOut);
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-// Periodically called during a cycle sequence to increment through digits
|
|
|
-// Returns true if the cycle sequence has completed
|
|
|
-pub fn cycle_interrupt() -> bool {
|
|
|
- free(|cs| {
|
|
|
- let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
|
|
|
- let clock = clock_ref.deref_mut();
|
|
|
-
|
|
|
- clock.cycle_tick()
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// Start cycling sequence for the given tube to prevent long term damage from cathode poisoning
|
|
|
-pub fn cycle_start(tube: usize) {
|
|
|
- free(|cs| {
|
|
|
- let mut clock_ref = CLOCK.borrow(cs).borrow_mut();
|
|
|
- let clock = clock_ref.deref_mut();
|
|
|
-
|
|
|
- clock.tubes[tube].cycle = Some(CycleSettings {
|
|
|
- last_digit: clock.tubes[tube].last_digit,
|
|
|
- next_digit: 0,
|
|
|
- iteration: CYCLE_ITERATIONS,
|
|
|
- last_fade_duration: DIGIT_FADE_DURATION_MS,
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- // Start the timer to cycle through individual digits
|
|
|
- free(|cs| {
|
|
|
- let mut cycle_timer_ref = super::CYCLE_TIMER.borrow(cs).borrow_mut();
|
|
|
- if let Some(ref mut cycle_timer) = cycle_timer_ref.deref_mut() {
|
|
|
- cycle_timer.listen(Event::TimeOut);
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
#[cfg(test)]
|
|
|
mod test {
|
|
|
use super::*;
|