firmware: Refactor dealing with EEPROM
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Use the API that was added to the AVR crate for EEPROM access.
This commit is contained in:
finga 2023-05-27 15:06:18 +02:00
parent d1faf584c5
commit 46bd28b46c
5 changed files with 40 additions and 78 deletions

View file

@ -1,48 +0,0 @@
use atmega_hal::Peripherals;
use avr_device::interrupt;
use core::convert::Infallible;
use nb::Error::WouldBlock;
pub fn read_byte(p_addr: *const u8) -> nb::Result<u8, Infallible> {
let dp = unsafe { Peripherals::steal() };
let eeprom = dp.EEPROM;
// Wait for completion of previous access
if eeprom.eecr.read().eepe().bit_is_set() {
return Err(WouldBlock);
}
interrupt::free(|_cs| {
// Write address into EEPROM address register
eeprom.eear.write(|w| w.bits(p_addr as u16));
// Start to read from EEPROM by setting EERE
eeprom.eecr.write(|w| w.eere().set_bit());
});
// Return data from EEPROM data register
Ok(eeprom.eedr.read().bits())
}
pub fn write_byte(p_addr: *const u8, data: u8) -> nb::Result<(), Infallible> {
let dp = unsafe { Peripherals::steal() };
let eeprom = dp.EEPROM;
// Wait for completion of previous access
if eeprom.eecr.read().eepe().bit_is_set() {
return Err(WouldBlock);
}
interrupt::free(|_cs| {
// Write address into EEPROM address register
eeprom.eear.write(|w| w.bits(p_addr as u16));
// Write data into EEPROM data register
eeprom.eedr.write(|w| w.bits(data));
// Enable writing to the EEPROM by setting EEMPE
eeprom.eecr.write(|w| w.eempe().set_bit());
// Start to write to EEPROM by setting EEPE
eeprom.eecr.write(|w| w.eepe().set_bit());
});
// Return data from EEPROM data register
Ok(())
}

View file

@ -7,7 +7,7 @@ use core::{convert::TryInto, iter};
use embedded_hal::{blocking::delay::DelayUs, spi::FullDuplex}; use embedded_hal::{blocking::delay::DelayUs, spi::FullDuplex};
use nb::block; use nb::block;
use crate::{assets::SYMBOL_TABLE, eeprom, DefaultClock, CONTRAST}; use crate::{assets::SYMBOL_TABLE, DefaultClock};
// TODO: Make `cd` and `rst` pins generic pins // TODO: Make `cd` and `rst` pins generic pins
pub struct Lcd { pub struct Lcd {
@ -41,27 +41,27 @@ impl Lcd {
self.cd.set_low(); self.cd.set_low();
} }
fn init_sequence() -> [u8; 13] { fn init_sequence(contrast: u8) -> [u8; 13] {
[ [
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 0xA1, // (13) Set SEG direction: SEG reverse
0xC0, // (14) Set COM direction: Normal COM0 - COM63 0xC0, // (14) Set COM direction: Normal COM0 - COM63
0xA6, // (11) Set Inverse Display: Display inverse off 0xA6, // (11) Set Inverse Display: Display inverse off
0xA2, // (17) Set LCD Bias Ratio: Set Bias 1/9 (Duty 1/65) 0xA2, // (17) Set LCD Bias Ratio: Set Bias 1/9 (Duty 1/65)
0x2F, // (5) Set Power Control: Booster, Regulator and Follower on 0x2F, // (5) Set Power Control: Booster, Regulator and Follower on
0x27, // (8) Set VLCD Resistor Ratio: Set Contrast 0x27, // (8) Set VLCD Resistor Ratio: Set Contrast
0xEE, // (18) Reset Cursor Update Mode 0xEE, // (18) Reset Cursor Update Mode
0x81, // (9) Set Electronic Volume: Set Contrast 0x81, // (9) Set Electronic Volume: Set Contrast
block!(eeprom::read_byte(&CONTRAST)).unwrap(), // (9) Set Electronic Volume: Set Contrast contrast, // (9) Set Electronic Volume: Set Contrast
0xFA, // (25) Set Adv. Program Control 0: Set Temperature compensation curve to -0.11%/°C 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 0x90, // (25) Set Adv. Program Control 0: Set Temperature compensation curve to -0.11%/°C
0xAF, // (12) Set Display Enable: Display on 0xAF, // (12) Set Display Enable: Display on
] ]
} }
pub fn init(&mut self) { pub fn init(&mut self, contrast: u8) {
self.rst.set_high(); self.rst.set_high();
self.control(Lcd::init_sequence().iter()); self.control(Lcd::init_sequence(contrast).iter());
} }
pub fn set_contrast(&mut self, contrast: u8) { pub fn set_contrast(&mut self, contrast: u8) {

View file

@ -20,7 +20,6 @@ use embedded_hal::{
use panic_halt as _; use panic_halt as _;
mod assets; mod assets;
mod eeprom;
mod lcd; mod lcd;
mod rotary; mod rotary;
mod screen; mod screen;
@ -80,6 +79,7 @@ impl ClockGenerator {
Self { Self {
screen: Screen::new( screen: Screen::new(
dp.TC0, dp.TC0,
dp.EEPROM,
spi, spi,
pins.pd5.into_output(), pins.pd5.into_output(),
pins.pb0.into_output(), pins.pb0.into_output(),

View file

@ -1,7 +1,7 @@
use atmega_hal::{ use atmega_hal::{
pac::TC0, pac::{EEPROM, TC0},
port::{mode::Output, Pin, PB0, PB1, PD5}, port::{mode::Output, Pin, PB0, PB1, PD5},
Spi, Eeprom, Spi,
}; };
use si5351::{ClockOutput, Si5351, Si5351Device, PLL}; use si5351::{ClockOutput, Si5351, Si5351Device, PLL};
@ -12,9 +12,8 @@ mod splash;
use crate::{ use crate::{
assets::{OFF, ON, PLL_A, PLL_B}, assets::{OFF, ON, PLL_A, PLL_B},
eeprom,
lcd::Lcd, lcd::Lcd,
I2c, Input, BACKLIGHT, I2c, Input, BACKLIGHT, CONTRAST,
}; };
pub use channel::Channel; pub use channel::Channel;
pub use home::Home; pub use home::Home;
@ -83,6 +82,7 @@ impl Screens {
pub struct Screen { pub struct Screen {
lcd: Lcd, lcd: Lcd,
tc0: TC0, tc0: TC0,
eeprom: Eeprom,
pwm: Pin<Output, PD5>, pwm: Pin<Output, PD5>,
screen: Screens, screen: Screens,
si5351: Si5351Device<I2c>, si5351: Si5351Device<I2c>,
@ -92,6 +92,7 @@ pub struct Screen {
impl Screen { impl Screen {
pub fn new( pub fn new(
tc0: TC0, tc0: TC0,
eeprom: EEPROM,
spi: Spi, spi: Spi,
pwm: Pin<Output, PD5>, pwm: Pin<Output, PD5>,
cd: Pin<Output, PB0>, cd: Pin<Output, PB0>,
@ -101,6 +102,7 @@ impl Screen {
Self { Self {
lcd: Lcd::new(spi, cd, rst), lcd: Lcd::new(spi, cd, rst),
tc0, tc0,
eeprom: Eeprom::new(eeprom),
pwm, pwm,
screen: Screens::Splash(Splash), screen: Screens::Splash(Splash),
si5351: Si5351Device::new_adafruit_module(i2c), si5351: Si5351Device::new_adafruit_module(i2c),
@ -134,10 +136,11 @@ impl Screen {
w.wgm0().pwm_fast(); w.wgm0().pwm_fast();
w.com0b().match_clear() w.com0b().match_clear()
}); });
self.set_backlight(nb::block!(eeprom::read_byte(&BACKLIGHT)).unwrap()); self.set_backlight(self.eeprom.read_byte(&BACKLIGHT as *const _ as u16));
// Init lcd display // Init lcd display controller
self.lcd.init(); self.lcd
.init(self.eeprom.read_byte(&CONTRAST as *const _ as u16));
self.draw(); self.draw();
// Init Si5351 // Init Si5351

View file

@ -1,6 +1,6 @@
use super::{Event, Home, Screens}; use super::{Event, Home, Screens};
use crate::{eeprom, lcd::Lcd, Input, BACKLIGHT, CONTRAST}; use crate::{lcd::Lcd, Input, BACKLIGHT, CONTRAST};
use nb::block; use atmega_hal::{Eeprom, Peripherals};
enum Selection { enum Selection {
Backlight, Backlight,
@ -14,14 +14,19 @@ pub struct Setup {
active: Selection, active: Selection,
backlight: u8, backlight: u8,
contrast: u8, contrast: u8,
eeprom: Eeprom,
} }
impl Setup { impl Setup {
pub fn new() -> Self { pub fn new() -> Self {
let dp = unsafe { Peripherals::steal() };
let ep = Eeprom::new(dp.EEPROM);
Self { Self {
active: Selection::Backlight, active: Selection::Backlight,
backlight: block!(eeprom::read_byte(&BACKLIGHT)).unwrap(), backlight: ep.read_byte(&BACKLIGHT as *const _ as u16),
contrast: block!(eeprom::read_byte(&CONTRAST)).unwrap(), contrast: ep.read_byte(&CONTRAST as *const _ as u16),
eeprom: ep,
} }
} }
@ -53,12 +58,13 @@ impl Setup {
return Event::Backlight(self.backlight); return Event::Backlight(self.backlight);
} }
Input::Select => { Input::Select => {
block!(eeprom::write_byte(&BACKLIGHT, self.backlight)).unwrap(); self.eeprom
.write_byte(&BACKLIGHT as *const _ as u16, self.backlight);
Selection::Backlight Selection::Backlight
} }
Input::Back => { Input::Back => {
self.active = Selection::Backlight; self.active = Selection::Backlight;
self.backlight = block!(eeprom::read_byte(&BACKLIGHT)).unwrap(); self.backlight = self.eeprom.read_byte(&BACKLIGHT as *const _ as u16);
return Event::Backlight(self.backlight); return Event::Backlight(self.backlight);
} }
}, },
@ -88,12 +94,13 @@ impl Setup {
return Event::Contrast(self.contrast); return Event::Contrast(self.contrast);
} }
Input::Select => { Input::Select => {
block!(eeprom::write_byte(&CONTRAST, self.contrast)).unwrap(); self.eeprom
.write_byte(&CONTRAST as *const _ as u16, self.contrast);
Selection::Contrast Selection::Contrast
} }
Input::Back => { Input::Back => {
self.active = Selection::Contrast; self.active = Selection::Contrast;
self.contrast = block!(eeprom::read_byte(&CONTRAST)).unwrap(); self.contrast = self.eeprom.read_byte(&CONTRAST as *const _ as u16);
return Event::Contrast(self.contrast); return Event::Contrast(self.contrast);
} }
}, },