dds: add register io

This commit is contained in:
occheung 2020-08-26 13:18:50 +08:00
parent 990fc075f1
commit 38b1c7528c
5 changed files with 155 additions and 39 deletions

View File

@ -1,5 +1,5 @@
[target.thumbv7em-none-eabihf]
runner = "gdb -q -x gdb_config/openocd.gdb"
runner = "gdb -q -x gdb_config/fpga_config.gdb"
rustflags = [
"-C", "link-arg=-Tlink.x",
]

View File

@ -10,7 +10,7 @@ use core::mem::size_of;
macro_rules! construct_bitmask {
($collection: ident; $unsigned_type: ty; $($name: ident, $shift: expr, $width: expr),+) => {
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum $collection {
$(
$name,
@ -41,7 +41,7 @@ macro_rules! construct_bitmask {
}
pub(crate) fn get_shifted_bits(self, arg: $unsigned_type) -> $unsigned_type {
assert!(arg < (2 << self.get_width()));
(arg << self.get_shift())
(arg << (self.get_shift() % ((size_of::<$unsigned_type>() as u8) * 8)))
}
pub(crate) fn set_data_by_arg(self, data: &mut $unsigned_type, arg: $unsigned_type) {
// Clear bits in field, then insert shifted argument

View File

@ -3,6 +3,9 @@ use cortex_m_semihosting::hprintln;
use crate::Error;
use core::mem::size_of;
/*
* Bitmask for all configurations (Order: CFR3, CFR2, CFR1)
*/
construct_bitmask!(DDSCFRMask; u32;
// CFR1 bitmasks
LSB_FIRST, 0, 1,
@ -86,12 +89,99 @@ where
}
}
// impl<SPI, E> DDS<SPI>
// where
// SPI: Transfer<u8, Error = E>
// {
// pub fn set_configuration
// }
/*
* Implement init
*/
impl<SPI, E> DDS<SPI>
where
SPI: Transfer<u8, Error = E>
{
pub fn init(&mut self) -> Result<(), Error<E>> {
match self.write_register(0x00, &mut [
0x00, 0x00, 0x00, 0x02
]) {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}
}
/*
* Impleement configurations registers I/O through bitmasks
*/
impl<SPI, E> DDS<SPI>
where
SPI: Transfer<u8, Error = E>
{
/*
* Return (cfr1, cfr2, cfr3) contents
*/
fn get_all_configurations(&mut self) -> Result<[u32; 3], Error<E>> {
let mut cfr_reg = [0; 12];
self.read_register(0x00, &mut cfr_reg[0..4])?;
self.read_register(0x01, &mut cfr_reg[4..8])?;
self.read_register(0x02, &mut cfr_reg[8..12])?;
Ok([
(cfr_reg[0] as u32) << 24 | (cfr_reg[1] as u32) << 16 | (cfr_reg[2] as u32) << 8 | (cfr_reg[3] as u32),
(cfr_reg[4] as u32) << 24 | (cfr_reg[5] as u32) << 16 | (cfr_reg[6] as u32) << 8 | (cfr_reg[7] as u32),
(cfr_reg[8] as u32) << 24 | (cfr_reg[9] as u32) << 16 | (cfr_reg[10] as u32) << 8 | (cfr_reg[11] as u32)
])
}
/*
* Get a set of configurations using DDSCFRMask
*/
pub fn get_configurations<'w>(&mut self, mask_pairs: &'w mut[(DDSCFRMask, u32)]) -> Result<&'w [(DDSCFRMask, u32)], Error<E>> {
let data_array = self.get_all_configurations()?;
for index in 0..mask_pairs.len() {
mask_pairs[index].1 = match mask_pairs[index].0.get_shift() {
0..=31 => mask_pairs[index].0.get_filtered_content(data_array[0]),
32..=63 => mask_pairs[index].0.get_filtered_content(data_array[1]),
64..=95 => mask_pairs[index].0.get_filtered_content(data_array[2]),
_ => panic!("Invalid DDSCFRMask!"),
}
}
Ok(mask_pairs)
}
/*
* Write (cfr1, cfr2, cfr3) contents
*/
fn set_all_configurations(&mut self, data_array: [u32; 3]) -> Result<(), Error<E>> {
for register in 0x00..=0x02 {
self.write_register(register, &mut [
((data_array[register as usize] >> 24) & 0xFF) as u8,
((data_array[register as usize] >> 16) & 0xFF) as u8,
((data_array[register as usize] >> 8 ) & 0xFF) as u8,
((data_array[register as usize] >> 0 ) & 0xFF) as u8
])?;
}
Ok(())
}
/*
* Set a set of configurations using DDSCFRMask
*/
pub fn set_configurations(&mut self, mask_pairs: &mut[(DDSCFRMask, u32)]) -> Result<(), Error<E>> {
let mut data_array = self.get_all_configurations()?;
hprintln!("Initial array {:#X?}", data_array).unwrap();
for index in 0..mask_pairs.len() {
// Reject any attempt to write LSB_FIRST and SBIO_INPUT_ONLY
if mask_pairs[index].0 == DDSCFRMask::LSB_FIRST || mask_pairs[index].0 == DDSCFRMask::SDIO_IN_ONLY {
continue;
}
match mask_pairs[index].0.get_shift() {
0..=31 => mask_pairs[index].0.set_data_by_arg(&mut data_array[0], mask_pairs[index].1),
32..=63 => mask_pairs[index].0.set_data_by_arg(&mut data_array[1], mask_pairs[index].1),
64..=95 => mask_pairs[index].0.set_data_by_arg(&mut data_array[2], mask_pairs[index].1),
_ => panic!("Invalid DDSCFRMask!"),
};
}
hprintln!("Modified array {:#X?}", data_array).unwrap();
self.set_all_configurations(data_array.clone())
}
}
macro_rules! impl_register_io {
($($reg_addr: expr, $reg_byte_size: expr),+) => {

View File

@ -32,6 +32,7 @@ pub enum Error<E> {
GetRefMutDataError,
AttenuatorError,
IOUpdateError,
DDSError,
}
/*

View File

@ -26,7 +26,10 @@ use firmware::{
CFGMask,
StatusMask,
},
dds::DDS,
dds::{
DDS,
DDSCFRMask,
},
};
#[entry]
@ -94,7 +97,7 @@ fn main() -> ! {
&ccdr.clocks,
);
let mut switch = CPLD::new(spi, (cs0, cs1, cs2), io_update);
let switch = CPLD::new(spi, (cs0, cs1, cs2), io_update);
let parts = switch.split();
let mut config = ConfigRegister::new(parts.spi1);
@ -111,35 +114,63 @@ fn main() -> ! {
config.set_configurations(&mut [
(CFGMask::IO_RST, 0),
(CFGMask::RST, 0),
(CFGMask::RF_SW, 1)
(CFGMask::RF_SW, 13),
(CFGMask::DIV, 2)
]).unwrap();
dds0.write_register(0x00, &mut[
0x00, 0x00, 0x00, 0x02
// dds0.write_register(0x00, &mut[
// 0x00, 0x00, 0x00, 0x02
// ]).unwrap();
// dds0.write_register(0x01, &mut[
// 0x01, 0x01, 0x00, 0x20
// ]).unwrap();
// dds0.write_register(0x02, &mut[
// 0x05, 0x38, 0xC5, 0x28
// ]).unwrap();
dds0.init().unwrap();
dds0.set_configurations(&mut [
(DDSCFRMask::PDCLK_ENABLE, 0),
(DDSCFRMask::READ_EFFECTIVE_FTW, 1),
(DDSCFRMask::DIGITAL_RAMP_ENABLE, 0),
(DDSCFRMask::EN_AMP_SCALE_SINGLE_TONE_PRO, 1),
(DDSCFRMask::N, 0x14),
(DDSCFRMask::PLL_ENABLE, 1),
(DDSCFRMask::PFD_RESET, 1),
(DDSCFRMask::REFCLK_IN_DIV_BYPASS, 1),
(DDSCFRMask::I_CP, 7),
(DDSCFRMask::VCO_SEL, 5),
(DDSCFRMask::DRV0, 0),
]).unwrap();
dds0.write_register(0x02, &mut[
0x01F, 0x3F, 0x41, 0x00
hprintln!("{:#X?}", dds0.read_register(0x02, &mut[
0x00, 0x00, 0x00, 0x00
]).unwrap()).unwrap();
dds0.set_configurations(&mut [
(DDSCFRMask::PFD_RESET, 0),
]).unwrap();
hprintln!("{:#X?}", dds0.read_register(0x00, &mut[
hprintln!("{:#X?}", dds0.read_register(0x02, &mut[
0x00, 0x00, 0x00, 0x00
]).unwrap()).unwrap();
// Calculate FTW
let f_out = 10_000_000;
let f_sclk = 100_000_000;
let f_out = 8_008_135;
let f_sclk = 100_000_000 / 2 * 20;
let resolution :u64 = 1 << 32;
let ftw = (resolution * f_out / f_sclk) as u32;
hprintln!("{}", ftw);
// Read single-tone profile 0
let mut profile :[u8; 8] = [0; 8];
dds0.read_register(0x0E, &mut profile).unwrap();
// Overwrite FTW on profile
profile[0] = 0x20;
// Overwrite FTW on profile 0
profile[0] = 0x1F;
profile[1] = 0xFF;
profile[4] = ((ftw >> 24) & 0xFF) as u8;
profile[5] = ((ftw >> 16) & 0xFF) as u8;
profile[6] = ((ftw >> 8 ) & 0xFF) as u8;
@ -147,28 +178,22 @@ fn main() -> ! {
dds0.write_register(0x0E, &mut profile).unwrap();
hprintln!("{:#X?}", dds0.read_register(0x0E, &mut profile).unwrap()).unwrap();
// Attenuator
att.set_attenuation([
0.0, 31.5, 24.0, 0.0
]).unwrap();
hprintln!("{:#X?}", att.get_attenuation().unwrap()).unwrap();
hprintln!("{:#X?}", dds0.get_configurations(&mut
[
(DDSCFRMask::SDIO_IN_ONLY, 0),
(DDSCFRMask::LSB_FIRST, 0),
(DDSCFRMask::PROFILE_CTRL, 0),
(DDSCFRMask::EN_AMP_SCALE_SINGLE_TONE_PRO, 0),
(DDSCFRMask::DRV0, 0),
(DDSCFRMask::VCO_SEL, 0)
]
).unwrap()).unwrap();
/*
// Write to FTW register
dds0.write_register(0x07, &mut [
((ftw >> 24) & 0xFF) as u8,
((ftw >> 16) & 0xFF) as u8,
((ftw >> 8 ) & 0xFF) as u8,
((ftw >> 0 ) & 0xFF) as u8,
]).unwrap();
hprintln!("{:#X?}", dds0.read_register(0x07, &mut [
0x00, 0x00, 0x00, 0x00
]).unwrap()).unwrap();
*/
loop {}
}