Fixing pounder timestamps after manual testing
This commit is contained in:
parent
72d14adfbf
commit
352884ea06
|
@ -172,6 +172,17 @@ impl<I: Interface> Ad9959<I> {
|
||||||
|
|
||||||
// Set the clock frequency to configure the device as necessary.
|
// Set the clock frequency to configure the device as necessary.
|
||||||
ad9959.configure_system_clock(clock_frequency, multiplier)?;
|
ad9959.configure_system_clock(clock_frequency, multiplier)?;
|
||||||
|
|
||||||
|
// Latch the new clock configuration.
|
||||||
|
io_update.set_high().or(Err(Error::Pin))?;
|
||||||
|
|
||||||
|
// Delay for at least 1 SYNC_CLK period for the update to occur. The SYNC_CLK is guaranteed
|
||||||
|
// to be at least 250KHz (1/4 of 1MHz minimum REF_CLK). We use 5uS instead of 4uS to
|
||||||
|
// guarantee conformance with datasheet requirements.
|
||||||
|
delay.delay_us(5);
|
||||||
|
|
||||||
|
io_update.set_low().or(Err(Error::Pin))?;
|
||||||
|
|
||||||
Ok(ad9959)
|
Ok(ad9959)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +206,7 @@ impl<I: Interface> Ad9959<I> {
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// The actual frequency configured for the internal system clock.
|
/// The actual frequency configured for the internal system clock.
|
||||||
pub fn configure_system_clock(
|
fn configure_system_clock(
|
||||||
&mut self,
|
&mut self,
|
||||||
reference_clock_frequency: f32,
|
reference_clock_frequency: f32,
|
||||||
multiplier: u8,
|
multiplier: u8,
|
||||||
|
|
|
@ -7,3 +7,12 @@ pub const ADC_DAC_SCK_MHZ_MAX: u32 = 50;
|
||||||
|
|
||||||
/// The optimal counting frequency of the hardware timers used for timestamping and sampling.
|
/// The optimal counting frequency of the hardware timers used for timestamping and sampling.
|
||||||
pub const TIMER_FREQUENCY_MHZ: u32 = 100;
|
pub const TIMER_FREQUENCY_MHZ: u32 = 100;
|
||||||
|
|
||||||
|
/// The DDS reference clock frequency in MHz.
|
||||||
|
pub const DDS_REF_CLK_MHZ: u32 = 100;
|
||||||
|
|
||||||
|
/// The multiplier used for the DDS reference clock PLL.
|
||||||
|
pub const DDS_MULTIPLIER: u8 = 5;
|
||||||
|
|
||||||
|
/// The rate of the DDS SYNC_CLK in MHz is always 1/4 that of the internal PLL clock.
|
||||||
|
pub const DDS_SYNC_CLK_MHZ: u32 = DDS_REF_CLK_MHZ * DDS_MULTIPLIER as u32 / 4;
|
||||||
|
|
26
src/main.rs
26
src/main.rs
|
@ -527,7 +527,7 @@ const APP: () = {
|
||||||
delay.delay_ms(2u8);
|
delay.delay_ms(2u8);
|
||||||
let (pounder_devices, dds_output) = if pounder_pgood.is_high().unwrap()
|
let (pounder_devices, dds_output) = if pounder_pgood.is_high().unwrap()
|
||||||
{
|
{
|
||||||
let mut ad9959 = {
|
let ad9959 = {
|
||||||
let qspi_interface = {
|
let qspi_interface = {
|
||||||
// Instantiate the QUADSPI pins and peripheral interface.
|
// Instantiate the QUADSPI pins and peripheral interface.
|
||||||
let qspi_pins = {
|
let qspi_pins = {
|
||||||
|
@ -580,8 +580,8 @@ const APP: () = {
|
||||||
&mut io_update,
|
&mut io_update,
|
||||||
&mut delay,
|
&mut delay,
|
||||||
ad9959::Mode::FourBitSerial,
|
ad9959::Mode::FourBitSerial,
|
||||||
100_000_000_f32,
|
design_parameters::DDS_REF_CLK_MHZ as f32 * 1_000_000_f32,
|
||||||
5,
|
design_parameters::DDS_MULTIPLIER,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -660,7 +660,6 @@ const APP: () = {
|
||||||
|
|
||||||
let pounder_devices = pounder::PounderDevices::new(
|
let pounder_devices = pounder::PounderDevices::new(
|
||||||
io_expander,
|
io_expander,
|
||||||
&mut ad9959,
|
|
||||||
spi,
|
spi,
|
||||||
adc1,
|
adc1,
|
||||||
adc2,
|
adc2,
|
||||||
|
@ -686,8 +685,8 @@ const APP: () = {
|
||||||
);
|
);
|
||||||
|
|
||||||
// IO_Update should be latched for 4 SYNC_CLK cycles after the QSPI profile
|
// IO_Update should be latched for 4 SYNC_CLK cycles after the QSPI profile
|
||||||
// write. With pounder SYNC_CLK running at 100MHz (1/4 of the pounder reference
|
// write. With pounder SYNC_CLK running at 125MHz (1/4 of the pounder reference
|
||||||
// clock of 400MHz), this corresponds to 40ns. To accomodate rounding errors, we
|
// clock of 500MHz), this corresponds to 32ns. To accomodate rounding errors, we
|
||||||
// use 50ns instead.
|
// use 50ns instead.
|
||||||
//
|
//
|
||||||
// Profile writes are always 16 bytes, with 2 cycles required per byte, coming
|
// Profile writes are always 16 bytes, with 2 cycles required per byte, coming
|
||||||
|
@ -859,8 +858,21 @@ const APP: () = {
|
||||||
let tim8 =
|
let tim8 =
|
||||||
dp.TIM8.timer(1.khz(), ccdr.peripheral.TIM8, &ccdr.clocks);
|
dp.TIM8.timer(1.khz(), ccdr.peripheral.TIM8, &ccdr.clocks);
|
||||||
let mut timestamp_timer = timers::PounderTimestampTimer::new(tim8);
|
let mut timestamp_timer = timers::PounderTimestampTimer::new(tim8);
|
||||||
|
|
||||||
|
// Pounder is configured to generate a 400MHz reference clock, so a 125MHz sync-clock is
|
||||||
|
// output. As a result, dividing the 125MHz sync-clk provides a 31.25MHz tick rate for
|
||||||
|
// the timestamp timer. 31.25MHz corresponds with a 32ns tick rate.
|
||||||
timestamp_timer.set_external_clock(timers::Prescaler::Div4);
|
timestamp_timer.set_external_clock(timers::Prescaler::Div4);
|
||||||
timestamp_timer.set_period(128);
|
timestamp_timer.start();
|
||||||
|
|
||||||
|
// We want the pounder timestamp timer to overflow once per batch.
|
||||||
|
let tick_ratio = design_parameters::DDS_SYNC_CLK_MHZ as f32
|
||||||
|
/ design_parameters::TIMER_FREQUENCY_MHZ as f32;
|
||||||
|
let period = (tick_ratio
|
||||||
|
* ADC_SAMPLE_TICKS as f32
|
||||||
|
* SAMPLE_BUFFER_SIZE as f32) as u32
|
||||||
|
/ 4;
|
||||||
|
timestamp_timer.set_period((period - 1).try_into().unwrap());
|
||||||
let tim8_channels = timestamp_timer.channels();
|
let tim8_channels = timestamp_timer.channels();
|
||||||
|
|
||||||
pounder::timestamp::Timestamper::new(
|
pounder::timestamp::Timestamper::new(
|
||||||
|
|
|
@ -275,7 +275,6 @@ impl PounderDevices {
|
||||||
/// Construct and initialize pounder-specific hardware.
|
/// Construct and initialize pounder-specific hardware.
|
||||||
///
|
///
|
||||||
/// Args:
|
/// Args:
|
||||||
/// * `ad9959` - The DDS driver for the pounder hardware.
|
|
||||||
/// * `attenuator_spi` - A SPI interface to control digital attenuators.
|
/// * `attenuator_spi` - A SPI interface to control digital attenuators.
|
||||||
/// * `adc1` - The ADC1 peripheral for measuring power.
|
/// * `adc1` - The ADC1 peripheral for measuring power.
|
||||||
/// * `adc2` - The ADC2 peripheral for measuring power.
|
/// * `adc2` - The ADC2 peripheral for measuring power.
|
||||||
|
@ -283,7 +282,6 @@ impl PounderDevices {
|
||||||
/// * `adc2_in_p` - The input channel for the RF power measurement on IN1.
|
/// * `adc2_in_p` - The input channel for the RF power measurement on IN1.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
|
mcp23017: mcp23017::MCP23017<hal::i2c::I2c<hal::stm32::I2C1>>,
|
||||||
ad9959: &mut ad9959::Ad9959<QspiInterface>,
|
|
||||||
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1, hal::spi::Enabled, u8>,
|
attenuator_spi: hal::spi::Spi<hal::stm32::SPI1, hal::spi::Enabled, u8>,
|
||||||
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
|
adc1: hal::adc::Adc<hal::stm32::ADC1, hal::adc::Enabled>,
|
||||||
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
|
adc2: hal::adc::Adc<hal::stm32::ADC2, hal::adc::Enabled>,
|
||||||
|
@ -315,14 +313,10 @@ impl PounderDevices {
|
||||||
.write_gpio(mcp23017::Port::GPIOB, 1 << 5)
|
.write_gpio(mcp23017::Port::GPIOB, 1 << 5)
|
||||||
.map_err(|_| Error::I2c)?;
|
.map_err(|_| Error::I2c)?;
|
||||||
|
|
||||||
// Select the on-board clock with a 4x prescaler (400MHz).
|
|
||||||
devices
|
devices
|
||||||
.mcp23017
|
.mcp23017
|
||||||
.digital_write(EXT_CLK_SEL_PIN, false)
|
.digital_write(EXT_CLK_SEL_PIN, false)
|
||||||
.map_err(|_| Error::I2c)?;
|
.map_err(|_| Error::I2c)?;
|
||||||
ad9959
|
|
||||||
.configure_system_clock(100_000_000f32, 4)
|
|
||||||
.map_err(|_| Error::Dds)?;
|
|
||||||
|
|
||||||
Ok(devices)
|
Ok(devices)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ pub enum TriggerSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Prescaler {
|
pub enum Prescaler {
|
||||||
|
Div1 = 0b00,
|
||||||
|
Div2 = 0b01,
|
||||||
Div4 = 0b10,
|
Div4 = 0b10,
|
||||||
Div8 = 0b11,
|
Div8 = 0b11,
|
||||||
}
|
}
|
||||||
|
@ -100,17 +102,17 @@ macro_rules! timer_channels {
|
||||||
let regs = unsafe { &*hal::stm32::$TY::ptr() };
|
let regs = unsafe { &*hal::stm32::$TY::ptr() };
|
||||||
regs.smcr.modify(|_, w| w.etps().bits(prescaler as u8).ece().set_bit());
|
regs.smcr.modify(|_, w| w.etps().bits(prescaler as u8).ece().set_bit());
|
||||||
|
|
||||||
// Use a DIV4 prescaler.
|
// Clear any other prescaler configuration.
|
||||||
|
regs.psc.write(|w| w.psc().bits(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start the timer.
|
/// Start the timer.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn start(mut self) {
|
pub fn start(&mut self) {
|
||||||
// Force a refresh of the frequency settings.
|
// Force a refresh of the frequency settings.
|
||||||
self.timer.apply_freq();
|
self.timer.apply_freq();
|
||||||
|
|
||||||
self.timer.reset_counter();
|
self.timer.reset_counter();
|
||||||
|
|
||||||
self.timer.resume();
|
self.timer.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue