From db182b923d82c3e8c6f5a5a02fa27be15585b7ec Mon Sep 17 00:00:00 2001 From: Ryan Summers Date: Wed, 21 Oct 2020 10:17:22 +0200 Subject: [PATCH] Adding WIP QSPI streaming --- Cargo.toml | 5 ++-- ad9959/src/lib.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++-- pounder_test.py | 4 +-- src/main.rs | 34 +++++++++++++++++++++-- src/pounder/mod.rs | 11 ++------ 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0595c33..db15743 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,9 +59,8 @@ features = ["stm32h743v"] [dependencies.stm32h7xx-hal] features = ["stm32h743v", "rt", "unproven"] - -[patch.crates-io] -stm32h7xx-hal = { git = "https://github.com/quartiq/stm32h7xx-hal.git", branch = "feature/pounder-support" } +git = "https://github.com/quartiq/stm32h7xx-hal.git" +branch = "feature/pounder-support" [features] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] diff --git a/ad9959/src/lib.rs b/ad9959/src/lib.rs index d12041c..a537397 100644 --- a/ad9959/src/lib.rs +++ b/ad9959/src/lib.rs @@ -376,9 +376,6 @@ where // Latch the configuration and restore the previous CSR. Note that the re-enable of the // channel happens immediately, so the CSR update does not need to be latched. self.latch_configuration()?; - self.interface - .write(Register::CSR as u8, &csr) - .map_err(|_| Error::Interface)?; Ok(()) } @@ -571,4 +568,69 @@ where Ok(tuning_word as f64 * self.system_clock_frequency() / (1u64 << 32) as f64) } + + pub fn write_profile(&mut self, channel: Channel, freq: f64, turns: f32, amplitude: f32) -> Result<(), Error> { + // The function for channel frequency is `f_out = FTW * f_s / 2^32`, where FTW is the + // frequency tuning word and f_s is the system clock rate. + let tuning_word: u32 = + ((freq as f64 / self.system_clock_frequency()) + * 1u64.wrapping_shl(32) as f64) as u32; + + let phase_offset: u16 = (turns * (1 << 14) as f32) as u16 & 0x3FFFu16; + + let amplitude_control: u16 = (amplitude * (1 << 10) as f32) as u16; + let mut acr: [u8; 3] = [0; 3]; + + // Enable the amplitude multiplier for the channel if required. The amplitude control has + // full-scale at 0x3FF (amplitude of 1), so the multiplier should be disabled whenever + // full-scale is used. + if amplitude_control < (1 << 10) { + let masked_control = amplitude_control & 0x3FF; + acr[1] = masked_control.to_be_bytes()[0]; + acr[2] = masked_control.to_be_bytes()[1]; + + // Enable the amplitude multiplier + acr[1].set_bit(4, true); + } + + self.modify_channel_closure(channel, |interface| { + let mut data: [u8; 11] = [0; 11]; + data[0..2].copy_from_slice(&phase_offset.to_be_bytes()); + data[2] = Register::CFTW0 as u8; + data[3..7].copy_from_slice(&tuning_word.to_be_bytes()); + data[7] = Register::ACR as u8; + data[8..11].copy_from_slice(&acr); + interface.write(Register::CPOW0 as u8, &data).map_err(|_| Error::Interface) + })?; + + Ok(()) + } + + fn modify_channel_closure(&mut self, channel: Channel, f: F) -> Result<(), Error> + where + F: FnOnce(&mut INTERFACE) -> Result<(), Error>, + { + // Disable all other outputs so that we can update the configuration register of only the + // specified channel. + let mut csr: [u8; 1] = [0]; + self.interface + .read(Register::CSR as u8, &mut csr) + .map_err(|_| Error::Interface)?; + + let mut new_csr = csr; + new_csr[0].set_bits(4..8, 0); + new_csr[0].set_bit(4 + channel as usize, true); + + self.interface + .write(Register::CSR as u8, &new_csr) + .map_err(|_| Error::Interface)?; + + let result = f(&mut self.interface); + + // Latch the configuration and restore the previous CSR. Note that the re-enable of the + // channel happens immediately, so the CSR update does not need to be latched. + self.latch_configuration()?; + + result + } } diff --git a/pounder_test.py b/pounder_test.py index a50856a..5d43dd3 100644 --- a/pounder_test.py +++ b/pounder_test.py @@ -91,11 +91,11 @@ def main(): # A sample configuration for an output channel. channel_config = { - 'attenuation': 31.5, + 'attenuation': 0.0, 'parameters': { 'phase_offset': 0.5, 'frequency': 100.0e6, - 'amplitude': 0.2, + 'amplitude': 1.0, 'enabled': True, } } diff --git a/src/main.rs b/src/main.rs index 9e0c0ff..a766914 100644 --- a/src/main.rs +++ b/src/main.rs @@ -187,8 +187,7 @@ const APP: () = { 'static, 'static, 'static, - ethernet::EthernetDMA<'static>, - >, + ethernet::EthernetDMA<'static>>, eth_mac: ethernet::EthernetMAC, mac_addr: net::wire::EthernetAddress, @@ -654,7 +653,7 @@ const APP: () = { ); // Configure timer 2 to trigger conversions for the ADC - let mut timer2 = dp.TIM2.timer(500.khz(), &mut clocks); + let mut timer2 = dp.TIM2.timer(50.khz(), &mut clocks); timer2.configure_channel(hal::timer::Channel::One, 0.25); timer2.configure_channel(hal::timer::Channel::Two, 0.75); @@ -746,6 +745,35 @@ const APP: () = { // TODO: Replace with reference to CPU clock from CCDR. next_ms += 400_000.cycles(); + match c.resources.pounder { + Some(pounder) => { + + let state = pounder::ChannelState { + parameters: pounder::DdsChannelState { + phase_offset: 0.0, + frequency: 100_000_000.0, + amplitude: 1.0, + enabled: true, + }, + attenuation: 10.0, + }; + + let state1 = pounder::ChannelState { + parameters: pounder::DdsChannelState { + phase_offset: 0.5, + frequency: 50_000_000.0, + amplitude: 1.0, + enabled: true, + }, + attenuation: 10.0, + }; + + pounder.set_channel_state(pounder::Channel::Out0, state).unwrap(); + pounder.set_channel_state(pounder::Channel::Out1, state1).unwrap(); + }, + _ => panic!("Failed"), + } + loop { let tick = Instant::now() > next_ms; diff --git a/src/pounder/mod.rs b/src/pounder/mod.rs index 1288765..97c9fd5 100644 --- a/src/pounder/mod.rs +++ b/src/pounder/mod.rs @@ -474,15 +474,8 @@ where channel: Channel, state: ChannelState, ) -> Result<(), Error> { - self.ad9959 - .set_frequency(channel.into(), state.parameters.frequency) - .map_err(|_| Error::Dds)?; - self.ad9959 - .set_phase(channel.into(), state.parameters.phase_offset) - .map_err(|_| Error::Dds)?; - self.ad9959 - .set_amplitude(channel.into(), state.parameters.amplitude) - .map_err(|_| Error::Dds)?; + self.ad9959.write_profile(channel.into(), state.parameters.frequency, + state.parameters.phase_offset, state.parameters.amplitude).map_err(|_| Error::Dds)?; if state.parameters.enabled { self.ad9959