From e1cfeff65f747bc78eeff2af7bfad5c51572e5ff Mon Sep 17 00:00:00 2001 From: Ryan Summers Date: Mon, 19 Jul 2021 13:01:31 +0200 Subject: [PATCH] Updating config to reject out-of-bounds amplitudes --- src/bin/dual-iir.rs | 20 ++++++++++++---- src/bin/lockin.rs | 7 ++++-- src/hardware/dac.rs | 22 ++++++++++------- src/hardware/signal_generator.rs | 41 +++++++++++++++++--------------- 4 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/bin/dual-iir.rs b/src/bin/dual-iir.rs index 16f7894..411c7de 100644 --- a/src/bin/dual-iir.rs +++ b/src/bin/dual-iir.rs @@ -29,7 +29,10 @@ #![no_std] #![no_main] -use core::sync::atomic::{fence, Ordering}; +use core::{ + convert::TryInto, + sync::atomic::{fence, Ordering}, +}; use mutex_trait::prelude::*; @@ -220,8 +223,12 @@ const APP: () = { telemetry: TelemetryBuffer::default(), settings, signal_generator: [ - SignalGenerator::new(settings.signal_generator[0]), - SignalGenerator::new(settings.signal_generator[1]), + SignalGenerator::new( + settings.signal_generator[0].try_into().unwrap(), + ), + SignalGenerator::new( + settings.signal_generator[1].try_into().unwrap(), + ), ], } } @@ -339,8 +346,11 @@ const APP: () = { // Update the signal generators c.resources.signal_generator.lock(|generator| { - generator[0].update_waveform(settings.signal_generator[0]); - generator[1].update_waveform(settings.signal_generator[1]); + for i in 0..2 { + if let Ok(config) = settings.signal_generator[i].try_into() { + generator[i].update_waveform(config); + } + } }); let target = settings.stream_target.into(); diff --git a/src/bin/lockin.rs b/src/bin/lockin.rs index bfd78e0..af7a747 100644 --- a/src/bin/lockin.rs +++ b/src/bin/lockin.rs @@ -28,7 +28,10 @@ #![no_std] #![no_main] -use core::sync::atomic::{fence, Ordering}; +use core::{ + convert::TryFrom, + sync::atomic::{fence, Ordering}, +}; use mutex_trait::prelude::*; @@ -269,7 +272,7 @@ const APP: () = { frequency_tuning_word, ], // 1V Amplitude - amplitude: DacCode::from(1.0).into(), + amplitude: DacCode::try_from(1.0).unwrap().into(), signal: signal_generator::Signal::Cosine, } diff --git a/src/hardware/dac.rs b/src/hardware/dac.rs index b40c5c6..5e77080 100644 --- a/src/hardware/dac.rs +++ b/src/hardware/dac.rs @@ -57,6 +57,8 @@ use mutex_trait::Mutex; use super::design_parameters::{SampleBuffer, SAMPLE_BUFFER_SIZE}; use super::timers; +use core::convert::TryFrom; + use hal::dma::{ dma::{DMAReq, DmaConfig}, traits::TargetAddress, @@ -75,21 +77,23 @@ static mut DAC_BUF: [[SampleBuffer; 2]; 2] = [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2]; #[derive(Copy, Clone)] pub struct DacCode(pub u16); -impl From for DacCode { - fn from(voltage: f32) -> DacCode { +impl TryFrom for DacCode { + type Error = (); + + fn try_from(voltage: f32) -> Result { // The DAC output range in bipolar mode (including the external output op-amp) is +/- 4.096 // V with 16-bit resolution. The anti-aliasing filter has an additional gain of 2.5. let dac_range = 4.096 * 2.5; - let voltage = if voltage > dac_range { - dac_range + if voltage > dac_range { + Err(()) } else if voltage < -1. * dac_range { - -1. * dac_range + Err(()) } else { - voltage - }; - - DacCode::from((voltage / dac_range * i16::MAX as f32) as i16) + Ok(DacCode::from( + (voltage / dac_range * i16::MAX as f32) as i16, + )) + } } } diff --git a/src/hardware/signal_generator.rs b/src/hardware/signal_generator.rs index 019d56d..5d3ea2e 100644 --- a/src/hardware/signal_generator.rs +++ b/src/hardware/signal_generator.rs @@ -1,4 +1,5 @@ use crate::hardware::{dac::DacCode, design_parameters::ADC_SAMPLE_TICKS}; +use core::convert::{TryFrom, TryInto}; use miniconf::Miniconf; use serde::Deserialize; @@ -45,8 +46,17 @@ impl Default for BasicConfig { } } -impl From for Config { - fn from(config: BasicConfig) -> Config { +/// Represents the errors that can occur when attempting to configure the signal generator. +#[derive(Copy, Clone, Debug)] +pub enum Error { + /// The provided amplitude is out-of-range. + InvalidAmplitude, +} + +impl TryFrom for Config { + type Error = Error; + + fn try_from(config: BasicConfig) -> Result { // Calculate the frequency tuning words let frequency_tuning_word: [u32; 2] = { let conversion_factor = @@ -72,20 +82,13 @@ impl From for Config { } }; - // Clamp amplitude and symmetry. - let amplitude = if config.amplitude > 10.24 { - 10.24 - } else if config.amplitude < 0.0 { - 0.0 - } else { - config.amplitude - }; - - Config { - amplitude: DacCode::from(amplitude).into(), + Ok(Config { + amplitude: DacCode::try_from(config.amplitude) + .or(Err(Error::InvalidAmplitude))? + .into(), signal: config.signal, frequency_tuning_word, - } + }) } } @@ -110,7 +113,7 @@ pub struct SignalGenerator { impl Default for SignalGenerator { fn default() -> Self { Self { - config: BasicConfig::default().into(), + config: BasicConfig::default().try_into().unwrap(), phase_accumulator: 0, } } @@ -124,16 +127,16 @@ impl SignalGenerator { /// /// # Returns /// The generator - pub fn new(config: impl Into) -> Self { + pub fn new(config: Config) -> Self { Self { - config: config.into(), + config, phase_accumulator: 0, } } /// Update waveform generation settings. - pub fn update_waveform(&mut self, new_config: impl Into) { - self.config = new_config.into(); + pub fn update_waveform(&mut self, new_config: Config) { + self.config = new_config; } }