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"); } } } }