fw-rust: Refactor everything
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Remove avr-eeprom dependency for now and introduce events.
This commit is contained in:
finga 2022-03-30 19:29:32 +02:00
parent 6cd8df515d
commit fdd1f4636d
9 changed files with 459 additions and 263 deletions

View file

@ -1,4 +1,4 @@
use super::{Screen, Screens, Setup, Splash};
use super::{Draw, Event, Screens, Setup, Splash};
use crate::{lcd::Lcd, Input};
enum Selection {
@ -19,39 +19,39 @@ impl Home {
}
}
pub fn input(&self, input: &Input) -> Screens {
Screens::Home(Self {
active: match self.active {
Selection::Ch1 => match input {
Input::Next => Selection::Ch2,
Input::Previous => Selection::Setup,
Input::Select => return Screens::Splash(Splash),
Input::Back => Selection::Ch1,
},
Selection::Ch2 => match input {
Input::Next => Selection::Ch3,
Input::Previous => Selection::Ch1,
Input::Select => return Screens::Splash(Splash),
Input::Back => Selection::Ch2,
},
Selection::Ch3 => match input {
Input::Next => Selection::Setup,
Input::Previous => Selection::Ch2,
Input::Select => return Screens::Splash(Splash),
Input::Back => Selection::Ch3,
},
Selection::Setup => match input {
Input::Next => Selection::Ch1,
Input::Previous => Selection::Ch3,
Input::Select => return Screens::Setup(Setup::new()),
Input::Back => Selection::Setup,
},
pub fn input(&mut self, input: &Input) -> Event {
self.active = match self.active {
Selection::Ch1 => match input {
Input::Next => Selection::Ch2,
Input::Previous => Selection::Setup,
Input::Select => return Event::Screen(Screens::Splash(Splash)),
Input::Back => Selection::Ch1,
},
})
Selection::Ch2 => match input {
Input::Next => Selection::Ch3,
Input::Previous => Selection::Ch1,
Input::Select => return Event::Screen(Screens::Splash(Splash)),
Input::Back => Selection::Ch2,
},
Selection::Ch3 => match input {
Input::Next => Selection::Setup,
Input::Previous => Selection::Ch2,
Input::Select => return Event::Screen(Screens::Splash(Splash)),
Input::Back => Selection::Ch3,
},
Selection::Setup => match input {
Input::Next => Selection::Ch1,
Input::Previous => Selection::Ch3,
Input::Select => return Event::Screen(Screens::Setup(Setup::new())),
Input::Back => Selection::Setup,
},
};
Event::None
}
}
impl Screen for Home {
impl Draw for Home {
fn draw(&self, lcd: &mut Lcd) {
match &self.active {
Selection::Ch1 => {

View file

@ -1,15 +1,28 @@
use atmega_hal::{
pac::TC0,
port::{mode::Output, Pin, PB0, PB1},
Spi,
};
mod home;
mod setup;
mod splash;
use crate::{lcd::Lcd, Input};
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 trait Screen {
pub enum Event {
Screen(Screens),
Backlight(u8),
Contrast(u8),
None,
}
pub trait Draw {
fn draw(&self, lcd: &mut Lcd);
}
@ -20,11 +33,76 @@ pub enum Screens {
}
impl Screens {
pub fn input(&mut self, input: &Input) {
pub fn input(&mut self, input: &Input) -> Event {
match self {
Screens::Splash(_) => {}
Screens::Home(home) => *self = home.input(input),
Screens::Setup(setup) => *self = setup.input(input),
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();
}
}

View file

@ -1,84 +1,164 @@
use super::{Home, Screen, Screens, Splash};
use crate::{lcd::Lcd, Input, BACKLIGHT, CONTRAST};
use core::sync::atomic::Ordering;
use super::{Draw, Event, Home, Screens};
use crate::{eeprom, lcd::Lcd, Input, BACKLIGHT, CONTRAST};
enum Selection {
Contrast,
Backlight,
BacklightEdit,
Contrast,
ContrastEdit,
Back,
}
pub struct Setup {
active: Selection,
backlight: u8,
contrast: u8,
}
impl Setup {
pub fn new() -> Self {
Self {
active: Selection::Contrast,
active: Selection::Backlight,
backlight: nb::block!(eeprom::read_byte(&BACKLIGHT)).unwrap(),
contrast: nb::block!(eeprom::read_byte(&CONTRAST)).unwrap(),
}
}
pub fn input(&self, input: &Input) -> Screens {
Screens::Setup(Self {
active: match self.active {
Selection::Contrast => match input {
Input::Next => Selection::Backlight,
Input::Previous => Selection::Back,
Input::Select => return Screens::Splash(Splash),
Input::Back => return Screens::Home(Home::new()),
},
Selection::Backlight => match input {
Input::Next => Selection::Back,
Input::Previous => Selection::Contrast,
Input::Select => return Screens::Splash(Splash),
Input::Back => return Screens::Home(Home::new()),
},
Selection::Back => match input {
Input::Next => Selection::Contrast,
Input::Previous => Selection::Backlight,
Input::Select => return Screens::Home(Home::new()),
Input::Back => return Screens::Home(Home::new()),
},
pub fn input(&mut self, input: &Input) -> Event {
self.active = match self.active {
Selection::Backlight => match input {
Input::Next => Selection::Contrast,
Input::Previous => Selection::Back,
Input::Select => Selection::BacklightEdit,
Input::Back => return Event::Screen(Screens::Home(Home::new())),
},
})
Selection::BacklightEdit => match input {
Input::Next => {
self.backlight = if self.backlight == u8::MAX {
u8::MIN
} else {
self.backlight + 1
};
return Event::Backlight(self.backlight);
}
Input::Previous => {
self.backlight = if self.backlight == u8::MIN {
u8::MAX
} else {
self.backlight - 1
};
return Event::Backlight(self.backlight);
}
Input::Select => {
nb::block!(eeprom::write_byte(&BACKLIGHT, self.backlight)).unwrap();
Selection::Backlight
}
Input::Back => {
self.active = Selection::Backlight;
self.backlight = nb::block!(eeprom::read_byte(&BACKLIGHT)).unwrap();
return Event::Backlight(self.backlight);
}
},
Selection::Contrast => match input {
Input::Next => Selection::Back,
Input::Previous => Selection::Backlight,
Input::Select => Selection::ContrastEdit,
Input::Back => return Event::Screen(Screens::Home(Home::new())),
},
Selection::ContrastEdit => match input {
Input::Next => {
self.contrast = if self.contrast >= 63 {
u8::MIN
} else {
self.contrast + 1
};
return Event::Contrast(self.contrast);
}
Input::Previous => {
self.contrast = if self.contrast == u8::MIN {
63
} else {
self.contrast - 1
};
return Event::Contrast(self.contrast);
}
Input::Select => {
nb::block!(eeprom::write_byte(&CONTRAST, self.contrast)).unwrap();
Selection::Contrast
}
Input::Back => {
self.active = Selection::Contrast;
self.contrast = nb::block!(eeprom::read_byte(&CONTRAST)).unwrap();
return Event::Contrast(self.contrast);
}
},
Selection::Back => match input {
Input::Next => Selection::Backlight,
Input::Previous => Selection::Contrast,
Input::Select => return Event::Screen(Screens::Home(Home::new())),
Input::Back => return Event::Screen(Screens::Home(Home::new())),
},
};
Event::None
}
}
impl Screen for Setup {
impl Draw for Setup {
fn draw(&self, lcd: &mut Lcd) {
let contrast = CONTRAST.load(Ordering::SeqCst);
let backlight = BACKLIGHT.load(Ordering::SeqCst);
match &self.active {
Selection::Contrast => {
lcd.fill_area(0, 0, 33, 2, 0xFF);
lcd.print_inverted(33, 0, "SETUP");
lcd.fill_area(69, 0, 33, 2, 0xFF);
lcd.print_inverted(0, 2, "CONTRAST:");
lcd.print_u8(89, 2, 2, contrast);
lcd.print(0, 4, "BACKLIGHT:");
lcd.print_u8(83, 2, 3, backlight);
lcd.print(0, 2, "BACKLIGHT:");
lcd.print_u8(81, 2, 3, self.backlight);
lcd.print_inverted(0, 4, "CONTRAST:");
lcd.print_u8(87, 4, 2, self.contrast);
lcd.print(36, 6, "BACK");
}
Selection::ContrastEdit => {
lcd.fill_area(0, 0, 33, 2, 0xFF);
lcd.print_inverted(33, 0, "SETUP");
lcd.fill_area(69, 0, 33, 2, 0xFF);
lcd.print(0, 2, "BACKLIGHT:");
lcd.print_u8(81, 2, 3, self.backlight);
lcd.print(0, 4, "CONTRAST:");
lcd.print_u8_inverted(87, 4, 2, self.contrast);
lcd.print(36, 6, "BACK");
}
Selection::Backlight => {
lcd.fill_area(0, 0, 33, 2, 0xFF);
lcd.print_inverted(33, 0, "SETUP");
lcd.fill_area(69, 0, 33, 2, 0xFF);
lcd.print(0, 2, "CONTRAST:");
lcd.print_u8(89, 2, 2, contrast);
lcd.print_inverted(0, 4, "BACKLIGHT:");
lcd.print_u8(83, 2, 3, backlight);
lcd.print_inverted(0, 2, "BACKLIGHT:");
lcd.print_u8(81, 2, 3, self.backlight);
lcd.print(0, 4, "CONTRAST:");
lcd.print_u8(87, 4, 2, self.contrast);
lcd.print(36, 6, "BACK");
}
Selection::BacklightEdit => {
lcd.fill_area(0, 0, 33, 2, 0xFF);
lcd.print_inverted(33, 0, "SETUP");
lcd.fill_area(69, 0, 33, 2, 0xFF);
lcd.print(0, 2, "BACKLIGHT:");
lcd.print_u8_inverted(81, 2, 3, self.backlight);
lcd.print(0, 4, "CONTRAST:");
lcd.print_u8(87, 4, 2, self.contrast);
lcd.print(36, 6, "BACK");
}
Selection::Back => {
lcd.fill_area(0, 0, 33, 2, 0xFF);
lcd.print_inverted(33, 0, "SETUP");
lcd.fill_area(69, 0, 33, 2, 0xFF);
lcd.print(0, 2, "CONTRAST:");
lcd.print_u8(89, 2, 2, contrast);
lcd.print(0, 4, "BACKLIGHT:");
lcd.print_u8(83, 2, 3, backlight);
lcd.print(0, 2, "BACKLIGHT:");
lcd.print_u8(81, 2, 3, self.backlight);
lcd.print(0, 4, "CONTRAST:");
lcd.print_u8(87, 4, 2, self.contrast);
lcd.print_inverted(36, 6, "BACK");
}
}

View file

@ -1,4 +1,4 @@
use super::Screen;
use super::Draw;
use crate::{
assets::{ONDERS_ORG, SACRED_CHAO},
lcd::Lcd,
@ -9,7 +9,7 @@ use nb::block;
pub struct Splash;
impl Screen for Splash {
impl Draw for Splash {
fn draw(&self, lcd: &mut Lcd) {
let mut delay = Delay::<MHz8>::new();