Adding WIP experimental code
This commit is contained in:
parent
db182b923d
commit
071ccd17dc
|
@ -462,7 +462,7 @@ dependencies = [
|
||||||
"serde-json-core",
|
"serde-json-core",
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
"stm32h7-ethernet",
|
"stm32h7-ethernet",
|
||||||
"stm32h7xx-hal 0.5.0 (git+https://github.com/quartiq/stm32h7xx-hal.git?branch=feature/pounder-support)",
|
"stm32h7xx-hal 0.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -497,7 +497,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stm32h7xx-hal"
|
name = "stm32h7xx-hal"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/quartiq/stm32h7xx-hal.git?branch=feature/pounder-support#ff00e938f2b226211c178f26c092f36462c44404"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bare-metal",
|
"bare-metal",
|
||||||
"cast",
|
"cast",
|
||||||
|
|
|
@ -59,8 +59,9 @@ features = ["stm32h743v"]
|
||||||
|
|
||||||
[dependencies.stm32h7xx-hal]
|
[dependencies.stm32h7xx-hal]
|
||||||
features = ["stm32h743v", "rt", "unproven"]
|
features = ["stm32h743v", "rt", "unproven"]
|
||||||
git = "https://github.com/quartiq/stm32h7xx-hal.git"
|
# git = "https://github.com/quartiq/stm32h7xx-hal.git"
|
||||||
branch = "feature/pounder-support"
|
# branch = "feature/pounder-support"
|
||||||
|
path = "../stm32h7xx-hal"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
||||||
|
|
|
@ -14,11 +14,12 @@ use embedded_hal::{blocking::delay::DelayMs, digital::v2::OutputPin};
|
||||||
/// The chip supports a number of serial interfaces to improve data throughput, including normal,
|
/// The chip supports a number of serial interfaces to improve data throughput, including normal,
|
||||||
/// dual, and quad SPI configurations.
|
/// dual, and quad SPI configurations.
|
||||||
pub struct Ad9959<INTERFACE, DELAY, UPDATE> {
|
pub struct Ad9959<INTERFACE, DELAY, UPDATE> {
|
||||||
interface: INTERFACE,
|
pub interface: INTERFACE,
|
||||||
delay: DELAY,
|
delay: DELAY,
|
||||||
reference_clock_frequency: f32,
|
reference_clock_frequency: f32,
|
||||||
system_clock_multiplier: u8,
|
system_clock_multiplier: u8,
|
||||||
io_update: UPDATE,
|
io_update: UPDATE,
|
||||||
|
communication_mode: Mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait that allows a HAL to provide a means of communicating with the AD9959.
|
/// A trait that allows a HAL to provide a means of communicating with the AD9959.
|
||||||
|
@ -30,6 +31,8 @@ pub trait Interface {
|
||||||
fn write(&mut self, addr: u8, data: &[u8]) -> Result<(), Self::Error>;
|
fn write(&mut self, addr: u8, data: &[u8]) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
fn read(&mut self, addr: u8, dest: &mut [u8]) -> Result<(), Self::Error>;
|
fn read(&mut self, addr: u8, dest: &mut [u8]) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
fn write_profile(&mut self, data: [u32; 4]) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates various communication modes of the DDS. The value of this enumeration is equivalent to
|
/// Indicates various communication modes of the DDS. The value of this enumeration is equivalent to
|
||||||
|
@ -125,6 +128,7 @@ where
|
||||||
delay,
|
delay,
|
||||||
reference_clock_frequency: clock_frequency,
|
reference_clock_frequency: clock_frequency,
|
||||||
system_clock_multiplier: 1,
|
system_clock_multiplier: 1,
|
||||||
|
communication_mode: desired_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
ad9959.io_update.set_low().or_else(|_| Err(Error::Pin))?;
|
ad9959.io_update.set_low().or_else(|_| Err(Error::Pin))?;
|
||||||
|
@ -176,7 +180,8 @@ 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> {
|
pub fn latch_configuration(&mut self) -> Result<(), Error> {
|
||||||
|
self.delay.delay_ms(2);
|
||||||
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.
|
||||||
|
@ -199,7 +204,7 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
reference_clock_frequency: f32,
|
reference_clock_frequency: f32,
|
||||||
multiplier: u8,
|
multiplier: u8,
|
||||||
) -> Result<f64, Error> {
|
) -> Result<f32, 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) {
|
||||||
|
@ -207,8 +212,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let frequency =
|
let frequency =
|
||||||
multiplier as f64 * self.reference_clock_frequency as f64;
|
multiplier as f32 * self.reference_clock_frequency as f32;
|
||||||
if frequency > 500_000_000.0f64 {
|
if frequency > 500_000_000.0f32 {
|
||||||
return Err(Error::Frequency);
|
return Err(Error::Frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +232,8 @@ where
|
||||||
.map_err(|_| Error::Interface)?;
|
.map_err(|_| Error::Interface)?;
|
||||||
self.system_clock_multiplier = multiplier;
|
self.system_clock_multiplier = multiplier;
|
||||||
|
|
||||||
|
self.latch_configuration()?;
|
||||||
|
|
||||||
Ok(self.system_clock_frequency())
|
Ok(self.system_clock_frequency())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,47 +306,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) -> f32 {
|
||||||
self.system_clock_multiplier as f64
|
self.system_clock_multiplier as f32
|
||||||
* self.reference_clock_frequency as f64
|
* self.reference_clock_frequency as f32
|
||||||
}
|
|
||||||
|
|
||||||
/// Enable an output channel.
|
|
||||||
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)
|
|
||||||
.map_err(|_| Error::Interface)?;
|
|
||||||
csr[0].set_bit(channel as usize + 4, true);
|
|
||||||
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> {
|
|
||||||
let mut csr: [u8; 1] = [0];
|
|
||||||
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)
|
|
||||||
.map_err(|_| Error::Interface)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determine if an output channel is enabled.
|
|
||||||
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)
|
|
||||||
.map_err(|_| Error::Interface)?;
|
|
||||||
|
|
||||||
Ok(csr[0].get_bit(channel as usize + 4))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update an output channel configuration register.
|
/// Update an output channel configuration register.
|
||||||
|
@ -356,17 +325,12 @@ where
|
||||||
) -> Result<(), Error> {
|
) -> 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 csr: u8 = *0x00_u8
|
||||||
self.interface
|
.set_bits(1..=2, self.communication_mode as u8)
|
||||||
.read(Register::CSR as u8, &mut csr)
|
.set_bit(4 + channel as usize, true);
|
||||||
.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
|
self.interface
|
||||||
.write(Register::CSR as u8, &new_csr)
|
.write(Register::CSR as u8, &[csr])
|
||||||
.map_err(|_| Error::Interface)?;
|
.map_err(|_| Error::Interface)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
|
@ -530,8 +494,8 @@ where
|
||||||
pub fn set_frequency(
|
pub fn set_frequency(
|
||||||
&mut self,
|
&mut self,
|
||||||
channel: Channel,
|
channel: Channel,
|
||||||
frequency: f64,
|
frequency: f32,
|
||||||
) -> Result<f64, Error> {
|
) -> Result<f32, 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);
|
||||||
}
|
}
|
||||||
|
@ -539,15 +503,15 @@ where
|
||||||
// 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 =
|
let tuning_word: u32 =
|
||||||
((frequency as f64 / self.system_clock_frequency())
|
((frequency as f32 / self.system_clock_frequency())
|
||||||
* 1u64.wrapping_shl(32) as f64) as u32;
|
* 1u64.wrapping_shl(32) as f32) as u32;
|
||||||
|
|
||||||
self.modify_channel(
|
self.modify_channel(
|
||||||
channel,
|
channel,
|
||||||
Register::CFTW0,
|
Register::CFTW0,
|
||||||
&tuning_word.to_be_bytes(),
|
&tuning_word.to_be_bytes(),
|
||||||
)?;
|
)?;
|
||||||
Ok((tuning_word as f64 / 1u64.wrapping_shl(32) as f64)
|
Ok((tuning_word as f32 / 1u64.wrapping_shl(32) as f32)
|
||||||
* self.system_clock_frequency())
|
* self.system_clock_frequency())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,79 +522,50 @@ 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> {
|
pub fn get_frequency(&mut self, channel: Channel) -> Result<f32, 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)?;
|
||||||
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()
|
Ok((tuning_word as f32 * self.system_clock_frequency()) / (1u64 << 32) as f32)
|
||||||
/ (1u64 << 32) as f64)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_profile(&mut self, channel: Channel, freq: f64, turns: f32, amplitude: f32) -> Result<(), Error> {
|
pub fn write_profile(&mut self, channel: Channel, freq: f32, turns: f32, amplitude: f32) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let csr: u8 = *0x00_u8
|
||||||
|
.set_bits(1..=2, self.communication_mode as u8)
|
||||||
|
.set_bit(4 + channel as usize, true);
|
||||||
|
|
||||||
// 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 =
|
let tuning_word: u32 = ((freq * (1u64 << 32) as f32) / self.system_clock_frequency()) as u32;
|
||||||
((freq as f64 / self.system_clock_frequency())
|
|
||||||
* 1u64.wrapping_shl(32) as f64) as u32;
|
|
||||||
|
|
||||||
let phase_offset: u16 = (turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
|
let phase_offset: u16 = (turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
|
||||||
|
let pow: u32 = *0u32.set_bits(24..32, Register::CPOW0 as u32)
|
||||||
|
.set_bits(8..24, phase_offset as u32)
|
||||||
|
.set_bits(0..8, Register::CFTW0 as u32);
|
||||||
|
|
||||||
let amplitude_control: u16 = (amplitude * (1 << 10) as f32) as u16;
|
|
||||||
let mut acr: [u8; 3] = [0; 3];
|
|
||||||
|
|
||||||
// Enable the amplitude multiplier for the channel if required. The amplitude control has
|
// Enable the amplitude multiplier for the channel if required. The amplitude control has
|
||||||
// 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) {
|
let amplitude_control: u16 = (amplitude * (1 << 10) as f32) as u16;
|
||||||
let masked_control = amplitude_control & 0x3FF;
|
|
||||||
acr[1] = masked_control.to_be_bytes()[0];
|
|
||||||
acr[2] = masked_control.to_be_bytes()[1];
|
|
||||||
|
|
||||||
// Enable the amplitude multiplier
|
let acr: u32 = *0u32.set_bits(24..32, Register::ACR as u32)
|
||||||
acr[1].set_bit(4, true);
|
.set_bits(0..10, amplitude_control as u32 & 0x3FF)
|
||||||
}
|
.set_bit(12, amplitude_control < (1 << 10));
|
||||||
|
|
||||||
self.modify_channel_closure(channel, |interface| {
|
let serialized: [u32; 4] = [
|
||||||
let mut data: [u8; 11] = [0; 11];
|
u32::from_le_bytes([Register::CSR as u8, csr, Register::CSR as u8, csr]),
|
||||||
data[0..2].copy_from_slice(&phase_offset.to_be_bytes());
|
acr.to_be(),
|
||||||
data[2] = Register::CFTW0 as u8;
|
pow.to_be(),
|
||||||
data[3..7].copy_from_slice(&tuning_word.to_be_bytes());
|
tuning_word.to_be(),
|
||||||
data[7] = Register::ACR as u8;
|
];
|
||||||
data[8..11].copy_from_slice(&acr);
|
|
||||||
interface.write(Register::CPOW0 as u8, &data).map_err(|_| Error::Interface)
|
self.interface.write_profile(serialized).map_err(|_| Error::Interface)?;
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modify_channel_closure<F>(&mut self, channel: Channel, f: F) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut INTERFACE) -> 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)
|
|
||||||
.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)
|
|
||||||
.map_err(|_| Error::Interface)?;
|
|
||||||
|
|
||||||
let result = f(&mut self.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()?;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -629,6 +629,7 @@ const APP: () = {
|
||||||
};
|
};
|
||||||
|
|
||||||
cp.SCB.enable_icache();
|
cp.SCB.enable_icache();
|
||||||
|
//cp.SCB.enable_dcache(&mut cp.CPUID);
|
||||||
|
|
||||||
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
||||||
// info!("Built on {}", build_info::BUILT_TIME_UTC);
|
// info!("Built on {}", build_info::BUILT_TIME_UTC);
|
||||||
|
@ -747,6 +748,7 @@ const APP: () = {
|
||||||
|
|
||||||
match c.resources.pounder {
|
match c.resources.pounder {
|
||||||
Some(pounder) => {
|
Some(pounder) => {
|
||||||
|
pounder.ad9959.interface.start_stream();
|
||||||
|
|
||||||
let state = pounder::ChannelState {
|
let state = pounder::ChannelState {
|
||||||
parameters: pounder::DdsChannelState {
|
parameters: pounder::DdsChannelState {
|
||||||
|
@ -755,21 +757,23 @@ const APP: () = {
|
||||||
amplitude: 1.0,
|
amplitude: 1.0,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
attenuation: 10.0,
|
attenuation: 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let state1 = pounder::ChannelState {
|
let state1 = pounder::ChannelState {
|
||||||
parameters: pounder::DdsChannelState {
|
parameters: pounder::DdsChannelState {
|
||||||
phase_offset: 0.5,
|
phase_offset: 0.5,
|
||||||
frequency: 50_000_000.0,
|
frequency: 100_000_000.0,
|
||||||
amplitude: 1.0,
|
amplitude: 1.0,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
attenuation: 10.0,
|
attenuation: 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pounder.set_channel_state(pounder::Channel::Out0, state).unwrap();
|
pounder.set_channel_state(pounder::Channel::Out0, state).unwrap();
|
||||||
pounder.set_channel_state(pounder::Channel::Out1, state1).unwrap();
|
pounder.set_channel_state(pounder::Channel::Out1, state1).unwrap();
|
||||||
|
|
||||||
|
pounder.ad9959.latch_configuration().unwrap();
|
||||||
},
|
},
|
||||||
_ => panic!("Failed"),
|
_ => panic!("Failed"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub enum Channel {
|
||||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
|
||||||
pub struct DdsChannelState {
|
pub struct DdsChannelState {
|
||||||
pub phase_offset: f32,
|
pub phase_offset: f32,
|
||||||
pub frequency: f64,
|
pub frequency: f32,
|
||||||
pub amplitude: f32,
|
pub amplitude: f32,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ impl Into<ad9959::Channel> for Channel {
|
||||||
pub struct QspiInterface {
|
pub struct QspiInterface {
|
||||||
pub qspi: hal::qspi::Qspi,
|
pub qspi: hal::qspi::Qspi,
|
||||||
mode: ad9959::Mode,
|
mode: ad9959::Mode,
|
||||||
|
streaming: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QspiInterface {
|
impl QspiInterface {
|
||||||
|
@ -106,8 +107,14 @@ impl QspiInterface {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
qspi,
|
qspi,
|
||||||
mode: ad9959::Mode::SingleBitTwoWire,
|
mode: ad9959::Mode::SingleBitTwoWire,
|
||||||
|
streaming: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn start_stream(&mut self) {
|
||||||
|
self.streaming = true;
|
||||||
|
self.qspi.enter_write_stream_mode().unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ad9959::Interface for QspiInterface {
|
impl ad9959::Interface for QspiInterface {
|
||||||
|
@ -205,13 +212,23 @@ impl ad9959::Interface for QspiInterface {
|
||||||
.map_err(|_| Error::Qspi)
|
.map_err(|_| Error::Qspi)
|
||||||
}
|
}
|
||||||
ad9959::Mode::FourBitSerial => {
|
ad9959::Mode::FourBitSerial => {
|
||||||
self.qspi.write(addr, &data).map_err(|_| Error::Qspi)
|
if self.streaming {
|
||||||
|
Err(Error::Qspi)
|
||||||
|
} else {
|
||||||
|
self.qspi.write(addr, data).map_err(|_| Error::Qspi)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => Err(Error::Qspi),
|
_ => Err(Error::Qspi),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&mut self, addr: u8, mut dest: &mut [u8]) -> Result<(), Error> {
|
fn write_profile(&mut self, data: [u32; 4]) -> Result<(), Error> {
|
||||||
|
self.qspi.write_profile(data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&mut self, addr: u8, dest: &mut [u8]) -> Result<(), Error> {
|
||||||
if (addr & 0x80) != 0 {
|
if (addr & 0x80) != 0 {
|
||||||
return Err(Error::InvalidAddress);
|
return Err(Error::InvalidAddress);
|
||||||
}
|
}
|
||||||
|
@ -221,9 +238,7 @@ impl ad9959::Interface for QspiInterface {
|
||||||
return Err(Error::Qspi);
|
return Err(Error::Qspi);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.qspi
|
self.qspi.read(0x80_u8 | addr, dest).map_err(|_| Error::Qspi)
|
||||||
.read(0x80_u8 | addr, &mut dest)
|
|
||||||
.map_err(|_| Error::Qspi)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,16 +441,12 @@ where
|
||||||
.ad9959
|
.ad9959
|
||||||
.get_amplitude(channel.into())
|
.get_amplitude(channel.into())
|
||||||
.map_err(|_| Error::Dds)?;
|
.map_err(|_| Error::Dds)?;
|
||||||
let enabled = self
|
|
||||||
.ad9959
|
|
||||||
.is_enabled(channel.into())
|
|
||||||
.map_err(|_| Error::Dds)?;
|
|
||||||
|
|
||||||
Ok(DdsChannelState {
|
Ok(DdsChannelState {
|
||||||
phase_offset,
|
phase_offset,
|
||||||
frequency,
|
frequency,
|
||||||
amplitude,
|
amplitude,
|
||||||
enabled,
|
enabled: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,17 +488,7 @@ where
|
||||||
self.ad9959.write_profile(channel.into(), state.parameters.frequency,
|
self.ad9959.write_profile(channel.into(), state.parameters.frequency,
|
||||||
state.parameters.phase_offset, state.parameters.amplitude).map_err(|_| Error::Dds)?;
|
state.parameters.phase_offset, state.parameters.amplitude).map_err(|_| Error::Dds)?;
|
||||||
|
|
||||||
if state.parameters.enabled {
|
//self.set_attenuation(channel, state.attenuation)?;
|
||||||
self.ad9959
|
|
||||||
.enable_channel(channel.into())
|
|
||||||
.map_err(|_| Error::Dds)?;
|
|
||||||
} else {
|
|
||||||
self.ad9959
|
|
||||||
.disable_channel(channel.into())
|
|
||||||
.map_err(|_| Error::Dds)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.set_attenuation(channel, state.attenuation)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue