From d6c87cb811c8551e769a19bc6e921ed6ff55c8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sun, 6 Aug 2023 22:54:33 +0200 Subject: [PATCH] feat(src): replace DisplayView with hide, show on clock parts The clock is meant to show only clock, so introducing DisplayView trait was an overkill, a simpler solution has been implemented instead. Previous solution did not allow for showing and hiding individual parts, hiding parts may be useful when setting time, to blink the current part being set. --- source/src/clock_app.rs | 13 +- source/src/clock_display.rs | 47 +++--- source/src/clock_display_viewer.rs | 148 +++++++++++++++--- source/src/display_view.rs | 54 ------- source/src/display_view/clock_display_view.rs | 69 -------- source/src/display_view/date_display_view.rs | 33 ---- source/src/lib.rs | 3 +- source/src/main.rs | 11 +- 8 files changed, 167 insertions(+), 211 deletions(-) delete mode 100644 source/src/display_view.rs delete mode 100644 source/src/display_view/clock_display_view.rs delete mode 100644 source/src/display_view/date_display_view.rs diff --git a/source/src/clock_app.rs b/source/src/clock_app.rs index b35f86c..410dd2f 100644 --- a/source/src/clock_app.rs +++ b/source/src/clock_app.rs @@ -5,7 +5,7 @@ use stm32f1xx_hal::rtc::Rtc; use crate::{ brightness_manager::BrightnessManager, button::ButtonState, - clock_display_viewer::ClockDisplayViewer, clock_state::ClockState, display_view::DisplayViews, + clock_display_viewer::{ClockDisplayViewer, DisplayView}, clock_state::ClockState, }; pub struct ClockApp { @@ -14,6 +14,7 @@ pub struct ClockApp { state: ClockState, buttons: [Box; 4], brightness: BrightnessManager, + current_view: DisplayView } struct AppState<'a> { @@ -21,6 +22,7 @@ struct AppState<'a> { display: &'a mut ClockDisplayViewer, state: &'a mut ClockState, brightness: &'a mut BrightnessManager, + current_view: &'a mut DisplayView } trait ClockButton { @@ -47,6 +49,7 @@ impl ClockApp { rtc, display, state, + current_view: DisplayView::ClockView, buttons: [ Box::new(ButtonSwitchView), Box::new(ButtonChangeTime), @@ -83,6 +86,7 @@ impl ClockApp { display: &mut self.display, state: &mut self.state, brightness: &mut self.brightness, + current_view: &mut self.current_view }, ); } @@ -97,9 +101,10 @@ impl ClockButton for ButtonSwitchView { 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()); + let current_view = *app.current_view as usize; + let new_view = ((current_view + 1) % core::mem::variant_count::()).try_into().unwrap(); + display.set_current_view(new_view); + *app.current_view = new_view; } _ => (), } diff --git a/source/src/clock_display.rs b/source/src/clock_display.rs index 55ae9b3..4a6e26c 100644 --- a/source/src/clock_display.rs +++ b/source/src/clock_display.rs @@ -64,10 +64,21 @@ impl ClockDisplay { &mut self, part: DisplayPart, number: u32, - pad: bool, + pad: bool ) -> Result<(), DisplayError> { let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); + + self.show_number_at(offset, size, number, pad) + } + + pub fn show_number_at( + &mut self, + offset: usize, + size: usize, + number: u32, + pad: bool, + ) -> Result<(), DisplayError> { let mut data = self.display.data(); let mut number = number; @@ -148,22 +159,7 @@ impl ClockDisplay { self.display.update() } - fn update_colon(&mut self) { - let data = self.display.data(); - if self.colon { - self.display - .set_digit(COLON_DIGIT_1, data[COLON_DIGIT_1] | 0b1); - self.display - .set_digit(COLON_DIGIT_2, data[COLON_DIGIT_2] | 0b1); - } else { - self.display - .set_digit(COLON_DIGIT_1, data[COLON_DIGIT_1] & 0xFE); - self.display - .set_digit(COLON_DIGIT_2, data[COLON_DIGIT_2] & 0xFE); - } - } - - fn get_part_size(part: DisplayPart) -> usize { + pub fn get_part_size(part: DisplayPart) -> usize { match part { DisplayPart::Whole => SIDE_DISPLAY_1_SIZE + MAIN_DISPLAY_SIZE + SIDE_DISPLAY_2_SIZE, DisplayPart::MainDisplay => MAIN_DISPLAY_SIZE, @@ -172,7 +168,7 @@ impl ClockDisplay { } } - fn get_part_offset(part: DisplayPart) -> usize { + pub fn get_part_offset(part: DisplayPart) -> usize { match part { DisplayPart::Whole => 0, DisplayPart::MainDisplay => MAIN_DISPLAY_OFFSET, @@ -180,4 +176,19 @@ impl ClockDisplay { DisplayPart::SideDisplay2 => SIDE_DISPLAY_2_OFFSET, } } + + fn update_colon(&mut self) { + let data = self.display.data(); + if self.colon { + self.display + .set_digit(COLON_DIGIT_1, data[COLON_DIGIT_1] | 0b1); + self.display + .set_digit(COLON_DIGIT_2, data[COLON_DIGIT_2] | 0b1); + } else { + self.display + .set_digit(COLON_DIGIT_1, data[COLON_DIGIT_1] & 0xFE); + self.display + .set_digit(COLON_DIGIT_2, data[COLON_DIGIT_2] & 0xFE); + } + } } diff --git a/source/src/clock_display_viewer.rs b/source/src/clock_display_viewer.rs index fbaa7b0..ba8160b 100644 --- a/source/src/clock_display_viewer.rs +++ b/source/src/clock_display_viewer.rs @@ -1,57 +1,153 @@ +use core::mem; + use crate::{ - clock_display::ClockDisplay, + clock_display::{ClockDisplay, DisplayPart}, clock_state::ClockState, - display_view::{ - clock_display_view::ClockDisplayView, date_display_view::DateDisplayView, DisplayView, - DisplayViews, - }, }; -use alloc::{boxed::Box, vec, vec::Vec}; use stm32f1xx_hal::timer; +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(usize)] +pub enum DisplayView { + ClockView = 0, + ClockSecondsView = 1, + ClockDateView = 2, + DateView = 3, +} + +impl TryFrom for DisplayView { + fn try_from(value: usize) -> Result { + if value <= DisplayView::DateView as usize { + unsafe { core::mem::transmute(value) } + } else { + Err(()) + } + } + + type Error = (); +} + +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(usize)] +pub enum ClockPart { + Hours = 0, + Minutes = 1, + Seconds = 2, + Year = 3, + Month = 4, + Day = 5, +} + +impl TryFrom for ClockPart { + fn try_from(value: usize) -> Result { + if value <= ClockPart::Day as usize { + unsafe { core::mem::transmute(value) } + } else { + Err(()) + } + } + + type Error = (); +} + pub struct ClockDisplayViewer { clock_display: ClockDisplay, - views: Vec>, - current_view: Option, + parts: [bool; core::mem::variant_count::()] } impl ClockDisplayViewer { pub fn new(clock_display: ClockDisplay) -> Self { Self { clock_display, - views: vec![ - Box::new(ClockDisplayView::new()), - Box::new(ClockDisplayView::with_seconds()), - Box::new(ClockDisplayView::with_date()), - Box::new(DateDisplayView::new()), - ], - current_view: None, + parts: [false; core::mem::variant_count::()] } } - pub fn clock_display(&mut self) -> &mut ClockDisplay { - &mut self.clock_display + pub fn show(&mut self, part: ClockPart) { + self.parts[part as usize] = true; } - pub fn current_view(&self) -> Option { - self.current_view + pub fn hide(&mut self, part: ClockPart) { + self.parts[part as usize] = false; + } + + pub fn hide_all(&mut self) { + for part in self.parts.iter_mut() { + *part = false; + } + + self.clock_display.hide(DisplayPart::MainDisplay); + self.clock_display.hide(DisplayPart::SideDisplay1); + self.clock_display.hide(DisplayPart::SideDisplay2); } - pub fn set_current_view(&mut self, view: DisplayViews) { - self.current_view = Some(view); + pub fn clock_display(&mut self) -> &mut ClockDisplay { + &mut self.clock_display } - pub fn clear_current_view(&mut self) { - self.current_view = None; + pub fn set_current_view(&mut self, view: DisplayView) { + self.hide_all(); + match view { + DisplayView::ClockView => { + self.show(ClockPart::Hours); + self.show(ClockPart::Minutes); + }, + DisplayView::ClockSecondsView => { + self.show(ClockPart::Hours); + self.show(ClockPart::Minutes); + self.show(ClockPart::Seconds); + }, + DisplayView::ClockDateView => { + self.show(ClockPart::Hours); + self.show(ClockPart::Minutes); + self.show(ClockPart::Day); + self.show(ClockPart::Month); + }, + DisplayView::DateView => { + self.show(ClockPart::Day); + self.show(ClockPart::Month); + self.show(ClockPart::Year); + } + } } pub fn update(&mut self, state: &ClockState) -> nb::Result<(), timer::Error> { self.clock_display.update()?; - if let Some(view) = self.current_view { - let view = &mut self.views[view as usize]; - view.update_display(state, &mut self.clock_display).unwrap(); // TODO: get rid of the unwrap + for (i, show) in self.parts.iter().enumerate().filter(|(_, x)| **x) { + if !show { + continue; + } + + let part: ClockPart = ClockPart::try_from(i).unwrap(); + match part { + ClockPart::Day => { + self.clock_display.show_ordinal(DisplayPart::SideDisplay1, state.calendar().day() as u32, true).unwrap(); + }, + ClockPart::Month => { + self.clock_display.show_ordinal(DisplayPart::SideDisplay2, state.calendar().month() as u32, true).unwrap(); + }, + ClockPart::Year => { + self.clock_display.show_number(DisplayPart::MainDisplay, state.calendar().year() as u32, true).unwrap(); + }, + ClockPart::Hours => { + self.clock_display.show_number_at(ClockDisplay::get_part_offset(DisplayPart::MainDisplay), 2, state.calendar().hours() as u32, true).unwrap(); + }, + ClockPart::Minutes => { + self.clock_display.show_number_at(ClockDisplay::get_part_offset(DisplayPart::MainDisplay) + 2, 2, state.calendar().minutes() as u32, true).unwrap(); + }, + ClockPart::Seconds => { + self.clock_display.show_number(DisplayPart::SideDisplay2, state.calendar().seconds() as u32, true).unwrap(); + }, + } } + + if self.parts[ClockPart::Hours as usize] && self.parts[ClockPart::Minutes as usize] { + self.clock_display.set_colon(state.calendar().seconds() % 2 == 0); + } else { + self.clock_display.set_colon(false); + } + Ok(()) } } diff --git a/source/src/display_view.rs b/source/src/display_view.rs deleted file mode 100644 index 8bf7c72..0000000 --- a/source/src/display_view.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::{ - clock_display::{ClockDisplay, DisplayError}, - clock_state::ClockState, -}; - -pub mod clock_display_view; -pub mod date_display_view; - -#[derive(Copy, Clone, PartialEq, Eq)] -#[repr(usize)] -pub enum DisplayViews { - ClockView = 0, - ClockSecondsView = 1, - ClockDateView = 2, - DateView = 3, -} - -impl DisplayViews { - pub fn count() -> usize { - 4 - } -} - -impl From for DisplayViews { - fn from(value: usize) -> Self { - match value { - 0 => Self::ClockView, - 1 => Self::ClockSecondsView, - 2 => Self::ClockDateView, - 3 => Self::DateView, - _ => panic!(), - } - } -} - -#[derive(Debug)] -pub enum DisplayViewError { - Unknown, - DisplayError(DisplayError), -} - -impl From for DisplayViewError { - fn from(value: DisplayError) -> Self { - Self::DisplayError(value) - } -} - -pub trait DisplayView { - fn update_display( - &mut self, - state: &ClockState, - display: &mut ClockDisplay, - ) -> Result<(), DisplayViewError>; -} diff --git a/source/src/display_view/clock_display_view.rs b/source/src/display_view/clock_display_view.rs deleted file mode 100644 index ba54204..0000000 --- a/source/src/display_view/clock_display_view.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::{ - clock_display::{ClockDisplay, DisplayPart}, - clock_state::ClockState, -}; - -use super::{DisplayView, DisplayViewError}; - -pub struct ClockDisplayView { - show_seconds: bool, - show_date: bool, -} - -impl Default for ClockDisplayView { - fn default() -> Self { - Self::new() - } -} - -impl ClockDisplayView { - pub fn new() -> Self { - Self { - show_date: false, - show_seconds: false, - } - } - - pub fn with_seconds() -> Self { - Self { - show_date: false, - show_seconds: true, - } - } - - pub fn with_date() -> Self { - Self { - show_date: true, - show_seconds: false, - } - } -} - -impl DisplayView for ClockDisplayView { - fn update_display( - &mut self, - state: &ClockState, - display: &mut ClockDisplay, - ) -> Result<(), DisplayViewError> { - let calendar = state.calendar(); - - if self.show_seconds { - display.hide(DisplayPart::SideDisplay1); - display.show_number(DisplayPart::SideDisplay2, calendar.seconds() as u32, true)?; - } else if self.show_date { - display.show_ordinal(DisplayPart::SideDisplay1, calendar.day() as u32, true)?; - display.show_ordinal(DisplayPart::SideDisplay2, calendar.month() as u32, true)?; - } else { - display.hide(DisplayPart::SideDisplay1); - display.hide(DisplayPart::SideDisplay2); - } - - display.set_colon(calendar.seconds() % 2 == 0); - display.show_number( - DisplayPart::MainDisplay, - (calendar.hours() as u32) * 100 + (calendar.minutes() as u32), - true, - )?; - Ok(()) - } -} diff --git a/source/src/display_view/date_display_view.rs b/source/src/display_view/date_display_view.rs deleted file mode 100644 index 2446cbb..0000000 --- a/source/src/display_view/date_display_view.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::clock_display::DisplayPart; - -use super::DisplayView; - -pub struct DateDisplayView; - -impl DateDisplayView { - pub fn new() -> Self { - Self - } -} - -impl Default for DateDisplayView { - fn default() -> Self { - Self::new() - } -} - -impl DisplayView for DateDisplayView { - fn update_display( - &mut self, - state: &crate::clock_state::ClockState, - display: &mut crate::clock_display::ClockDisplay, - ) -> Result<(), super::DisplayViewError> { - let calendar = state.calendar(); - - display.show_ordinal(DisplayPart::SideDisplay1, calendar.day() as u32, true)?; - display.show_ordinal(DisplayPart::SideDisplay2, calendar.month() as u32, true)?; - display.show_number(DisplayPart::MainDisplay, calendar.year() as u32, false)?; - display.set_colon(false); - Ok(()) - } -} diff --git a/source/src/lib.rs b/source/src/lib.rs index 6b000a1..6651e94 100644 --- a/source/src/lib.rs +++ b/source/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(test, no_main)] #![no_std] +#![feature(variant_count)] use defmt_rtt as _; // global logger @@ -16,8 +17,8 @@ pub mod clock_display_viewer; pub mod clock_state; pub mod count_down; pub mod display; -pub mod display_view; pub mod linear_interpolation; +pub mod mono_timer; pub mod number_digits; pub mod seven_segments; diff --git a/source/src/main.rs b/source/src/main.rs index 5405d2a..30fc558 100644 --- a/source/src/main.rs +++ b/source/src/main.rs @@ -1,6 +1,7 @@ #![no_std] #![no_main] #![feature(alloc_error_handler)] +#![feature(variant_count)] extern crate alloc; @@ -13,7 +14,6 @@ pub mod clock_display_viewer; pub mod clock_state; pub mod count_down; pub mod display; -pub mod display_view; pub mod linear_interpolation; pub mod number_digits; pub mod seven_segments; @@ -23,7 +23,7 @@ use button::{ActiveHigh, Button, ButtonState}; use calendar::Calendar; use clock_app::{ClockApp, ClockInterrupt}; use clock_display::{ClockDisplay, DisplayPart}; -use clock_display_viewer::ClockDisplayViewer; +use clock_display_viewer::{ClockDisplayViewer, DisplayView}; use clock_state::ClockState; use core::{alloc::Layout, cell::RefCell, convert::Infallible, panic::PanicInfo}; use cortex_m::asm::wfi; @@ -31,7 +31,6 @@ use cortex_m_rt::entry; use count_down::{CountDown, CountDowner}; use critical_section::Mutex; use display::Display; -use display_view::DisplayViews; use embedded_alloc::Heap; use embedded_hal::digital::v2::OutputPin; use fugit::MicrosDurationU32; @@ -291,7 +290,7 @@ fn main() -> ! { &mut afio.mapr, &clocks, ); - display.set_current_view(DisplayViews::ClockSecondsView); + display.set_current_view(DisplayView::ClockView); let mut rtc = match Rtc::restore_or_new(dp.RTC, &mut backup_domain) { Restored(rtc) => rtc, @@ -367,7 +366,7 @@ fn panic(info: &PanicInfo) -> ! { let mut app = APP.borrow_ref_mut(cs); let app = app.as_mut().unwrap(); let display = app.display(); - display.clear_current_view(); + display.hide_all(); let _ = display .clock_display() .show_text(DisplayPart::MainDisplay, "Erro"); @@ -387,7 +386,7 @@ fn oom(_: Layout) -> ! { let mut app = APP.borrow_ref_mut(cs); let app = app.as_mut().unwrap(); let display = app.display(); - display.clear_current_view(); + display.hide_all(); let _ = display .clock_display() .show_text(DisplayPart::MainDisplay, "oom"); -- 2.49.0