clock_generator/firmware/rust/src/screen/channel.rs
finga 343b95dc78
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fw-rust: Refactor printing to the LCD
Pass iterators for control and display data to the printing function
instead of just printing it.
2022-04-10 18:18:37 +02:00

192 lines
7.1 KiB
Rust

use super::{ClockChannel, Event, Home, Screens};
use crate::{lcd::Lcd, Input};
use si5351::{ClockOutput, PLL};
enum Selection {
Frequency,
FrequencyDigit(u8),
Digit(u8),
Enabled,
Pll,
Back,
}
pub struct Channel {
active: Selection,
channel: ClockChannel,
}
impl Channel {
pub fn new(channel: ClockChannel) -> Self {
Self {
active: Selection::Frequency,
channel,
}
}
pub fn input(&mut self, input: &Input) -> Event {
self.active = match self.active {
Selection::Frequency => match input {
Input::Next => Selection::Enabled,
Input::Previous => Selection::Back,
Input::Select => Selection::FrequencyDigit(8),
Input::Back => return Event::Screen(Screens::Home(Home::new())),
},
Selection::FrequencyDigit(digit) => match input {
Input::Next => {
if digit == u8::MIN {
Selection::FrequencyDigit(8)
} else {
Selection::FrequencyDigit(digit - 1)
}
}
Input::Previous => {
if digit >= 8 {
Selection::FrequencyDigit(u8::MIN)
} else {
Selection::FrequencyDigit(digit + 1)
}
}
Input::Select => Selection::Digit(digit),
Input::Back => Selection::Frequency,
},
Selection::Digit(digit) => match input {
Input::Next => {
let new_freq = self.channel.freq + 10_u32.pow(digit.into());
if new_freq < 162_000_000 {
self.channel.freq = new_freq;
} else {
self.channel.freq = 162_000_000
}
return Event::Channel(self.channel);
}
Input::Previous => {
let difference = 10_u32.pow(digit.into());
if self.channel.freq > difference {
let new_freq = self.channel.freq - difference;
if new_freq > 15_000 {
self.channel.freq = new_freq;
} else {
self.channel.freq = 15_000;
}
} else {
self.channel.freq = 15_000;
}
return Event::Channel(self.channel);
}
Input::Select => Selection::Frequency,
Input::Back => Selection::FrequencyDigit(digit),
},
Selection::Enabled => match input {
Input::Next => Selection::Pll,
Input::Previous => Selection::Frequency,
Input::Select => {
self.channel.enabled = !self.channel.enabled;
return Event::Channel(self.channel);
}
Input::Back => return Event::Screen(Screens::Home(Home::new())),
},
Selection::Pll => match input {
Input::Next => Selection::Back,
Input::Previous => Selection::Enabled,
Input::Select => {
self.channel.pll = match self.channel.pll {
PLL::A => PLL::B,
PLL::B => PLL::A,
};
return Event::Channel(self.channel);
}
Input::Back => return Event::Screen(Screens::Home(Home::new())),
},
Selection::Back => match input {
Input::Next => Selection::Frequency,
Input::Previous => Selection::Pll,
_ => return Event::Screen(Screens::Home(Home::new())),
},
};
Event::None
}
fn draw_enabled(&self, lcd: &mut Lcd, inverted: bool) {
if inverted {
match self.channel.enabled {
false => lcd.print(13, 4, true, "OFF"),
true => lcd.print(16, 4, true, "ON"),
}
} else {
match self.channel.enabled {
false => lcd.print(13, 4, false, "OFF"),
true => lcd.print(16, 4, false, "ON"),
}
}
}
pub fn draw(&self, lcd: &mut Lcd) {
lcd.fill_area(0, 0, 19, 2, 0xFF);
match self.channel.output {
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(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, false, "PLL_A"),
PLL::B => lcd.print(59, 4, false, "PLL_B"),
}
lcd.print(36, 6, false, "BACK");
}
Selection::FrequencyDigit(digit) | Selection::Digit(digit) => {
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, false, "PLL_A"),
PLL::B => lcd.print(59, 4, false, "PLL_B"),
}
lcd.print(36, 6, false, "BACK");
}
Selection::Enabled => {
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, false, "PLL_A"),
PLL::B => lcd.print(59, 4, false, "PLL_B"),
}
lcd.print(36, 6, false, "BACK");
}
Selection::Pll => {
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(59, 4, true, "PLL_A"),
PLL::B => lcd.print(59, 4, true, "PLL_B"),
}
lcd.print(36, 6, false, "BACK");
}
Selection::Back => {
lcd.print(0, 2, false, "FREQ:");
lcd.print_freq(39, 2, self.channel.freq);
match self.channel.enabled {
false => lcd.print(13, 4, false, "OFF"),
true => lcd.print(16, 4, false, "ON"),
}
match self.channel.pll {
PLL::A => lcd.print(59, 4, false, "PLL_A"),
PLL::B => lcd.print(59, 4, false, "PLL_B"),
}
lcd.print(36, 6, true, "BACK");
}
}
}
}