config: finalize load/save

pull/20/head
Astro 2020-09-24 23:04:29 +02:00
parent 3b050347d4
commit 8d70c03520
2 changed files with 67 additions and 11 deletions

View File

@ -1,18 +1,40 @@
use serde::{Serialize, Deserialize};
use postcard::{from_bytes, to_slice};
use serde::{Serialize, Deserialize};
use stm32f4xx_hal::i2c;
use uom::si::{
electric_potential::volt,
electric_current::ampere,
electrical_resistance::ohm,
f64::{ElectricCurrent, ElectricPotential, ElectricalResistance, ThermodynamicTemperature},
thermodynamic_temperature::degree_celsius,
};
use crate::{
channels::{CHANNELS, Channels},
command_parser::CenterPoint,
EEPROM_SIZE, EEPROM_PAGE_SIZE,
pid,
pins,
steinhart_hart,
};
#[derive(Debug)]
pub enum Error {
Eeprom(eeprom24x::Error<i2c::Error>),
Encode(postcard::Error),
}
impl From<eeprom24x::Error<i2c::Error>> for Error {
fn from(e: eeprom24x::Error<i2c::Error>) -> Self {
Error::Eeprom(e)
}
}
impl From<postcard::Error> for Error {
fn from(e: postcard::Error) -> Self {
Error::Encode(e)
}
}
/// Just for encoding/decoding, actual state resides in ChannelState
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Config {
@ -60,6 +82,14 @@ impl ChannelConfig {
}
}
pub fn apply(&self, channels: &mut Channels, channel: usize) {
let state = channels.channel_state(channel);
state.center = self.center.clone();
state.pid.parameters = self.pid.clone();
state.pid.target = self.pid_target.into();
state.sh = (&self.sh).into();
self.pwm.apply(channels, channel);
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -79,6 +109,16 @@ impl From<&steinhart_hart::Parameters> for SteinhartHartConfig {
}
}
impl Into<steinhart_hart::Parameters> for &SteinhartHartConfig {
fn into(self) -> steinhart_hart::Parameters {
steinhart_hart::Parameters {
t0: ThermodynamicTemperature::new::<degree_celsius>(self.t0.into()),
r0: ElectricalResistance::new::<ohm>(self.r0.into()),
b: self.b.into(),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
struct PwmLimits {
max_v: f32,
@ -97,6 +137,12 @@ impl PwmLimits {
max_i_neg: max_i_neg.get::<ampere>() as f32,
}
}
pub fn apply(&self, channels: &mut Channels, channel: usize) {
channels.set_max_v(channel, ElectricPotential::new::<volt>(self.max_v.into()));
channels.set_max_i_pos(channel, ElectricCurrent::new::<ampere>(self.max_i_pos.into()));
channels.set_max_i_neg(channel, ElectricCurrent::new::<ampere>(self.max_i_neg.into()));
}
}
#[cfg(test)]
@ -123,7 +169,6 @@ mod test {
],
};
const EEPROM_SIZE: usize = 0x80;
let mut buffer = [0; EEPROM_SIZE];
let buffer = config.encode(&mut buffer).unwrap();
assert!(buffer.len() <= EEPROM_SIZE);
@ -149,7 +194,6 @@ mod test {
],
};
const EEPROM_SIZE: usize = 0x80;
let mut buffer = [0; EEPROM_SIZE];
config.encode(&mut buffer).unwrap();
let decoded = Config::decode(&buffer).unwrap();

View File

@ -73,6 +73,9 @@ const WATCHDOG_INTERVAL: u32 = 1_000;
#[cfg(feature = "semihosting")]
const WATCHDOG_INTERVAL: u32 = 30_000;
pub const EEPROM_PAGE_SIZE: usize = 8;
pub const EEPROM_SIZE: usize = 128;
const TCP_PORT: u16 = 23;
@ -429,16 +432,25 @@ fn main() -> ! {
}
}
}
Command::Load => {}
Command::Save => {
let config = Config::new(&mut channels);
let mut buf = [0; 128];
match config.encode(&mut buf) {
Ok(buf) => {
let _ = writeln!(socket, "Encoded {}: {:?}", buf.len(), buf);
Command::Load => {
match Config::load(&mut eeprom) {
Ok(config) => {
config.apply(&mut channels);
let _ = writeln!(socket, "Config loaded from EEPROM.");
}
Err(e) => {
let _ = writeln!(socket, "Error encoding configuration: {}", e);
let _ = writeln!(socket, "Error: {:?}", e);
}
}
}
Command::Save => {
let config = Config::new(&mut channels);
match config.save(&mut eeprom) {
Ok(()) => {
let _ = writeln!(socket, "Config saved to EEPROM.");
}
Err(e) => {
let _ = writeln!(socket, "Error saving config: {:?}", e);
}
}
}