From 343b95dc780624c9766784ac4108de7cd6a9126d Mon Sep 17 00:00:00 2001 From: finga Date: Sun, 10 Apr 2022 18:09:35 +0200 Subject: [PATCH] fw-rust: Refactor printing to the LCD Pass iterators for control and display data to the printing function instead of just printing it. --- firmware/rust/src/lcd.rs | 183 +++++++++------------------- firmware/rust/src/screen/channel.rs | 58 ++++----- firmware/rust/src/screen/home.rs | 32 ++--- firmware/rust/src/screen/setup.rs | 52 ++++---- 4 files changed, 127 insertions(+), 198 deletions(-) diff --git a/firmware/rust/src/lcd.rs b/firmware/rust/src/lcd.rs index d6d86d0..dc8f744 100644 --- a/firmware/rust/src/lcd.rs +++ b/firmware/rust/src/lcd.rs @@ -3,7 +3,7 @@ use atmega_hal::{ port::{mode::Output, Pin, PB0, PB1}, Spi, }; -use core::convert::TryInto; +use core::{convert::TryInto, iter}; use embedded_hal::{blocking::delay::DelayUs, spi::FullDuplex}; use nb::block; @@ -21,10 +21,28 @@ impl Lcd { Self { spi, cd, rst } } - pub fn init(&mut self) { - self.rst.set_high(); + pub fn control<'a>(&mut self, data: impl Iterator) { + data.for_each(|d| block!(self.spi.send(*d)).unwrap()); + } - let init_sequence = [ + pub fn display<'a>(&mut self, invert: bool, data: impl Iterator) { + let mut delay = Delay::::new(); + + delay.delay_us(5_u8); + self.cd.set_high(); + + if invert { + data.for_each(|d| block!(self.spi.send(!*d)).unwrap()); + } else { + data.for_each(|d| block!(self.spi.send(*d)).unwrap()); + } + + delay.delay_us(5_u8); + self.cd.set_low(); + } + + fn init_sequence() -> [u8; 13] { + [ 0x40, // (6) Set Scroll Line: Display start line 0 0xA1, // (13) Set SEG direction: SEG reverse 0xC0, // (14) Set COM direction: Normal COM0 - COM63 @@ -38,47 +56,36 @@ impl Lcd { 0xFA, // (25) Set Adv. Program Control 0: Set Temperature compensation curve to -0.11%/°C 0x90, // (25) Set Adv. Program Control 0: Set Temperature compensation curve to -0.11%/°C 0xAF, // (12) Set Display Enable: Display on - ]; + ] + } - for i in init_sequence.iter() { - block!(self.spi.send(*i)).unwrap(); - } + pub fn init(&mut self) { + self.rst.set_high(); + self.control(Lcd::init_sequence().iter()); } pub fn set_contrast(&mut self, contrast: u8) { assert!(contrast <= 63); - block!(self.spi.send(0x81)).unwrap(); // (9) Set Electronic Volume: Set Contrast - block!(self.spi.send(contrast)).unwrap(); // (9) Set Electronic Volume: Set Contrast + self.control([0x81, contrast].iter()); } 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(); + self.control([0x0F & segment, 0x10 + (segment >> 4), 0xB0 + page].iter()); } fn fill(&mut self, segment: u8, page: u8, width: u8, data: u8) { assert!(segment + width <= 102); - let mut delay = Delay::::new(); self.move_cursor(segment, page); - - delay.delay_us(5_u8); - self.cd.set_high(); - - for _ in 0..width { - block!(self.spi.send(data)).unwrap(); - } - - delay.delay_us(5_u8); - self.cd.set_low(); + self.display(false, iter::repeat(&data).take(width.into())); } pub fn fill_area(&mut self, segment: u8, page: u8, width: u8, height: u8, data: u8) { + assert!(segment + width <= 102); assert!(page + height <= 8); for i in 0..height { @@ -86,57 +93,25 @@ impl Lcd { } } - pub fn print(&mut self, segment: u8, page: u8, string: &str) { - let mut delay = Delay::::new(); - + pub fn print(&mut self, segment: u8, page: u8, invert: bool, string: &str) { for i in 0..2 { self.move_cursor(segment, page + i); - - delay.delay_us(5_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 - 46][i as usize] { - block!(self.spi.send(*segment)).unwrap(); - } - block!(self.spi.send(0x00)).unwrap(); - } - block!(self.spi.send(0x00)).unwrap(); - - delay.delay_us(5_u8); - self.cd.set_low(); + self.display( + invert, + [0x00, 0x00] + .iter() + .chain(string.chars().flat_map(|c| { + SYMBOL_TABLE[c as usize - 46][i as usize] + .iter() + .chain(&[0x00]) + })) + .chain(&[0x00]), + ); } } - pub fn print_inverted(&mut self, segment: u8, page: u8, string: &str) { - let mut delay = Delay::::new(); - - for i in 0..2 { - self.move_cursor(segment, page + i); - - delay.delay_us(5_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 - 46][i as usize] { - block!(self.spi.send(!*segment)).unwrap(); - } - block!(self.spi.send(0xFF)).unwrap(); - } - block!(self.spi.send(0xFF)).unwrap(); - - delay.delay_us(5_u8); - self.cd.set_low(); - } - } - - pub fn print_u8(&mut self, segment: u8, page: u8, digits: u8, data: u8) { + pub fn print_u8(&mut self, segment: u8, page: u8, digits: u8, invert: bool, data: u8) { assert!(digits <= 3); - let mut delay = Delay::::new(); let mut array = [0_usize; 3]; for (i, item) in array.iter_mut().enumerate() { @@ -146,53 +121,17 @@ impl Lcd { for i in 0..2 { self.move_cursor(segment, page + i); - - delay.delay_us(5_u8); - self.cd.set_high(); - - block!(self.spi.send(0x00)).unwrap(); - block!(self.spi.send(0x00)).unwrap(); - for j in 3 - digits..3 { - for segment in SYMBOL_TABLE[array[j as usize]][i as usize] { - block!(self.spi.send(*segment)).unwrap(); - } - block!(self.spi.send(0x00)).unwrap(); - } - block!(self.spi.send(0x00)).unwrap(); - - delay.delay_us(5_u8); - self.cd.set_low(); - } - } - - pub fn print_u8_inverted(&mut self, segment: u8, page: u8, digits: u8, data: u8) { - assert!(digits <= 3); - let mut delay = Delay::::new(); - - let mut array = [0usize; 3]; - for (i, item) in array.iter_mut().enumerate() { - *item = (((data / 10_u8.pow(i.try_into().unwrap())) % 10) + 2).into(); - } - array.reverse(); - - for i in 0..2 { - self.move_cursor(segment, page + i); - - delay.delay_us(5_u8); - self.cd.set_high(); - - block!(self.spi.send(0xFF)).unwrap(); - block!(self.spi.send(0xFF)).unwrap(); - for j in 3 - digits..3 { - for segment in SYMBOL_TABLE[array[j as usize]][i as usize] { - block!(self.spi.send(!*segment)).unwrap(); - } - block!(self.spi.send(0xFF)).unwrap(); - } - block!(self.spi.send(0xFF)).unwrap(); - - delay.delay_us(5_u8); - self.cd.set_low(); + self.display( + invert, + [0x00, 0x00] + .iter() + .chain(array.iter().flat_map(|c| { + SYMBOL_TABLE[array[*c as usize]][i as usize] + .iter() + .chain(&[0x00]) + })) + .chain(&[0x00]), + ); } } @@ -320,17 +259,7 @@ impl Lcd { } pub fn print_icon(&mut self, segment: u8, page: u8, symbol: &[u8]) { - let mut delay = Delay::::new(); self.move_cursor(segment, page); - - delay.delay_us(5_u8); - self.cd.set_high(); - - for c in symbol { - block!(self.spi.send(*c)).unwrap(); - } - - delay.delay_us(5_u8); - self.cd.set_low(); + self.display(false, symbol.iter()); } } diff --git a/firmware/rust/src/screen/channel.rs b/firmware/rust/src/screen/channel.rs index 0ee5dc3..b634794 100644 --- a/firmware/rust/src/screen/channel.rs +++ b/firmware/rust/src/screen/channel.rs @@ -111,13 +111,13 @@ impl Channel { fn draw_enabled(&self, lcd: &mut Lcd, inverted: bool) { if inverted { match self.channel.enabled { - false => lcd.print_inverted(13, 4, "OFF"), - true => lcd.print_inverted(16, 4, "ON"), + false => lcd.print(13, 4, true, "OFF"), + true => lcd.print(16, 4, true, "ON"), } } else { match self.channel.enabled { - false => lcd.print(13, 4, "OFF"), - true => lcd.print(16, 4, "ON"), + false => lcd.print(13, 4, false, "OFF"), + true => lcd.print(16, 4, false, "ON"), } } } @@ -125,66 +125,66 @@ impl Channel { pub fn draw(&self, lcd: &mut Lcd) { lcd.fill_area(0, 0, 19, 2, 0xFF); match self.channel.output { - ClockOutput::Clk0 => lcd.print_inverted(19, 0, "CHANNEL_1"), - ClockOutput::Clk1 => lcd.print_inverted(19, 0, "CHANNEL_2"), - ClockOutput::Clk2 => lcd.print_inverted(19, 0, "CHANNEL_3"), + ClockOutput::Clk0 => lcd.print(19, 0, true, "CHANNEL_1"), + ClockOutput::Clk1 => lcd.print(19, 0, true, "CHANNEL_2"), + ClockOutput::Clk2 => lcd.print(19, 0, true, "CHANNEL_3"), _ => unimplemented!(), } lcd.fill_area(83, 0, 19, 2, 0xFF); match &self.active { Selection::Frequency => { - lcd.print_inverted(0, 2, "FREQ:"); + lcd.print(0, 2, true, "FREQ:"); lcd.print_freq(39, 2, self.channel.freq); self.draw_enabled(lcd, false); match self.channel.pll { - PLL::A => lcd.print(59, 4, "PLL_A"), - PLL::B => lcd.print(59, 4, "PLL_B"), + PLL::A => lcd.print(59, 4, false, "PLL_A"), + PLL::B => lcd.print(59, 4, false, "PLL_B"), } - lcd.print(36, 6, "BACK"); + lcd.print(36, 6, false, "BACK"); } Selection::FrequencyDigit(digit) | Selection::Digit(digit) => { - lcd.print(0, 2, "FREQ:"); + lcd.print(0, 2, false, "FREQ:"); lcd.print_freq_digit(39, 2, self.channel.freq, *digit); self.draw_enabled(lcd, false); match self.channel.pll { - PLL::A => lcd.print(59, 4, "PLL_A"), - PLL::B => lcd.print(59, 4, "PLL_B"), + PLL::A => lcd.print(59, 4, false, "PLL_A"), + PLL::B => lcd.print(59, 4, false, "PLL_B"), } - lcd.print(36, 6, "BACK"); + lcd.print(36, 6, false, "BACK"); } Selection::Enabled => { - lcd.print(0, 2, "FREQ:"); + lcd.print(0, 2, false, "FREQ:"); lcd.print_freq(39, 2, self.channel.freq); self.draw_enabled(lcd, true); match self.channel.pll { - PLL::A => lcd.print(59, 4, "PLL_A"), - PLL::B => lcd.print(59, 4, "PLL_B"), + PLL::A => lcd.print(59, 4, false, "PLL_A"), + PLL::B => lcd.print(59, 4, false, "PLL_B"), } - lcd.print(36, 6, "BACK"); + lcd.print(36, 6, false, "BACK"); } Selection::Pll => { - lcd.print(0, 2, "FREQ:"); + lcd.print(0, 2, false, "FREQ:"); lcd.print_freq(39, 2, self.channel.freq); self.draw_enabled(lcd, false); match self.channel.pll { - PLL::A => lcd.print_inverted(59, 4, "PLL_A"), - PLL::B => lcd.print_inverted(59, 4, "PLL_B"), + PLL::A => lcd.print(59, 4, true, "PLL_A"), + PLL::B => lcd.print(59, 4, true, "PLL_B"), } - lcd.print(36, 6, "BACK"); + lcd.print(36, 6, false, "BACK"); } Selection::Back => { - lcd.print(0, 2, "FREQ:"); + lcd.print(0, 2, false, "FREQ:"); lcd.print_freq(39, 2, self.channel.freq); match self.channel.enabled { - false => lcd.print(13, 4, "OFF"), - true => lcd.print(16, 4, "ON"), + false => lcd.print(13, 4, false, "OFF"), + true => lcd.print(16, 4, false, "ON"), } match self.channel.pll { - PLL::A => lcd.print(59, 4, "PLL_A"), - PLL::B => lcd.print(59, 4, "PLL_B"), + PLL::A => lcd.print(59, 4, false, "PLL_A"), + PLL::B => lcd.print(59, 4, false, "PLL_B"), } - lcd.print_inverted(36, 6, "BACK"); + lcd.print(36, 6, true, "BACK"); } } } diff --git a/firmware/rust/src/screen/home.rs b/firmware/rust/src/screen/home.rs index 68c064d..e87effd 100644 --- a/firmware/rust/src/screen/home.rs +++ b/firmware/rust/src/screen/home.rs @@ -53,40 +53,40 @@ impl Home { pub fn draw(&self, lcd: &mut Lcd, channels: [ClockChannel; 3]) { match &self.active { Selection::Ch1 => { - lcd.print_inverted(0, 0, "CH1"); + lcd.print(0, 0, true, "CH1"); channels[0].print(lcd, 0); - lcd.print(0, 2, "CH2"); + lcd.print(0, 2, false, "CH2"); channels[1].print(lcd, 2); - lcd.print(0, 4, "CH3"); + lcd.print(0, 4, false, "CH3"); channels[2].print(lcd, 4); - lcd.print(33, 6, "SETUP"); + lcd.print(33, 6, false, "SETUP"); } Selection::Ch2 => { - lcd.print(0, 0, "CH1"); + lcd.print(0, 0, false, "CH1"); channels[0].print(lcd, 0); - lcd.print_inverted(0, 2, "CH2"); + lcd.print(0, 2, true, "CH2"); channels[1].print(lcd, 2); - lcd.print(0, 4, "CH3"); + lcd.print(0, 4, false, "CH3"); channels[2].print(lcd, 4); - lcd.print(33, 6, "SETUP"); + lcd.print(33, 6, false, "SETUP"); } Selection::Ch3 => { - lcd.print(0, 0, "CH1"); + lcd.print(0, 0, false, "CH1"); channels[0].print(lcd, 0); - lcd.print(0, 2, "CH2"); + lcd.print(0, 2, false, "CH2"); channels[1].print(lcd, 2); - lcd.print_inverted(0, 4, "CH3"); + lcd.print(0, 4, true, "CH3"); channels[2].print(lcd, 4); - lcd.print(33, 6, "SETUP"); + lcd.print(33, 6, false, "SETUP"); } Selection::Setup => { - lcd.print(0, 0, "CH1"); + lcd.print(0, 0, false, "CH1"); channels[0].print(lcd, 0); - lcd.print(0, 2, "CH2"); + lcd.print(0, 2, false, "CH2"); channels[1].print(lcd, 2); - lcd.print(0, 4, "CH3"); + lcd.print(0, 4, false, "CH3"); channels[2].print(lcd, 4); - lcd.print_inverted(33, 6, "SETUP"); + lcd.print(33, 6, true, "SETUP"); } } } diff --git a/firmware/rust/src/screen/setup.rs b/firmware/rust/src/screen/setup.rs index 37946e0..7e5ce82 100644 --- a/firmware/rust/src/screen/setup.rs +++ b/firmware/rust/src/screen/setup.rs @@ -109,44 +109,44 @@ impl Setup { pub fn draw(&self, lcd: &mut Lcd) { lcd.fill_area(0, 0, 33, 2, 0xFF); - lcd.print_inverted(33, 0, "SETUP"); + lcd.print(33, 0, true, "SETUP"); lcd.fill_area(69, 0, 33, 2, 0xFF); match &self.active { Selection::Contrast => { - 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"); + lcd.print(0, 2, false, "BACKLIGHT:"); + lcd.print_u8(81, 2, 3, false, self.backlight); + lcd.print(0, 4, true, "CONTRAST:"); + lcd.print_u8(87, 4, 2, false, self.contrast); + lcd.print(36, 6, false, "BACK"); } Selection::ContrastEdit => { - 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"); + lcd.print(0, 2, false, "BACKLIGHT:"); + lcd.print_u8(81, 2, 3, false, self.backlight); + lcd.print(0, 4, false, "CONTRAST:"); + lcd.print_u8(87, 4, 2, true, self.contrast); + lcd.print(36, 6, false, "BACK"); } Selection::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"); + lcd.print(0, 2, true, "BACKLIGHT:"); + lcd.print_u8(81, 2, 3, false, self.backlight); + lcd.print(0, 4, false, "CONTRAST:"); + lcd.print_u8(87, 4, 2, false, self.contrast); + lcd.print(36, 6, false, "BACK"); } Selection::BacklightEdit => { - 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"); + lcd.print(0, 2, false, "BACKLIGHT:"); + lcd.print_u8(81, 2, 3, true, self.backlight); + lcd.print(0, 4, false, "CONTRAST:"); + lcd.print_u8(87, 4, 2, false, self.contrast); + lcd.print(36, 6, false, "BACK"); } Selection::Back => { - 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"); + lcd.print(0, 2, false, "BACKLIGHT:"); + lcd.print_u8(81, 2, 3, false, self.backlight); + lcd.print(0, 4, false, "CONTRAST:"); + lcd.print_u8(87, 4, 2, false, self.contrast); + lcd.print(36, 6, true, "BACK"); } } }