clock_generator/firmware/rust/src/screen/mod.rs
finga fdd1f4636d
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fw-rust: Refactor everything
Remove avr-eeprom dependency for now and introduce events.
2022-03-30 22:59:24 +02:00

109 lines
2.4 KiB
Rust

use atmega_hal::{
pac::TC0,
port::{mode::Output, Pin, PB0, PB1},
Spi,
};
mod home;
mod setup;
mod splash;
use crate::{eeprom, lcd::Lcd, Input, BACKLIGHT};
pub use home::Home;
pub use setup::Setup;
pub use splash::Splash;
// TODO: Only update changes instead of whole screen
pub enum Event {
Screen(Screens),
Backlight(u8),
Contrast(u8),
None,
}
pub trait Draw {
fn draw(&self, lcd: &mut Lcd);
}
pub enum Screens {
Splash(Splash),
Home(Home),
Setup(Setup),
}
impl Screens {
pub fn input(&mut self, input: &Input) -> Event {
match self {
Screens::Splash(_) => Event::None,
Screens::Home(home) => home.input(input),
Screens::Setup(setup) => setup.input(input),
}
}
}
pub struct Screen {
lcd: Lcd,
tc0: TC0,
screen: Screens,
}
impl Screen {
pub fn new(tc0: TC0, spi: Spi, cd: Pin<Output, PB0>, rst: Pin<Output, PB1>) -> Self {
Self {
lcd: Lcd::new(spi, cd, rst),
tc0,
screen: Screens::Splash(Splash),
}
}
pub fn init(&mut self) {
// Init display backlight
self.tc0.tccr0a.write(|w| {
w.wgm0().pwm_fast();
w.com0b().match_clear();
w
});
self.tc0.tccr0b.write(|w| {
w.wgm02().set_bit();
w.cs0().prescale_64();
w
});
self.tc0.ocr0a.write(|w| unsafe { w.bits(255) });
self.tc0
.ocr0b
.write(|w| unsafe { w.bits(nb::block!(eeprom::read_byte(&BACKLIGHT)).unwrap()) });
// Init lcd display
self.lcd.init();
self.draw();
}
pub fn draw(&mut self) {
self.lcd.fill_area(0, 0, 102, 8, 0x00);
match &self.screen {
Screens::Splash(splash) => splash.draw(&mut self.lcd),
Screens::Home(home) => home.draw(&mut self.lcd),
Screens::Setup(setup) => setup.draw(&mut self.lcd),
}
}
pub fn input(&mut self, input: &Input) {
match self.screen.input(input) {
Event::Screen(screen) => self.screen = screen,
Event::Backlight(backlight) => self.tc0.ocr0b.write(|w| unsafe { w.bits(backlight) }),
Event::Contrast(contrast) => self.lcd.set_contrast(contrast),
Event::None => {}
}
self.draw();
}
pub fn change(&mut self, screen: Screens) {
self.screen = screen;
self.draw();
}
}