diff --git a/src/main.rs b/src/main.rs index 3f5588e..9033895 100644 --- a/src/main.rs +++ b/src/main.rs @@ -592,44 +592,10 @@ const APP: () = { let adc1_in_p = gpiof.pf11.into_analog(); let adc2_in_p = gpiof.pf14.into_analog(); - let io_update_trigger = { - let _io_update = gpiog - .pg7 - .into_alternate_af2() - .set_speed(hal::gpio::Speed::VeryHigh); - - // Configure the IO_Update signal for the DDS. - let mut hrtimer = hrtimer::HighResTimerE::new( - dp.HRTIM_TIME, - dp.HRTIM_MASTER, - dp.HRTIM_COMMON, - ccdr.clocks, - ccdr.peripheral.HRTIM, - ); - - // IO_Update should be latched for 50ns after the QSPI profile write. Profile writes - // are always 16 bytes, with 2 cycles required per byte, coming out to a total of 32 - // QSPI clock cycles. The QSPI is configured for 40MHz, so this comes out to an - // offset of 800nS. We use 900ns to be safe - note that the timer is triggered after - // the QSPI write, which can take approximately 120nS, so there is additional - // margin. - hrtimer.configure_single_shot( - hrtimer::Channel::Two, - 50_e-9, - 900_e-9, - ); - - // Ensure that we have enough time for an IO-update every sample. - assert!(1.0 / (1000 * SAMPLE_FREQUENCY_KHZ) as f32 > 900_e-9); - - hrtimer - }; - Some( pounder::PounderDevices::new( io_expander, ad9959, - io_update_trigger, spi, adc1, adc2, @@ -763,13 +729,46 @@ const APP: () = { cp.DWT.enable_cycle_counter(); let dds_output = { + let io_update_trigger = { + let _io_update = gpiog + .pg7 + .into_alternate_af2() + .set_speed(hal::gpio::Speed::VeryHigh); + + // Configure the IO_Update signal for the DDS. + let mut hrtimer = hrtimer::HighResTimerE::new( + dp.HRTIM_TIME, + dp.HRTIM_MASTER, + dp.HRTIM_COMMON, + ccdr.clocks, + ccdr.peripheral.HRTIM, + ); + + // IO_Update should be latched for 50ns after the QSPI profile write. Profile writes + // are always 16 bytes, with 2 cycles required per byte, coming out to a total of 32 + // QSPI clock cycles. The QSPI is configured for 40MHz, so this comes out to an + // offset of 800nS. We use 900ns to be safe - note that the timer is triggered after + // the QSPI write, which can take approximately 120nS, so there is additional + // margin. + hrtimer.configure_single_shot( + hrtimer::Channel::Two, + 50_e-9, + 900_e-9, + ); + + // Ensure that we have enough time for an IO-update every sample. + assert!(1.0 / (1000 * SAMPLE_FREQUENCY_KHZ) as f32 > 900_e-9); + + hrtimer + }; + let timer3 = dp.TIM3.timer( SAMPLE_FREQUENCY_KHZ.khz(), ccdr.peripheral.TIM3, &ccdr.clocks, ); - DdsOutput::new(timer3) + DdsOutput::new(timer3, io_update_trigger) }; // Start sampling ADCs. @@ -792,14 +791,9 @@ const APP: () = { } } - #[task(binds = TIM3, resources=[dds_output, pounder], priority = 3)] + #[task(binds = TIM3, resources=[dds_output], priority = 3)] fn dds_update(c: dds_update::Context) { - if let Some(pounder) = c.resources.pounder { - if let Some(profile) = c.resources.dds_output.update_handler() { - pounder.ad9959.interface.write_profile(profile).unwrap(); - pounder.io_update_trigger.trigger(); - } - } + c.resources.dds_output.update_handler(); } #[task(binds=DMA1_STR3, resources=[adcs, dacs, pounder, dds_output, iir_state, iir_ch], priority=2)] @@ -828,22 +822,20 @@ const APP: () = { }; let dds_output = &mut c.resources.dds_output; - c.resources.pounder.lock(|pounder| { - if let Some(pounder) = pounder { - dds_output.lock(|dds_output| { - let profile = pounder - .ad9959 - .serialize_profile( - pounder::Channel::Out0.into(), - 100_000_000_f32, - 0.0_f32, - *adc0 as f32 / 0xFFFF as f32, - ) - .unwrap(); - dds_output.push(profile); - }); - } - }); + if let Some(pounder) = c.resources.pounder { + dds_output.lock(|dds_output| { + let profile = pounder + .ad9959 + .serialize_profile( + pounder::Channel::Out0.into(), + 100_000_000_f32, + 0.0_f32, + *adc0 as f32 / 0xFFFF as f32, + ) + .unwrap(); + dds_output.push(profile); + }); + } } c.resources.dacs.next_data(&dac0, &dac1); @@ -944,42 +936,6 @@ const APP: () = { Ok::(req) }) }), - "pounder/in0": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::In0, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/in1": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::In1, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/out0": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::Out0, state), - _ => Err(pounder::Error::Access), - } - }) - }), - "pounder/out1": pounder::ChannelState, (|state| { - c.resources.pounder.lock(|pounder| { - match pounder { - Some(pounder) => - pounder.set_channel_state(pounder::Channel::Out1, state), - _ => Err(pounder::Error::Access), - } - }) - }), "pounder/dds/clock": pounder::DdsClockConfig, (|config| { c.resources.pounder.lock(|pounder| { match pounder { diff --git a/src/pounder/mod.rs b/src/pounder/mod.rs index b673887..ac37491 100644 --- a/src/pounder/mod.rs +++ b/src/pounder/mod.rs @@ -7,7 +7,6 @@ mod rf_power; pub use dds_output::DdsOutput; use super::hal; -use super::hrtimer::HighResTimerE; use attenuators::AttenuatorInterface; use rf_power::PowerMeasurementInterface; @@ -37,6 +36,7 @@ pub enum Error { } #[derive(Debug, Copy, Clone)] +#[allow(dead_code)] pub enum Channel { In0, In1, @@ -291,7 +291,6 @@ impl ad9959::Interface for QspiInterface { /// A structure containing implementation for Pounder hardware. pub struct PounderDevices { pub ad9959: ad9959::Ad9959, - pub io_update_trigger: HighResTimerE, mcp23017: mcp23017::MCP23017>, attenuator_spi: hal::spi::Spi, adc1: hal::adc::Adc, @@ -306,7 +305,6 @@ impl PounderDevices { /// Args: /// * `ad9959` - The DDS driver for the pounder hardware. /// * `attenuator_spi` - A SPI interface to control digital attenuators. - /// * `io_update_timer` - The HRTimer with the IO_update signal connected to the output. /// * `adc1` - The ADC1 peripheral for measuring power. /// * `adc2` - The ADC2 peripheral for measuring power. /// * `adc1_in_p` - The input channel for the RF power measurement on IN0. @@ -314,7 +312,6 @@ impl PounderDevices { pub fn new( mcp23017: mcp23017::MCP23017>, ad9959: ad9959::Ad9959, - io_update_trigger: HighResTimerE, attenuator_spi: hal::spi::Spi, adc1: hal::adc::Adc, adc2: hal::adc::Adc, @@ -323,7 +320,6 @@ impl PounderDevices { ) -> Result { let mut devices = Self { mcp23017, - io_update_trigger, ad9959, attenuator_spi, adc1, @@ -431,33 +427,6 @@ impl PounderDevices { external_clock, }) } - - /// Configure a DDS channel. - /// - /// Args: - /// * `channel` - The pounder channel to configure. - /// * `state` - The state to configure the channel for. - pub fn set_channel_state( - &mut self, - channel: Channel, - state: ChannelState, - ) -> Result<(), Error> { - let profile = self - .ad9959 - .serialize_profile( - channel.into(), - state.parameters.frequency, - state.parameters.phase_offset, - state.parameters.amplitude, - ) - .map_err(|_| Error::Dds)?; - self.ad9959.interface.write_profile(profile).unwrap(); - self.io_update_trigger.trigger(); - - self.set_attenuation(channel, state.attenuation)?; - - Ok(()) - } } impl AttenuatorInterface for PounderDevices {