mirror of https://github.com/m-labs/artiq.git
75 lines
2.3 KiB
Rust
75 lines
2.3 KiB
Rust
pub const INIT: u8 = 0x00;
|
|
pub const PRINT_STATUS: u8 = 0x01;
|
|
pub const PRBS: u8 = 0x02;
|
|
pub const STPL: u8 = 0x03;
|
|
|
|
pub const SYSREF_DELAY_DAC: u8 = 0x10;
|
|
pub const SYSREF_SLIP: u8 = 0x11;
|
|
pub const SYNC: u8 = 0x12;
|
|
|
|
pub const DDMTD_SYSREF_RAW: u8 = 0x20;
|
|
pub const DDMTD_SYSREF: u8 = 0x21;
|
|
|
|
|
|
fn average_2phases(a: i32, b: i32, modulo: i32) -> i32 {
|
|
let diff = ((a - b + modulo/2 + modulo) % modulo) - modulo/2;
|
|
return (modulo + b + diff/2) % modulo;
|
|
}
|
|
|
|
pub fn average_phases(phases: &[i32], modulo: i32) -> i32 {
|
|
if phases.len() == 1 {
|
|
panic!("input array length must be a power of 2");
|
|
} else if phases.len() == 2 {
|
|
average_2phases(phases[0], phases[1], modulo)
|
|
} else {
|
|
let cut = phases.len()/2;
|
|
average_2phases(
|
|
average_phases(&phases[..cut], modulo),
|
|
average_phases(&phases[cut..], modulo),
|
|
modulo)
|
|
}
|
|
}
|
|
|
|
pub const RAW_DDMTD_N_SHIFT: i32 = 6;
|
|
pub const RAW_DDMTD_N: i32 = 1 << RAW_DDMTD_N_SHIFT;
|
|
pub const DDMTD_DITHER_BITS: i32 = 1;
|
|
pub const DDMTD_N_SHIFT: i32 = RAW_DDMTD_N_SHIFT + DDMTD_DITHER_BITS;
|
|
pub const DDMTD_N: i32 = 1 << DDMTD_N_SHIFT;
|
|
|
|
#[cfg(has_ad9154)]
|
|
use board_misoc::{clock, csr};
|
|
|
|
#[cfg(has_ad9154)]
|
|
pub fn init_ddmtd() -> Result<(), &'static str> {
|
|
unsafe {
|
|
csr::sysref_ddmtd::reset_write(1);
|
|
clock::spin_us(1);
|
|
csr::sysref_ddmtd::reset_write(0);
|
|
clock::spin_us(100);
|
|
if csr::sysref_ddmtd::locked_read() != 0 {
|
|
Ok(())
|
|
} else {
|
|
Err("DDMTD helper PLL failed to lock")
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(has_ad9154)]
|
|
pub fn measure_ddmdt_phase_raw() -> i32 {
|
|
unsafe { csr::sysref_ddmtd::dt_read() as i32 }
|
|
}
|
|
|
|
#[cfg(has_ad9154)]
|
|
pub fn measure_ddmdt_phase() -> i32 {
|
|
const AVG_PRECISION_SHIFT: i32 = 6;
|
|
const AVG_PRECISION: i32 = 1 << AVG_PRECISION_SHIFT;
|
|
const AVG_MOD: i32 = 1 << (RAW_DDMTD_N_SHIFT + AVG_PRECISION_SHIFT + DDMTD_DITHER_BITS);
|
|
|
|
let mut measurements = [0; AVG_PRECISION as usize];
|
|
for i in 0..AVG_PRECISION {
|
|
measurements[i as usize] = measure_ddmdt_phase_raw() << (AVG_PRECISION_SHIFT + DDMTD_DITHER_BITS);
|
|
clock::spin_us(10);
|
|
}
|
|
average_phases(&measurements, AVG_MOD) >> AVG_PRECISION_SHIFT
|
|
}
|