Adding input power measurement support

This commit is contained in:
Ryan Summers 2020-04-29 13:00:29 +02:00
parent 6f7bb0569c
commit 6792ab5469
7 changed files with 112 additions and 26 deletions

View File

@ -58,7 +58,7 @@ branch = "feature/device-dependency"
[dependencies.stm32h7xx-hal] [dependencies.stm32h7xx-hal]
git = "https://github.com/quartiq/stm32h7xx-hal.git" git = "https://github.com/quartiq/stm32h7xx-hal.git"
branch = "feature/quad-spi" branch = "feature/quad-spi"
features = ["stm32h743v", "rt"] features = ["stm32h743v", "rt", "unproven"]
[features] [features]
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"] semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]

View File

@ -166,6 +166,8 @@ const APP: () = {
clocks.rb.d2ccip1r.modify(|_, w| w.spi123sel().pll2_p().spi45sel().pll2_q()); 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 gpioa = dp.GPIOA.split(&mut clocks.ahb4);
let gpiob = dp.GPIOB.split(&mut clocks.ahb4); let gpiob = dp.GPIOB.split(&mut clocks.ahb4);
let gpioc = dp.GPIOC.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 io_update = gpiog.pg7.into_push_pull_output();
let delay = { let asm_delay = {
let frequency_hz = clocks.clocks.c_ck().0; let frequency_hz = clocks.clocks.c_ck().0;
asm_delay::AsmDelay::new(asm_delay::bitrate::Hertz (frequency_hz)) asm_delay::AsmDelay::new(asm_delay::bitrate::Hertz (frequency_hz))
}; };
@ -299,7 +301,7 @@ const APP: () = {
ad9959::Ad9959::new(qspi_interface, ad9959::Ad9959::new(qspi_interface,
&mut reset_pin, &mut reset_pin,
io_update, io_update,
delay, asm_delay,
ad9959::Mode::FourBitSerial, ad9959::Mode::FourBitSerial,
100_000_000).unwrap() 100_000_000).unwrap()
}; };
@ -325,7 +327,30 @@ const APP: () = {
dp.SPI1.spi((spi_sck, spi_miso, spi_mosi), config, 25.mhz(), &clocks) 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(); let mut fp_led_0 = gpiod.pd5.into_push_pull_output();

View File

@ -1,16 +1,8 @@
use super::error::Error; use super::error::Error;
use super::DdsChannel;
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum Channel {
One = 0,
Two = 1,
Three = 2,
Four = 3,
}
pub trait AttenuatorInterface { pub trait AttenuatorInterface {
fn modify(&mut self, attenuation: f32, channel: Channel) -> Result<f32, Error> { fn modify(&mut self, attenuation: f32, channel: DdsChannel) -> Result<f32, Error> {
if attenuation > 31.5 { if attenuation > 31.5 {
return Err(Error::Bounds); return Err(Error::Bounds);
} }
@ -31,7 +23,7 @@ pub trait AttenuatorInterface {
Ok(attenuation_code as f32 / 2.0) Ok(attenuation_code as f32 / 2.0)
} }
fn read(&mut self, channel: Channel) -> Result<f32, Error> { fn read(&mut self, channel: DdsChannel) -> Result<f32, Error> {
let mut channels = [0_u8; 4]; let mut channels = [0_u8; 4];
// Reading the data always shifts data out of the staging registers, so we perform a // 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 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 read_all(&mut self, channels: &mut [u8; 4]) -> Result<(), Error>;
fn write_all(&mut self, channels: &[u8; 4]) -> Result<(), Error>; fn write_all(&mut self, channels: &[u8; 4]) -> Result<(), Error>;
} }

View File

@ -6,4 +6,6 @@ pub enum Error {
Qspi, Qspi,
Bounds, Bounds,
InvalidAddress, InvalidAddress,
InvalidChannel,
Adc,
} }

View File

@ -3,13 +3,20 @@ use ad9959;
pub mod error; pub mod error;
pub mod attenuators; pub mod attenuators;
mod rf_power;
pub mod types;
use super::hal; use super::hal;
use error::Error; 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)] #[allow(dead_code)]
const OSC_EN_N_PIN: u8 = 8 + 7; const OSC_EN_N_PIN: u8 = 8 + 7;
@ -62,7 +69,11 @@ pub struct PounderDevices<DELAY> {
DELAY, DELAY,
hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>>, hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>>,
mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>, mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1> attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
adc1_in_p: hal::gpio::gpiof::PF11<hal::gpio::Analog>,
adc2_in_p: hal::gpio::gpiof::PF14<hal::gpio::Analog>,
} }
impl<DELAY> PounderDevices<DELAY> impl<DELAY> PounderDevices<DELAY>
@ -74,11 +85,20 @@ where
DELAY, DELAY,
hal::gpio::gpiog::PG7< hal::gpio::gpiog::PG7<
hal::gpio::Output<hal::gpio::PushPull>>>, hal::gpio::Output<hal::gpio::PushPull>>>,
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>) -> Result<Self, Error> { attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
adc1_in_p: hal::gpio::gpiof::PF11<hal::gpio::Analog>,
adc2_in_p: hal::gpio::gpiof::PF14<hal::gpio::Analog>,
) -> Result<Self, Error> {
let mut devices = Self { let mut devices = Self {
mcp23017, mcp23017,
ad9959, 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 // Configure power-on-default state for pounder. All LEDs are on, on-board oscillator
@ -117,12 +137,12 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
Ok(()) Ok(())
} }
fn latch(&mut self, channel: Channel) -> Result<(), Error> { fn latch(&mut self, channel: DdsChannel) -> Result<(), Error> {
let pin = match channel { let pin = match channel {
Channel::One => ATT_LE0_PIN, DdsChannel::Zero => ATT_LE0_PIN,
Channel::Two => ATT_LE1_PIN, DdsChannel::One => ATT_LE1_PIN,
Channel::Three => ATT_LE2_PIN, DdsChannel::Two => ATT_LE2_PIN,
Channel::Four => ATT_LE3_PIN, DdsChannel::Three => ATT_LE3_PIN,
}; };
self.mcp23017.digital_write(pin, 1).map_err(|_| Error::I2c)?; self.mcp23017.digital_write(pin, 1).map_err(|_| Error::I2c)?;
@ -146,3 +166,21 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
Ok(()) Ok(())
} }
} }
impl<DELAY> PowerMeasurementInterface for PounderDevices<DELAY> {
fn sample_converter(&mut self, channel: InputChannel) -> Result<f32, Error> {
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)
}
}

13
src/pounder/rf_power.rs Normal file
View File

@ -0,0 +1,13 @@
use super::Error;
use super::InputChannel;
pub trait PowerMeasurementInterface {
fn sample_converter(&mut self, channel: InputChannel) -> Result<f32, Error>;
fn measure_power(&mut self, channel: InputChannel) -> Result<f32, Error> {
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)
}
}

16
src/pounder/types.rs Normal file
View File

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