M source/src/clock_app.rs => source/src/clock_app.rs +9 -4
@@ 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<dyn ClockButton + Send>; 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::<DisplayView>()).try_into().unwrap();
+ display.set_current_view(new_view);
+ *app.current_view = new_view;
}
_ => (),
}
M source/src/clock_display.rs => source/src/clock_display.rs +29 -18
@@ 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);
+ }
+ }
}
M source/src/clock_display_viewer.rs => source/src/clock_display_viewer.rs +122 -26
@@ 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<usize> for DisplayView {
+ fn try_from(value: usize) -> Result<Self, ()> {
+ 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<usize> for ClockPart {
+ fn try_from(value: usize) -> Result<Self, ()> {
+ if value <= ClockPart::Day as usize {
+ unsafe { core::mem::transmute(value) }
+ } else {
+ Err(())
+ }
+ }
+
+ type Error = ();
+}
+
pub struct ClockDisplayViewer {
clock_display: ClockDisplay,
- views: Vec<Box<dyn DisplayView + Send>>,
- current_view: Option<DisplayViews>,
+ parts: [bool; core::mem::variant_count::<ClockPart>()]
}
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::<ClockPart>()]
}
}
- 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<DisplayViews> {
- 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(())
}
}
D source/src/display_view.rs => source/src/display_view.rs +0 -54
@@ 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<usize> 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<DisplayError> 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>;
-}
D source/src/display_view/clock_display_view.rs => source/src/display_view/clock_display_view.rs +0 -69
@@ 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(())
- }
-}
D source/src/display_view/date_display_view.rs => source/src/display_view/date_display_view.rs +0 -33
@@ 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(())
- }
-}
M source/src/lib.rs => source/src/lib.rs +2 -1
@@ 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;
M source/src/main.rs => source/src/main.rs +5 -6
@@ 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");