fw-rust: Make Si5351 useable
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.
This commit is contained in:
finga 2022-04-02 18:38:46 +02:00
parent 7f14974146
commit c36581e703
5 changed files with 430 additions and 119 deletions

View file

@ -146,6 +146,12 @@ const SYM_E: [&[u8]; 2] = [
&[0x3F, 0x3F, 0x31, 0x31, 0x30, 0x30], &[0x3F, 0x3F, 0x31, 0x31, 0x30, 0x30],
]; ];
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
const SYM_F: [&[u8]; 2] = [
&[0xFC, 0xFC, 0x8C, 0x8C, 0x0C, 0x0C],
&[0x3F, 0x3F, 0x01, 0x01, 0x00, 0x00],
];
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized // TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
const SYM_G: [&[u8]; 2] = [ const SYM_G: [&[u8]; 2] = [
&[0xF8, 0xFC, 0x0C, 0x0C, 0x3C, 0x38], &[0xF8, 0xFC, 0x0C, 0x0C, 0x3C, 0x38],
@ -191,6 +197,12 @@ const SYM_P: [&[u8]; 2] = [
&[0x3F, 0x3F, 0x01, 0x01, 0x01, 0x00], &[0x3F, 0x3F, 0x01, 0x01, 0x01, 0x00],
]; ];
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
const SYM_Q: [&[u8]; 2] = [
&[0xF8, 0xFC, 0x0C, 0x0C, 0xFC, 0xF8],
&[0x1F, 0x3F, 0x30, 0x38, 0x7F, 0x6F],
];
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized // TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
const SYM_R: [&[u8]; 2] = [ const SYM_R: [&[u8]; 2] = [
&[0xFC, 0xFC, 0x8C, 0x8C, 0xFC, 0xF8], &[0xFC, 0xFC, 0x8C, 0x8C, 0xFC, 0xF8],
@ -215,6 +227,12 @@ const SYM_U: [&[u8]; 2] = [
&[0x1F, 0x3F, 0x30, 0x30, 0x3F, 0x1F], &[0x1F, 0x3F, 0x30, 0x30, 0x3F, 0x1F],
]; ];
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
const SYM_UNDERSCORE: [&[u8]; 2] = [
&[0x00, 0x00, 0x00, 0x00, 0x00],
&[0x30, 0x30, 0x30, 0x30, 0x30],
];
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized // TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
const SYM_INVALID: [&[u8]; 2] = [ const SYM_INVALID: [&[u8]; 2] = [
&[0x80, 0xE0, 0x98, 0xCC, 0x4C, 0x18, 0xE0, 0x80], &[0x80, 0xE0, 0x98, 0xCC, 0x4C, 0x18, 0xE0, 0x80],
@ -223,54 +241,54 @@ const SYM_INVALID: [&[u8]; 2] = [
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized // TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
pub const SYMBOL_TABLE: [&[&[u8]; 2]; 50] = [ pub const SYMBOL_TABLE: [&[&[u8]; 2]; 50] = [
&SYM_DOT, // '.' &SYM_DOT, // '.'
&SYM_INVALID, // '/' &SYM_INVALID, // '/'
&SYM_0, // '0' &SYM_0, // '0'
&SYM_1, // '1' &SYM_1, // '1'
&SYM_2, // '2' &SYM_2, // '2'
&SYM_3, // '3' &SYM_3, // '3'
&SYM_4, // '4' &SYM_4, // '4'
&SYM_5, // '5' &SYM_5, // '5'
&SYM_6, // '6' &SYM_6, // '6'
&SYM_7, // '7' &SYM_7, // '7'
&SYM_8, // '8' &SYM_8, // '8'
&SYM_9, // '9' &SYM_9, // '9'
&SYM_COLON, // ':' &SYM_COLON, // ':'
&SYM_INVALID, // ';' &SYM_INVALID, // ';'
&SYM_INVALID, // '<' &SYM_INVALID, // '<'
&SYM_INVALID, // '=' &SYM_INVALID, // '='
&SYM_INVALID, // '>' &SYM_INVALID, // '>'
&SYM_INVALID, // '?' &SYM_INVALID, // '?'
&SYM_INVALID, // '@' &SYM_INVALID, // '@'
&SYM_A, // 'A' &SYM_A, // 'A'
&SYM_B, // 'B' &SYM_B, // 'B'
&SYM_C, // 'C' &SYM_C, // 'C'
&SYM_INVALID, // 'D' &SYM_INVALID, // 'D'
&SYM_E, // 'E' &SYM_E, // 'E'
&SYM_INVALID, // 'F' &SYM_F, // 'F'
&SYM_G, // 'G' &SYM_G, // 'G'
&SYM_H, // 'H' &SYM_H, // 'H'
&SYM_I, // 'I' &SYM_I, // 'I'
&SYM_INVALID, // 'J' &SYM_INVALID, // 'J'
&SYM_K, // 'K' &SYM_K, // 'K'
&SYM_L, // 'L' &SYM_L, // 'L'
&SYM_INVALID, // 'M' &SYM_INVALID, // 'M'
&SYM_N, // 'N' &SYM_N, // 'N'
&SYM_O, // 'O' &SYM_O, // 'O'
&SYM_P, // 'P' &SYM_P, // 'P'
&SYM_INVALID, // 'Q' &SYM_Q, // 'Q'
&SYM_R, // 'R' &SYM_R, // 'R'
&SYM_S, // 'S' &SYM_S, // 'S'
&SYM_T, // 'T' &SYM_T, // 'T'
&SYM_U, // 'U' &SYM_U, // 'U'
&SYM_INVALID, // 'V' &SYM_INVALID, // 'V'
&SYM_INVALID, // 'W' &SYM_INVALID, // 'W'
&SYM_INVALID, // 'X' &SYM_INVALID, // 'X'
&SYM_INVALID, // 'Y' &SYM_INVALID, // 'Y'
&SYM_INVALID, // 'Z' &SYM_INVALID, // 'Z'
&SYM_INVALID, // '[' &SYM_INVALID, // '['
&SYM_INVALID, // '\' &SYM_INVALID, // '\'
&SYM_INVALID, // ']' &SYM_INVALID, // ']'
&SYM_INVALID, // '^' &SYM_INVALID, // '^'
&SYM_INVALID, // '_' &SYM_UNDERSCORE, // '_'
]; ];

View file

@ -268,6 +268,79 @@ impl Lcd {
} }
} }
pub fn print_freq_digit(&mut self, segment: u8, page: u8, data: u32, digit: u8) {
let mut delay = Delay::<MHz8>::new();
let mut array = [0usize; 9];
for (i, item) in array.iter_mut().enumerate() {
*item = (((data / 10_u32.pow(i.try_into().unwrap())) % 10) + 2)
.try_into()
.unwrap();
}
array.reverse();
let digit = 8 - digit;
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 j in 0..3 {
if j == digit {
for segment in SYMBOL_TABLE[array[j as usize]][i as usize] {
block!(self.spi.send(!*segment)).unwrap();
}
} else {
for segment in SYMBOL_TABLE[array[j as usize]][i as usize] {
block!(self.spi.send(*segment)).unwrap();
}
}
block!(self.spi.send(0x00)).unwrap();
}
for segment in SYMBOL_TABLE[0][i as usize] {
block!(self.spi.send(*segment)).unwrap();
}
block!(self.spi.send(0x00)).unwrap();
for j in 3..6 {
if j == digit {
for segment in SYMBOL_TABLE[array[j as usize]][i as usize] {
block!(self.spi.send(!*segment)).unwrap();
}
} else {
for segment in SYMBOL_TABLE[array[j as usize]][i as usize] {
block!(self.spi.send(*segment)).unwrap();
}
}
block!(self.spi.send(0x00)).unwrap();
}
for segment in SYMBOL_TABLE[0][i as usize] {
block!(self.spi.send(*segment)).unwrap();
}
block!(self.spi.send(0x00)).unwrap();
for j in 6..9 {
if j == digit {
for segment in SYMBOL_TABLE[array[j as usize]][i as usize] {
block!(self.spi.send(!*segment)).unwrap();
}
} else {
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();
// TODO: This delay fixes issues, try find a better solution
delay.delay_ms(1_u8);
self.cd.set_low();
}
}
pub fn print_icon(&mut self, segment: u8, page: u8, symbol: &[u8]) { pub fn print_icon(&mut self, segment: u8, page: u8, symbol: &[u8]) {
let mut delay = Delay::<MHz8>::new(); let mut delay = Delay::<MHz8>::new();
self.move_cursor(segment, page); self.move_cursor(segment, page);

View file

@ -0,0 +1,191 @@
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");
}
}
}
}

View file

@ -1,10 +1,5 @@
use super::{Event, Screens, Setup, Splash}; use super::{Channel, Event, Screens, Setup};
use crate::{ use crate::{lcd::Lcd, screen::ClockChannel, Input};
assets::{OFF, ON, PLL_A, PLL_B},
lcd::Lcd,
Input,
};
use si5351::PLL;
enum Selection { enum Selection {
Ch1, Ch1,
@ -13,74 +8,35 @@ enum Selection {
Setup, Setup,
} }
struct Channel {
freq: u32,
enabled: bool,
pll: PLL,
}
impl Channel {
fn print(&self, lcd: &mut Lcd, page: u8) {
lcd.print_freq(25, page, self.freq);
lcd.print_icon(91, page, if self.enabled { &ON } else { &OFF });
lcd.print_icon(
94,
page + 1,
match self.pll {
PLL::A => &PLL_A,
PLL::B => &PLL_B,
},
);
}
}
pub struct Home { pub struct Home {
active: Selection, active: Selection,
channels: [Channel; 3],
} }
impl Home { impl Home {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
active: Selection::Ch1, active: Selection::Ch1,
channels: [
Channel {
freq: 0,
enabled: false,
pll: PLL::A,
},
Channel {
freq: 0,
enabled: false,
pll: PLL::A,
},
Channel {
freq: 0,
enabled: false,
pll: PLL::A,
},
],
} }
} }
pub fn input(&mut self, input: &Input) -> Event { pub fn input(&mut self, input: &Input, channels: [ClockChannel; 3]) -> Event {
self.active = match self.active { self.active = match self.active {
Selection::Ch1 => match input { Selection::Ch1 => match input {
Input::Next => Selection::Ch2, Input::Next => Selection::Ch2,
Input::Previous => Selection::Setup, Input::Previous => Selection::Setup,
Input::Select => return Event::Screen(Screens::Splash(Splash)), Input::Select => return Event::Screen(Screens::Channel(Channel::new(channels[0]))),
Input::Back => Selection::Ch1, Input::Back => Selection::Ch1,
}, },
Selection::Ch2 => match input { Selection::Ch2 => match input {
Input::Next => Selection::Ch3, Input::Next => Selection::Ch3,
Input::Previous => Selection::Ch1, Input::Previous => Selection::Ch1,
Input::Select => return Event::Screen(Screens::Splash(Splash)), Input::Select => return Event::Screen(Screens::Channel(Channel::new(channels[1]))),
Input::Back => Selection::Ch2, Input::Back => Selection::Ch2,
}, },
Selection::Ch3 => match input { Selection::Ch3 => match input {
Input::Next => Selection::Setup, Input::Next => Selection::Setup,
Input::Previous => Selection::Ch2, Input::Previous => Selection::Ch2,
Input::Select => return Event::Screen(Screens::Splash(Splash)), Input::Select => return Event::Screen(Screens::Channel(Channel::new(channels[2]))),
Input::Back => Selection::Ch3, Input::Back => Selection::Ch3,
}, },
Selection::Setup => match input { Selection::Setup => match input {
@ -94,42 +50,42 @@ impl Home {
Event::None Event::None
} }
pub fn draw(&self, lcd: &mut Lcd) { pub fn draw(&self, lcd: &mut Lcd, channels: [ClockChannel; 3]) {
match &self.active { match &self.active {
Selection::Ch1 => { Selection::Ch1 => {
lcd.print_inverted(0, 0, "CH1"); lcd.print_inverted(0, 0, "CH1");
self.channels[0].print(lcd, 0); channels[0].print(lcd, 0);
lcd.print(0, 2, "CH2"); lcd.print(0, 2, "CH2");
self.channels[1].print(lcd, 2); channels[1].print(lcd, 2);
lcd.print(0, 4, "CH3"); lcd.print(0, 4, "CH3");
self.channels[2].print(lcd, 4); channels[2].print(lcd, 4);
lcd.print(33, 6, "SETUP"); lcd.print(33, 6, "SETUP");
} }
Selection::Ch2 => { Selection::Ch2 => {
lcd.print(0, 0, "CH1"); lcd.print(0, 0, "CH1");
self.channels[0].print(lcd, 0); channels[0].print(lcd, 0);
lcd.print_inverted(0, 2, "CH2"); lcd.print_inverted(0, 2, "CH2");
self.channels[1].print(lcd, 2); channels[1].print(lcd, 2);
lcd.print(0, 4, "CH3"); lcd.print(0, 4, "CH3");
self.channels[2].print(lcd, 4); channels[2].print(lcd, 4);
lcd.print(33, 6, "SETUP"); lcd.print(33, 6, "SETUP");
} }
Selection::Ch3 => { Selection::Ch3 => {
lcd.print(0, 0, "CH1"); lcd.print(0, 0, "CH1");
self.channels[0].print(lcd, 0); channels[0].print(lcd, 0);
lcd.print(0, 2, "CH2"); lcd.print(0, 2, "CH2");
self.channels[1].print(lcd, 2); channels[1].print(lcd, 2);
lcd.print_inverted(0, 4, "CH3"); lcd.print_inverted(0, 4, "CH3");
self.channels[2].print(lcd, 4); channels[2].print(lcd, 4);
lcd.print(33, 6, "SETUP"); lcd.print(33, 6, "SETUP");
} }
Selection::Setup => { Selection::Setup => {
lcd.print(0, 0, "CH1"); lcd.print(0, 0, "CH1");
self.channels[0].print(lcd, 0); channels[0].print(lcd, 0);
lcd.print(0, 2, "CH2"); lcd.print(0, 2, "CH2");
self.channels[1].print(lcd, 2); channels[1].print(lcd, 2);
lcd.print(0, 4, "CH3"); lcd.print(0, 4, "CH3");
self.channels[2].print(lcd, 4); channels[2].print(lcd, 4);
lcd.print_inverted(33, 6, "SETUP"); lcd.print_inverted(33, 6, "SETUP");
} }
} }

View file

@ -3,13 +3,20 @@ use atmega_hal::{
port::{mode::Output, Pin, PB0, PB1, PD5}, port::{mode::Output, Pin, PB0, PB1, PD5},
Spi, Spi,
}; };
use si5351::{Si5351, Si5351Device}; use si5351::{ClockOutput, Si5351, Si5351Device, PLL};
mod channel;
mod home; mod home;
mod setup; mod setup;
mod splash; mod splash;
use crate::{eeprom, lcd::Lcd, I2c, Input, BACKLIGHT}; use crate::{
assets::{OFF, ON, PLL_A, PLL_B},
eeprom,
lcd::Lcd,
I2c, Input, BACKLIGHT,
};
pub use channel::Channel;
pub use home::Home; pub use home::Home;
pub use setup::Setup; pub use setup::Setup;
pub use splash::Splash; pub use splash::Splash;
@ -20,21 +27,55 @@ pub enum Event {
Screen(Screens), Screen(Screens),
Backlight(u8), Backlight(u8),
Contrast(u8), Contrast(u8),
Channel(ClockChannel),
None, None,
} }
#[derive(Clone, Copy)]
pub struct ClockChannel {
output: ClockOutput,
freq: u32,
enabled: bool,
pll: PLL,
}
impl ClockChannel {
fn print(&self, lcd: &mut Lcd, page: u8) {
lcd.print_freq(25, page, self.freq);
lcd.print_icon(91, page, if self.enabled { &ON } else { &OFF });
lcd.print_icon(
94,
page + 1,
match self.pll {
PLL::A => &PLL_A,
PLL::B => &PLL_B,
},
);
}
fn update(&self, si5351: &mut Si5351Device<I2c>) {
si5351
.set_frequency(self.pll, self.output, self.freq)
.unwrap();
si5351.set_clock_enabled(self.output, self.enabled);
si5351.flush_output_enabled().unwrap();
}
}
pub enum Screens { pub enum Screens {
Splash(Splash), Splash(Splash),
Home(Home), Home(Home),
Setup(Setup), Setup(Setup),
Channel(Channel),
} }
impl Screens { impl Screens {
pub fn input(&mut self, input: &Input) -> Event { pub fn input(&mut self, input: &Input, channels: [ClockChannel; 3]) -> Event {
match self { match self {
Screens::Splash(_) => Event::None, Screens::Splash(_) => Event::None,
Screens::Home(home) => home.input(input), Screens::Home(home) => home.input(input, channels),
Screens::Setup(setup) => setup.input(input), Screens::Setup(setup) => setup.input(input),
Screens::Channel(channel) => channel.input(input),
} }
} }
} }
@ -45,6 +86,7 @@ pub struct Screen {
pwm: Pin<Output, PD5>, pwm: Pin<Output, PD5>,
screen: Screens, screen: Screens,
si5351: Si5351Device<I2c>, si5351: Si5351Device<I2c>,
channels: [ClockChannel; 3],
} }
impl Screen { impl Screen {
@ -62,6 +104,26 @@ impl Screen {
pwm, pwm,
screen: Screens::Splash(Splash), screen: Screens::Splash(Splash),
si5351: Si5351Device::new_adafruit_module(i2c), si5351: Si5351Device::new_adafruit_module(i2c),
channels: [
ClockChannel {
output: ClockOutput::Clk0,
freq: 1_000_000,
enabled: false,
pll: PLL::A,
},
ClockChannel {
output: ClockOutput::Clk1,
freq: 1_000_000,
enabled: false,
pll: PLL::A,
},
ClockChannel {
output: ClockOutput::Clk2,
freq: 1_000_000,
enabled: false,
pll: PLL::A,
},
],
} }
} }
@ -110,16 +172,27 @@ impl Screen {
match &self.screen { match &self.screen {
Screens::Splash(splash) => splash.draw(&mut self.lcd), Screens::Splash(splash) => splash.draw(&mut self.lcd),
Screens::Home(home) => home.draw(&mut self.lcd), Screens::Home(home) => home.draw(&mut self.lcd, self.channels),
Screens::Setup(setup) => setup.draw(&mut self.lcd), Screens::Setup(setup) => setup.draw(&mut self.lcd),
Screens::Channel(channel) => channel.draw(&mut self.lcd),
} }
} }
pub fn input(&mut self, input: &Input) { pub fn input(&mut self, input: &Input) {
match self.screen.input(input) { match self.screen.input(input, self.channels) {
Event::Screen(screen) => self.screen = screen, Event::Screen(screen) => self.screen = screen,
Event::Backlight(backlight) => self.set_backlight(backlight), Event::Backlight(backlight) => self.set_backlight(backlight),
Event::Contrast(contrast) => self.lcd.set_contrast(contrast), Event::Contrast(contrast) => self.lcd.set_contrast(contrast),
Event::Channel(channel) => {
match channel.output {
ClockOutput::Clk0 => self.channels[0] = channel,
ClockOutput::Clk1 => self.channels[1] = channel,
ClockOutput::Clk2 => self.channels[2] = channel,
_ => unimplemented!(),
}
channel.update(&mut self.si5351);
}
Event::None => {} Event::None => {}
} }