diff --git a/Cargo.lock b/Cargo.lock index c6083ae..b1c6fbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,13 +341,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "derive_stringset" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dsp" version = "0.1.0" dependencies = [ "criterion", "libm", + "miniconf", "serde", + "serde-json-core 0.1.0", ] [[package]] @@ -375,6 +386,17 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-nal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae46eb1b02de5a76d9d0ea21d657ff5b0ad2cc47f3a7723608227b1dd1b3eb18" +dependencies = [ + "heapless", + "nb 1.0.0", + "no-std-net", +] + [[package]] name = "enum-iterator" version = "0.6.0" @@ -556,6 +578,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniconf" +version = "0.1.0" +dependencies = [ + "derive_stringset", + "serde", + "serde-json-core 0.2.0", +] + +[[package]] +name = "minimq" +version = "0.1.0" +source = "git+https://github.com/quartiq/minimq.git#dc459f5a3978fd90410adc916ce12b56ca449c47" +dependencies = [ + "bit_field", + "embedded-nal", + "enum-iterator", + "generic-array 0.14.4", + "heapless", +] + [[package]] name = "nb" version = "0.1.3" @@ -571,6 +614,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" +[[package]] +name = "no-std-net" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2178127478ae4ee9be7180bc9c3bffb6354dd7238400db567102f98c413a9f35" + [[package]] name = "num-traits" version = "0.2.14" @@ -641,9 +690,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" dependencies = [ "proc-macro2", ] @@ -784,6 +833,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-json-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89fd6016a00149b485f66da701f76d909210d319040c97b6eff300f6e2ba2153" +dependencies = [ + "heapless", + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.1" @@ -843,12 +902,14 @@ dependencies = [ "heapless", "log", "mcp23017", + "miniconf", + "minimq", "nb 1.0.0", "panic-halt", "panic-semihosting", "paste", "serde", - "serde-json-core", + "serde-json-core 0.1.0", "smoltcp", "stm32h7xx-hal", ] diff --git a/Cargo.toml b/Cargo.toml index 2789de0..bdc73e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,12 @@ enum-iterator = "0.6.0" paste = "1" dsp = { path = "dsp" } ad9959 = { path = "ad9959" } -minimq = "0.1.0" +minimq = { git = "https://github.com/quartiq/minimq.git" } + +[dependencies.miniconf] +# git = "https://github.com/vertigo-designs/miniconf.git" +# branch = "james/derive_stringset" +path = "../../vertigo-designs/miniconf" [dependencies.mcp23017] git = "https://github.com/mrd0ll4r/mcp23017.git" diff --git a/dsp/Cargo.toml b/dsp/Cargo.toml index 548e64f..661bf78 100644 --- a/dsp/Cargo.toml +++ b/dsp/Cargo.toml @@ -7,6 +7,12 @@ edition = "2018" [dependencies] libm = "0.2.1" serde = { version = "1.0", features = ["derive"], default-features = false } +serde-json-core = "0.1" + +[dependencies.miniconf] +# git = "https://github.com/vertigo-designs/miniconf.git" +# branch = "james/derive_stringset" +path = "../../../vertigo-designs/miniconf" [dev-dependencies] criterion = "0.3" diff --git a/src/bin/dual-iir.rs b/src/bin/dual-iir.rs index 53d1924..f7bb97b 100644 --- a/src/bin/dual-iir.rs +++ b/src/bin/dual-iir.rs @@ -3,19 +3,16 @@ #![no_main] #![cfg_attr(feature = "nightly", feature(core_intrinsics))] -use stm32h7xx_hal as hal; +use miniconf::StringSet; -#[macro_use] -extern crate log; +use stm32h7xx_hal as hal; use rtic::cyccnt::{Instant, U32Ext}; -use heapless::{consts::*, String}; - -use stabilizer::{hardware, server}; +use stabilizer::hardware; use dsp::iir; -use hardware::{Adc0Input, Adc1Input, Dac0Output, Dac1Output, AFE0, AFE1}; +use hardware::{Adc0Input, Adc1Input, Dac0Output, Dac1Output, AFE0, AFE1, MqttAction}; const SCALE: f32 = ((1 << 15) - 1) as f32; @@ -25,10 +22,10 @@ const TCP_TX_BUFFER_SIZE: usize = 8192; // The number of cascaded IIR biquads per channel. Select 1 or 2! const IIR_CASCADE_LENGTH: usize = 1; -#[derive(miniconf::StringSet)] +#[derive(Default, StringSet)] struct Settings { - afe_gain: [hardware::AfeGain; 2], - iir: [[iir::IIR; IIR_CASCADE_LENGTH]; 2], + pub afe_gain: [hardware::AfeGain; 2], + //iir: [[iir::IIR; IIR_CASCADE_LENGTH]; 2], } #[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] @@ -37,7 +34,6 @@ const APP: () = { afes: (AFE0, AFE1), adcs: (Adc0Input, Adc1Input), dacs: (Dac0Output, Dac1Output), - net_interface: hardware::Ethernet, mqtt_interface: hardware::MqttInterface, // Format: iir_state[ch][cascade-no][coeff] @@ -62,10 +58,10 @@ const APP: () = { stabilizer.adc_dac_timer.start(); init::LateResources { + mqtt_interface: hardware::MqttInterface::new(stabilizer.net.stack, Settings::default()), afes: stabilizer.afes, adcs: stabilizer.adcs, dacs: stabilizer.dacs, - net_interface: stabilizer.net.interface, } } @@ -130,22 +126,18 @@ const APP: () = { time += 1; } - let sleep = c.resources.network_stack.update( - smoltcp::time::Instant::from_millis(time as i64), - ); - match c.resources.mqtt_interface.lock(|interface| interface.update(time).unwrap()) { - Action::Sleep => cortex_m::asm::wfi(), - Action::Continue => {}, - Action::CommitSettings => c.spawn.settings_update().unwrap(); + MqttAction::Sleep => cortex_m::asm::wfi(), + MqttAction::Continue => {}, + MqttAction::CommitSettings => c.spawn.settings_update().unwrap(), } } } #[task(priority = 1, resources=[mqtt_interface, afes, iir_ch])] fn settings_update(c: settings_update::Context) { - let settings = c.resources.mqtt_interface.current_settings(); - c.resources.iir_ch.lock(|iir_ch| *iir_ch = settings.iir); + let settings = c.resources.mqtt_interface.settings.borrow(); + //c.resources.iir_ch.lock(|iir_ch| *iir_ch = settings.iir); c.resources.afes.0.set_gain(settings.afe_gain[0]); c.resources.afes.1.set_gain(settings.afe_gain[1]); } diff --git a/src/hardware/configuration.rs b/src/hardware/configuration.rs index 925d684..721c523 100644 --- a/src/hardware/configuration.rs +++ b/src/hardware/configuration.rs @@ -527,15 +527,25 @@ pub fn setup( let sockets = { // Note(unsafe): Configuration is only called once, so we only access the global // storage a single time. - let socket_storage = unsafe { &mut NET_STORE.sockets }; + let socket_storage = unsafe { &mut NET_STORE.sockets[..] }; let mut sockets = smoltcp::socket::SocketSet::new(socket_storage); let tcp_socket = { - // Note(unsafe): Configuration is only called once, so we only access the global - // storage a single time. - let rx_storage = unsafe { &mut NET_STORE.rx_storage[..] }; - let tx_storage = unsafe { &mut NET_STORE.tx_storage[..] }; - smoltcp::socket::TcpSocket::new(rx_storage, tx_storage) + let rx_buffer = { + // Note(unsafe): Configuration is only called once, so we only access the global + // storage a single time. + let storage = unsafe { &mut NET_STORE.rx_storage[..] }; + smoltcp::socket::TcpSocketBuffer::new(storage) + }; + + let tx_buffer = { + // Note(unsafe): Configuration is only called once, so we only access the global + // storage a single time. + let storage = unsafe { &mut NET_STORE.tx_storage[..] }; + smoltcp::socket::TcpSocketBuffer::new(storage) + }; + + smoltcp::socket::TcpSocket::new(rx_buffer, tx_buffer) }; sockets.add(tcp_socket); diff --git a/src/hardware/mod.rs b/src/hardware/mod.rs index 2d638c4..47620cd 100644 --- a/src/hardware/mod.rs +++ b/src/hardware/mod.rs @@ -17,12 +17,14 @@ mod eeprom; mod pounder; mod smoltcp_nal; mod timers; +mod mqtt_interface; pub use adc::{Adc0Input, Adc1Input}; pub use afe::Gain as AfeGain; pub use dac::{Dac0Output, Dac1Output}; pub use digital_input_stamper::InputStamper; pub use pounder::DdsOutput; +pub use mqtt_interface::{MqttInterface, Action as MqttAction}; // Type alias for the analog front-end (AFE) for ADC0. pub type AFE0 = afe::ProgrammableGainAmplifier< @@ -37,7 +39,7 @@ pub type AFE1 = afe::ProgrammableGainAmplifier< >; // Type alias for the ethernet interface on Stabilizer. -type Ethernet = smoltcp::iface::EthernetInterface< +pub type Ethernet = smoltcp::iface::EthernetInterface< 'static, 'static, 'static, diff --git a/src/hardware/mqtt_interface.rs b/src/hardware/mqtt_interface.rs index 7ce6544..6ab5745 100644 --- a/src/hardware/mqtt_interface.rs +++ b/src/hardware/mqtt_interface.rs @@ -1,6 +1,11 @@ use super::NetworkStack; -use minimq::{QoS, Error, Property, MqttClient}; +use minimq::{ + embedded_nal::{IpAddr, Ipv4Addr}, + QoS, Error, Property, MqttClient +}; +use heapless::{String, consts}; +use core::fmt::Write; pub enum Action { Continue, @@ -8,10 +13,10 @@ pub enum Action { CommitSettings, } -struct MqttInterface { - client: MqttClient, +pub struct MqttInterface { + client: core::cell::RefCell>, subscribed: bool, - settings: T, + pub settings: core::cell::RefCell, } impl MqttInterface @@ -25,29 +30,25 @@ where stack).unwrap(); Self { - client, + client: core::cell::RefCell::new(client), subscribed: false, - settings, + settings: core::cell::RefCell::new(settings), } } - pub fn current_settings(&self) -> &T { - &self.settings - } + pub fn update(&mut self, time: u32) -> Result { - pub fn update(&mut self, time: u32) -> Result { + let sleep = self.client.borrow_mut().network_stack.update(time); - let sleep = self.client.network_stack.update(smoltcp::time::Instant::from_millis(time as i64)); - - if !self.subscribed && self.client.is_connected().unwrap() { - self.client.subscribe("stabilizer/settings/#", &[]); - self.client.subscribe("stabilizer/commit", &[]); + if !self.subscribed && self.client.borrow_mut().is_connected().unwrap() { + self.client.borrow_mut().subscribe("stabilizer/settings/#", &[]).unwrap(); + self.client.borrow_mut().subscribe("stabilizer/commit", &[]).unwrap(); } let mut commit = false; - match self.client.poll(|client, topic, message, properties| { - let split = topic.split('/').iter(); + match self.client.borrow_mut().poll(|client, topic, message, properties| { + let mut split = topic.split('/'); // TODO: Verify topic ID against our ID. let id = split.next().unwrap(); @@ -57,10 +58,10 @@ where "settings" => { // Handle settings failures let mut response: String = String::new(); - match self.settings.string_set(split.peekable(), message) { + match self.settings.borrow_mut().string_set(split.peekable(), message) { Ok(_) => write!(&mut response, "{} written", topic).unwrap(), Err(error) => { - write!(&mut response, "Settings failure: {}", error).unwrap(); + write!(&mut response, "Settings failure: {:?}", error).unwrap(); } }; @@ -68,8 +69,9 @@ where }, "commit" => { commit = true; - String::from("Committing pending settings"); - } + String::from("Committing pending settings") + }, + _ => String::from("Unknown topic"), }; // Publish the response to the request over MQTT using the ResponseTopic property if @@ -81,7 +83,7 @@ where false } }).or(Some(&Property::ResponseTopic("stabilizer/log"))).unwrap() { - self.client.publish(topic, &response.into_bytes(), QoS::AtMostOnce, &[]).unwrap(); + client.publish(topic, &response.into_bytes(), QoS::AtMostOnce, &[]).unwrap(); } }) { Ok(_) => {}, @@ -90,7 +92,7 @@ where }; let action = if commit { - Action::Commit + Action::CommitSettings } else if sleep { Action::Sleep } else { diff --git a/src/hardware/smoltcp_nal.rs b/src/hardware/smoltcp_nal.rs index 8cd7f46..ac0bf2e 100644 --- a/src/hardware/smoltcp_nal.rs +++ b/src/hardware/smoltcp_nal.rs @@ -77,7 +77,10 @@ impl<'a, 'b, 'c> NetworkStack<'a, 'b, 'c> { } } -impl<'a, 'b, 'c> NetworkStack<'a, 'b, 'c> { +impl<'a, 'b, 'c> nal::TcpStack for NetworkStack<'a, 'b, 'c> { + type Error = NetworkError; + type TcpSocket = smoltcp::socket::SocketHandle; + fn open( &self, _mode: nal::Mode,