fw-rust: Prepare to implement Si5351 commands
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Show settings of Si5351 channels on home screen. Initialize I2c and Si5351.
This commit is contained in:
parent
134db298f6
commit
52bf0e6eec
8 changed files with 188 additions and 13 deletions
|
@ -3,3 +3,4 @@ target = "avr-specs/avr-atmega328p.json"
|
|||
|
||||
[unstable]
|
||||
build-std = ["core"]
|
||||
build-std-features = ["compiler-builtins-mangled-names"]
|
||||
|
|
17
firmware/rust/Cargo.lock
generated
17
firmware/rust/Cargo.lock
generated
|
@ -55,6 +55,12 @@ dependencies = [
|
|||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
|
@ -70,6 +76,7 @@ dependencies = [
|
|||
"embedded-hal",
|
||||
"nb 1.0.0",
|
||||
"panic-halt",
|
||||
"si5351",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -157,6 +164,16 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "si5351"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06c1f1f280165963ce5fdff953a5303ac186b2b723aa1ed33916db70ceabfb8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"embedded-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.86"
|
||||
|
|
|
@ -15,6 +15,7 @@ panic-halt = "0.2"
|
|||
nb = "1.0"
|
||||
embedded-hal = "0.2"
|
||||
avr-device = { version = "0.3", features = ["atmega328p"] }
|
||||
si5351 = "0.2"
|
||||
|
||||
[dependencies.atmega-hal]
|
||||
git = "https://github.com/rahix/avr-hal"
|
||||
|
|
|
@ -43,6 +43,22 @@ pub const ONDERS_ORG: [[u8; 48]; 2] = [
|
|||
],
|
||||
];
|
||||
|
||||
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
|
||||
pub const ON: [u8; 11] = [
|
||||
0x00, 0x7E, 0x66, 0x7E, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00,
|
||||
];
|
||||
|
||||
pub const OFF: [u8; 11] = [
|
||||
0x7E, 0x66, 0x7E, 0x00, 0x7E, 0x16, 0x16, 0x00, 0x7E, 0x16, 0x16,
|
||||
];
|
||||
|
||||
pub const PLL_A: [u8; 6] = [0x00, 0x7C, 0x12, 0x12, 0x7C, 0x00];
|
||||
|
||||
pub const PLL_B: [u8; 6] = [0x00, 0x7E, 0x4A, 0x4A, 0x74, 0x00];
|
||||
|
||||
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
|
||||
const SYM_DOT: [&[u8]; 2] = [&[0x00, 0x00], &[0x30, 0x30]];
|
||||
|
||||
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
|
||||
const SYM_0: [&[u8]; 2] = [
|
||||
&[0xF8, 0xFC, 0x0C, 0xFC, 0xF8],
|
||||
|
@ -206,7 +222,9 @@ const SYM_INVALID: [&[u8]; 2] = [
|
|||
];
|
||||
|
||||
// TODO: Use https://github.com/rust-lang/rust/issues/85077 when stabilized
|
||||
pub const SYMBOL_TABLE: [&[&[u8]; 2]; 48] = [
|
||||
pub const SYMBOL_TABLE: [&[&[u8]; 2]; 50] = [
|
||||
&SYM_DOT, // '.'
|
||||
&SYM_INVALID, // '/'
|
||||
&SYM_0, // '0'
|
||||
&SYM_1, // '1'
|
||||
&SYM_2, // '2'
|
||||
|
|
|
@ -32,10 +32,9 @@ impl Lcd {
|
|||
delay.delay_ms(1_u8);
|
||||
|
||||
let init_sequence = [
|
||||
0x40, // (6) Set Scroll Line: Display start line 0
|
||||
0x40, // (6) Set Scroll Line: Display start line 0
|
||||
0xA1, // (13) Set SEG direction: SEG reverse
|
||||
0xC0, // (14) Set COM direction: Normal COM0 - COM63
|
||||
// 0xA4, // (10) Set All Pixel On: Disable -> Set All Pixel to ON
|
||||
0xA6, // (11) Set Inverse Display: Display inverse off
|
||||
0xA2, // (17) Set LCD Bias Ratio: Set Bias 1/9 (Duty 1/65)
|
||||
0x2F, // (5) Set Power Control: Booster, Regulator and Follower on
|
||||
|
@ -43,8 +42,6 @@ impl Lcd {
|
|||
0xEE, // (18) Reset Cursor Update Mode
|
||||
0x81, // (9) Set Electronic Volume: Set Contrast
|
||||
nb::block!(eeprom::read_byte(&CONTRAST)).unwrap(), // (9) Set Electronic Volume: Set Contrast
|
||||
// 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
|
||||
];
|
||||
|
||||
|
@ -112,7 +109,7 @@ impl Lcd {
|
|||
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 - 48][i as usize] {
|
||||
for segment in SYMBOL_TABLE[c as usize - 46][i as usize] {
|
||||
block!(self.spi.send(*segment)).unwrap();
|
||||
}
|
||||
block!(self.spi.send(0x00)).unwrap();
|
||||
|
@ -138,7 +135,7 @@ impl Lcd {
|
|||
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 - 48][i as usize] {
|
||||
for segment in SYMBOL_TABLE[c as usize - 46][i as usize] {
|
||||
block!(self.spi.send(!*segment)).unwrap();
|
||||
}
|
||||
block!(self.spi.send(0xFF)).unwrap();
|
||||
|
@ -157,7 +154,7 @@ impl Lcd {
|
|||
|
||||
let mut array = [0usize; 3];
|
||||
for (i, item) in array.iter_mut().enumerate() {
|
||||
*item = ((data / 10_u8.pow(i.try_into().unwrap())) % 10).into();
|
||||
*item = (((data / 10_u8.pow(i.try_into().unwrap())) % 10) + 2).into();
|
||||
}
|
||||
array.reverse();
|
||||
|
||||
|
@ -190,7 +187,7 @@ impl Lcd {
|
|||
|
||||
let mut array = [0usize; 3];
|
||||
for (i, item) in array.iter_mut().enumerate() {
|
||||
*item = ((data / 10_u8.pow(i.try_into().unwrap())) % 10).into();
|
||||
*item = (((data / 10_u8.pow(i.try_into().unwrap())) % 10) + 2).into();
|
||||
}
|
||||
array.reverse();
|
||||
|
||||
|
@ -216,4 +213,75 @@ impl Lcd {
|
|||
self.cd.set_low();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_freq(&mut self, segment: u8, page: u8, data: u32) {
|
||||
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();
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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]) {
|
||||
let mut delay = Delay::<MHz8>::new();
|
||||
self.move_cursor(segment, page);
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_high();
|
||||
|
||||
for c in symbol {
|
||||
block!(self.spi.send(*c)).unwrap();
|
||||
}
|
||||
|
||||
// TODO: This delay fixes issues, try find a better solution
|
||||
delay.delay_ms(1_u8);
|
||||
self.cd.set_low();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ mod screen;
|
|||
use rotary::{Direction, Rotary};
|
||||
use screen::{Screen, Screens};
|
||||
|
||||
pub type DefaultClock = MHz8;
|
||||
pub type I2c = atmega_hal::i2c::I2c<DefaultClock>;
|
||||
|
||||
#[used]
|
||||
#[link_section = ".eeprom"]
|
||||
static BACKLIGHT: u8 = 0;
|
||||
|
@ -54,7 +57,6 @@ struct ClockGenerator {
|
|||
|
||||
impl ClockGenerator {
|
||||
fn new() -> Self {
|
||||
// Get peripherals, pins and eeprom
|
||||
let dp = Peripherals::take().unwrap();
|
||||
let pins = pins!(dp);
|
||||
|
||||
|
@ -82,6 +84,12 @@ impl ClockGenerator {
|
|||
pins.pd5.into_output(),
|
||||
pins.pb0.into_output(),
|
||||
pins.pb1.into_output(),
|
||||
I2c::new(
|
||||
dp.TWI,
|
||||
pins.pc4.into_pull_up_input(),
|
||||
pins.pc5.into_pull_up_input(),
|
||||
50000,
|
||||
),
|
||||
),
|
||||
tc1: dp.TC1,
|
||||
exint: dp.EXINT,
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
use super::{Draw, Event, Screens, Setup, Splash};
|
||||
use crate::{lcd::Lcd, Input};
|
||||
use crate::{
|
||||
assets::{OFF, ON, PLL_A, PLL_B},
|
||||
lcd::Lcd,
|
||||
Input,
|
||||
};
|
||||
use si5351::PLL;
|
||||
|
||||
enum Selection {
|
||||
Ch1,
|
||||
|
@ -8,14 +13,53 @@ enum Selection {
|
|||
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 {
|
||||
active: Selection,
|
||||
channels: [Channel; 3],
|
||||
}
|
||||
|
||||
impl Home {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
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,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,26 +100,38 @@ impl Draw for Home {
|
|||
match &self.active {
|
||||
Selection::Ch1 => {
|
||||
lcd.print_inverted(0, 0, "CH1");
|
||||
self.channels[0].print(lcd, 0);
|
||||
lcd.print(0, 2, "CH2");
|
||||
self.channels[1].print(lcd, 2);
|
||||
lcd.print(0, 4, "CH3");
|
||||
self.channels[2].print(lcd, 4);
|
||||
lcd.print(33, 6, "SETUP");
|
||||
}
|
||||
Selection::Ch2 => {
|
||||
lcd.print(0, 0, "CH1");
|
||||
self.channels[0].print(lcd, 0);
|
||||
lcd.print_inverted(0, 2, "CH2");
|
||||
self.channels[1].print(lcd, 2);
|
||||
lcd.print(0, 4, "CH3");
|
||||
self.channels[2].print(lcd, 4);
|
||||
lcd.print(33, 6, "SETUP");
|
||||
}
|
||||
Selection::Ch3 => {
|
||||
lcd.print(0, 0, "CH1");
|
||||
self.channels[0].print(lcd, 0);
|
||||
lcd.print(0, 2, "CH2");
|
||||
self.channels[1].print(lcd, 2);
|
||||
lcd.print_inverted(0, 4, "CH3");
|
||||
self.channels[2].print(lcd, 4);
|
||||
lcd.print(33, 6, "SETUP");
|
||||
}
|
||||
Selection::Setup => {
|
||||
lcd.print(0, 0, "CH1");
|
||||
self.channels[0].print(lcd, 0);
|
||||
lcd.print(0, 2, "CH2");
|
||||
self.channels[1].print(lcd, 2);
|
||||
lcd.print(0, 4, "CH3");
|
||||
self.channels[2].print(lcd, 4);
|
||||
lcd.print_inverted(33, 6, "SETUP");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ use atmega_hal::{
|
|||
port::{mode::Output, Pin, PB0, PB1, PD5},
|
||||
Spi,
|
||||
};
|
||||
use si5351::{Si5351, Si5351Device};
|
||||
|
||||
mod home;
|
||||
mod setup;
|
||||
mod splash;
|
||||
|
||||
use crate::{eeprom, lcd::Lcd, Input, BACKLIGHT};
|
||||
use crate::{eeprom, lcd::Lcd, I2c, Input, BACKLIGHT};
|
||||
pub use home::Home;
|
||||
pub use setup::Setup;
|
||||
pub use splash::Splash;
|
||||
|
@ -47,6 +48,7 @@ pub struct Screen {
|
|||
tc0: TC0,
|
||||
pwm: Pin<Output, PD5>,
|
||||
screen: Screens,
|
||||
si5351: Si5351Device<I2c>,
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
|
@ -56,12 +58,14 @@ impl Screen {
|
|||
pwm: Pin<Output, PD5>,
|
||||
cd: Pin<Output, PB0>,
|
||||
rst: Pin<Output, PB1>,
|
||||
i2c: I2c,
|
||||
) -> Self {
|
||||
Self {
|
||||
lcd: Lcd::new(spi, cd, rst),
|
||||
tc0,
|
||||
pwm,
|
||||
screen: Screens::Splash(Splash),
|
||||
si5351: Si5351Device::new_adafruit_module(i2c),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,8 +80,10 @@ impl Screen {
|
|||
|
||||
// Init lcd display
|
||||
self.lcd.init();
|
||||
|
||||
self.draw();
|
||||
|
||||
// Init Si5351
|
||||
self.si5351.init_adafruit_module().unwrap();
|
||||
}
|
||||
|
||||
fn set_backlight(&mut self, backlight: u8) {
|
||||
|
|
Loading…
Reference in a new issue