diff --git a/Cargo.lock b/Cargo.lock index fd6ffa8..1a434fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,6 +173,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "half" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" + [[package]] name = "libm" version = "0.2.1" @@ -305,6 +311,36 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "serde" +version = "1.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "smoltcp" version = "0.6.0" @@ -404,6 +440,8 @@ dependencies = [ "num-traits", "panic-abort", "panic-semihosting", + "serde", + "serde_cbor", "smoltcp", "stm32-eth", "stm32f4xx-hal", @@ -431,6 +469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bb593f5252356bfb829112f8fca2d0982d48588d2d6bb5a92553b0dfc4c9aba" dependencies = [ "num-traits", + "serde", "typenum", ] diff --git a/Cargo.toml b/Cargo.toml index e5c9918..f9dda31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,8 +31,10 @@ num-traits = { version = "0.2", default-features = false, features = ["libm"] } usb-device = "0.2" usbd-serial = "0.1" nb = "0.1" -uom = { version = "0.29", default-features = false, features = ["autoconvert", "si", "f64"] } +uom = { version = "0.29", default-features = false, features = ["autoconvert", "si", "f64", "use_serde"] } eeprom24x = "0.3" +serde = { version = "1.0", default-features = false, features = ["derive"] } +serde_cbor = { version = "0.11.1", default-features = false } [patch.crates-io] stm32f4xx-hal = { git = "https://github.com/stm32-rs/stm32f4xx-hal.git" } diff --git a/src/command_parser.rs b/src/command_parser.rs index fd78315..fa0e994 100644 --- a/src/command_parser.rs +++ b/src/command_parser.rs @@ -12,6 +12,7 @@ use nom::{ error::ErrorKind, }; use num_traits::{Num, ParseFloatError}; +use serde::{Serialize, Deserialize}; #[derive(Clone, Debug, PartialEq)] @@ -122,7 +123,7 @@ pub enum PwmPin { MaxV, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum CenterPoint { Vref, Override(f64), diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..792998b --- /dev/null +++ b/src/config.rs @@ -0,0 +1,57 @@ +use serde::{Serialize, Deserialize}; +use serde_cbor::Serializer; +use serde_cbor::ser::SliceWrite; +use crate::{ + channel_state::ChannelState, + channels::{CHANNELS, Channels}, + command_parser::CenterPoint, + pid, + steinhart_hart, +}; + +/// Just for encoding/decoding, actual state resides in ChannelState +#[derive(Serialize, Deserialize)] +pub struct Config { + channels: [ChannelConfig; CHANNELS], +} + +impl Config { + pub fn new(channels: &mut Channels) -> Self { + Config { + channels: [ + ChannelConfig::new(channels.channel_state(0usize)), + ChannelConfig::new(channels.channel_state(1usize)), + ], + } + } + + pub fn encode(&self, buffer: &mut [u8]) -> Result { + let writer = SliceWrite::new(buffer); + let mut ser = Serializer::new(writer); + self.serialize(&mut ser)?; + let writer = ser.into_inner(); + let size = writer.bytes_written(); + Ok(size) + } +} + +#[derive(Serialize, Deserialize)] +pub struct ChannelConfig { + center: CenterPoint, + pid: pid::Parameters, + pid_target: f64, + sh: steinhart_hart::Parameters, + // TODO: pwm limits +} + +impl ChannelConfig { + pub fn new(state: &ChannelState) -> Self { + ChannelConfig { + center: state.center.clone(), + pid: state.pid.parameters.clone(), + pid_target: state.pid.target, + sh: state.sh.clone(), + } + } + +} diff --git a/src/main.rs b/src/main.rs index afb1981..f2ce5be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -63,6 +63,8 @@ mod channels; use channels::{CHANNELS, Channels}; mod channel; mod channel_state; +mod config; +use config::Config; const HSE: MegaHertz = MegaHertz(8); @@ -428,7 +430,18 @@ fn main() -> ! { } } Command::Load => {} - Command::Save => {} + Command::Save => { + let config = Config::new(&mut channels); + let mut buf = [0; 0x200]; + match config.encode(&mut buf) { + Ok(len) => { + let _ = writeln!(socket, "Encoded: {:?}", &buf[..len]); + } + Err(e) => { + let _ = writeln!(socket, "Error encoding configuration: {}", e); + } + } + } } Ok(SessionOutput::Error(e)) => { let _ = writeln!(socket, "Command error: {:?}", e); diff --git a/src/pid.rs b/src/pid.rs index 7e1d02d..198664c 100644 --- a/src/pid.rs +++ b/src/pid.rs @@ -1,4 +1,6 @@ -#[derive(Clone, Copy)] +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Serialize, Deserialize)] pub struct Parameters { pub kp: f64, pub ki: f64, diff --git a/src/steinhart_hart.rs b/src/steinhart_hart.rs index f0b231f..bcd6f41 100644 --- a/src/steinhart_hart.rs +++ b/src/steinhart_hart.rs @@ -8,9 +8,10 @@ use uom::si::{ ratio::ratio, thermodynamic_temperature::{degree_celsius, kelvin}, }; +use serde::{Serialize, Deserialize}; /// Steinhart-Hart equation parameters -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Parameters { /// Base temperature pub t0: ThermodynamicTemperature,