forked from M-Labs/humpback-dds
dds: add single tone control
This commit is contained in:
parent
1d3ced0d16
commit
649b5b498b
52
src/dds.rs
52
src/dds.rs
|
@ -66,6 +66,7 @@ const READ_MASK :u8 = 0x80;
|
|||
pub struct DDS<SPI> {
|
||||
spi: SPI,
|
||||
f_ref_clk: u64,
|
||||
f_sys_clk: u64,
|
||||
}
|
||||
|
||||
impl<SPI, E> DDS<SPI>
|
||||
|
@ -76,6 +77,7 @@ where
|
|||
DDS {
|
||||
spi,
|
||||
f_ref_clk,
|
||||
f_sys_clk: f_ref_clk,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +121,9 @@ where
|
|||
(DDSCFRMask::REFCLK_IN_DIV_BYPASS, 0),
|
||||
// Ensure divider is not reset
|
||||
(DDSCFRMask::REFCLK_IN_DIV_RESETB, 1),
|
||||
])
|
||||
])?;
|
||||
self.f_sys_clk = self.f_ref_clk / 2;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enable_normal_ref_clk(&mut self) -> Result<(), Error<E>> {
|
||||
|
@ -130,7 +134,9 @@ where
|
|||
(DDSCFRMask::REFCLK_IN_DIV_BYPASS, 1),
|
||||
// Reset does not matter
|
||||
(DDSCFRMask::REFCLK_IN_DIV_RESETB, 1),
|
||||
])
|
||||
])?;
|
||||
self.f_sys_clk = self.f_ref_clk;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enable_pll(&mut self, f_sys_clk: u64) -> Result<(), Error<E>> {
|
||||
|
@ -170,16 +176,19 @@ where
|
|||
])?;
|
||||
self.set_configurations(&mut [
|
||||
(DDSCFRMask::PFD_RESET, 0),
|
||||
])
|
||||
])?;
|
||||
self.f_sys_clk = self.f_ref_clk * divider;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Change external clock source (ref_clk)
|
||||
pub fn set_ref_clk_frequency(&mut self, f_ref_clk: u64) {
|
||||
self.f_ref_clk = f_ref_clk;
|
||||
// TODO: Examine clock tree and update f_sys_clk
|
||||
}
|
||||
|
||||
/*
|
||||
* Impleement configurations registers I/O through bitmasks
|
||||
* Implement configurations registers I/O through bitmasks
|
||||
*
|
||||
* Get all (cfr1, cfr2, cfr3) contents
|
||||
*/
|
||||
|
@ -246,6 +255,41 @@ where
|
|||
self.set_all_configurations(data_array.clone())
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a single tone profile
|
||||
* Phase: Expressed in positive degree
|
||||
* Frequency: Must be integer
|
||||
* Amplitude: In a scale from 0 to 1, taking float
|
||||
*/
|
||||
pub fn set_single_tone_profile(&mut self, profile: u8, f_out: u64, phase_offset: f64, amp_scale_factor: f64) -> Result<(), Error<E>> {
|
||||
|
||||
assert!(profile < 8);
|
||||
assert!(phase_offset >= 0.0 && phase_offset < 360.0);
|
||||
assert!(amp_scale_factor >=0.0 && amp_scale_factor <= 1.0);
|
||||
|
||||
let resolutions :[u64; 3] = [1 << 32, 1 << 16, 1 << 14];
|
||||
let ftw = (resolutions[0] * f_out / self.f_sys_clk) as u32;
|
||||
let pow = ((resolutions[1] as f64) * phase_offset / 360.0) as u16;
|
||||
let asf = ((resolutions[2] as f64) * amp_scale_factor) as u16;
|
||||
// Setup configuration registers before writing single tone register
|
||||
self.set_configurations(&mut [
|
||||
(DDSCFRMask::RAM_ENABLE, 0),
|
||||
(DDSCFRMask::DIGITAL_RAMP_ENABLE, 0),
|
||||
(DDSCFRMask::PARALLEL_DATA_PORT_ENABLE, 0),
|
||||
])?;
|
||||
// Transfer single tone profile data
|
||||
self.write_register(0x0E + profile, &mut [
|
||||
((asf >> 8 ) & 0xFF) as u8,
|
||||
((asf >> 0 ) & 0xFF) as u8,
|
||||
((pow >> 8 ) & 0xFF) as u8,
|
||||
((pow >> 0 ) & 0xFF) as u8,
|
||||
((ftw >> 24) & 0xFF) as u8,
|
||||
((ftw >> 16) & 0xFF) as u8,
|
||||
((ftw >> 8 ) & 0xFF) as u8,
|
||||
((ftw >> 0 ) & 0xFF) as u8,
|
||||
])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
macro_rules! impl_register_io {
|
||||
|
|
Loading…
Reference in New Issue