Updating config to reject out-of-bounds amplitudes

master
Ryan Summers 2021-07-19 13:01:31 +02:00
parent 2f6e2a5ef5
commit e1cfeff65f
4 changed files with 55 additions and 35 deletions

View File

@ -29,7 +29,10 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use core::sync::atomic::{fence, Ordering}; use core::{
convert::TryInto,
sync::atomic::{fence, Ordering},
};
use mutex_trait::prelude::*; use mutex_trait::prelude::*;
@ -220,8 +223,12 @@ const APP: () = {
telemetry: TelemetryBuffer::default(), telemetry: TelemetryBuffer::default(),
settings, settings,
signal_generator: [ signal_generator: [
SignalGenerator::new(settings.signal_generator[0]), SignalGenerator::new(
SignalGenerator::new(settings.signal_generator[1]), 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 // Update the signal generators
c.resources.signal_generator.lock(|generator| { c.resources.signal_generator.lock(|generator| {
generator[0].update_waveform(settings.signal_generator[0]); for i in 0..2 {
generator[1].update_waveform(settings.signal_generator[1]); if let Ok(config) = settings.signal_generator[i].try_into() {
generator[i].update_waveform(config);
}
}
}); });
let target = settings.stream_target.into(); let target = settings.stream_target.into();

View File

@ -28,7 +28,10 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use core::sync::atomic::{fence, Ordering}; use core::{
convert::TryFrom,
sync::atomic::{fence, Ordering},
};
use mutex_trait::prelude::*; use mutex_trait::prelude::*;
@ -269,7 +272,7 @@ const APP: () = {
frequency_tuning_word, frequency_tuning_word,
], ],
// 1V Amplitude // 1V Amplitude
amplitude: DacCode::from(1.0).into(), amplitude: DacCode::try_from(1.0).unwrap().into(),
signal: signal_generator::Signal::Cosine, signal: signal_generator::Signal::Cosine,
} }

View File

@ -57,6 +57,8 @@ use mutex_trait::Mutex;
use super::design_parameters::{SampleBuffer, SAMPLE_BUFFER_SIZE}; use super::design_parameters::{SampleBuffer, SAMPLE_BUFFER_SIZE};
use super::timers; use super::timers;
use core::convert::TryFrom;
use hal::dma::{ use hal::dma::{
dma::{DMAReq, DmaConfig}, dma::{DMAReq, DmaConfig},
traits::TargetAddress, traits::TargetAddress,
@ -75,21 +77,23 @@ static mut DAC_BUF: [[SampleBuffer; 2]; 2] = [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2];
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct DacCode(pub u16); pub struct DacCode(pub u16);
impl From<f32> for DacCode { impl TryFrom<f32> for DacCode {
fn from(voltage: f32) -> DacCode { type Error = ();
fn try_from(voltage: f32) -> Result<DacCode, ()> {
// The DAC output range in bipolar mode (including the external output op-amp) is +/- 4.096 // 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. // V with 16-bit resolution. The anti-aliasing filter has an additional gain of 2.5.
let dac_range = 4.096 * 2.5; let dac_range = 4.096 * 2.5;
let voltage = if voltage > dac_range { if voltage > dac_range {
dac_range Err(())
} else if voltage < -1. * dac_range { } else if voltage < -1. * dac_range {
-1. * dac_range Err(())
} else { } else {
voltage Ok(DacCode::from(
}; (voltage / dac_range * i16::MAX as f32) as i16,
))
DacCode::from((voltage / dac_range * i16::MAX as f32) as i16) }
} }
} }

View File

@ -1,4 +1,5 @@
use crate::hardware::{dac::DacCode, design_parameters::ADC_SAMPLE_TICKS}; use crate::hardware::{dac::DacCode, design_parameters::ADC_SAMPLE_TICKS};
use core::convert::{TryFrom, TryInto};
use miniconf::Miniconf; use miniconf::Miniconf;
use serde::Deserialize; use serde::Deserialize;
@ -45,8 +46,17 @@ impl Default for BasicConfig {
} }
} }
impl From<BasicConfig> for Config { /// Represents the errors that can occur when attempting to configure the signal generator.
fn from(config: BasicConfig) -> Config { #[derive(Copy, Clone, Debug)]
pub enum Error {
/// The provided amplitude is out-of-range.
InvalidAmplitude,
}
impl TryFrom<BasicConfig> for Config {
type Error = Error;
fn try_from(config: BasicConfig) -> Result<Config, Error> {
// Calculate the frequency tuning words // Calculate the frequency tuning words
let frequency_tuning_word: [u32; 2] = { let frequency_tuning_word: [u32; 2] = {
let conversion_factor = let conversion_factor =
@ -72,20 +82,13 @@ impl From<BasicConfig> for Config {
} }
}; };
// Clamp amplitude and symmetry. Ok(Config {
let amplitude = if config.amplitude > 10.24 { amplitude: DacCode::try_from(config.amplitude)
10.24 .or(Err(Error::InvalidAmplitude))?
} else if config.amplitude < 0.0 { .into(),
0.0
} else {
config.amplitude
};
Config {
amplitude: DacCode::from(amplitude).into(),
signal: config.signal, signal: config.signal,
frequency_tuning_word, frequency_tuning_word,
} })
} }
} }
@ -110,7 +113,7 @@ pub struct SignalGenerator {
impl Default for SignalGenerator { impl Default for SignalGenerator {
fn default() -> Self { fn default() -> Self {
Self { Self {
config: BasicConfig::default().into(), config: BasicConfig::default().try_into().unwrap(),
phase_accumulator: 0, phase_accumulator: 0,
} }
} }
@ -124,16 +127,16 @@ impl SignalGenerator {
/// ///
/// # Returns /// # Returns
/// The generator /// The generator
pub fn new(config: impl Into<Config>) -> Self { pub fn new(config: Config) -> Self {
Self { Self {
config: config.into(), config,
phase_accumulator: 0, phase_accumulator: 0,
} }
} }
/// Update waveform generation settings. /// Update waveform generation settings.
pub fn update_waveform(&mut self, new_config: impl Into<Config>) { pub fn update_waveform(&mut self, new_config: Config) {
self.config = new_config.into(); self.config = new_config;
} }
} }