Updating settings update function

This commit is contained in:
Ryan Summers 2021-02-17 12:59:24 +01:00
parent 13e02710cd
commit cb16e9a85f
5 changed files with 51 additions and 44 deletions

16
Cargo.lock generated
View File

@ -351,7 +351,6 @@ dependencies = [
[[package]] [[package]]
name = "derive_stringset" name = "derive_stringset"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/vertigo-designs/miniconf.git?branch=develop#256098cafc6db93b456b5014c8ef1b835b5e239d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -365,10 +364,10 @@ dependencies = [
"criterion", "criterion",
"generic-array 0.14.4", "generic-array 0.14.4",
"libm", "libm",
"miniconf",
"ndarray", "ndarray",
"rand", "rand",
"serde", "serde",
"serde-json-core 0.1.0",
] ]
[[package]] [[package]]
@ -620,13 +619,12 @@ dependencies = [
[[package]] [[package]]
name = "miniconf" name = "miniconf"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/vertigo-designs/miniconf.git?branch=develop#256098cafc6db93b456b5014c8ef1b835b5e239d"
dependencies = [ dependencies = [
"derive_stringset", "derive_stringset",
"heapless", "heapless",
"minimq", "minimq",
"serde", "serde",
"serde-json-core 0.2.0", "serde-json-core",
] ]
[[package]] [[package]]
@ -966,16 +964,6 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-json-core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf406405ada9ef326ca78677324ac66994ff348fc48a16030be08caeed29825"
dependencies = [
"heapless",
"serde",
]
[[package]] [[package]]
name = "serde-json-core" name = "serde-json-core"
version = "0.2.0" version = "0.2.0"

View File

@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::Deserialize;
use miniconf::StringSet;
use super::{abs, copysign, macc, max, min}; use super::{abs, copysign, macc, max, min};
use core::f32; use core::f32;
@ -11,8 +12,7 @@ use core::f32;
/// To represent the IIR coefficients, this contains the feed-forward /// To represent the IIR coefficients, this contains the feed-forward
/// coefficients (b0, b1, b2) followd by the negated feed-back coefficients /// coefficients (b0, b1, b2) followd by the negated feed-back coefficients
/// (-a1, -a2), all five normalized such that a0 = 1. /// (-a1, -a2), all five normalized such that a0 = 1.
#[derive(Copy, Clone, Default, Deserialize, Serialize)] pub type Vec5 = [f32; 5];
pub struct Vec5(pub [f32; 5]);
/// IIR configuration. /// IIR configuration.
/// ///
@ -39,7 +39,7 @@ pub struct Vec5(pub [f32; 5]);
/// Therefore it can trivially implement bump-less transfer. /// Therefore it can trivially implement bump-less transfer.
/// * Cascading multiple IIR filters allows stable and robust /// * Cascading multiple IIR filters allows stable and robust
/// implementation of transfer functions beyond bequadratic terms. /// implementation of transfer functions beyond bequadratic terms.
#[derive(Copy, Clone, Default, Deserialize, Serialize)] #[derive(Copy, Clone, Debug, Default, Deserialize, StringSet)]
pub struct IIR { pub struct IIR {
pub ba: Vec5, pub ba: Vec5,
pub y_offset: f32, pub y_offset: f32,
@ -50,7 +50,7 @@ pub struct IIR {
impl IIR { impl IIR {
pub const fn new(gain: f32, y_min: f32, y_max: f32) -> Self { pub const fn new(gain: f32, y_min: f32, y_max: f32) -> Self {
Self { Self {
ba: Vec5([gain, 0., 0., 0., 0.]), ba: [gain, 0., 0., 0., 0.],
y_offset: 0., y_offset: 0.,
y_min, y_min,
y_max, y_max,
@ -84,13 +84,13 @@ impl IIR {
} }
(a1, b0, b1) (a1, b0, b1)
}; };
self.ba.0.copy_from_slice(&[b0, b1, 0., a1, 0.]); self.ba.copy_from_slice(&[b0, b1, 0., a1, 0.]);
Ok(()) Ok(())
} }
/// Compute the overall (DC feed-forward) gain. /// Compute the overall (DC feed-forward) gain.
pub fn get_k(&self) -> f32 { pub fn get_k(&self) -> f32 {
self.ba.0[..3].iter().sum() self.ba[..3].iter().sum()
} }
/// Compute input-referred (`x`) offset from output (`y`) offset. /// Compute input-referred (`x`) offset from output (`y`) offset.
@ -118,21 +118,21 @@ impl IIR {
/// * `xy` - Current filter state. /// * `xy` - Current filter state.
/// * `x0` - New input. /// * `x0` - New input.
pub fn update(&self, xy: &mut Vec5, x0: f32) -> f32 { pub fn update(&self, xy: &mut Vec5, x0: f32) -> f32 {
let n = self.ba.0.len(); let n = self.ba.len();
debug_assert!(xy.0.len() == n); debug_assert!(xy.len() == n);
// `xy` contains x0 x1 y0 y1 y2 // `xy` contains x0 x1 y0 y1 y2
// Increment time x1 x2 y1 y2 y3 // Increment time x1 x2 y1 y2 y3
// Shift x1 x1 x2 y1 y2 // Shift x1 x1 x2 y1 y2
// This unrolls better than xy.rotate_right(1) // This unrolls better than xy.rotate_right(1)
xy.0.copy_within(0..n - 1, 1); xy.copy_within(0..n - 1, 1);
// Store x0 x0 x1 x2 y1 y2 // Store x0 x0 x1 x2 y1 y2
xy.0[0] = x0; xy[0] = x0;
// Compute y0 by multiply-accumulate // Compute y0 by multiply-accumulate
let y0 = macc(self.y_offset, &xy.0, &self.ba.0); let y0 = macc(self.y_offset, xy, &self.ba);
// Limit y0 // Limit y0
let y0 = max(self.y_min, min(self.y_max, y0)); let y0 = max(self.y_min, min(self.y_max, y0));
// Store y0 x0 x1 y0 y1 y2 // Store y0 x0 x1 y0 y1 y2
xy.0[n / 2] = y0; xy[n / 2] = y0;
y0 y0
} }
} }

View File

@ -15,7 +15,7 @@ use serde::Deserialize;
use dsp::iir; use dsp::iir;
use hardware::{ use hardware::{
Adc0Input, Adc1Input, CycleCounter, Dac0Output, Dac1Output, NetworkStack, Adc0Input, Adc1Input, CycleCounter, Dac0Output, Dac1Output, NetworkStack,
AFE0, AFE1, AFE0, AFE1, AfeGain,
}; };
const SCALE: f32 = i16::MAX as _; const SCALE: f32 = i16::MAX as _;
@ -25,12 +25,18 @@ const IIR_CASCADE_LENGTH: usize = 1;
#[derive(Debug, Deserialize, StringSet)] #[derive(Debug, Deserialize, StringSet)]
pub struct Settings { pub struct Settings {
test: u32, afe: [AfeGain; 2],
iir_state: [[iir::Vec5; IIR_CASCADE_LENGTH]; 2],
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
} }
impl Settings { impl Default for Settings {
pub fn new() -> Self { fn default() -> Self {
Self { test: 0 } Self {
afe: [AfeGain::G1, AfeGain::G1],
iir_state: [[[0.; 5]; IIR_CASCADE_LENGTH]; 2],
iir_ch: [[iir::IIR::new(1., -SCALE, SCALE); IIR_CASCADE_LENGTH]; 2],
}
} }
} }
@ -45,7 +51,7 @@ const APP: () = {
clock: CycleCounter, clock: CycleCounter,
// Format: iir_state[ch][cascade-no][coeff] // Format: iir_state[ch][cascade-no][coeff]
#[init([[iir::Vec5([0.; 5]); IIR_CASCADE_LENGTH]; 2])] #[init([[[0.; 5]; IIR_CASCADE_LENGTH]; 2])]
iir_state: [[iir::Vec5; IIR_CASCADE_LENGTH]; 2], iir_state: [[iir::Vec5; IIR_CASCADE_LENGTH]; 2],
#[init([[iir::IIR::new(1., -SCALE, SCALE); IIR_CASCADE_LENGTH]; 2])] #[init([[iir::IIR::new(1., -SCALE, SCALE); IIR_CASCADE_LENGTH]; 2])]
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2], iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
@ -67,7 +73,7 @@ const APP: () = {
.unwrap() .unwrap()
}; };
MqttInterface::new(mqtt_client, "stabilizer", Settings::new()) MqttInterface::new(mqtt_client, "stabilizer", Settings::default())
.unwrap() .unwrap()
}; };
@ -160,11 +166,19 @@ const APP: () = {
} }
} }
#[task(priority = 1, resources=[mqtt_interface, afes, iir_ch])] #[task(priority = 1, resources=[mqtt_interface, afes, iir_ch, iir_state])]
fn settings_update(c: settings_update::Context) { fn settings_update(mut c: settings_update::Context) {
let _settings = &c.resources.mqtt_interface.settings; let settings = &c.resources.mqtt_interface.settings;
//c.resources.iir_ch.lock(|iir| *iir = settings.iir);
// TODO: Update AFEs // Update the IIR channels.
c.resources.iir_ch.lock(|iir| *iir = settings.iir_ch);
// Update the IIR states.
c.resources.iir_state.lock(|iir| *iir = settings.iir_state);
// Update AFEs
c.resources.afes.0.set_gain(settings.afe[0]);
c.resources.afes.1.set_gain(settings.afe[1]);
} }
#[task(binds = ETH, priority = 1)] #[task(binds = ETH, priority = 1)]

View File

@ -1,9 +1,10 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use miniconf::StringSet;
use core::convert::TryFrom; use core::convert::TryFrom;
use enum_iterator::IntoEnumIterator; use enum_iterator::IntoEnumIterator;
#[derive(Copy, Clone, Debug, Serialize, Deserialize, IntoEnumIterator)] #[derive(Copy, Clone, Debug, Serialize, Deserialize, IntoEnumIterator, StringSet)]
pub enum Gain { pub enum Gain {
G1 = 0b00, G1 = 0b00,
G2 = 0b01, G2 = 0b01,

View File

@ -3,7 +3,7 @@ use rtic::cyccnt::{Duration, Instant, U32Ext};
use stm32h7xx_hal::time::Hertz; use stm32h7xx_hal::time::Hertz;
pub struct CycleCounter { pub struct CycleCounter {
next_tick: Instant, next_tick: Option<Instant>,
ticks: u32, ticks: u32,
increment: Duration, increment: Duration,
} }
@ -20,14 +20,18 @@ impl CycleCounter {
Self { Self {
increment, increment,
ticks: 0, ticks: 0,
next_tick: Instant::now() + increment, next_tick: None,
} }
} }
pub fn current_ms(&mut self) -> u32 { pub fn current_ms(&mut self) -> u32 {
if self.next_tick.is_none() {
self.next_tick = Some(Instant::now() + self.increment);
}
let now = Instant::now(); let now = Instant::now();
while now > self.next_tick { while now > self.next_tick.unwrap() {
self.next_tick += self.increment; *self.next_tick.as_mut().unwrap() += self.increment;
self.ticks += 1; self.ticks += 1;
} }