From 6792ab5469d95716489017415f0ed9280f139151 Mon Sep 17 00:00:00 2001 From: Ryan Summers Date: Wed, 29 Apr 2020 13:00:29 +0200 Subject: [PATCH] Adding input power measurement support --- Cargo.toml | 2 +- src/main.rs | 31 ++++++++++++++++++-- src/pounder/attenuators.rs | 16 +++-------- src/pounder/error.rs | 2 ++ src/pounder/mod.rs | 58 +++++++++++++++++++++++++++++++------- src/pounder/rf_power.rs | 13 +++++++++ src/pounder/types.rs | 16 +++++++++++ 7 files changed, 112 insertions(+), 26 deletions(-) create mode 100644 src/pounder/rf_power.rs create mode 100644 src/pounder/types.rs diff --git a/Cargo.toml b/Cargo.toml index 6a0e10a..619b198 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ branch = "feature/device-dependency" [dependencies.stm32h7xx-hal] git = "https://github.com/quartiq/stm32h7xx-hal.git" branch = "feature/quad-spi" -features = ["stm32h743v", "rt"] +features = ["stm32h743v", "rt", "unproven"] [features] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] diff --git a/src/main.rs b/src/main.rs index d67ed37..38d122d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -166,6 +166,8 @@ const APP: () = { clocks.rb.d2ccip1r.modify(|_, w| w.spi123sel().pll2_p().spi45sel().pll2_q()); + let mut delay = hal::delay::Delay::new(cp.SYST, clocks.clocks); + let gpioa = dp.GPIOA.split(&mut clocks.ahb4); let gpiob = dp.GPIOB.split(&mut clocks.ahb4); let gpioc = dp.GPIOC.split(&mut clocks.ahb4); @@ -291,7 +293,7 @@ const APP: () = { let io_update = gpiog.pg7.into_push_pull_output(); - let delay = { + let asm_delay = { let frequency_hz = clocks.clocks.c_ck().0; asm_delay::AsmDelay::new(asm_delay::bitrate::Hertz (frequency_hz)) }; @@ -299,7 +301,7 @@ const APP: () = { ad9959::Ad9959::new(qspi_interface, &mut reset_pin, io_update, - delay, + asm_delay, ad9959::Mode::FourBitSerial, 100_000_000).unwrap() }; @@ -325,7 +327,30 @@ const APP: () = { dp.SPI1.spi((spi_sck, spi_miso, spi_mosi), config, 25.mhz(), &clocks) }; - pounder::PounderDevices::new(io_expander, ad9959, spi).unwrap() + let adc1 = { + let mut adc = dp.ADC1.adc(&mut delay, &mut clocks); + adc.calibrate(); + + adc.enable() + }; + + let adc2 = { + let mut adc = dp.ADC2.adc(&mut delay, &mut clocks); + adc.calibrate(); + + adc.enable() + }; + + let adc1_in_p = gpiof.pf11.into_analog(); + let adc2_in_p = gpiof.pf14.into_analog(); + + pounder::PounderDevices::new(io_expander, + ad9959, + spi, + adc1, + adc2, + adc1_in_p, + adc2_in_p).unwrap() }; let mut fp_led_0 = gpiod.pd5.into_push_pull_output(); diff --git a/src/pounder/attenuators.rs b/src/pounder/attenuators.rs index b8569d8..cff8337 100644 --- a/src/pounder/attenuators.rs +++ b/src/pounder/attenuators.rs @@ -1,16 +1,8 @@ use super::error::Error; - -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -pub enum Channel { - One = 0, - Two = 1, - Three = 2, - Four = 3, -} +use super::DdsChannel; pub trait AttenuatorInterface { - fn modify(&mut self, attenuation: f32, channel: Channel) -> Result { + fn modify(&mut self, attenuation: f32, channel: DdsChannel) -> Result { if attenuation > 31.5 { return Err(Error::Bounds); } @@ -31,7 +23,7 @@ pub trait AttenuatorInterface { Ok(attenuation_code as f32 / 2.0) } - fn read(&mut self, channel: Channel) -> Result { + fn read(&mut self, channel: DdsChannel) -> Result { let mut channels = [0_u8; 4]; // Reading the data always shifts data out of the staging registers, so we perform a @@ -48,7 +40,7 @@ pub trait AttenuatorInterface { fn reset(&mut self) -> Result<(), Error>; - fn latch(&mut self, channel: Channel) -> Result<(), Error>; + fn latch(&mut self, channel: DdsChannel) -> Result<(), Error>; fn read_all(&mut self, channels: &mut [u8; 4]) -> Result<(), Error>; fn write_all(&mut self, channels: &[u8; 4]) -> Result<(), Error>; } diff --git a/src/pounder/error.rs b/src/pounder/error.rs index 56a9e09..b3cc596 100644 --- a/src/pounder/error.rs +++ b/src/pounder/error.rs @@ -6,4 +6,6 @@ pub enum Error { Qspi, Bounds, InvalidAddress, + InvalidChannel, + Adc, } diff --git a/src/pounder/mod.rs b/src/pounder/mod.rs index bcd24bd..7946100 100644 --- a/src/pounder/mod.rs +++ b/src/pounder/mod.rs @@ -3,13 +3,20 @@ use ad9959; pub mod error; pub mod attenuators; +mod rf_power; +pub mod types; use super::hal; use error::Error; -use attenuators::{AttenuatorInterface, Channel}; +use attenuators::AttenuatorInterface; +use types::{DdsChannel, InputChannel}; +use rf_power::PowerMeasurementInterface; -use embedded_hal::blocking::spi::Transfer; +use embedded_hal::{ + blocking::spi::Transfer, + adc::OneShot +}; #[allow(dead_code)] const OSC_EN_N_PIN: u8 = 8 + 7; @@ -62,7 +69,11 @@ pub struct PounderDevices { DELAY, hal::gpio::gpiog::PG7>>, mcp23017: mcp23017::MCP23017>, - attenuator_spi: hal::spi::Spi + attenuator_spi: hal::spi::Spi, + adc1: hal::adc::Adc, + adc2: hal::adc::Adc, + adc1_in_p: hal::gpio::gpiof::PF11, + adc2_in_p: hal::gpio::gpiof::PF14, } impl PounderDevices @@ -74,11 +85,20 @@ where DELAY, hal::gpio::gpiog::PG7< hal::gpio::Output>>, - attenuator_spi: hal::spi::Spi) -> Result { + attenuator_spi: hal::spi::Spi, + adc1: hal::adc::Adc, + adc2: hal::adc::Adc, + adc1_in_p: hal::gpio::gpiof::PF11, + adc2_in_p: hal::gpio::gpiof::PF14, + ) -> Result { let mut devices = Self { mcp23017, ad9959, - attenuator_spi + attenuator_spi, + adc1, + adc2, + adc1_in_p, + adc2_in_p, }; // Configure power-on-default state for pounder. All LEDs are on, on-board oscillator @@ -117,12 +137,12 @@ impl AttenuatorInterface for PounderDevices Ok(()) } - fn latch(&mut self, channel: Channel) -> Result<(), Error> { + fn latch(&mut self, channel: DdsChannel) -> Result<(), Error> { let pin = match channel { - Channel::One => ATT_LE0_PIN, - Channel::Two => ATT_LE1_PIN, - Channel::Three => ATT_LE2_PIN, - Channel::Four => ATT_LE3_PIN, + DdsChannel::Zero => ATT_LE0_PIN, + DdsChannel::One => ATT_LE1_PIN, + DdsChannel::Two => ATT_LE2_PIN, + DdsChannel::Three => ATT_LE3_PIN, }; self.mcp23017.digital_write(pin, 1).map_err(|_| Error::I2c)?; @@ -146,3 +166,21 @@ impl AttenuatorInterface for PounderDevices Ok(()) } } + +impl PowerMeasurementInterface for PounderDevices { + fn sample_converter(&mut self, channel: InputChannel) -> Result { + let adc_scale = match channel { + InputChannel::Zero => { + let adc_reading: u32 = self.adc1.read(&mut self.adc1_in_p).map_err(|_| Error::Adc)?; + adc_reading as f32 / self.adc1.max_sample() as f32 + }, + InputChannel::One => { + let adc_reading: u32 = self.adc2.read(&mut self.adc2_in_p).map_err(|_| Error::Adc)?; + adc_reading as f32 / self.adc2.max_sample() as f32 + }, + }; + + // Convert analog percentage to voltage. + Ok(adc_scale * 3.3) + } +} diff --git a/src/pounder/rf_power.rs b/src/pounder/rf_power.rs new file mode 100644 index 0000000..cc3f654 --- /dev/null +++ b/src/pounder/rf_power.rs @@ -0,0 +1,13 @@ +use super::Error; +use super::InputChannel; + +pub trait PowerMeasurementInterface { + fn sample_converter(&mut self, channel: InputChannel) -> Result; + + fn measure_power(&mut self, channel: InputChannel) -> Result { + let analog_measurement = self.sample_converter(channel)?; + + // The AD8363 with VSET connected to VOUT provides an output voltage of 52mV / dB. + Ok(analog_measurement / 0.052) + } +} diff --git a/src/pounder/types.rs b/src/pounder/types.rs new file mode 100644 index 0000000..9938bfe --- /dev/null +++ b/src/pounder/types.rs @@ -0,0 +1,16 @@ + +#[allow(dead_code)] +#[derive(Debug, Copy, Clone)] +pub enum DdsChannel { + Zero, + One, + Two, + Three, +} + +#[allow(dead_code)] +#[derive(Debug, Copy, Clone)] +pub enum InputChannel { + Zero, + One, +}