use stm32f1xx_hal::timer; use crate::{display::Display, seven_segments::SevenSegments}; const MAIN_DISPLAY_OFFSET: usize = 2; const MAIN_DISPLAY_SIZE: usize = 4; const SIDE_DISPLAY_1_OFFSET: usize = 0; const SIDE_DISPLAY_1_SIZE: usize = 2; const SIDE_DISPLAY_2_OFFSET: usize = 6; const SIDE_DISPLAY_2_SIZE: usize = 2; const COLON_DIGIT_1: usize = 3; const COLON_DIGIT_2: usize = 4; pub struct ClockDisplay { display: Display<8>, colon: bool, } #[derive(Copy, Clone)] pub enum DisplayPart { Whole, MainDisplay, SideDisplay1, SideDisplay2, } #[derive(Debug)] pub enum DisplayError { DoesNotFit, } impl ClockDisplay { pub fn new(display: Display<8>) -> Self { Self { display, colon: false, } } pub fn display(&mut self) -> &mut Display<8> { &mut self.display } pub fn show_ordinal( &mut self, part: DisplayPart, number: u32, pad: bool, ) -> Result<(), DisplayError> { self.show_number(part, number, pad)?; let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); let target_index = offset + size - 1; let data = self.display.data()[target_index]; self.display.set_digit(target_index, data | 1); Ok(()) } pub fn show_number( &mut self, part: DisplayPart, number: u32, pad: bool, ) -> Result<(), DisplayError> { let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); let mut data = self.display.data(); let mut number = number; for i in 1..=size { let digit = number % 10; number /= 10; data[offset + size - i] = if number != 0 || digit != 0 || pad { SevenSegments::digit_to_segments(digit as u8) } else { 0 }; } if number > 0 { return Err(DisplayError::DoesNotFit); } self.display.set_data(data); self.update_colon(); Ok(()) } pub fn show_text(&mut self, part: DisplayPart, text: &str) -> Result<(), DisplayError> { let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); if text.len() > size { return Err(DisplayError::DoesNotFit); } let mut data = self.display.data(); for (i, c) in text.chars().enumerate() { data[offset + i] = SevenSegments::letter_to_segments(c); } self.display.set_data(data); self.update_colon(); Ok(()) } pub fn hide(&mut self, part: DisplayPart) { let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); let mut data = self.display.data(); for current_data in data.iter_mut().skip(offset).take(size) { *current_data = 0; } self.display.set_data(data); } pub fn brightness(&self, part: DisplayPart) -> &[u16] { let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); &self.display.ref_brightness()[offset..offset + size] } pub fn set_brightness(&mut self, part: DisplayPart, brightness: u16) { let offset = Self::get_part_offset(part); let size = Self::get_part_size(part); let mut brightnesses = self.display.brightness(); for current_brightness in brightnesses.iter_mut().skip(offset).take(size) { *current_brightness = brightness; } self.display.set_brightness(brightnesses); } pub fn set_colon(&mut self, colon: bool) { self.colon = colon; self.update_colon(); } pub fn update(&mut self) -> nb::Result<(), timer::Error> { 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 { match part { DisplayPart::Whole => SIDE_DISPLAY_1_SIZE + MAIN_DISPLAY_SIZE + SIDE_DISPLAY_2_SIZE, DisplayPart::MainDisplay => MAIN_DISPLAY_SIZE, DisplayPart::SideDisplay1 => SIDE_DISPLAY_1_SIZE, DisplayPart::SideDisplay2 => SIDE_DISPLAY_2_SIZE, } } fn get_part_offset(part: DisplayPart) -> usize { match part { DisplayPart::Whole => 0, DisplayPart::MainDisplay => MAIN_DISPLAY_OFFSET, DisplayPart::SideDisplay1 => SIDE_DISPLAY_1_OFFSET, DisplayPart::SideDisplay2 => SIDE_DISPLAY_2_OFFSET, } } }