diff --git a/src/bin/dual-iir.rs b/src/bin/dual-iir.rs index ba0a508..eb35e00 100644 --- a/src/bin/dual-iir.rs +++ b/src/bin/dual-iir.rs @@ -14,9 +14,9 @@ use stabilizer::{ dac::{Dac0Output, Dac1Output, DacCode}, embedded_hal::digital::v2::InputPin, hal, + signal_generator::{self, SignalGenerator}, system_timer::SystemTimer, DigitalInput0, DigitalInput1, AFE0, AFE1, - signal_generator::SignalGenerator, }, net::{ data_stream::{BlockGenerator, StreamTarget}, @@ -40,11 +40,12 @@ pub struct Settings { force_hold: bool, telemetry_period: u16, stream_target: StreamTarget, - signal_generator: signal_generator::Config; + signal_generator: signal_generator::Config, output_mode: [OutputMode; 2], } -pub struct OutputMode { +#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Miniconf)] +pub enum OutputMode { IirFilter, SignalGenerator, } @@ -70,6 +71,7 @@ impl Default for Settings { signal_generator: signal_generator::Config::default(), stream_target: StreamTarget::default(), + output_mode: [OutputMode::IirFilter, OutputMode::IirFilter], } } } @@ -83,6 +85,7 @@ const APP: () = { dacs: (Dac0Output, Dac1Output), network: NetworkUsers, generator: BlockGenerator, + signal_generator: SignalGenerator, settings: Settings, telemetry: TelemetryBuffer, @@ -123,6 +126,8 @@ const APP: () = { // Start sampling ADCs. stabilizer.adc_dac_timer.start(); + let settings = Settings::default(); + init::LateResources { afes: stabilizer.afes, adcs: stabilizer.adcs, @@ -131,7 +136,8 @@ const APP: () = { network, digital_inputs: stabilizer.digital_inputs, telemetry: TelemetryBuffer::default(), - settings: Settings::default(), + settings, + signal_generator: SignalGenerator::new(settings.signal_generator), } } @@ -151,7 +157,7 @@ const APP: () = { /// /// Because the ADC and DAC operate at the same rate, these two constraints actually implement /// the same time bounds, meeting one also means the other is also met. - #[task(binds=DMA1_STR4, resources=[adcs, digital_inputs, dacs, iir_state, settings, telemetry, generator], priority=2)] + #[task(binds=DMA1_STR4, resources=[adcs, digital_inputs, dacs, iir_state, settings, signal_generator, telemetry, generator], priority=2)] #[inline(never)] #[link_section = ".itcm.process"] fn process(mut c: process::Context) { @@ -163,6 +169,7 @@ const APP: () = { ref mut iir_state, ref mut telemetry, ref mut generator, + ref mut signal_generator, } = c.resources; let digital_inputs = [ @@ -207,17 +214,25 @@ const APP: () = { // Do not generate the samples twice, or we may mess up phasing of the // signal generator. Instead, copy the previously-generated signal. // TODO: Is there a nicer way we can handle this edge case? - if (channel == 1) && settings.output_mode[0] == OutputMode::SignalGenerator { - adc_samples[1].copy_from_slice(adc_samples[0]); + if (channel == 1) + && settings.output_mode[0] + == OutputMode::SignalGenerator + { + *dac_samples[1] = *dac_samples[0]; } else { - signal_generator.generate(&mut adc_samples[channel]); + signal_generator + .generate(&mut dac_samples[channel][..]); } } } } - if !settings.output_mode.iter().any(|&mode| mode == OutputMode::SignalGenerator) { - signal_generator.skip(adc_samples[0].len()); + if !settings + .output_mode + .iter() + .any(|&mode| mode == OutputMode::SignalGenerator) + { + signal_generator.skip(adc_samples[0].len() as u32); } // Stream the data. @@ -248,7 +263,7 @@ const APP: () = { } } - #[task(priority = 1, resources=[network, afes, settings])] + #[task(priority = 1, resources=[network, afes, settings, signal_generator])] fn settings_update(mut c: settings_update::Context) { // Update the IIR channels. let settings = c.resources.network.miniconf.settings(); @@ -259,7 +274,9 @@ const APP: () = { c.resources.afes.1.set_gain(settings.afe[1]); // Update the signal generator - c.resources.signal_generator.update_waveform(settings.signal_generator); + c.resources.signal_generator.lock(|generator| { + generator.update_waveform(settings.signal_generator) + }); let target = settings.stream_target.into(); c.resources.network.direct_stream(target); diff --git a/src/bin/lockin.rs b/src/bin/lockin.rs index 24a18be..681b5ad 100644 --- a/src/bin/lockin.rs +++ b/src/bin/lockin.rs @@ -96,7 +96,7 @@ const APP: () = { telemetry: TelemetryBuffer, digital_inputs: (DigitalInput0, DigitalInput1), generator: BlockGenerator, - signal_generator: signal_generator::Generator, + signal_generator: signal_generator::SignalGenerator, timestamper: InputStamper, pll: RPLL, @@ -156,7 +156,7 @@ const APP: () = { digital_inputs: stabilizer.digital_inputs, timestamper: stabilizer.timestamper, telemetry: TelemetryBuffer::default(), - signal_generator: signal_generator::Generator::new( + signal_generator: signal_generator::SignalGenerator::new( signal_generator::Config { period: design_parameters::SAMPLE_BUFFER_SIZE as u32, symmetry: 0.5, diff --git a/src/hardware/signal_generator.rs b/src/hardware/signal_generator.rs index 7cbe331..4fc4893 100644 --- a/src/hardware/signal_generator.rs +++ b/src/hardware/signal_generator.rs @@ -1,11 +1,15 @@ -#[derive(Copy, Clone, Debug)] +use crate::hardware::dac::DacCode; +use miniconf::Miniconf; +use serde::Deserialize; + +#[derive(Copy, Clone, Debug, Deserialize, Miniconf)] pub enum Signal { Sine, Square, Triangle, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Miniconf, Deserialize)] pub struct Config { // TODO: Should period be specified in Hz? pub period: u32, @@ -102,19 +106,21 @@ impl SignalGenerator { /// /// # Args /// * `samples` - The location to store generated values into. - pub fn generate(&mut self, samples: &mut [i16]) { + pub fn generate(&mut self, samples: &mut [u16]) { for sample in samples.iter_mut() { - *sample = self.next(); + *sample = DacCode::from(self.next()).0; } } /// Skip `count` elements of the generator - pub fn skip(&mut self, count: usize) { + pub fn skip(&mut self, count: u32) { let index = self.index.wrapping_add(count); // If we skip past the period of the signal, apply any pending config. - if index > self.config.period && let Some(config) = self.pendig_config.take() { - self.config = config; + if index > self.config.period { + if let Some(config) = self.pending_config.take() { + self.config = config; + } } self.index = index % self.config.period; @@ -140,25 +146,37 @@ impl SignalGenerator { } Signal::Triangle => { if phase < self.config.phase_symmetry { - let duration_of_phase = (self.config.phase_symmetry.wrapping_sub(i32::MIN) >> 16) as u16; - let phase_progress = (phase.wrapping_sub(i32::MIN) >> 16) as u16; + let duration_of_phase = + (self.config.phase_symmetry.wrapping_sub(i32::MIN) + >> 16) as u16; + let phase_progress = + (phase.wrapping_sub(i32::MIN) >> 16) as u16; if duration_of_phase == 0 { i16::MIN } else { - i16::MIN.wrapping_add((u16::MAX as u32 * phase_progress as u32 / - duration_of_phase as u32) as i16) + i16::MIN.wrapping_add( + (u16::MAX as u32 * phase_progress as u32 + / duration_of_phase as u32) + as i16, + ) } } else { - - let duration_of_phase = (i32::MAX.wrapping_sub(self.config.phase_symmetry) >> 16) as u16; - let phase_progress = (phase.wrapping_sub(self.config.phase_symmetry) >> 16) as - u16; + let duration_of_phase = + (i32::MAX.wrapping_sub(self.config.phase_symmetry) + >> 16) as u16; + let phase_progress = (phase + .wrapping_sub(self.config.phase_symmetry) + >> 16) as u16; if duration_of_phase == 0 { i16::MAX } else { - i16::MAX.wrapping_sub((u16::MAX as u32 * phase_progress as u32 / duration_of_phase as u32) as i16) + i16::MAX.wrapping_sub( + (u16::MAX as u32 * phase_progress as u32 + / duration_of_phase as u32) + as i16, + ) } } }