cargo fmt --all

This commit is contained in:
Robert Jördens 2020-06-16 14:22:12 +00:00
parent 09298bd534
commit 54f51f9484
8 changed files with 692 additions and 348 deletions

View File

@ -1,10 +1,7 @@
#![no_std] #![no_std]
use bit_field::BitField; use bit_field::BitField;
use embedded_hal::{ use embedded_hal::{blocking::delay::DelayMs, digital::v2::OutputPin};
digital::v2::OutputPin,
blocking::delay::DelayMs,
};
/// A device driver for the AD9959 direct digital synthesis (DDS) chip. /// A device driver for the AD9959 direct digital synthesis (DDS) chip.
/// ///
@ -93,12 +90,11 @@ pub enum Error {
Frequency, Frequency,
} }
impl <PinE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE> impl<PinE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
where where
INTERFACE: Interface, INTERFACE: Interface,
DELAY: DelayMs<u8>, DELAY: DelayMs<u8>,
UPDATE: OutputPin<Error = PinE>, UPDATE: OutputPin<Error = PinE>,
{ {
/// Construct and initialize the DDS. /// Construct and initialize the DDS.
/// ///
@ -111,13 +107,15 @@ where
/// * `clock_frequency` - The clock frequency of the reference clock input. /// * `clock_frequency` - The clock frequency of the reference clock input.
/// * `multiplier` - The desired clock multiplier for the system clock. This multiplies /// * `multiplier` - The desired clock multiplier for the system clock. This multiplies
/// `clock_frequency` to generate the system clock. /// `clock_frequency` to generate the system clock.
pub fn new<RST>(interface: INTERFACE, pub fn new<RST>(
reset_pin: &mut RST, interface: INTERFACE,
io_update: UPDATE, reset_pin: &mut RST,
delay: DELAY, io_update: UPDATE,
desired_mode: Mode, delay: DELAY,
clock_frequency: f32, desired_mode: Mode,
multiplier: u8) -> Result<Self, Error> clock_frequency: f32,
multiplier: u8,
) -> Result<Self, Error>
where where
RST: OutputPin, RST: OutputPin,
{ {
@ -135,25 +133,39 @@ where
reset_pin.set_high().or_else(|_| Err(Error::Pin))?; reset_pin.set_high().or_else(|_| Err(Error::Pin))?;
// Delay for a clock cycle to allow the device to reset. // Delay for a clock cycle to allow the device to reset.
ad9959.delay.delay_ms((1000.0 / clock_frequency as f32) as u8); ad9959
.delay
.delay_ms((1000.0 / clock_frequency as f32) as u8);
reset_pin.set_low().or_else(|_| Err(Error::Pin))?; reset_pin.set_low().or_else(|_| Err(Error::Pin))?;
ad9959.interface.configure_mode(Mode::SingleBitTwoWire).map_err(|_| Error::Interface)?; ad9959
.interface
.configure_mode(Mode::SingleBitTwoWire)
.map_err(|_| Error::Interface)?;
// Program the interface configuration in the AD9959. Default to all channels enabled. // Program the interface configuration in the AD9959. Default to all channels enabled.
let mut csr: [u8; 1] = [0xF0]; let mut csr: [u8; 1] = [0xF0];
csr[0].set_bits(1..3, desired_mode as u8); csr[0].set_bits(1..3, desired_mode as u8);
ad9959.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; ad9959
.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
// Latch the configuration registers to make them active. // Latch the configuration registers to make them active.
ad9959.latch_configuration()?; ad9959.latch_configuration()?;
ad9959.interface.configure_mode(desired_mode).map_err(|_| Error::Interface)?; ad9959
.interface
.configure_mode(desired_mode)
.map_err(|_| Error::Interface)?;
// Read back the CSR to ensure it specifies the mode correctly. // Read back the CSR to ensure it specifies the mode correctly.
let mut updated_csr: [u8; 1] = [0]; let mut updated_csr: [u8; 1] = [0];
ad9959.interface.read(Register::CSR as u8, &mut updated_csr).map_err(|_| Error::Interface)?; ad9959
.interface
.read(Register::CSR as u8, &mut updated_csr)
.map_err(|_| Error::Interface)?;
if updated_csr[0] != csr[0] { if updated_csr[0] != csr[0] {
return Err(Error::Check); return Err(Error::Check);
} }
@ -165,13 +177,14 @@ where
/// Latch the DDS configuration to ensure it is active on the output channels. /// Latch the DDS configuration to ensure it is active on the output channels.
fn latch_configuration(&mut self) -> Result<(), Error> { fn latch_configuration(&mut self) -> Result<(), Error> {
self.io_update.set_high().or_else(|_| Err(Error::Pin))?; self.io_update.set_high().or_else(|_| Err(Error::Pin))?;
// The SYNC_CLK is 1/4 the system clock frequency. The IO_UPDATE pin must be latched for one // The SYNC_CLK is 1/4 the system clock frequency. The IO_UPDATE pin must be latched for one
// full SYNC_CLK pulse to register. For safety, we latch for 5 here. // full SYNC_CLK pulse to register. For safety, we latch for 5 here.
self.delay.delay_ms((5000.0 / self.system_clock_frequency()) as u8); self.delay
self.io_update.set_low().or_else(|_| Err(Error::Pin))?; .delay_ms((5000.0 / self.system_clock_frequency()) as u8);
self.io_update.set_low().or_else(|_| Err(Error::Pin))?;
Ok(()) Ok(())
} }
/// Configure the internal system clock of the chip. /// Configure the internal system clock of the chip.
@ -182,30 +195,36 @@ where
/// ///
/// Returns: /// Returns:
/// The actual frequency configured for the internal system clock. /// The actual frequency configured for the internal system clock.
pub fn configure_system_clock(&mut self, pub fn configure_system_clock(
reference_clock_frequency: f32, &mut self,
multiplier: u8) -> Result<f64, Error> reference_clock_frequency: f32,
{ multiplier: u8,
) -> Result<f64, Error> {
self.reference_clock_frequency = reference_clock_frequency; self.reference_clock_frequency = reference_clock_frequency;
if multiplier != 1 && (multiplier > 20 || multiplier < 4) { if multiplier != 1 && (multiplier > 20 || multiplier < 4) {
return Err(Error::Bounds); return Err(Error::Bounds);
} }
let frequency = multiplier as f64 * self.reference_clock_frequency as f64; let frequency =
multiplier as f64 * self.reference_clock_frequency as f64;
if frequency > 500_000_000.0f64 { if frequency > 500_000_000.0f64 {
return Err(Error::Frequency); return Err(Error::Frequency);
} }
// TODO: Update / disable any enabled channels? // TODO: Update / disable any enabled channels?
let mut fr1: [u8; 3] = [0, 0, 0]; let mut fr1: [u8; 3] = [0, 0, 0];
self.interface.read(Register::FR1 as u8, &mut fr1).map_err(|_| Error::Interface)?; self.interface
.read(Register::FR1 as u8, &mut fr1)
.map_err(|_| Error::Interface)?;
fr1[0].set_bits(2..=6, multiplier); fr1[0].set_bits(2..=6, multiplier);
let vco_range = frequency > 255e6; let vco_range = frequency > 255e6;
fr1[0].set_bit(7, vco_range); fr1[0].set_bit(7, vco_range);
self.interface.write(Register::FR1 as u8, &fr1).map_err(|_| Error::Interface)?; self.interface
.write(Register::FR1 as u8, &fr1)
.map_err(|_| Error::Interface)?;
self.system_clock_multiplier = multiplier; self.system_clock_multiplier = multiplier;
Ok(self.system_clock_frequency()) Ok(self.system_clock_frequency())
@ -219,7 +238,9 @@ where
/// Get the current reference clock multiplier. /// Get the current reference clock multiplier.
pub fn get_reference_clock_multiplier(&mut self) -> Result<u8, Error> { pub fn get_reference_clock_multiplier(&mut self) -> Result<u8, Error> {
let mut fr1: [u8; 3] = [0, 0, 0]; let mut fr1: [u8; 3] = [0, 0, 0];
self.interface.read(Register::FR1 as u8, &mut fr1).map_err(|_| Error::Interface)?; self.interface
.read(Register::FR1 as u8, &mut fr1)
.map_err(|_| Error::Interface)?;
Ok(fr1[0].get_bits(2..=6) as u8) Ok(fr1[0].get_bits(2..=6) as u8)
} }
@ -233,49 +254,66 @@ where
/// True if the self test succeeded. False otherwise. /// True if the self test succeeded. False otherwise.
pub fn self_test(&mut self) -> Result<bool, Error> { pub fn self_test(&mut self) -> Result<bool, Error> {
let mut csr: [u8; 1] = [0]; let mut csr: [u8; 1] = [0];
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
let old_csr = csr[0]; let old_csr = csr[0];
// Enable all channels. // Enable all channels.
csr[0].set_bits(4..8, 0xF); csr[0].set_bits(4..8, 0xF);
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
// Read back the enable. // Read back the enable.
csr[0] = 0; csr[0] = 0;
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
if csr[0].get_bits(4..8) != 0xF { if csr[0].get_bits(4..8) != 0xF {
return Ok(false); return Ok(false);
} }
// Clear all channel enables. // Clear all channel enables.
csr[0].set_bits(4..8, 0x0); csr[0].set_bits(4..8, 0x0);
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
// Read back the enable. // Read back the enable.
csr[0] = 0xFF; csr[0] = 0xFF;
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
if csr[0].get_bits(4..8) != 0 { if csr[0].get_bits(4..8) != 0 {
return Ok(false); return Ok(false);
} }
// Restore the CSR. // Restore the CSR.
csr[0] = old_csr; csr[0] = old_csr;
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
Ok(true) Ok(true)
} }
/// Get the current system clock frequency in Hz. /// Get the current system clock frequency in Hz.
fn system_clock_frequency(&self) -> f64 { fn system_clock_frequency(&self) -> f64 {
self.system_clock_multiplier as f64 * self.reference_clock_frequency as f64 self.system_clock_multiplier as f64
* self.reference_clock_frequency as f64
} }
/// Enable an output channel. /// Enable an output channel.
pub fn enable_channel(&mut self, channel: Channel) -> Result<(), Error> { pub fn enable_channel(&mut self, channel: Channel) -> Result<(), Error> {
let mut csr: [u8; 1] = [0]; let mut csr: [u8; 1] = [0];
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
csr[0].set_bit(channel as usize + 4, true); csr[0].set_bit(channel as usize + 4, true);
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
@ -283,9 +321,13 @@ where
/// Disable an output channel. /// Disable an output channel.
pub fn disable_channel(&mut self, channel: Channel) -> Result<(), Error> { pub fn disable_channel(&mut self, channel: Channel) -> Result<(), Error> {
let mut csr: [u8; 1] = [0]; let mut csr: [u8; 1] = [0];
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
csr[0].set_bit(channel as usize + 4, false); csr[0].set_bit(channel as usize + 4, false);
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
@ -293,7 +335,9 @@ where
/// Determine if an output channel is enabled. /// Determine if an output channel is enabled.
pub fn is_enabled(&mut self, channel: Channel) -> Result<bool, Error> { pub fn is_enabled(&mut self, channel: Channel) -> Result<bool, Error> {
let mut csr: [u8; 1] = [0; 1]; let mut csr: [u8; 1] = [0; 1];
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
Ok(csr[0].get_bit(channel as usize + 4)) Ok(csr[0].get_bit(channel as usize + 4))
} }
@ -304,24 +348,37 @@ where
/// * `channel` - The channel to configure. /// * `channel` - The channel to configure.
/// * `register` - The register to update. /// * `register` - The register to update.
/// * `data` - The contents to write to the provided register. /// * `data` - The contents to write to the provided register.
fn modify_channel(&mut self, channel: Channel, register: Register, data: &[u8]) -> Result<(), Error> { fn modify_channel(
&mut self,
channel: Channel,
register: Register,
data: &[u8],
) -> Result<(), Error> {
// Disable all other outputs so that we can update the configuration register of only the // Disable all other outputs so that we can update the configuration register of only the
// specified channel. // specified channel.
let mut csr: [u8; 1] = [0]; let mut csr: [u8; 1] = [0];
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
let mut new_csr = csr; let mut new_csr = csr;
new_csr[0].set_bits(4..8, 0); new_csr[0].set_bits(4..8, 0);
new_csr[0].set_bit(4 + channel as usize, true); new_csr[0].set_bit(4 + channel as usize, true);
self.interface.write(Register::CSR as u8, &new_csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &new_csr)
.map_err(|_| Error::Interface)?;
self.interface.write(register as u8, &data).map_err(|_| Error::Interface)?; self.interface
.write(register as u8, &data)
.map_err(|_| Error::Interface)?;
// Latch the configuration and restore the previous CSR. Note that the re-enable of the // 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. // channel happens immediately, so the CSR update does not need to be latched.
self.latch_configuration()?; self.latch_configuration()?;
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
@ -332,23 +389,36 @@ where
/// * `channel` - The channel to read. /// * `channel` - The channel to read.
/// * `register` - The register to read. /// * `register` - The register to read.
/// * `data` - A location to store the read register contents. /// * `data` - A location to store the read register contents.
fn read_channel(&mut self, channel: Channel, register: Register, mut data: &mut [u8]) -> Result<(), Error> { fn read_channel(
&mut self,
channel: Channel,
register: Register,
mut data: &mut [u8],
) -> Result<(), Error> {
// Disable all other channels in the CSR so that we can read the configuration register of // Disable all other channels in the CSR so that we can read the configuration register of
// only the desired channel. // only the desired channel.
let mut csr: [u8; 1] = [0]; let mut csr: [u8; 1] = [0];
self.interface.read(Register::CSR as u8, &mut csr).map_err(|_| Error::Interface)?; self.interface
.read(Register::CSR as u8, &mut csr)
.map_err(|_| Error::Interface)?;
let mut new_csr = csr; let mut new_csr = csr;
new_csr[0].set_bits(4..8, 0); new_csr[0].set_bits(4..8, 0);
new_csr[0].set_bit(4 + channel as usize, true); new_csr[0].set_bit(4 + channel as usize, true);
self.interface.write(Register::CSR as u8, &new_csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &new_csr)
.map_err(|_| Error::Interface)?;
self.interface.read(register as u8, &mut data).map_err(|_| Error::Interface)?; self.interface
.read(register as u8, &mut data)
.map_err(|_| Error::Interface)?;
// Restore the previous CSR. Note that the re-enable of the channel happens immediately, so // Restore the previous CSR. Note that the re-enable of the channel happens immediately, so
// the CSR update does not need to be latched. // the CSR update does not need to be latched.
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?; self.interface
.write(Register::CSR as u8, &csr)
.map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
@ -361,10 +431,19 @@ where
/// ///
/// Returns: /// Returns:
/// The actual programmed phase offset of the channel in turns. /// The actual programmed phase offset of the channel in turns.
pub fn set_phase(&mut self, channel: Channel, phase_turns: f32) -> Result<f32, Error> { pub fn set_phase(
let phase_offset: u16 = (phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16; &mut self,
channel: Channel,
phase_turns: f32,
) -> Result<f32, Error> {
let phase_offset: u16 =
(phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
self.modify_channel(channel, Register::CPOW0, &phase_offset.to_be_bytes())?; self.modify_channel(
channel,
Register::CPOW0,
&phase_offset.to_be_bytes(),
)?;
Ok((phase_offset as f32) / ((1 << 14) as f32)) Ok((phase_offset as f32) / ((1 << 14) as f32))
} }
@ -393,7 +472,11 @@ where
/// ///
/// Returns: /// Returns:
/// The actual normalized amplitude of the channel relative to full-scale range. /// The actual normalized amplitude of the channel relative to full-scale range.
pub fn set_amplitude(&mut self, channel: Channel, amplitude: f32) -> Result<f32, Error> { pub fn set_amplitude(
&mut self,
channel: Channel,
amplitude: f32,
) -> Result<f32, Error> {
if amplitude < 0.0 || amplitude > 1.0 { if amplitude < 0.0 || amplitude > 1.0 {
return Err(Error::Bounds); return Err(Error::Bounds);
} }
@ -406,7 +489,6 @@ where
// full-scale at 0x3FF (amplitude of 1), so the multiplier should be disabled whenever // full-scale at 0x3FF (amplitude of 1), so the multiplier should be disabled whenever
// full-scale is used. // full-scale is used.
if amplitude_control < (1 << 10) { if amplitude_control < (1 << 10) {
let masked_control = amplitude_control & 0x3FF; let masked_control = amplitude_control & 0x3FF;
acr[1] = masked_control.to_be_bytes()[0]; acr[1] = masked_control.to_be_bytes()[0];
acr[2] = masked_control.to_be_bytes()[1]; acr[2] = masked_control.to_be_bytes()[1];
@ -432,7 +514,8 @@ where
self.read_channel(channel, Register::ACR, &mut acr)?; self.read_channel(channel, Register::ACR, &mut acr)?;
if acr[1].get_bit(4) { if acr[1].get_bit(4) {
let amplitude_control: u16 = (((acr[1] as u16) << 8) | (acr[2] as u16)) & 0x3FF; let amplitude_control: u16 =
(((acr[1] as u16) << 8) | (acr[2] as u16)) & 0x3FF;
Ok(amplitude_control as f32 / (1 << 10) as f32) Ok(amplitude_control as f32 / (1 << 10) as f32)
} else { } else {
Ok(1.0) Ok(1.0)
@ -447,18 +530,28 @@ where
/// ///
/// Returns: /// Returns:
/// The actual programmed frequency of the channel. /// The actual programmed frequency of the channel.
pub fn set_frequency(&mut self, channel: Channel, frequency: f64) -> Result<f64, Error> { pub fn set_frequency(
&mut self,
channel: Channel,
frequency: f64,
) -> Result<f64, Error> {
if frequency < 0.0 || frequency > self.system_clock_frequency() { if frequency < 0.0 || frequency > self.system_clock_frequency() {
return Err(Error::Bounds); return Err(Error::Bounds);
} }
// The function for channel frequency is `f_out = FTW * f_s / 2^32`, where FTW is the // 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. // frequency tuning word and f_s is the system clock rate.
let tuning_word: u32 = ((frequency as f64 / self.system_clock_frequency()) let tuning_word: u32 =
* 1u64.wrapping_shl(32) as f64) as u32; ((frequency as f64 / self.system_clock_frequency())
* 1u64.wrapping_shl(32) as f64) as u32;
self.modify_channel(channel, Register::CFTW0, &tuning_word.to_be_bytes())?; self.modify_channel(
Ok((tuning_word as f64 / 1u64.wrapping_shl(32) as f64) * self.system_clock_frequency()) channel,
Register::CFTW0,
&tuning_word.to_be_bytes(),
)?;
Ok((tuning_word as f64 / 1u64.wrapping_shl(32) as f64)
* self.system_clock_frequency())
} }
/// Get the frequency of a channel. /// Get the frequency of a channel.
@ -475,6 +568,7 @@ where
let tuning_word = u32::from_be_bytes(tuning_word); let tuning_word = u32::from_be_bytes(tuning_word);
// Convert the tuning word into a frequency. // Convert the tuning word into a frequency.
Ok(tuning_word as f64 * self.system_clock_frequency() / ((1u64 << 32)) as f64) Ok(tuning_word as f64 * self.system_clock_frequency()
/ (1u64 << 32) as f64)
} }
} }

View File

@ -1,5 +1,5 @@
use embedded_hal; use embedded_hal;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use core::convert::TryFrom; use core::convert::TryFrom;
use enum_iterator::IntoEnumIterator; use enum_iterator::IntoEnumIterator;
@ -9,13 +9,13 @@ pub enum Gain {
G1 = 0b00, G1 = 0b00,
G2 = 0b01, G2 = 0b01,
G5 = 0b10, G5 = 0b10,
G10 = 0b11 G10 = 0b11,
} }
/// A programmable gain amplifier that allows for setting the gain via GPIO. /// A programmable gain amplifier that allows for setting the gain via GPIO.
pub struct ProgrammableGainAmplifier<A0, A1> { pub struct ProgrammableGainAmplifier<A0, A1> {
a0: A0, a0: A0,
a1: A1 a1: A1,
} }
impl TryFrom<u8> for Gain { impl TryFrom<u8> for Gain {
@ -24,7 +24,7 @@ impl TryFrom<u8> for Gain {
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self, Self::Error> {
for gain in Gain::into_enum_iter() { for gain in Gain::into_enum_iter() {
if value == gain as u8 { if value == gain as u8 {
return Ok(gain) return Ok(gain);
} }
} }
@ -44,9 +44,8 @@ where
/// Args: /// Args:
/// * `a0` - An output connected to the A0 input of the amplifier. /// * `a0` - An output connected to the A0 input of the amplifier.
/// * `a1` - An output connected to the A1 input of the amplifier. /// * `a1` - An output connected to the A1 input of the amplifier.
pub fn new(a0: A0, a1: A1) -> Self pub fn new(a0: A0, a1: A1) -> Self {
{ let mut afe = Self { a0: a0, a1: a1 };
let mut afe = Self { a0: a0, a1: a1};
afe.set_gain(Gain::G1); afe.set_gain(Gain::G1);

View File

@ -4,7 +4,8 @@ const I2C_ADDR: u8 = 0x50;
#[allow(dead_code)] #[allow(dead_code)]
pub fn read_eui48<T>(i2c: &mut T) -> Result<[u8; 6], T::Error> pub fn read_eui48<T>(i2c: &mut T) -> Result<[u8; 6], T::Error>
where T: WriteRead where
T: WriteRead,
{ {
let mut buffer = [0u8; 6]; let mut buffer = [0u8; 6];
i2c.write_read(I2C_ADDR, &[0xFA_u8], &mut buffer)?; i2c.write_read(I2C_ADDR, &[0xFA_u8], &mut buffer)?;

View File

@ -29,25 +29,18 @@ extern crate log;
// use core::sync::atomic::{AtomicU32, AtomicBool, Ordering}; // use core::sync::atomic::{AtomicU32, AtomicBool, Ordering};
use asm_delay; use asm_delay;
use rtfm::cyccnt::{Instant, U32Ext};
use cortex_m_rt::exception;
use cortex_m; use cortex_m;
use cortex_m_rt::exception;
use rtfm::cyccnt::{Instant, U32Ext};
use stm32h7xx_hal as hal; use stm32h7xx_hal as hal;
use stm32h7xx_hal::{ use stm32h7xx_hal::prelude::*;
prelude::*,
};
use embedded_hal::{ use embedded_hal::digital::v2::OutputPin;
digital::v2::OutputPin,
};
use stm32h7_ethernet as ethernet;
use smoltcp as net; use smoltcp as net;
use stm32h7_ethernet as ethernet;
use heapless::{ use heapless::{consts::*, String};
String,
consts::*,
};
#[link_section = ".sram3.eth"] #[link_section = ".sram3.eth"]
static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new(); static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new();
@ -89,7 +82,9 @@ pub struct NetStorage {
static mut NET_STORE: NetStorage = NetStorage { static mut NET_STORE: NetStorage = NetStorage {
// Placeholder for the real IP address, which is initialized at runtime. // Placeholder for the real IP address, which is initialized at runtime.
ip_addrs: [net::wire::IpCidr::Ipv6(net::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX)], ip_addrs: [net::wire::IpCidr::Ipv6(
net::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX,
)],
neighbor_cache: [None; 8], neighbor_cache: [None; 8],
}; };
@ -105,11 +100,13 @@ const TCP_TX_BUFFER_SIZE: usize = 8192;
type AFE1 = afe::ProgrammableGainAmplifier< type AFE1 = afe::ProgrammableGainAmplifier<
hal::gpio::gpiof::PF2<hal::gpio::Output<hal::gpio::PushPull>>, hal::gpio::gpiof::PF2<hal::gpio::Output<hal::gpio::PushPull>>,
hal::gpio::gpiof::PF5<hal::gpio::Output<hal::gpio::PushPull>>>; hal::gpio::gpiof::PF5<hal::gpio::Output<hal::gpio::PushPull>>,
>;
type AFE2 = afe::ProgrammableGainAmplifier< type AFE2 = afe::ProgrammableGainAmplifier<
hal::gpio::gpiod::PD14<hal::gpio::Output<hal::gpio::PushPull>>, hal::gpio::gpiod::PD14<hal::gpio::Output<hal::gpio::PushPull>>,
hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>>; hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>,
>;
macro_rules! route_request { macro_rules! route_request {
($request:ident, ($request:ident,
@ -176,8 +173,12 @@ const APP: () = {
eeprom_i2c: hal::i2c::I2c<hal::stm32::I2C2>, eeprom_i2c: hal::i2c::I2c<hal::stm32::I2C2>,
timer: hal::timer::Timer<hal::stm32::TIM2>, timer: hal::timer::Timer<hal::stm32::TIM2>,
net_interface: net::iface::EthernetInterface<'static, 'static, 'static, net_interface: net::iface::EthernetInterface<
ethernet::EthernetDMA<'static>>, 'static,
'static,
'static,
ethernet::EthernetDMA<'static>,
>,
eth_mac: ethernet::EthernetMAC, eth_mac: ethernet::EthernetMAC,
mac_addr: net::wire::EthernetAddress, mac_addr: net::wire::EthernetAddress,
@ -200,7 +201,7 @@ const APP: () = {
let rcc = dp.RCC.constrain(); let rcc = dp.RCC.constrain();
let mut clocks = rcc let mut clocks = rcc
//TODO: Re-enable HSE for Stabilizer platform. //TODO: Re-enable HSE for Stabilizer platform.
// .use_hse(8.mhz()) // .use_hse(8.mhz())
.sysclk(400.mhz()) .sysclk(400.mhz())
.hclk(200.mhz()) .hclk(200.mhz())
.per_ck(100.mhz()) .per_ck(100.mhz())
@ -215,7 +216,10 @@ const APP: () = {
clocks.rb.rsr.write(|w| w.rmvf().set_bit()); clocks.rb.rsr.write(|w| w.rmvf().set_bit());
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 mut delay = hal::delay::Delay::new(cp.SYST, clocks.clocks);
@ -241,25 +245,32 @@ const APP: () = {
// Configure the SPI interfaces to the ADCs and DACs. // Configure the SPI interfaces to the ADCs and DACs.
let adc1_spi = { let adc1_spi = {
let spi_miso = gpiob.pb14.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); let spi_miso = gpiob
let spi_sck = gpiob.pb10.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); .pb14
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let spi_sck = gpiob
.pb10
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let _spi_nss = gpiob.pb9.into_alternate_af5(); let _spi_nss = gpiob.pb9.into_alternate_af5();
let config = hal::spi::Config::new(hal::spi::Mode{ let config = hal::spi::Config::new(hal::spi::Mode {
polarity: hal::spi::Polarity::IdleHigh, polarity: hal::spi::Polarity::IdleHigh,
phase: hal::spi::Phase::CaptureOnSecondTransition, phase: hal::spi::Phase::CaptureOnSecondTransition,
}) })
.communication_mode(hal::spi::CommunicationMode::Receiver) .communication_mode(hal::spi::CommunicationMode::Receiver)
.manage_cs() .manage_cs()
.transfer_size(1) .transfer_size(1)
.frame_size(16) .frame_size(16)
.cs_delay(220e-9); .cs_delay(220e-9);
let mut spi = dp.SPI2.spi( let mut spi = dp.SPI2.spi(
(spi_sck, spi_miso, hal::spi::NoMosi), (spi_sck, spi_miso, hal::spi::NoMosi),
config, config,
50.mhz(), 50.mhz(),
&clocks); &clocks,
);
spi.listen(hal::spi::Event::Eot); spi.listen(hal::spi::Event::Eot);
@ -267,26 +278,32 @@ const APP: () = {
}; };
let adc2_spi = { let adc2_spi = {
let spi_miso = gpiob.pb4.into_alternate_af6().set_speed(hal::gpio::Speed::VeryHigh); let spi_miso = gpiob
let spi_sck = gpioc.pc10.into_alternate_af6().set_speed(hal::gpio::Speed::VeryHigh); .pb4
.into_alternate_af6()
.set_speed(hal::gpio::Speed::VeryHigh);
let spi_sck = gpioc
.pc10
.into_alternate_af6()
.set_speed(hal::gpio::Speed::VeryHigh);
let _spi_nss = gpioa.pa15.into_alternate_af6(); let _spi_nss = gpioa.pa15.into_alternate_af6();
let config = hal::spi::Config::new(hal::spi::Mode {
let config = hal::spi::Config::new(hal::spi::Mode{ polarity: hal::spi::Polarity::IdleHigh,
polarity: hal::spi::Polarity::IdleHigh, phase: hal::spi::Phase::CaptureOnSecondTransition,
phase: hal::spi::Phase::CaptureOnSecondTransition, })
}) .communication_mode(hal::spi::CommunicationMode::Receiver)
.communication_mode(hal::spi::CommunicationMode::Receiver) .manage_cs()
.manage_cs() .transfer_size(1)
.transfer_size(1) .frame_size(16)
.frame_size(16) .cs_delay(220e-9);
.cs_delay(220e-9);
let mut spi = dp.SPI3.spi( let mut spi = dp.SPI3.spi(
(spi_sck, spi_miso, hal::spi::NoMosi), (spi_sck, spi_miso, hal::spi::NoMosi),
config, config,
50.mhz(), 50.mhz(),
&clocks); &clocks,
);
spi.listen(hal::spi::Event::Eot); spi.listen(hal::spi::Event::Eot);
@ -294,40 +311,62 @@ const APP: () = {
}; };
let dac1_spi = { let dac1_spi = {
let spi_miso = gpioe.pe5.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); let spi_miso = gpioe
let spi_sck = gpioe.pe2.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); .pe5
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let spi_sck = gpioe
.pe2
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let _spi_nss = gpioe.pe4.into_alternate_af5(); let _spi_nss = gpioe.pe4.into_alternate_af5();
let config = hal::spi::Config::new(hal::spi::Mode{ let config = hal::spi::Config::new(hal::spi::Mode {
polarity: hal::spi::Polarity::IdleHigh, polarity: hal::spi::Polarity::IdleHigh,
phase: hal::spi::Phase::CaptureOnSecondTransition, phase: hal::spi::Phase::CaptureOnSecondTransition,
}) })
.communication_mode(hal::spi::CommunicationMode::Transmitter) .communication_mode(hal::spi::CommunicationMode::Transmitter)
.manage_cs() .manage_cs()
.transfer_size(1) .transfer_size(1)
.frame_size(16) .frame_size(16)
.swap_mosi_miso(); .swap_mosi_miso();
let spi = dp.SPI4.spi((spi_sck, spi_miso, hal::spi::NoMosi), config, 50.mhz(), &clocks); let spi = dp.SPI4.spi(
(spi_sck, spi_miso, hal::spi::NoMosi),
config,
50.mhz(),
&clocks,
);
spi spi
}; };
let dac2_spi = { let dac2_spi = {
let spi_miso = gpiof.pf8.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); let spi_miso = gpiof
let spi_sck = gpiof.pf7.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); .pf8
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let spi_sck = gpiof
.pf7
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let _spi_nss = gpiof.pf6.into_alternate_af5(); let _spi_nss = gpiof.pf6.into_alternate_af5();
let config = hal::spi::Config::new(hal::spi::Mode{ let config = hal::spi::Config::new(hal::spi::Mode {
polarity: hal::spi::Polarity::IdleHigh, polarity: hal::spi::Polarity::IdleHigh,
phase: hal::spi::Phase::CaptureOnSecondTransition, phase: hal::spi::Phase::CaptureOnSecondTransition,
}) })
.communication_mode(hal::spi::CommunicationMode::Transmitter) .communication_mode(hal::spi::CommunicationMode::Transmitter)
.manage_cs() .manage_cs()
.transfer_size(1) .transfer_size(1)
.frame_size(16) .frame_size(16)
.swap_mosi_miso(); .swap_mosi_miso();
let spi = dp.SPI5.spi((spi_sck, spi_miso, hal::spi::NoMosi), config, 50.mhz(), &clocks); let spi = dp.SPI5.spi(
(spi_sck, spi_miso, hal::spi::NoMosi),
config,
50.mhz(),
&clocks,
);
spi spi
}; };
@ -342,40 +381,63 @@ const APP: () = {
fp_led_2.set_low().unwrap(); fp_led_2.set_low().unwrap();
fp_led_3.set_low().unwrap(); fp_led_3.set_low().unwrap();
let pounder_devices = { let pounder_devices = {
let ad9959 = { let ad9959 = {
let qspi_interface = { let qspi_interface = {
// Instantiate the QUADSPI pins and peripheral interface. // Instantiate the QUADSPI pins and peripheral interface.
// TODO: Place these into a pins structure that is provided to the QSPI // TODO: Place these into a pins structure that is provided to the QSPI
// constructor. // constructor.
let _qspi_clk = gpiob.pb2.into_alternate_af9().set_speed(hal::gpio::Speed::VeryHigh); let _qspi_clk = gpiob
let _qspi_ncs = gpioc.pc11.into_alternate_af9().set_speed(hal::gpio::Speed::VeryHigh); .pb2
let _qspi_io0 = gpioe.pe7.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh); .into_alternate_af9()
let _qspi_io1 = gpioe.pe8.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh); .set_speed(hal::gpio::Speed::VeryHigh);
let _qspi_io2 = gpioe.pe9.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh); let _qspi_ncs = gpioc
let _qspi_io3 = gpioe.pe10.into_alternate_af10().set_speed(hal::gpio::Speed::VeryHigh); .pc11
.into_alternate_af9()
.set_speed(hal::gpio::Speed::VeryHigh);
let _qspi_io0 = gpioe
.pe7
.into_alternate_af10()
.set_speed(hal::gpio::Speed::VeryHigh);
let _qspi_io1 = gpioe
.pe8
.into_alternate_af10()
.set_speed(hal::gpio::Speed::VeryHigh);
let _qspi_io2 = gpioe
.pe9
.into_alternate_af10()
.set_speed(hal::gpio::Speed::VeryHigh);
let _qspi_io3 = gpioe
.pe10
.into_alternate_af10()
.set_speed(hal::gpio::Speed::VeryHigh);
let qspi = hal::qspi::Qspi::new(dp.QUADSPI, &mut clocks, 10.mhz()).unwrap(); let qspi =
hal::qspi::Qspi::new(dp.QUADSPI, &mut clocks, 10.mhz())
.unwrap();
pounder::QspiInterface::new(qspi).unwrap() pounder::QspiInterface::new(qspi).unwrap()
}; };
let mut reset_pin = gpioa.pa0.into_push_pull_output(); let mut reset_pin = gpioa.pa0.into_push_pull_output();
let io_update = gpiog.pg7.into_push_pull_output(); let io_update = gpiog.pg7.into_push_pull_output();
let asm_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,
))
}; };
ad9959::Ad9959::new(qspi_interface, ad9959::Ad9959::new(
&mut reset_pin, qspi_interface,
io_update, &mut reset_pin,
asm_delay, io_update,
ad9959::Mode::FourBitSerial, asm_delay,
100_000_000f32, ad9959::Mode::FourBitSerial,
5).unwrap() 100_000_000f32,
5,
)
.unwrap()
}; };
let io_expander = { let io_expander = {
@ -386,19 +448,33 @@ const APP: () = {
}; };
let spi = { let spi = {
let spi_mosi = gpiod.pd7.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); let spi_mosi = gpiod
let spi_miso = gpioa.pa6.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); .pd7
let spi_sck = gpiog.pg11.into_alternate_af5().set_speed(hal::gpio::Speed::VeryHigh); .into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let spi_miso = gpioa
.pa6
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let spi_sck = gpiog
.pg11
.into_alternate_af5()
.set_speed(hal::gpio::Speed::VeryHigh);
let config = hal::spi::Config::new(hal::spi::Mode{ let config = hal::spi::Config::new(hal::spi::Mode {
polarity: hal::spi::Polarity::IdleHigh, polarity: hal::spi::Polarity::IdleHigh,
phase: hal::spi::Phase::CaptureOnSecondTransition, phase: hal::spi::Phase::CaptureOnSecondTransition,
}) })
.frame_size(8); .frame_size(8);
// The maximum frequency of this SPI must be limited due to capacitance on the MISO // The maximum frequency of this SPI must be limited due to capacitance on the MISO
// line causing a long RC decay. // line causing a long RC decay.
dp.SPI1.spi((spi_sck, spi_miso, spi_mosi), config, 5.mhz(), &clocks) dp.SPI1.spi(
(spi_sck, spi_miso, spi_mosi),
config,
5.mhz(),
&clocks,
)
}; };
let adc1 = { let adc1 = {
@ -418,13 +494,16 @@ const APP: () = {
let adc1_in_p = gpiof.pf11.into_analog(); let adc1_in_p = gpiof.pf11.into_analog();
let adc2_in_p = gpiof.pf14.into_analog(); let adc2_in_p = gpiof.pf14.into_analog();
pounder::PounderDevices::new(io_expander, pounder::PounderDevices::new(
ad9959, io_expander,
spi, ad9959,
adc1, spi,
adc2, adc1,
adc1_in_p, adc2,
adc2_in_p).unwrap() adc1_in_p,
adc2_in_p,
)
.unwrap()
}; };
let mut eeprom_i2c = { let mut eeprom_i2c = {
@ -440,15 +519,42 @@ const APP: () = {
eth_phy_nrst.set_low().unwrap(); eth_phy_nrst.set_low().unwrap();
delay.delay_us(200u8); delay.delay_us(200u8);
eth_phy_nrst.set_high().unwrap(); eth_phy_nrst.set_high().unwrap();
let _rmii_ref_clk = gpioa.pa1.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); let _rmii_ref_clk = gpioa
let _rmii_mdio = gpioa.pa2.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); .pa1
let _rmii_mdc = gpioc.pc1.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); .into_alternate_af11()
let _rmii_crs_dv = gpioa.pa7.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); .set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_rxd0 = gpioc.pc4.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); let _rmii_mdio = gpioa
let _rmii_rxd1 = gpioc.pc5.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); .pa2
let _rmii_tx_en = gpiob.pb11.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); .into_alternate_af11()
let _rmii_txd0 = gpiob.pb12.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); .set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_txd1 = gpiog.pg14.into_alternate_af11().set_speed(hal::gpio::Speed::VeryHigh); let _rmii_mdc = gpioc
.pc1
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_crs_dv = gpioa
.pa7
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_rxd0 = gpioc
.pc4
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_rxd1 = gpioc
.pc5
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_tx_en = gpiob
.pb11
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_txd0 = gpiob
.pb12
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
let _rmii_txd1 = gpiog
.pg14
.into_alternate_af11()
.set_speed(hal::gpio::Speed::VeryHigh);
} }
let mac_addr = match eeprom::read_eui48(&mut eeprom_i2c) { let mac_addr = match eeprom::read_eui48(&mut eeprom_i2c) {
@ -463,26 +569,31 @@ const APP: () = {
// Configure the ethernet controller // Configure the ethernet controller
let (eth_dma, eth_mac) = unsafe { let (eth_dma, eth_mac) = unsafe {
ethernet::ethernet_init( ethernet::ethernet_init(
dp.ETHERNET_MAC, dp.ETHERNET_MAC,
dp.ETHERNET_MTL, dp.ETHERNET_MTL,
dp.ETHERNET_DMA, dp.ETHERNET_DMA,
&mut DES_RING, &mut DES_RING,
mac_addr.clone()) mac_addr.clone(),
)
}; };
unsafe { ethernet::enable_interrupt() }; unsafe { ethernet::enable_interrupt() };
let store = unsafe { &mut NET_STORE }; let store = unsafe { &mut NET_STORE };
store.ip_addrs[0] = net::wire::IpCidr::new(net::wire::IpAddress::v4(10, 0, 16, 99), 24); store.ip_addrs[0] = net::wire::IpCidr::new(
net::wire::IpAddress::v4(10, 0, 16, 99),
24,
);
let neighbor_cache = net::iface::NeighborCache::new(&mut store.neighbor_cache[..]); let neighbor_cache =
net::iface::NeighborCache::new(&mut store.neighbor_cache[..]);
let interface = net::iface::EthernetInterfaceBuilder::new(eth_dma) let interface = net::iface::EthernetInterfaceBuilder::new(eth_dma)
.ethernet_addr(mac_addr) .ethernet_addr(mac_addr)
.neighbor_cache(neighbor_cache) .neighbor_cache(neighbor_cache)
.ip_addrs(&mut store.ip_addrs[..]) .ip_addrs(&mut store.ip_addrs[..])
.finalize(); .finalize();
(interface, eth_mac) (interface, eth_mac)
}; };
@ -497,15 +608,19 @@ const APP: () = {
cp.DWT.enable_cycle_counter(); cp.DWT.enable_cycle_counter();
let mut dma = hal::dma::Dma::dma(dp.DMA1, dp.DMAMUX1, &clocks); let mut dma = hal::dma::Dma::dma(dp.DMA1, dp.DMAMUX1, &clocks);
dma.configure_m2p_stream(hal::dma::Stream::One, dma.configure_m2p_stream(
&SPI_START_CODE as *const _ as u32, hal::dma::Stream::One,
&adc1_spi.spi.cr1 as *const _ as u32, &SPI_START_CODE as *const _ as u32,
hal::dma::DMAREQ_ID::TIM2_CH1); &adc1_spi.spi.cr1 as *const _ as u32,
hal::dma::DMAREQ_ID::TIM2_CH1,
);
dma.configure_m2p_stream(hal::dma::Stream::Two, dma.configure_m2p_stream(
&SPI_START_CODE as *const _ as u32, hal::dma::Stream::Two,
&adc2_spi.spi.cr1 as *const _ as u32, &SPI_START_CODE as *const _ as u32,
hal::dma::DMAREQ_ID::TIM2_CH2); &adc2_spi.spi.cr1 as *const _ as u32,
hal::dma::DMAREQ_ID::TIM2_CH2,
);
// Configure timer 2 to trigger conversions for the ADC // 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(500.khz(), &mut clocks);
@ -540,11 +655,16 @@ const APP: () = {
let output: u16 = { let output: u16 = {
let a: u16 = c.resources.adc2.read().unwrap(); let a: u16 = c.resources.adc2.read().unwrap();
let x0 = f32::from(a as i16); let x0 = f32::from(a as i16);
let y0 = c.resources.iir_ch[1].update(&mut c.resources.iir_state[1], x0); let y0 =
c.resources.iir_ch[1].update(&mut c.resources.iir_state[1], x0);
y0 as i16 as u16 ^ 0x8000 y0 as i16 as u16 ^ 0x8000
}; };
c.resources.dac2.spi.ifcr.write(|w| w.eotc().set_bit().txtfc().set_bit()); c.resources
.dac2
.spi
.ifcr
.write(|w| w.eotc().set_bit().txtfc().set_bit());
c.resources.dac2.send(output).unwrap(); c.resources.dac2.send(output).unwrap();
} }
@ -555,26 +675,34 @@ const APP: () = {
let output: u16 = { let output: u16 = {
let a: u16 = c.resources.adc1.read().unwrap(); let a: u16 = c.resources.adc1.read().unwrap();
let x0 = f32::from(a as i16); let x0 = f32::from(a as i16);
let y0 = c.resources.iir_ch[0].update(&mut c.resources.iir_state[0], x0); let y0 =
c.resources.iir_ch[0].update(&mut c.resources.iir_state[0], x0);
y0 as i16 as u16 ^ 0x8000 y0 as i16 as u16 ^ 0x8000
}; };
c.resources.dac1.spi.ifcr.write(|w| w.eotc().set_bit().txtfc().set_bit()); c.resources
.dac1
.spi
.ifcr
.write(|w| w.eotc().set_bit().txtfc().set_bit());
c.resources.dac1.send(output).unwrap(); c.resources.dac1.send(output).unwrap();
} }
#[idle(resources=[net_interface, pounder, mac_addr, eth_mac, iir_state, iir_ch, afe1, afe2])] #[idle(resources=[net_interface, pounder, mac_addr, eth_mac, iir_state, iir_ch, afe1, afe2])]
fn idle(mut c: idle::Context) -> ! { fn idle(mut c: idle::Context) -> ! {
let mut socket_set_entries: [_; 8] = Default::default(); let mut socket_set_entries: [_; 8] = Default::default();
let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]); let mut sockets =
net::socket::SocketSet::new(&mut socket_set_entries[..]);
let mut rx_storage = [0; TCP_RX_BUFFER_SIZE]; let mut rx_storage = [0; TCP_RX_BUFFER_SIZE];
let mut tx_storage = [0; TCP_TX_BUFFER_SIZE]; let mut tx_storage = [0; TCP_TX_BUFFER_SIZE];
let tcp_handle = { let tcp_handle = {
let tcp_rx_buffer = net::socket::TcpSocketBuffer::new(&mut rx_storage[..]); let tcp_rx_buffer =
let tcp_tx_buffer = net::socket::TcpSocketBuffer::new(&mut tx_storage[..]); net::socket::TcpSocketBuffer::new(&mut rx_storage[..]);
let tcp_socket = net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); let tcp_tx_buffer =
net::socket::TcpSocketBuffer::new(&mut tx_storage[..]);
let tcp_socket =
net::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
sockets.add(tcp_socket) sockets.add(tcp_socket)
}; };
@ -697,8 +825,10 @@ const APP: () = {
} }
} }
let sleep = match c.resources.net_interface.poll(&mut sockets, let sleep = match c.resources.net_interface.poll(
net::time::Instant::from_millis(time as i64)) { &mut sockets,
net::time::Instant::from_millis(time as i64),
) {
Ok(changed) => changed == false, Ok(changed) => changed == false,
Err(net::Error::Unrecognized) => true, Err(net::Error::Unrecognized) => true,
Err(e) => { Err(e) => {

View File

@ -8,14 +8,17 @@ use super::{Channel, Error};
/// reading the shfit register. The downside of this approach is that any read is destructive, so a /// reading the shfit register. The downside of this approach is that any read is destructive, so a
/// read-writeback approach is employed. /// read-writeback approach is employed.
pub trait AttenuatorInterface { pub trait AttenuatorInterface {
/// Set the attenuation of a single channel. /// Set the attenuation of a single channel.
/// ///
/// Args: /// Args:
/// * `channel` - The pounder channel to configure the attenuation of. /// * `channel` - The pounder channel to configure the attenuation of.
/// * `attenuation` - The desired attenuation of the channel in dB. This has a resolution of /// * `attenuation` - The desired attenuation of the channel in dB. This has a resolution of
/// 0.5dB. /// 0.5dB.
fn set_attenuation(&mut self, channel: Channel, attenuation: f32) -> Result<f32, Error> { fn set_attenuation(
&mut self,
channel: Channel,
attenuation: f32,
) -> Result<f32, Error> {
if attenuation > 31.5 || attenuation < 0.0 { if attenuation > 31.5 || attenuation < 0.0 {
return Err(Error::Bounds); return Err(Error::Bounds);
} }
@ -72,6 +75,12 @@ pub trait AttenuatorInterface {
fn reset_attenuators(&mut self) -> Result<(), Error>; fn reset_attenuators(&mut self) -> Result<(), Error>;
fn latch_attenuators(&mut self, channel: Channel) -> Result<(), Error>; fn latch_attenuators(&mut self, channel: Channel) -> Result<(), Error>;
fn read_all_attenuators(&mut self, channels: &mut [u8; 4]) -> Result<(), Error>; fn read_all_attenuators(
fn write_all_attenuators(&mut self, channels: &[u8; 4]) -> Result<(), Error>; &mut self,
channels: &mut [u8; 4],
) -> Result<(), Error>;
fn write_all_attenuators(
&mut self,
channels: &[u8; 4],
) -> Result<(), Error>;
} }

View File

@ -1,7 +1,7 @@
use mcp23017;
use ad9959; use ad9959;
use mcp23017;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
mod attenuators; mod attenuators;
mod rf_power; mod rf_power;
@ -11,10 +11,7 @@ use super::hal;
use attenuators::AttenuatorInterface; use attenuators::AttenuatorInterface;
use rf_power::PowerMeasurementInterface; use rf_power::PowerMeasurementInterface;
use embedded_hal::{ use embedded_hal::{adc::OneShot, blocking::spi::Transfer};
blocking::spi::Transfer,
adc::OneShot,
};
const EXT_CLK_SEL_PIN: u8 = 8 + 7; const EXT_CLK_SEL_PIN: u8 = 8 + 7;
#[allow(dead_code)] #[allow(dead_code)]
@ -106,8 +103,12 @@ impl QspiInterface {
// This driver only supports operation in 4-bit mode due to bus inconsistencies between the // This driver only supports operation in 4-bit mode due to bus inconsistencies between the
// QSPI peripheral and the DDS. Instead, we will bit-bang communications in // QSPI peripheral and the DDS. Instead, we will bit-bang communications in
// single-bit-two-wire to the DDS to configure it to 4-bit operation. // single-bit-two-wire to the DDS to configure it to 4-bit operation.
qspi.configure_mode(hal::qspi::QspiMode::FourBit).map_err(|_| Error::Qspi)?; qspi.configure_mode(hal::qspi::QspiMode::FourBit)
Ok(Self { qspi: qspi, mode: ad9959::Mode::SingleBitTwoWire }) .map_err(|_| Error::Qspi)?;
Ok(Self {
qspi: qspi,
mode: ad9959::Mode::SingleBitTwoWire,
})
} }
} }
@ -189,7 +190,9 @@ impl ad9959::Interface for QspiInterface {
let byte_position = 3 - (bit >> 1) as usize; let byte_position = 3 - (bit >> 1) as usize;
if byte & (1 << bit) != 0 { if byte & (1 << bit) != 0 {
encoded_data[(byte_index + 1) * 4 + byte_position] |= 1 << offset; encoded_data
[(byte_index + 1) * 4 + byte_position] |=
1 << offset;
} }
} }
} }
@ -199,14 +202,14 @@ impl ad9959::Interface for QspiInterface {
(encoded_data[0], &encoded_data[1..end_index]) (encoded_data[0], &encoded_data[1..end_index])
}; };
self.qspi.write(encoded_address, &encoded_payload).map_err(|_| Error::Qspi) self.qspi
}, .write(encoded_address, &encoded_payload)
.map_err(|_| Error::Qspi)
}
ad9959::Mode::FourBitSerial => { ad9959::Mode::FourBitSerial => {
self.qspi.write(addr, &data).map_err(|_| Error::Qspi) self.qspi.write(addr, &data).map_err(|_| Error::Qspi)
},
_ => {
Err(Error::Qspi)
} }
_ => Err(Error::Qspi),
} }
} }
@ -220,15 +223,19 @@ impl ad9959::Interface for QspiInterface {
return Err(Error::Qspi); return Err(Error::Qspi);
} }
self.qspi.read(0x80_u8 | addr, &mut dest).map_err(|_| Error::Qspi) self.qspi
.read(0x80_u8 | addr, &mut dest)
.map_err(|_| Error::Qspi)
} }
} }
/// A structure containing implementation for Pounder hardware. /// A structure containing implementation for Pounder hardware.
pub struct PounderDevices<DELAY> { pub struct PounderDevices<DELAY> {
pub ad9959: ad9959::Ad9959<QspiInterface, pub ad9959: ad9959::Ad9959<
DELAY, QspiInterface,
hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>>, DELAY,
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>, adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
@ -250,17 +257,19 @@ where
/// * `adc2` - The ADC2 peripheral for measuring power. /// * `adc2` - The ADC2 peripheral for measuring power.
/// * `adc1_in_p` - The input channel for the RF power measurement on IN0. /// * `adc1_in_p` - The input channel for the RF power measurement on IN0.
/// * `adc2_in_p` - The input channel for the RF power measurement on IN1. /// * `adc2_in_p` - The input channel for the RF power measurement on IN1.
pub fn new(mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>, pub fn new(
ad9959: ad9959::Ad9959<QspiInterface, mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
DELAY, ad9959: ad9959::Ad9959<
hal::gpio::gpiog::PG7< QspiInterface,
hal::gpio::Output<hal::gpio::PushPull>>>, DELAY,
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>, hal::gpio::gpiog::PG7<hal::gpio::Output<hal::gpio::PushPull>>,
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>, >,
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>, attenuator_spi: hal::spi::Spi<hal::stm32::SPI1>,
adc1_in_p: hal::gpio::gpiof::PF11<hal::gpio::Analog>, adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
adc2_in_p: hal::gpio::gpiof::PF14<hal::gpio::Analog>, adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
) -> Result<Self, Error> { 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,
@ -274,9 +283,18 @@ where
// 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
// selected, attenuators out of reset. Note that testing indicates the output state needs to // selected, attenuators out of reset. Note that testing indicates the output state needs to
// be set first to properly update the output registers. // be set first to properly update the output registers.
devices.mcp23017.all_pin_mode(mcp23017::PinMode::OUTPUT).map_err(|_| Error::I2c)?; devices
devices.mcp23017.write_gpio(mcp23017::Port::GPIOA, 0x3F).map_err(|_| Error::I2c)?; .mcp23017
devices.mcp23017.write_gpio(mcp23017::Port::GPIOB, 1 << 5).map_err(|_| Error::I2c)?; .all_pin_mode(mcp23017::PinMode::OUTPUT)
.map_err(|_| Error::I2c)?;
devices
.mcp23017
.write_gpio(mcp23017::Port::GPIOA, 0x3F)
.map_err(|_| Error::I2c)?;
devices
.mcp23017
.write_gpio(mcp23017::Port::GPIOB, 1 << 5)
.map_err(|_| Error::I2c)?;
// Select the on-board clock with a 4x prescaler (400MHz). // Select the on-board clock with a 4x prescaler (400MHz).
devices.select_onboard_clock(4u8)?; devices.select_onboard_clock(4u8)?;
@ -289,9 +307,17 @@ where
/// Args: /// Args:
/// * `frequency` - The frequency of the external clock source. /// * `frequency` - The frequency of the external clock source.
/// * `multiplier` - The multiplier of the reference clock to use in the DDS. /// * `multiplier` - The multiplier of the reference clock to use in the DDS.
fn select_external_clock(&mut self, frequency: f32, prescaler: u8) -> Result<(), Error>{ fn select_external_clock(
self.mcp23017.digital_write(EXT_CLK_SEL_PIN, true).map_err(|_| Error::I2c)?; &mut self,
self.ad9959.configure_system_clock(frequency, prescaler).map_err(|_| Error::Dds)?; frequency: f32,
prescaler: u8,
) -> Result<(), Error> {
self.mcp23017
.digital_write(EXT_CLK_SEL_PIN, true)
.map_err(|_| Error::I2c)?;
self.ad9959
.configure_system_clock(frequency, prescaler)
.map_err(|_| Error::Dds)?;
Ok(()) Ok(())
} }
@ -301,8 +327,12 @@ where
/// Args: /// Args:
/// * `multiplier` - The multiplier of the reference clock to use in the DDS. /// * `multiplier` - The multiplier of the reference clock to use in the DDS.
fn select_onboard_clock(&mut self, multiplier: u8) -> Result<(), Error> { fn select_onboard_clock(&mut self, multiplier: u8) -> Result<(), Error> {
self.mcp23017.digital_write(EXT_CLK_SEL_PIN, false).map_err(|_| Error::I2c)?; self.mcp23017
self.ad9959.configure_system_clock(100_000_000f32, multiplier).map_err(|_| Error::Dds)?; .digital_write(EXT_CLK_SEL_PIN, false)
.map_err(|_| Error::I2c)?;
self.ad9959
.configure_system_clock(100_000_000f32, multiplier)
.map_err(|_| Error::Dds)?;
Ok(()) Ok(())
} }
@ -311,9 +341,15 @@ where
/// ///
/// Args: /// Args:
/// * `config` - The configuration of the DDS clock desired. /// * `config` - The configuration of the DDS clock desired.
pub fn configure_dds_clock(&mut self, config: DdsClockConfig) -> Result<(), Error> { pub fn configure_dds_clock(
&mut self,
config: DdsClockConfig,
) -> Result<(), Error> {
if config.external_clock { if config.external_clock {
self.select_external_clock(config.reference_clock, config.multiplier) self.select_external_clock(
config.reference_clock,
config.multiplier,
)
} else { } else {
self.select_onboard_clock(config.multiplier) self.select_onboard_clock(config.multiplier)
} }
@ -324,11 +360,21 @@ where
/// Returns: /// Returns:
/// The current pounder DDS clock configuration. /// The current pounder DDS clock configuration.
pub fn get_dds_clock_config(&mut self) -> Result<DdsClockConfig, Error> { pub fn get_dds_clock_config(&mut self) -> Result<DdsClockConfig, Error> {
let external_clock = self.mcp23017.digital_read(EXT_CLK_SEL_PIN).map_err(|_| Error::I2c)?; let external_clock = self
let multiplier = self.ad9959.get_reference_clock_multiplier().map_err(|_| Error::Dds)?; .mcp23017
.digital_read(EXT_CLK_SEL_PIN)
.map_err(|_| Error::I2c)?;
let multiplier = self
.ad9959
.get_reference_clock_multiplier()
.map_err(|_| Error::Dds)?;
let reference_clock = self.ad9959.get_reference_clock_frequency(); let reference_clock = self.ad9959.get_reference_clock_frequency();
Ok(DdsClockConfig{multiplier, reference_clock, external_clock}) Ok(DdsClockConfig {
multiplier,
reference_clock,
external_clock,
})
} }
/// Get the state of a Pounder input channel. /// Get the state of a Pounder input channel.
@ -338,7 +384,10 @@ where
/// ///
/// Returns: /// Returns:
/// The read-back channel input state. /// The read-back channel input state.
pub fn get_input_channel_state(&mut self, channel: Channel) -> Result<InputChannelState, Error> { pub fn get_input_channel_state(
&mut self,
channel: Channel,
) -> Result<InputChannelState, Error> {
match channel { match channel {
Channel::In0 | Channel::In1 => { Channel::In0 | Channel::In1 => {
let channel_state = self.get_dds_channel_state(channel)?; let channel_state = self.get_dds_channel_state(channel)?;
@ -349,7 +398,7 @@ where
Ok(InputChannelState { Ok(InputChannelState {
attenuation: attenuation, attenuation: attenuation,
power: power, power: power,
mixer: channel_state mixer: channel_state,
}) })
} }
_ => Err(Error::InvalidChannel), _ => Err(Error::InvalidChannel),
@ -363,13 +412,33 @@ where
/// ///
/// Returns: /// Returns:
/// The read-back channel state. /// The read-back channel state.
fn get_dds_channel_state(&mut self, channel: Channel) -> Result<DdsChannelState, Error> { fn get_dds_channel_state(
let frequency = self.ad9959.get_frequency(channel.into()).map_err(|_| Error::Dds)?; &mut self,
let phase_offset = self.ad9959.get_phase(channel.into()).map_err(|_| Error::Dds)?; channel: Channel,
let amplitude = self.ad9959.get_amplitude(channel.into()).map_err(|_| Error::Dds)?; ) -> Result<DdsChannelState, Error> {
let enabled = self.ad9959.is_enabled(channel.into()).map_err(|_| Error::Dds)?; let frequency = self
.ad9959
.get_frequency(channel.into())
.map_err(|_| Error::Dds)?;
let phase_offset = self
.ad9959
.get_phase(channel.into())
.map_err(|_| Error::Dds)?;
let amplitude = self
.ad9959
.get_amplitude(channel.into())
.map_err(|_| Error::Dds)?;
let enabled = self
.ad9959
.is_enabled(channel.into())
.map_err(|_| Error::Dds)?;
Ok(DdsChannelState {phase_offset, frequency, amplitude, enabled}) Ok(DdsChannelState {
phase_offset,
frequency,
amplitude,
enabled,
})
} }
/// Get the state of a DDS output channel. /// Get the state of a DDS output channel.
@ -379,7 +448,10 @@ where
/// ///
/// Returns: /// Returns:
/// The read-back output channel state. /// The read-back output channel state.
pub fn get_output_channel_state(&mut self, channel: Channel) -> Result<OutputChannelState, Error> { pub fn get_output_channel_state(
&mut self,
channel: Channel,
) -> Result<OutputChannelState, Error> {
match channel { match channel {
Channel::Out0 | Channel::Out1 => { Channel::Out0 | Channel::Out1 => {
let channel_state = self.get_dds_channel_state(channel)?; let channel_state = self.get_dds_channel_state(channel)?;
@ -399,15 +471,29 @@ where
/// Args: /// Args:
/// * `channel` - The pounder channel to configure. /// * `channel` - The pounder channel to configure.
/// * `state` - The state to configure the channel for. /// * `state` - The state to configure the channel for.
pub fn set_channel_state(&mut self, channel: Channel, state: ChannelState) -> Result<(), Error> { pub fn set_channel_state(
self.ad9959.set_frequency(channel.into(), state.parameters.frequency).map_err(|_| Error::Dds)?; &mut self,
self.ad9959.set_phase(channel.into(), state.parameters.phase_offset).map_err(|_| Error::Dds)?; channel: Channel,
self.ad9959.set_amplitude(channel.into(), state.parameters.amplitude).map_err(|_| Error::Dds)?; 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)?;
if state.parameters.enabled { if state.parameters.enabled {
self.ad9959.enable_channel(channel.into()).map_err(|_| Error::Dds)?; self.ad9959
.enable_channel(channel.into())
.map_err(|_| Error::Dds)?;
} else { } else {
self.ad9959.disable_channel(channel.into()).map_err(|_| Error::Dds)?; self.ad9959
.disable_channel(channel.into())
.map_err(|_| Error::Dds)?;
} }
self.set_attenuation(channel, state.attenuation)?; self.set_attenuation(channel, state.attenuation)?;
@ -416,14 +502,17 @@ where
} }
} }
impl<DELAY> AttenuatorInterface for PounderDevices<DELAY> impl<DELAY> AttenuatorInterface for PounderDevices<DELAY> {
{
/// Reset all of the attenuators to a power-on default state. /// Reset all of the attenuators to a power-on default state.
fn reset_attenuators(&mut self) -> Result<(), Error> { fn reset_attenuators(&mut self) -> Result<(), Error> {
self.mcp23017.digital_write(ATT_RST_N_PIN, false).map_err(|_| Error::I2c)?; self.mcp23017
.digital_write(ATT_RST_N_PIN, false)
.map_err(|_| Error::I2c)?;
// TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is // TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is
// sufficient. Document the delay here. // sufficient. Document the delay here.
self.mcp23017.digital_write(ATT_RST_N_PIN, true).map_err(|_| Error::I2c)?; self.mcp23017
.digital_write(ATT_RST_N_PIN, true)
.map_err(|_| Error::I2c)?;
Ok(()) Ok(())
} }
@ -440,10 +529,14 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
Channel::Out1 => ATT_LE3_PIN, Channel::Out1 => ATT_LE3_PIN,
}; };
self.mcp23017.digital_write(pin, true).map_err(|_| Error::I2c)?; self.mcp23017
.digital_write(pin, true)
.map_err(|_| Error::I2c)?;
// TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is // TODO: Measure the I2C transaction speed to the RST pin to ensure that the delay is
// sufficient. Document the delay here. // sufficient. Document the delay here.
self.mcp23017.digital_write(pin, false).map_err(|_| Error::I2c)?; self.mcp23017
.digital_write(pin, false)
.map_err(|_| Error::I2c)?;
Ok(()) Ok(())
} }
@ -452,8 +545,13 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
/// ///
/// Args: /// Args:
/// * `channels` - A slice to store the channel readings into. /// * `channels` - A slice to store the channel readings into.
fn read_all_attenuators(&mut self, channels: &mut [u8; 4]) -> Result<(), Error> { fn read_all_attenuators(
self.attenuator_spi.transfer(channels).map_err(|_| Error::Spi)?; &mut self,
channels: &mut [u8; 4],
) -> Result<(), Error> {
self.attenuator_spi
.transfer(channels)
.map_err(|_| Error::Spi)?;
Ok(()) Ok(())
} }
@ -462,10 +560,15 @@ impl<DELAY> AttenuatorInterface for PounderDevices<DELAY>
/// ///
/// Args: /// Args:
/// * `channels` - The data to write into the attenuators. /// * `channels` - The data to write into the attenuators.
fn write_all_attenuators(&mut self, channels: &[u8; 4]) -> Result<(), Error> { fn write_all_attenuators(
&mut self,
channels: &[u8; 4],
) -> Result<(), Error> {
let mut result = [0_u8; 4]; let mut result = [0_u8; 4];
result.clone_from_slice(channels); result.clone_from_slice(channels);
self.attenuator_spi.transfer(&mut result).map_err(|_| Error::Spi)?; self.attenuator_spi
.transfer(&mut result)
.map_err(|_| Error::Spi)?;
Ok(()) Ok(())
} }
@ -482,13 +585,19 @@ impl<DELAY> PowerMeasurementInterface for PounderDevices<DELAY> {
fn sample_converter(&mut self, channel: Channel) -> Result<f32, Error> { fn sample_converter(&mut self, channel: Channel) -> Result<f32, Error> {
let adc_scale = match channel { let adc_scale = match channel {
Channel::In0 => { Channel::In0 => {
let adc_reading: u32 = self.adc1.read(&mut self.adc1_in_p).map_err(|_| Error::Adc)?; 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 adc_reading as f32 / self.adc1.max_sample() as f32
}, }
Channel::In1 => { Channel::In1 => {
let adc_reading: u32 = self.adc2.read(&mut self.adc2_in_p).map_err(|_| Error::Adc)?; 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 adc_reading as f32 / self.adc2.max_sample() as f32
}, }
_ => return Err(Error::InvalidChannel), _ => return Err(Error::InvalidChannel),
}; };

View File

@ -1,4 +1,4 @@
use super::{Error, Channel}; use super::{Channel, Error};
/// Provide an interface to measure RF input power in dB. /// Provide an interface to measure RF input power in dB.
pub trait PowerMeasurementInterface { pub trait PowerMeasurementInterface {

View File

@ -1,24 +1,13 @@
use heapless::{ use heapless::{consts::*, String, Vec};
consts::*,
String,
Vec
};
use core::fmt::Write; use core::fmt::Write;
use serde::{Deserialize, Serialize};
use serde::{ use serde_json_core::{de::from_slice, ser::to_string};
Deserialize,
Serialize
};
use serde_json_core::{
de::from_slice,
ser::to_string
};
use super::net;
use super::iir; use super::iir;
use super::net;
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub enum AccessRequest { pub enum AccessRequest {
@ -62,7 +51,6 @@ impl<'a> Request<'a> {
} }
impl Response { impl Response {
/// Remove all double quotation marks from the `value` field of a response. /// Remove all double quotation marks from the `value` field of a response.
fn sanitize_value(&mut self) { fn sanitize_value(&mut self) {
let mut new_value: String<U256> = String::new(); let mut new_value: String<U256> = String::new();
@ -101,9 +89,12 @@ impl Response {
/// Args: /// Args:
/// * `attrbute` - The attribute of the success. /// * `attrbute` - The attribute of the success.
/// * `value` - The value of the attribute. /// * `value` - The value of the attribute.
pub fn success<'a, 'b>(attribute: &'a str, value: &'b str) -> Self pub fn success<'a, 'b>(attribute: &'a str, value: &'b str) -> Self {
{ let mut res = Self {
let mut res = Self { code: 200, attribute: String::from(attribute), value: String::from(value)}; code: 200,
attribute: String::from(attribute),
value: String::from(value),
};
res.sanitize_value(); res.sanitize_value();
res res
} }
@ -115,9 +106,12 @@ impl Response {
/// Args: /// Args:
/// * `attrbute` - The attribute of the success. /// * `attrbute` - The attribute of the success.
/// * `message` - The message denoting the error. /// * `message` - The message denoting the error.
pub fn error<'a, 'b>(attribute: &'a str, message: &'b str) -> Self pub fn error<'a, 'b>(attribute: &'a str, message: &'b str) -> Self {
{ let mut res = Self {
let mut res = Self { code: 400, attribute: String::from(attribute), value: String::from(message)}; code: 400,
attribute: String::from(attribute),
value: String::from(message),
};
res.wrap_and_sanitize_value(); res.wrap_and_sanitize_value();
res res
} }
@ -129,9 +123,12 @@ impl Response {
/// Args: /// Args:
/// * `attrbute` - The attribute of the success. /// * `attrbute` - The attribute of the success.
/// * `message` - The message denoting the status. /// * `message` - The message denoting the status.
pub fn custom<'a>(code: i32, message : &'a str) -> Self pub fn custom<'a>(code: i32, message: &'a str) -> Self {
{ let mut res = Self {
let mut res = Self { code: code, attribute: String::from(""), value: String::from(message)}; code: code,
attribute: String::from(""),
value: String::from(message),
};
res.wrap_and_sanitize_value(); res.wrap_and_sanitize_value();
res res
} }
@ -171,36 +168,39 @@ impl Server {
/// Args: /// Args:
/// * `socket` - The socket to check contents from. /// * `socket` - The socket to check contents from.
/// * `f` - A closure that can be called if a request has been received on the server. /// * `f` - A closure that can be called if a request has been received on the server.
pub fn poll<F>( pub fn poll<F>(&mut self, socket: &mut net::socket::TcpSocket, mut f: F)
&mut self,
socket: &mut net::socket::TcpSocket,
mut f: F,
)
where where
F: FnMut(&Request) -> Response F: FnMut(&Request) -> Response,
{ {
while socket.can_recv() { while socket.can_recv() {
let found = socket.recv(|buf| { let found = socket
let (len, found) = .recv(|buf| {
match buf.iter().position(|&c| c as char == '\n') { let (len, found) =
Some(end) => (end + 1, true), match buf.iter().position(|&c| c as char == '\n') {
None => (buf.len(), false), Some(end) => (end + 1, true),
}; None => (buf.len(), false),
if self.data.len() + len >= self.data.capacity() { };
self.discard = true; if self.data.len() + len >= self.data.capacity() {
self.data.clear(); self.discard = true;
} else if !self.discard && len > 0 { self.data.clear();
self.data.extend_from_slice(&buf[..len]).unwrap(); } else if !self.discard && len > 0 {
} self.data.extend_from_slice(&buf[..len]).unwrap();
(len, found) }
}).unwrap(); (len, found)
})
.unwrap();
if found { if found {
if self.discard { if self.discard {
self.discard = false; self.discard = false;
json_reply(socket, &Response::custom(520, "command buffer overflow")); json_reply(
socket,
&Response::custom(520, "command buffer overflow"),
);
} else { } else {
let r = from_slice::<Request>(&self.data[..self.data.len() - 1]); let r = from_slice::<Request>(
&self.data[..self.data.len() - 1],
);
match r { match r {
Ok(mut res) => { Ok(mut res) => {
// Note that serde_json_core doesn't escape quotations within a string. // Note that serde_json_core doesn't escape quotations within a string.
@ -210,10 +210,13 @@ impl Server {
res.restore_value(); res.restore_value();
let response = f(&res); let response = f(&res);
json_reply(socket, &response); json_reply(socket, &response);
}, }
Err(err) => { Err(err) => {
warn!("parse error {:?}", err); warn!("parse error {:?}", err);
json_reply(socket, &Response::custom(550, "parse error")); json_reply(
socket,
&Response::custom(550, "parse error"),
);
} }
} }
} }
@ -222,4 +225,3 @@ impl Server {
} }
} }
} }