use core::marker::PhantomData; use alloc::boxed::Box; use stm32f1xx_hal::rtc::Rtc; use crate::{ brightness_manager::BrightnessManager, button::ButtonState, clock_display_viewer::ClockDisplayViewer, clock_state::ClockState, display_view::DisplayViews, }; pub struct ClockApp { rtc: Rtc, display: ClockDisplayViewer, state: ClockState, buttons: [Box; 4], brightness: BrightnessManager, } struct AppState<'a> { rtc: &'a mut Rtc, display: &'a mut ClockDisplayViewer, state: &'a mut ClockState, brightness: &'a mut BrightnessManager, } trait ClockButton { fn handle(&self, state: ButtonState, state: AppState); } struct ButtonSwitchView; struct ButtonChangeTime; struct Up; struct Down; struct ButtonBrightness { direction: PhantomData, } pub enum ClockInterrupt { Rtc, DisplayTimer, } impl ClockApp { pub fn new(rtc: Rtc, display: ClockDisplayViewer, state: ClockState) -> Self { Self { rtc, display, state, buttons: [ Box::new(ButtonSwitchView), Box::new(ButtonChangeTime), Box::new(ButtonBrightness:: { direction: PhantomData::, }), Box::new(ButtonBrightness:: { direction: PhantomData::, }), ], brightness: BrightnessManager::new(), } } pub fn interrupt(&mut self, interrupt: ClockInterrupt) { match interrupt { ClockInterrupt::Rtc => { self.state.second_elapsed(); self.rtc.clear_second_flag(); } ClockInterrupt::DisplayTimer => { let _ = self.display.update(&self.state); self.brightness.update(&self.state); self.brightness.apply_brightness(&mut self.display); } } } pub fn handle_button(&mut self, index: usize, state: ButtonState) { self.buttons[index].handle( state, AppState { rtc: &mut self.rtc, display: &mut self.display, state: &mut self.state, brightness: &mut self.brightness, }, ); } pub fn display(&mut self) -> &mut ClockDisplayViewer { &mut self.display } } impl ClockButton for ButtonSwitchView { fn handle(&self, state: ButtonState, app: AppState) { match state { ButtonState::JustPressed => { let display = app.display; let current_view = display.current_view().unwrap_or(DisplayViews::ClockView) as usize; display.set_current_view(((current_view + 1) % DisplayViews::count()).into()); } _ => (), } } } impl ClockButton for ButtonBrightness { fn handle(&self, state: ButtonState, app: AppState) { match state { ButtonState::JustPressed => { app.brightness .set_brightness(app.brightness.brightness() as i8 - 10); } _ => (), } } } impl ClockButton for ButtonBrightness { fn handle(&self, state: ButtonState, app: AppState) { match state { ButtonState::JustPressed => { app.brightness .set_brightness(app.brightness.brightness() as i8 + 10); } _ => (), } } } impl ClockButton for ButtonChangeTime { fn handle(&self, state: ButtonState, app: AppState) { match state { ButtonState::JustPressed => { app.rtc.set_time(app.rtc.current_time() + 2); } _ => (), } } }