Adding WIP QSPI streaming
This commit is contained in:
parent
66c917b576
commit
db182b923d
@ -59,9 +59,8 @@ features = ["stm32h743v"]
|
|||||||
|
|
||||||
[dependencies.stm32h7xx-hal]
|
[dependencies.stm32h7xx-hal]
|
||||||
features = ["stm32h743v", "rt", "unproven"]
|
features = ["stm32h743v", "rt", "unproven"]
|
||||||
|
git = "https://github.com/quartiq/stm32h7xx-hal.git"
|
||||||
[patch.crates-io]
|
branch = "feature/pounder-support"
|
||||||
stm32h7xx-hal = { git = "https://github.com/quartiq/stm32h7xx-hal.git", branch = "feature/pounder-support" }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
semihosting = ["panic-semihosting", "cortex-m-log/semihosting"]
|
||||||
|
@ -376,9 +376,6 @@ where
|
|||||||
// 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)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -571,4 +568,69 @@ where
|
|||||||
Ok(tuning_word as f64 * self.system_clock_frequency()
|
Ok(tuning_word as f64 * self.system_clock_frequency()
|
||||||
/ (1u64 << 32) as f64)
|
/ (1u64 << 32) as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_profile(&mut self, channel: Channel, freq: f64, turns: f32, amplitude: f32) -> Result<(), Error> {
|
||||||
|
// 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.
|
||||||
|
let tuning_word: 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 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
|
||||||
|
// full-scale at 0x3FF (amplitude of 1), so the multiplier should be disabled whenever
|
||||||
|
// full-scale is used.
|
||||||
|
if amplitude_control < (1 << 10) {
|
||||||
|
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
|
||||||
|
acr[1].set_bit(4, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.modify_channel_closure(channel, |interface| {
|
||||||
|
let mut data: [u8; 11] = [0; 11];
|
||||||
|
data[0..2].copy_from_slice(&phase_offset.to_be_bytes());
|
||||||
|
data[2] = Register::CFTW0 as u8;
|
||||||
|
data[3..7].copy_from_slice(&tuning_word.to_be_bytes());
|
||||||
|
data[7] = Register::ACR as u8;
|
||||||
|
data[8..11].copy_from_slice(&acr);
|
||||||
|
interface.write(Register::CPOW0 as u8, &data).map_err(|_| Error::Interface)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,11 +91,11 @@ def main():
|
|||||||
|
|
||||||
# A sample configuration for an output channel.
|
# A sample configuration for an output channel.
|
||||||
channel_config = {
|
channel_config = {
|
||||||
'attenuation': 31.5,
|
'attenuation': 0.0,
|
||||||
'parameters': {
|
'parameters': {
|
||||||
'phase_offset': 0.5,
|
'phase_offset': 0.5,
|
||||||
'frequency': 100.0e6,
|
'frequency': 100.0e6,
|
||||||
'amplitude': 0.2,
|
'amplitude': 1.0,
|
||||||
'enabled': True,
|
'enabled': True,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/main.rs
34
src/main.rs
@ -187,8 +187,7 @@ const APP: () = {
|
|||||||
'static,
|
'static,
|
||||||
'static,
|
'static,
|
||||||
'static,
|
'static,
|
||||||
ethernet::EthernetDMA<'static>,
|
ethernet::EthernetDMA<'static>>,
|
||||||
>,
|
|
||||||
eth_mac: ethernet::EthernetMAC,
|
eth_mac: ethernet::EthernetMAC,
|
||||||
mac_addr: net::wire::EthernetAddress,
|
mac_addr: net::wire::EthernetAddress,
|
||||||
|
|
||||||
@ -654,7 +653,7 @@ const APP: () = {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 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(50.khz(), &mut clocks);
|
||||||
timer2.configure_channel(hal::timer::Channel::One, 0.25);
|
timer2.configure_channel(hal::timer::Channel::One, 0.25);
|
||||||
timer2.configure_channel(hal::timer::Channel::Two, 0.75);
|
timer2.configure_channel(hal::timer::Channel::Two, 0.75);
|
||||||
|
|
||||||
@ -746,6 +745,35 @@ const APP: () = {
|
|||||||
// TODO: Replace with reference to CPU clock from CCDR.
|
// TODO: Replace with reference to CPU clock from CCDR.
|
||||||
next_ms += 400_000.cycles();
|
next_ms += 400_000.cycles();
|
||||||
|
|
||||||
|
match c.resources.pounder {
|
||||||
|
Some(pounder) => {
|
||||||
|
|
||||||
|
let state = pounder::ChannelState {
|
||||||
|
parameters: pounder::DdsChannelState {
|
||||||
|
phase_offset: 0.0,
|
||||||
|
frequency: 100_000_000.0,
|
||||||
|
amplitude: 1.0,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
attenuation: 10.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let state1 = pounder::ChannelState {
|
||||||
|
parameters: pounder::DdsChannelState {
|
||||||
|
phase_offset: 0.5,
|
||||||
|
frequency: 50_000_000.0,
|
||||||
|
amplitude: 1.0,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
attenuation: 10.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
pounder.set_channel_state(pounder::Channel::Out0, state).unwrap();
|
||||||
|
pounder.set_channel_state(pounder::Channel::Out1, state1).unwrap();
|
||||||
|
},
|
||||||
|
_ => panic!("Failed"),
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let tick = Instant::now() > next_ms;
|
let tick = Instant::now() > next_ms;
|
||||||
|
|
||||||
|
@ -474,15 +474,8 @@ where
|
|||||||
channel: Channel,
|
channel: Channel,
|
||||||
state: ChannelState,
|
state: ChannelState,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.ad9959
|
self.ad9959.write_profile(channel.into(), state.parameters.frequency,
|
||||||
.set_frequency(channel.into(), state.parameters.frequency)
|
state.parameters.phase_offset, state.parameters.amplitude).map_err(|_| Error::Dds)?;
|
||||||
.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
|
self.ad9959
|
||||||
|
Loading…
Reference in New Issue
Block a user