finga
c36581e703
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
In order to make the Si5351 configurable add some needed assets, create the ability to print the frequency with selected digits and add a channel screen.
192 lines
7 KiB
Rust
192 lines
7 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_inverted(13, 4, "OFF"),
|
|
true => lcd.print_inverted(16, 4, "ON"),
|
|
}
|
|
} else {
|
|
match self.channel.enabled {
|
|
false => lcd.print(13, 4, "OFF"),
|
|
true => lcd.print(16, 4, "ON"),
|
|
}
|
|
}
|
|
}
|
|
|
|
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"),
|
|
_ => unimplemented!(),
|
|
}
|
|
lcd.fill_area(83, 0, 19, 2, 0xFF);
|
|
|
|
match &self.active {
|
|
Selection::Frequency => {
|
|
lcd.print_inverted(0, 2, "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"),
|
|
}
|
|
lcd.print(36, 6, "BACK");
|
|
}
|
|
Selection::FrequencyDigit(digit) | Selection::Digit(digit) => {
|
|
lcd.print(0, 2, "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"),
|
|
}
|
|
lcd.print(36, 6, "BACK");
|
|
}
|
|
Selection::Enabled => {
|
|
lcd.print(0, 2, "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"),
|
|
}
|
|
lcd.print(36, 6, "BACK");
|
|
}
|
|
Selection::Pll => {
|
|
lcd.print(0, 2, "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"),
|
|
}
|
|
lcd.print(36, 6, "BACK");
|
|
}
|
|
Selection::Back => {
|
|
lcd.print(0, 2, "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"),
|
|
}
|
|
match self.channel.pll {
|
|
PLL::A => lcd.print(59, 4, "PLL_A"),
|
|
PLL::B => lcd.print(59, 4, "PLL_B"),
|
|
}
|
|
lcd.print_inverted(36, 6, "BACK");
|
|
}
|
|
}
|
|
}
|
|
}
|