Refactoring AD9959 errors
This commit is contained in:
parent
67b7dbcb70
commit
58bd61afd5
@ -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)?;
|
||||
|
Loading…
Reference in New Issue
Block a user