From 46c87964dd3c8a929bbc21c5fc52b351546437ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Fri, 25 Oct 2024 11:54:56 +0000 Subject: [PATCH 1/2] rm spurious comment --- src/hardware/setup.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hardware/setup.rs b/src/hardware/setup.rs index 6f52070..3cf6c90 100644 --- a/src/hardware/setup.rs +++ b/src/hardware/setup.rs @@ -384,7 +384,6 @@ where None, None, ]; 4]; - // Sensor::ntc(25.0, 10.0e3, 5.0e3, 3988.0), #[cfg(feature = "all_single_ended")] let adc_input_config = [[ From fdfe038d9737ea5c2e23348966f696097ab13506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Fri, 25 Oct 2024 12:13:14 +0000 Subject: [PATCH 2/2] bump deps, miniconf 0.17 --- Cargo.lock | 74 +++++++++++++++++++++---------------------- Cargo.toml | 4 +-- py/pyproject.toml | 4 +-- src/hardware/adc.rs | 48 +++++++++++++--------------- src/hardware/setup.rs | 6 ++-- src/main.rs | 52 +++++++++++------------------- src/net/mod.rs | 19 ++++++----- src/output_channel.rs | 69 ++++++++++++++++++++-------------------- src/settings.rs | 23 +++++++------- 9 files changed, 139 insertions(+), 160 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 590962c..c952c64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,7 +53,7 @@ dependencies = [ "arbitrary-int", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -100,7 +100,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -117,9 +117,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.28" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", @@ -173,9 +173,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "darling" @@ -198,7 +198,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -209,7 +209,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -485,9 +485,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libgit2-sys" @@ -561,9 +561,9 @@ dependencies = [ [[package]] name = "miniconf" -version = "0.16.3" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf52da0fbf409a8a008b661e476127fa79b954169af83586cc1ceebb15e5ccb" +checksum = "75e453c8c2bdb4367152a3057eeb3dc4cc2346c4d9d7985a76d27b2b070d46c3" dependencies = [ "itoa", "miniconf_derive", @@ -574,21 +574,21 @@ dependencies = [ [[package]] name = "miniconf_derive" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4720786aa0863bd853f54a95da244c2598d2216ba6711b7b95d8043aa9a83e43" +checksum = "86704131b3dad62adfcee4cc7cc314778465976e80a515b64918ee81681424ff" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] name = "miniconf_mqtt" -version = "0.16.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052f576f313d9bbec2786e1d749e84142f4efc547117ef8c039c6d974211d6ff" +checksum = "4c05e73e94df6dcfce14ac82ff3ed54ce24f77030f9edb355f2b51d42e605d65" dependencies = [ "embedded-io", "heapless 0.8.0", @@ -742,7 +742,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -778,9 +778,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -837,9 +837,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -892,14 +892,14 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] name = "rtic-monotonics" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e17f88319061d17d3b99997263397b176e3260177e2b4ff4ffed0078d97894c" +checksum = "f1cb90bcfdbbacf3ca37340cdab52ec2de5611c744095ef7889e9c50c233b748" dependencies = [ "cfg-if", "cortex-m", @@ -977,9 +977,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -1025,9 +1025,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] @@ -1045,13 +1045,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1074,13 +1074,13 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] name = "serial-settings" version = "0.1.0" -source = "git+https://github.com/quartiq/stabilizer.git#50eff37a90b50a73754f4cb29aa54694444b1c0c" +source = "git+https://github.com/quartiq/stabilizer.git#8aff7d2403774134aaf68c522b39b6348992814b" dependencies = [ "embedded-io", "heapless 0.8.0", @@ -1256,7 +1256,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1272,9 +1272,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 33dcb0d..51e8c25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,8 +63,8 @@ bytemuck = { version = "1.19.0", features = [ "derive", ], default-features = false } # Note: Keep in-sync with `py/setup.py` -miniconf = { version = "0.16", features = ["json-core", "derive", "postcard"] } -miniconf_mqtt = { version = "0.16" } +miniconf = { version = "0.17", features = ["json-core", "derive", "postcard"] } +miniconf_mqtt = { version = "0.17" } strum = { version = "0.26.1", default-features = false, features = ["derive"] } serial-settings = "0.1" postcard = "1" diff --git a/py/pyproject.toml b/py/pyproject.toml index 5cf0146..a0a8164 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -15,8 +15,8 @@ authors = [ { name = "Norman Krackow", email = "nk@quartiq.de" }, ] dependencies = [ - "miniconf-mqtt@git+https://github.com/quartiq/miniconf@v0.16.0#subdirectory=py/miniconf-mqtt", - "stabilizer@git+https://github.com/quartiq/stabilizer@50eff37a#subdirectory=py", + "miniconf-mqtt@git+https://github.com/quartiq/miniconf@v0.17.0#subdirectory=py/miniconf-mqtt", + "stabilizer@git+https://github.com/quartiq/stabilizer@8aff7d2#subdirectory=py", ] [project.urls] diff --git a/src/hardware/adc.rs b/src/hardware/adc.rs index 84ed995..f5988dd 100644 --- a/src/hardware/adc.rs +++ b/src/hardware/adc.rs @@ -1,7 +1,7 @@ // Thermostat ADC struct. use arbitrary_int::u2; -use miniconf::Tree; +use miniconf::{Leaf, Tree}; use num_traits::float::Float; use smlang::statemachine; use strum::{AsRefStr, EnumString, IntoEnumIterator}; @@ -114,22 +114,22 @@ pub trait Convert { #[derive(Clone, Copy, Debug, Tree)] pub struct Linear { /// Units: output - offset: f32, + offset: Leaf, /// Units: output/input - gain: f32, + gain: Leaf, } impl Convert for Linear { fn convert(&self, code: AdcCode) -> f64 { - (f32::from(code) * self.gain) as f64 + self.offset as f64 + (f32::from(code) * *self.gain) as f64 + *self.offset as f64 } } impl Default for Linear { fn default() -> Self { Self { - offset: 0., - gain: 1., + offset: 0.0.into(), + gain: 1.0.into(), } } } @@ -137,17 +137,17 @@ impl Default for Linear { /// Beta equation (Steinhart-Hart with c=0) #[derive(Clone, Copy, Debug, Tree)] pub struct Ntc { - t0_inv: f32, // inverse reference temperature (1/K) - r_rel: f32, // reference resistor over NTC resistance at t0, - beta_inv: f32, // inverse beta + t0_inv: Leaf, // inverse reference temperature (1/K) + r_rel: Leaf, // reference resistor over NTC resistance at t0, + beta_inv: Leaf, // inverse beta } impl Ntc { pub fn new(t0: f32, r0: f32, r_ref: f32, beta: f32) -> Self { Self { - t0_inv: 1.0 / (t0 + ZERO_C), - r_rel: r_ref / r0, - beta_inv: 1.0 / beta, + t0_inv: (1.0 / (t0 + ZERO_C)).into(), + r_rel: (r_ref / r0).into(), + beta_inv: (1.0 / beta).into(), } } } @@ -160,37 +160,33 @@ impl Convert for Ntc { // avoided. Input values must not close to minimum/maximum (~1000 codes difference) // https://en.wikipedia.org/wiki/Thermistor#B_or_%CE%B2_parameter_equation let relative_voltage = f32::from(code) as f64; - let relative_resistance = relative_voltage / (1.0 - relative_voltage) * self.r_rel as f64; - 1.0 / (self.t0_inv as f64 + self.beta_inv as f64 * relative_resistance.ln()) - ZERO_C as f64 + let relative_resistance = relative_voltage / (1.0 - relative_voltage) * *self.r_rel as f64; + 1.0 / (*self.t0_inv as f64 + *self.beta_inv as f64 * relative_resistance.ln()) + - ZERO_C as f64 } } impl Default for Ntc { fn default() -> Self { - Self { - t0_inv: 1. / (25. + ZERO_C), - #[allow(clippy::eq_op)] - r_rel: 10.0e3 / 10.0e3, - beta_inv: 1. / 3988., - } + Self::new(25., 10.0e3, 10.0e3, 3988.) } } /// DT-670 Silicon diode #[derive(Clone, Copy, Debug, Tree)] pub struct Dt670 { - v_ref: f32, // effective reference voltage (V) + v_ref: Leaf, // effective reference voltage (V) } impl Default for Dt670 { fn default() -> Self { - Self { v_ref: 5. } + Self { v_ref: 5.0.into() } } } impl Convert for Dt670 { fn convert(&self, code: AdcCode) -> f64 { - let voltage = f32::from(code) * self.v_ref; + let voltage = f32::from(code) * *self.v_ref; const CURVE: &[(f32, f32, f32)] = &super::dt670::CURVE; let idx = CURVE.partition_point(|&(_t, v, _dvdt)| v < voltage); CURVE @@ -204,9 +200,9 @@ impl Convert for Dt670 { /// ADC configuration structure. #[derive(Clone, Copy, Debug, Tree, EnumString, AsRefStr)] pub enum Sensor { - Linear(#[tree(depth = 1)] Linear), - Ntc(#[tree(depth = 1)] Ntc), - Dt670(#[tree(depth = 1)] Dt670), + Linear(Linear), + Ntc(Ntc), + Dt670(Dt670), } const ZERO_C: f32 = 273.15; // 0°C in °K diff --git a/src/hardware/setup.rs b/src/hardware/setup.rs index 3cf6c90..9aeabe9 100644 --- a/src/hardware/setup.rs +++ b/src/hardware/setup.rs @@ -98,7 +98,7 @@ pub struct NetworkDevices { } /// The available hardware interfaces on Thermostat. -pub struct ThermostatDevices + 'static, const Y: usize> { +pub struct ThermostatDevices { pub clocks: hal::rcc::CoreClocks, pub net: NetworkDevices, pub dac: Dac, @@ -126,7 +126,7 @@ pub fn setup( clock: crate::SystemTimer, ) -> ThermostatDevices where - C: serial_settings::Settings + crate::settings::AppSettings, + C: serial_settings::Settings + crate::settings::AppSettings, { // Set up RTT logging { @@ -472,7 +472,7 @@ where }; let mut settings = C::new(crate::NetSettings::new(mac_addr)); - crate::settings::SerialSettingsPlatform::load(&mut settings, &mut flash); + crate::settings::SerialSettingsPlatform::<_, Y>::load(&mut settings, &mut flash); (flash, settings) }; diff --git a/src/main.rs b/src/main.rs index fe19727..e5ecec6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,7 @@ use rtic_monotonics::Monotonic; use rtic_sync::{channel::*, make_channel}; use fugit::ExtU32; -use miniconf::{TreeDeserialize, TreeKey, TreeSerialize}; +use miniconf::{Leaf, StrLeaf, TreeDeserialize, TreeKey, TreeSerialize}; use net::{ data_stream::{FrameGenerator, StreamFormat, StreamTarget}, Alarm, NetworkState, NetworkUsers, @@ -41,21 +41,10 @@ use statistics::{Buffer, Statistics}; #[derive(Clone, Debug, TreeSerialize, TreeDeserialize, TreeKey, Default)] pub struct InputChannel { - #[tree(typ="&str", get=Self::get_typ, validate=Self::validate_typ)] - typ: (), - #[tree(depth = 2)] - sensor: Sensor, -} - -impl InputChannel { - fn get_typ(&self) -> Result<&str, &'static str> { - Ok(self.sensor.as_ref()) - } - - fn validate_typ(&mut self, value: &str) -> Result<(), &'static str> { - self.sensor = Sensor::try_from(value).or(Err("invalid sensor type"))?; - Ok(()) - } + #[tree(rename = "typ")] + sensor: StrLeaf, + #[tree(rename="sensor", typ = "Sensor", defer=*self.sensor)] + _sensor: (), } #[derive(Clone, Debug, TreeSerialize, TreeDeserialize, TreeKey)] @@ -67,10 +56,9 @@ pub struct ThermostatEem { /// /// # Value /// Any positive non-zero value. Will be rounded to milliseconds. - telemetry_period: f32, + telemetry_period: Leaf, /// Input sensor configuration - #[tree(depth = 6)] input: [[Option; 4]; 4], /// Array of settings for the Thermostat output channels. @@ -81,7 +69,6 @@ pub struct ThermostatEem { /// /// # Value /// See [OutputChannel] - #[tree(depth = 3)] output: [OutputChannel; 4], /// Alarm settings. @@ -91,16 +78,15 @@ pub struct ThermostatEem { /// /// # Value /// See [Alarm] - #[tree(depth = 3)] alarm: Alarm, - stream: StreamTarget, + stream: Leaf, } impl Default for ThermostatEem { fn default() -> Self { Self { - telemetry_period: 1.0, + telemetry_period: 1.0.into(), input: Default::default(), output: Default::default(), alarm: Default::default(), @@ -111,10 +97,8 @@ impl Default for ThermostatEem { #[derive(Clone, Debug, TreeSerialize, TreeDeserialize, TreeKey)] pub struct Settings { - #[tree(depth = 7)] pub thermostat_eem: ThermostatEem, - #[tree(depth = 1)] pub net: NetSettings, } @@ -131,7 +115,7 @@ impl settings::AppSettings for Settings { } } -impl serial_settings::Settings<8> for Settings { +impl serial_settings::Settings for Settings { fn reset(&mut self) { *self = Self { thermostat_eem: ThermostatEem::default(), @@ -234,7 +218,7 @@ mod app { if let Some(mux) = mux { let r_ref = if mux.is_single_ended() { 5.0e3 } else { 10.0e3 }; *channel = Some(InputChannel { - sensor: Sensor::Ntc(Ntc::new(25.0, 10.0e3, r_ref, 3988.0)), + sensor: Sensor::Ntc(Ntc::new(25.0, 10.0e3, r_ref, 3988.0)).into(), ..Default::default() }); } @@ -305,15 +289,15 @@ mod app { (c.shared.network, c.shared.gpio, c.shared.settings).lock(|network, gpio, settings| { for (ch, s) in OutputChannelIdx::iter().zip(settings.thermostat_eem.output.iter_mut()) { s.finalize_settings(); // clamp limits and normalize weights - pwm.set_limit(Limit::Voltage(ch), s.voltage_limit).unwrap(); + pwm.set_limit(Limit::Voltage(ch), *s.voltage_limit).unwrap(); let [pos, neg] = s.current_limits(); pwm.set_limit(Limit::PositiveCurrent(ch), pos).unwrap(); pwm.set_limit(Limit::NegativeCurrent(ch), neg).unwrap(); - gpio.set_shutdown(ch, (s.state == State::Off).into()); - gpio.set_led(ch.into(), (s.state != State::Off).into()); // fix leds to channel state + gpio.set_shutdown(ch, (*s.state == State::Off).into()); + gpio.set_led(ch.into(), (*s.state != State::Off).into()); // fix leds to channel state } - network.direct_stream(settings.thermostat_eem.stream); + network.direct_stream(*settings.thermostat_eem.stream); }); } @@ -356,7 +340,7 @@ mod app { .shared .settings .lock(|settings| settings.thermostat_eem.telemetry_period); - Systick::delay((telemetry_period as u32).secs()).await; + Systick::delay((*telemetry_period as u32).secs()).await; } } @@ -367,14 +351,14 @@ mod app { .shared .settings .lock(|settings| settings.thermostat_eem.alarm.clone()); - if alarm.armed { + if *alarm.armed { let temperatures = c.shared.temperature.lock(|temp| *temp); let mut alarms = [[None; 4]; 4]; let mut alarm_state = false; for phy_i in 0..4 { for cfg_i in 0..4 { if let Some(l) = &alarm.temperature_limits[phy_i][cfg_i] { - let a = !(l[0]..l[1]).contains(&(temperatures[phy_i][cfg_i] as _)); + let a = !(*l[0]..*l[1]).contains(&(temperatures[phy_i][cfg_i] as _)); alarms[phy_i][cfg_i] = Some(a); alarm_state |= a; } @@ -388,7 +372,7 @@ mod app { .lock(|net| net.telemetry.publish_alarm(&alarm.target, &alarm_state)); } // Note that you have to wait for a full period of the previous setting first for a change of period to take affect. - Systick::delay(((alarm.period * 1000.0) as u32).millis()).await; + Systick::delay(((*alarm.period * 1000.0) as u32).millis()).await; } } diff --git a/src/net/mod.rs b/src/net/mod.rs index fe47681..b79ea45 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -24,7 +24,7 @@ use telemetry::TelemetryClient; use core::fmt::Write; use heapless::String; -use miniconf::{Tree, TreeDeserializeOwned, TreeSerialize}; +use miniconf::{Leaf, Tree, TreeDeserializeOwned, TreeKey, TreeSerialize}; pub type NetworkReference = smoltcp_nal::shared::NetworkStackProxy<'static, NetworkStack>; @@ -57,7 +57,7 @@ pub enum NetworkState { /// A structure of Stabilizer's default network users. pub struct NetworkUsers where - S: Default + TreeDeserializeOwned + TreeSerialize + Clone, + S: Default + TreeDeserializeOwned + TreeSerialize + TreeKey + Clone, { pub miniconf: miniconf_mqtt::MqttClient< 'static, @@ -75,7 +75,7 @@ where impl NetworkUsers where - S: Default + TreeDeserializeOwned + TreeSerialize + Clone, + S: Default + TreeDeserializeOwned + TreeSerialize + TreeKey + Clone, { /// Construct Stabilizer's default network users. /// @@ -251,7 +251,7 @@ pub struct Alarm { /// /// # Value /// True to arm, false to disarm. - pub armed: bool, + pub armed: Leaf, /// Alarm target. /// The alarm will publish its state (true or false) onto this mqtt path. @@ -259,14 +259,14 @@ pub struct Alarm { /// /// # Value /// Any string up to 128 characters. - pub target: String<128>, + pub target: Leaf>, /// Alarm period in milliseconds. /// The alarm will publish its state with this period. /// /// # Value /// f32 - pub period: f32, + pub period: Leaf, /// Temperature limits for the alarm. /// @@ -281,16 +281,15 @@ pub struct Alarm { /// /// # Value /// `[f32, f32]` or `None` - #[tree(depth = 2)] - pub temperature_limits: [[Option<[f32; 2]>; 4]; 4], + pub temperature_limits: [[Option<[Leaf; 2]>; 4]; 4], } impl Default for Alarm { fn default() -> Self { Self { - armed: false, + armed: false.into(), target: Default::default(), - period: 1.0, + period: 1.0.into(), temperature_limits: Default::default(), } } diff --git a/src/output_channel.rs b/src/output_channel.rs index 776f507..50c84c6 100644 --- a/src/output_channel.rs +++ b/src/output_channel.rs @@ -3,32 +3,32 @@ use crate::{hardware::pwm::Pwm, DacCode}; use idsp::iir; -use miniconf::Tree; +use miniconf::{Leaf, Tree}; use num_traits::Float; #[derive(Copy, Clone, Debug, Tree)] pub struct Pid { - pub ki: f32, - pub kp: f32, // sign reference for all gains and limits - pub kd: f32, - pub li: f32, - pub ld: f32, - pub setpoint: f32, - pub min: f32, - pub max: f32, + pub ki: Leaf, + pub kp: Leaf, // sign reference for all gains and limits + pub kd: Leaf, + pub li: Leaf, + pub ld: Leaf, + pub setpoint: Leaf, + pub min: Leaf, + pub max: Leaf, } impl Default for Pid { fn default() -> Self { Self { - ki: 0., - kp: 0., // positive default - kd: 0., - li: f32::INFINITY, - ld: f32::INFINITY, - setpoint: 25., - min: f32::NEG_INFINITY, - max: f32::INFINITY, + ki: 0.0.into(), + kp: 0.0.into(), // positive default + kd: 0.0.into(), + li: f32::INFINITY.into(), + ld: f32::INFINITY.into(), + setpoint: 25.0.into(), + min: f32::NEG_INFINITY.into(), + max: f32::INFINITY.into(), } } } @@ -38,37 +38,37 @@ impl TryFrom for iir::Biquad { fn try_from(value: Pid) -> Result { let mut biquad: iir::Biquad = iir::Pid::::default() .period(1.0 / 1007.0) // ADC sample rate (ODR) including zero-oder-holds - .gain(iir::Action::Ki, value.ki.copysign(value.kp) as _) - .gain(iir::Action::Kp, value.kp as _) - .gain(iir::Action::Kd, value.kd.copysign(value.kp) as _) + .gain(iir::Action::Ki, value.ki.copysign(*value.kp) as _) + .gain(iir::Action::Kp, *value.kp as _) + .gain(iir::Action::Kd, value.kd.copysign(*value.kp) as _) .limit( iir::Action::Ki, if value.li.is_finite() { - value.li + *value.li } else { f32::INFINITY } - .copysign(value.kp) as _, + .copysign(*value.kp) as _, ) .limit( iir::Action::Kd, if value.ld.is_finite() { - value.ld + *value.ld } else { f32::INFINITY } - .copysign(value.kp) as _, + .copysign(*value.kp) as _, ) .build()? .into(); - biquad.set_input_offset(-value.setpoint as _); + biquad.set_input_offset(-*value.setpoint as _); biquad.set_min(if value.min.is_finite() { - value.min + *value.min } else { f32::NEG_INFINITY } as _); biquad.set_max(if value.max.is_finite() { - value.max + *value.max } else { f32::INFINITY } as _); @@ -91,16 +91,15 @@ pub enum State { #[derive(Copy, Clone, Debug, Tree)] pub struct OutputChannel { - pub state: State, + pub state: Leaf, /// Maximum absolute (positive and negative) TEC voltage in volt. /// These will be clamped to the maximum of 4.3 V. /// /// # Value /// 0.0 to 4.3 - pub voltage_limit: f32, + pub voltage_limit: Leaf, - #[tree(depth = 1)] pub pid: Pid, /// IIR filter parameters. @@ -123,14 +122,14 @@ pub struct OutputChannel { /// /// # Value /// f32 - pub weights: [[f32; 4]; 4], + pub weights: Leaf<[[f32; 4]; 4]>, } impl Default for OutputChannel { fn default() -> Self { Self { - state: State::Off, - voltage_limit: Pwm::MAX_VOLTAGE_LIMIT, + state: State::Off.into(), + voltage_limit: Pwm::MAX_VOLTAGE_LIMIT.into(), pid: Default::default(), iir: Default::default(), weights: Default::default(), @@ -147,7 +146,7 @@ impl OutputChannel { .zip(self.weights.iter().flatten()) .map(|(t, w)| t * *w as f64) .sum(); - let iir = if self.state == State::On { + let iir = if *self.state == State::On { &self.iir } else { &iir::Biquad::HOLD @@ -171,7 +170,7 @@ impl OutputChannel { .set_max(self.iir.max().clamp(-range as _, range as _)); self.iir .set_min(self.iir.min().clamp(-range as _, range as _)); - self.voltage_limit = self.voltage_limit.clamp(0.0, Pwm::MAX_VOLTAGE_LIMIT); + *self.voltage_limit = (*self.voltage_limit).clamp(0.0, Pwm::MAX_VOLTAGE_LIMIT); let divisor: f32 = self.weights.iter().flatten().map(|w| w.abs()).sum(); // Note: The weights which are not 'None' should always affect an enabled channel and therefore count for normalization. if divisor != 0.0 { diff --git a/src/settings.rs b/src/settings.rs index 08a56dd..e78d368 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -27,7 +27,7 @@ use core::fmt::Write; use embassy_futures::block_on; use embedded_io::Write as EioWrite; use heapless::{String, Vec}; -use miniconf::{postcard, Path, Tree, TreeDeserializeOwned, TreeSerialize}; +use miniconf::{postcard, Leaf, Path, Tree, TreeDeserializeOwned, TreeKey, TreeSerialize}; use sequential_storage::{ cache::NoCache, map::{fetch_item, store_item, SerializationError}, @@ -40,14 +40,15 @@ use stm32h7xx_hal::flash::LockedFlashBank; #[derive(Clone, Debug, Tree)] pub struct NetSettings { /// The broker domain name (or IP address) to use for MQTT connections. - pub broker: String<255>, + pub broker: Leaf>, /// The MQTT ID to use upon connection with a broker. - pub id: String<23>, + pub id: Leaf>, /// An optional static IP address to use. An unspecified IP address (or malformed address) will /// use DHCP. - pub ip: String<15>, + pub ip: Leaf>, + #[tree(skip)] /// The MAC address of Stabilizer, which is used to reinitialize the ID to default settings. pub mac: EthernetAddress, @@ -59,9 +60,9 @@ impl NetSettings { write!(&mut id, "{mac}").unwrap(); Self { - broker: "mqtt".try_into().unwrap(), - ip: "0.0.0.0".try_into().unwrap(), - id, + broker: Leaf("mqtt".try_into().unwrap()), + ip: Leaf("0.0.0.0".try_into().unwrap()), + id: id.into(), mac, } } @@ -108,12 +109,12 @@ pub struct SerialSettingsPlatform { impl SerialSettingsPlatform where - C: TreeDeserializeOwned + TreeSerialize, + C: TreeDeserializeOwned + TreeSerialize + TreeKey, { pub fn load(structure: &mut C, storage: &mut Flash) { // Loop over flash and read settings let mut buffer = [0u8; 512]; - for path in C::nodes::, '/'>>() { + for path in C::nodes::, '/'>, Y>() { let (path, _node) = path.unwrap(); // Try to fetch the setting from flash. @@ -151,9 +152,9 @@ where } } -impl Platform for SerialSettingsPlatform +impl Platform for SerialSettingsPlatform where - C: Settings, + C: Settings, { type Interface = BestEffortInterface; type Settings = C;