Refactoring AD9959 errors

master
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.
#[derive(Debug)]
pub enum Error<InterfaceE> {
Interface(InterfaceE),
pub enum Error {
Interface,
Check,
Bounds,
Pin,
Frequency,
}
impl <InterfaceE> From<InterfaceE> for Error<InterfaceE> {
fn from(interface_error: InterfaceE) -> Self {
Error::Interface(interface_error)
}
}
impl <PinE, InterfaceE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
impl <PinE, INTERFACE, DELAY, UPDATE> Ad9959<INTERFACE, DELAY, UPDATE>
where
INTERFACE: Interface<Error = InterfaceE>,
INTERFACE: Interface,
DELAY: DelayMs<u8>,
UPDATE: OutputPin<Error = PinE>,
@ -123,7 +117,7 @@ where
delay: DELAY,
desired_mode: Mode,
clock_frequency: f32,
multiplier: u8) -> Result<Self, Error<InterfaceE>>
multiplier: u8) -> Result<Self, Error>
where
RST: OutputPin,
{
@ -145,24 +139,21 @@ where
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.
let mut csr: [u8; 1] = [0xF0];
csr[0].set_bits(1..3, desired_mode as u8);
ad9959.interface.write(Register::CSR as u8, &csr)?;
// Configure the interface to the desired mode.
ad9959.interface.configure_mode(Mode::FourBitSerial)?;
ad9959.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
// Latch the configuration registers to make them active.
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.
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] {
return Err(Error::Check);
}
@ -173,7 +164,7 @@ where
}
/// 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))?;
// 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.
@ -193,7 +184,7 @@ where
/// The actual frequency configured for the internal system clock.
pub fn configure_system_clock(&mut self,
reference_clock_frequency: f32,
multiplier: u8) -> Result<f64, Error<InterfaceE>>
multiplier: u8) -> Result<f64, Error>
{
self.reference_clock_frequency = reference_clock_frequency;
@ -208,13 +199,13 @@ where
// TODO: Update / disable any enabled channels?
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);
let vco_range = frequency > 255e6;
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;
Ok(self.system_clock_frequency())
@ -226,9 +217,9 @@ where
}
/// 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];
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)
}
@ -240,36 +231,36 @@ where
///
/// Returns:
/// 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];
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];
// Enable all channels.
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.
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 {
return Ok(false);
}
// Clear all channel enables.
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.
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 {
return Ok(false);
}
// Restore the 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)
}
@ -280,29 +271,29 @@ where
}
/// 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];
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);
self.interface.write(Register::CSR as u8, &csr)?;
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(())
}
/// 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];
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);
self.interface.write(Register::CSR as u8, &csr)?;
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(())
}
/// 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];
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))
}
@ -313,24 +304,24 @@ where
/// * `channel` - The channel to configure.
/// * `register` - The register to update.
/// * `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
// specified channel.
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;
new_csr[0].set_bits(4..8, 0);
new_csr[0].set_bit(4 + channel as usize, true);
self.interface.write(Register::CSR as u8, &new_csr)?;
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
// channel happens immediately, so the CSR update does not need to be latched.
self.latch_configuration()?;
self.interface.write(Register::CSR as u8, &csr)?;
self.interface.write(Register::CSR as u8, &csr).map_err(|_| Error::Interface)?;
Ok(())
}
@ -341,23 +332,23 @@ where
/// * `channel` - The channel to read.
/// * `register` - The register to read.
/// * `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
// only the desired channel.
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;
new_csr[0].set_bits(4..8, 0);
new_csr[0].set_bit(4 + channel as usize, true);
self.interface.write(Register::CSR as u8, &new_csr)?;
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
// 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(())
}
@ -370,7 +361,7 @@ where
///
/// Returns:
/// 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;
self.modify_channel(channel, Register::CPOW0, &phase_offset.to_be_bytes())?;
@ -385,7 +376,7 @@ where
///
/// Returns:
/// 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];
self.read_channel(channel, Register::CPOW0, &mut phase_offset)?;
@ -402,7 +393,7 @@ where
///
/// Returns:
/// 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 {
return Err(Error::Bounds);
}
@ -436,7 +427,7 @@ where
///
/// Returns:
/// 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];
self.read_channel(channel, Register::ACR, &mut acr)?;
@ -456,7 +447,7 @@ where
///
/// Returns:
/// 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() {
return Err(Error::Bounds);
}
@ -477,7 +468,7 @@ where
///
/// Returns:
/// 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.
let mut tuning_word: [u8; 4] = [0; 4];
self.read_channel(channel, Register::CFTW0, &mut tuning_word)?;