Refactoring AD9959 errors

This commit is contained in:
Ryan Summers 2020-06-11 18:02:01 +02:00
parent 67b7dbcb70
commit 58bd61afd5
1 changed files with 46 additions and 55 deletions

View File

@ -85,23 +85,17 @@ pub enum Channel {
/// Possible errors generated by the AD9959 driver. /// Possible errors generated by the AD9959 driver.
#[derive(Debug)] #[derive(Debug)]
pub enum Error<InterfaceE> { pub enum Error {
Interface(InterfaceE), Interface,
Check, Check,
Bounds, Bounds,
Pin, Pin,
Frequency, Frequency,
} }
impl <InterfaceE> From<InterfaceE> for Error<InterfaceE> { impl <PinE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
fn from(interface_error: InterfaceE) -> Self {
Error::Interface(interface_error)
}
}
impl <PinE, InterfaceE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
where where
INTERFACE: Interface<Error = InterfaceE>, INTERFACE: Interface,
DELAY: DelayMs<u8>, DELAY: DelayMs<u8>,
UPDATE: OutputPin<Error = PinE>, UPDATE: OutputPin<Error = PinE>,
@ -123,7 +117,7 @@ where
delay: DELAY, delay: DELAY,
desired_mode: Mode, desired_mode: Mode,
clock_frequency: f32, clock_frequency: f32,
multiplier: u8) -> Result<Self, Error<InterfaceE>> multiplier: u8) -> Result<Self, Error>
where where
RST: OutputPin, RST: OutputPin,
{ {
@ -145,24 +139,21 @@ where
reset_pin.set_low().or_else(|_| Err(Error::Pin))?; reset_pin.set_low().or_else(|_| Err(Error::Pin))?;
ad9959.interface.configure_mode(Mode::SingleBitTwoWire)?; 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)?; ad9959.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
// Configure the interface to the desired mode.
ad9959.interface.configure_mode(Mode::FourBitSerial)?;
// 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)?; 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)?; 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);
} }
@ -173,7 +164,7 @@ 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<InterfaceE>> { 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.
@ -193,7 +184,7 @@ where
/// 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(&mut self,
reference_clock_frequency: f32, reference_clock_frequency: f32,
multiplier: u8) -> Result<f64, Error<InterfaceE>> multiplier: u8) -> Result<f64, Error>
{ {
self.reference_clock_frequency = reference_clock_frequency; self.reference_clock_frequency = reference_clock_frequency;
@ -208,13 +199,13 @@ where
// 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)?; 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)?; 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())
@ -226,9 +217,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<InterfaceE>> { 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)?; 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)
} }
@ -240,36 +231,36 @@ where
/// ///
/// Returns: /// Returns:
/// 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<InterfaceE>> { 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)?; 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)?; 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)?; 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)?; 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)?; 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)?; self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(true) Ok(true)
} }
@ -280,29 +271,29 @@ where
} }
/// Enable an output channel. /// Enable an output channel.
pub fn enable_channel(&mut self, channel: Channel) -> Result<(), Error<InterfaceE>> { 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)?; 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)?; self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
/// Disable an output channel. /// Disable an output channel.
pub fn disable_channel(&mut self, channel: Channel) -> Result<(), Error<InterfaceE>> { 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)?; 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)?; self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
/// 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<InterfaceE>> { 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)?; 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))
} }
@ -313,24 +304,24 @@ 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<InterfaceE>> { 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)?; 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)?; self.interface.write(Register::CSR as u8, &new_csr).map_err(|_| Error::Interface)?;
self.interface.write(register as u8, &data)?; 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)?; self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
@ -341,23 +332,23 @@ 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<InterfaceE>> { 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)?; 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)?; self.interface.write(Register::CSR as u8, &new_csr).map_err(|_| Error::Interface)?;
self.interface.read(register as u8, &mut data)?; 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)?; self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(()) Ok(())
} }
@ -370,7 +361,7 @@ 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<InterfaceE>> { pub fn set_phase(&mut self, channel: Channel, phase_turns: f32) -> Result<f32, Error> {
let phase_offset: u16 = (phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16; 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())?;
@ -385,7 +376,7 @@ where
/// ///
/// Returns: /// Returns:
/// The phase of the channel in turns. /// The phase of the channel in turns.
pub fn get_phase(&mut self, channel: Channel) -> Result<f32, Error<InterfaceE>> { pub fn get_phase(&mut self, channel: Channel) -> Result<f32, Error> {
let mut phase_offset: [u8; 2] = [0; 2]; let mut phase_offset: [u8; 2] = [0; 2];
self.read_channel(channel, Register::CPOW0, &mut phase_offset)?; self.read_channel(channel, Register::CPOW0, &mut phase_offset)?;
@ -402,7 +393,7 @@ 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<InterfaceE>> { 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);
} }
@ -436,7 +427,7 @@ where
/// ///
/// Returns: /// Returns:
/// The normalized amplitude of the channel. /// The normalized amplitude of the channel.
pub fn get_amplitude(&mut self, channel: Channel) -> Result<f32, Error<InterfaceE>> { pub fn get_amplitude(&mut self, channel: Channel) -> Result<f32, Error> {
let mut acr: [u8; 3] = [0; 3]; let mut acr: [u8; 3] = [0; 3];
self.read_channel(channel, Register::ACR, &mut acr)?; self.read_channel(channel, Register::ACR, &mut acr)?;
@ -456,7 +447,7 @@ 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<InterfaceE>> { 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);
} }
@ -477,7 +468,7 @@ where
/// ///
/// Returns: /// Returns:
/// The frequency of the channel in Hz. /// The frequency of the channel in Hz.
pub fn get_frequency(&mut self, channel: Channel) -> Result<f64, Error<InterfaceE>> { pub fn get_frequency(&mut self, channel: Channel) -> Result<f64, Error> {
// Read the frequency tuning word for the channel. // Read the frequency tuning word for the channel.
let mut tuning_word: [u8; 4] = [0; 4]; let mut tuning_word: [u8; 4] = [0; 4];
self.read_channel(channel, Register::CFTW0, &mut tuning_word)?; self.read_channel(channel, Register::CFTW0, &mut tuning_word)?;