fw-rust: Break everything down in multiple files
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
To reduce length of `main.rs` and therefor improve readability create source files for: - Assets (`assets.rs`): Contains all graphical assets such as the splash screen assets, symbols and the symbol table. - LCD (`lcd.rs`): Contains all lower level things regarding the LCD such as the `Lcd` struct and its implementations. - Screen (`screen/mod.rs`): - Splash (`screen/splash.rs`) - Home (`screen/home.rs`) - Setup (`screen/setup.rs`) In the future it would probably make sense to move the LCD module into the screen module.
This commit is contained in:
parent
91e120b258
commit
c2920ea334
7 changed files with 693 additions and 647 deletions
181
firmware/rust/src/lcd.rs
Normal file
181
firmware/rust/src/lcd.rs
Normal file
|
@ -0,0 +1,181 @@
|
|||
use atmega_hal::{
|
||||
clock::MHz8,
|
||||
delay::Delay,
|
||||
port::{mode::Output, Pin, PB0, PB1},
|
||||
Spi,
|
||||
};
|
||||
use avr_device::interrupt;
|
||||
use embedded_hal::{blocking::delay::DelayMs, spi::FullDuplex};
|
||||
use nb::block;
|
||||
|
||||
use crate::{
|
||||
assets::SYMBOL_TABLE,
|
||||
screen::{Screen, Screens},
|
||||
};
|
||||
|
||||
// TODO: Make `cd` and `rst` pins generic pins
|
||||
pub struct Lcd {
|
||||
pub spi: Spi,
|
||||
pub cd: Pin<Output, PB0>,
|
||||
rst: Pin<Output, PB1>,
|
||||
}
|
||||
|
||||
impl Lcd {
|
||||
pub fn new(spi: Spi, cd: Pin<Output, PB0>, rst: Pin<Output, PB1>) -> Self {
|
||||
Self { spi, cd, rst }
|
||||
}
|
||||
|
||||
pub fn init(&mut self, contrast: u8) {
|
||||
let mut delay = Delay::<MHz8>::new();
|
||||
|
||||
// TODO: Test if delay is really needed
|
||||
delay.delay_ms(1_u8);
|
||||
self.rst.set_high();
|
||||
// TODO: Try to reduce delay to a minimum
|
||||
delay.delay_ms(1_u8);
|
||||
|
||||
block!(self.spi.send(0x40)).unwrap(); // (6) Set Scroll Line: Display start line 0
|
||||
block!(self.spi.send(0xA1)).unwrap(); // (13) Set SEG direction: SEG reverse
|
||||
block!(self.spi.send(0xC0)).unwrap(); // (14) Set COM direction: Normal COM0 - COM63
|
||||
// block!(spi.send(0xA4)).unwrap(); // (10) Set All Pixel On: Disable -> Set All Pixel to ON */
|
||||
block!(self.spi.send(0xA6)).unwrap(); // (11) Set Inverse Display: Display inverse off
|
||||
block!(self.spi.send(0xA2)).unwrap(); // (17) Set LCD Bias Ratio: Set Bias 1/9 (Duty 1/65)
|
||||
block!(self.spi.send(0x2F)).unwrap(); // (5) Set Power Control: Booster, Regulator and Follower on
|
||||
block!(self.spi.send(0x27)).unwrap(); // (8) Set VLCD Resistor Ratio: Set Contrast
|
||||
// block!(spi.send(0xEE)).unwrap(); // (18) Reset Cursor Update Mode
|
||||
block!(self.spi.send(0x81)).unwrap(); // (9) Set Electronic Volume: Set Contrast
|
||||
block!(self.spi.send(contrast)).unwrap(); // (9) Set Electronic Volume: Set Contrast
|
||||
// block!(spi.send(0xFA)).unwrap(); // (25) Set Adv. Program Control 0: Set Temperature compensation curve to -0.11%/°C
|
||||
// block!(spi.send(0x90)).unwrap(); // (25) Set Adv. Program Control 0: Set Temperature compensation curve to -0.11%/°C
|
||||
block!(self.spi.send(0xAF)).unwrap(); // (12) Set Display Enable: Display on
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
}
|
||||
|
||||
pub fn move_cursor(&mut self, segment: u8, page: u8) {
|
||||
assert!(segment < 102);
|
||||
assert!(page < 8);
|
||||
|
||||
block!(self.spi.send(0x0F & segment)).unwrap();
|
||||
block!(self.spi.send(0x10 + (segment >> 4))).unwrap();
|
||||
block!(self.spi.send(0xB0 + page)).unwrap();
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
let mut delay = Delay::<MHz8>::new();
|
||||
|
||||
for page in 0..8 {
|
||||
self.move_cursor(0, page as u8);
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_high();
|
||||
|
||||
for _ in 0..102 {
|
||||
block!(self.spi.send(0x00)).unwrap();
|
||||
}
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_low();
|
||||
}
|
||||
}
|
||||
|
||||
fn fill(&mut self, segment: u8, page: u8, width: u8, data: u8) {
|
||||
assert!(segment + width <= 102);
|
||||
let mut delay = Delay::<MHz8>::new();
|
||||
|
||||
self.move_cursor(segment, page);
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_high();
|
||||
|
||||
for _ in 0..width {
|
||||
block!(self.spi.send(data)).unwrap();
|
||||
}
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_low();
|
||||
}
|
||||
|
||||
pub fn fill_area(&mut self, segment: u8, page: u8, width: u8, height: u8, data: u8) {
|
||||
assert!(page + height <= 8);
|
||||
|
||||
for i in 0..height {
|
||||
self.fill(segment, page + i, width, data);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(&mut self, segment: u8, page: u8, string: &str) {
|
||||
let mut delay = Delay::<MHz8>::new();
|
||||
|
||||
for i in 0..2 {
|
||||
self.move_cursor(segment, page + i);
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_high();
|
||||
|
||||
block!(self.spi.send(0x00)).unwrap();
|
||||
block!(self.spi.send(0x00)).unwrap();
|
||||
for c in string.chars() {
|
||||
for segment in SYMBOL_TABLE[c as usize - 48][i as usize] {
|
||||
block!(self.spi.send(*segment)).unwrap();
|
||||
}
|
||||
block!(self.spi.send(0x00)).unwrap();
|
||||
}
|
||||
block!(self.spi.send(0x00)).unwrap();
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_low();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_inverted(&mut self, segment: u8, page: u8, string: &str) {
|
||||
let mut delay = Delay::<MHz8>::new();
|
||||
|
||||
for i in 0..2 {
|
||||
self.move_cursor(segment, page + i);
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_high();
|
||||
|
||||
block!(self.spi.send(0xFF)).unwrap();
|
||||
block!(self.spi.send(0xFF)).unwrap();
|
||||
for c in string.chars() {
|
||||
for segment in SYMBOL_TABLE[c as usize - 48][i as usize] {
|
||||
block!(self.spi.send(!*segment)).unwrap();
|
||||
}
|
||||
block!(self.spi.send(0xFF)).unwrap();
|
||||
}
|
||||
block!(self.spi.send(0xFF)).unwrap();
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_low();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, screen: &Screens) {
|
||||
interrupt::free(|_cs| {
|
||||
self.clear();
|
||||
|
||||
match screen {
|
||||
Screens::Splash(splash) => {
|
||||
splash.draw(self);
|
||||
}
|
||||
Screens::Home(home) => {
|
||||
home.draw(self);
|
||||
}
|
||||
Screens::Setup(setup) => {
|
||||
setup.draw(self);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue