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_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();

View File

@ -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,
}

View File

@ -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<f32> for DacCode {
fn from(voltage: f32) -> DacCode {
impl TryFrom<f32> for 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
// 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,
))
}
}
}

View File

@ -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<BasicConfig> 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<BasicConfig> for Config {
type Error = Error;
fn try_from(config: BasicConfig) -> Result<Config, Error> {
// Calculate the frequency tuning words
let frequency_tuning_word: [u32; 2] = {
let conversion_factor =
@ -72,20 +82,13 @@ impl From<BasicConfig> 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<Config>) -> 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<Config>) {
self.config = new_config.into();
pub fn update_waveform(&mut self, new_config: Config) {
self.config = new_config;
}
}