humpback-dds/src/dds.rs

164 lines
3.5 KiB
Rust
Raw Normal View History

2020-08-12 15:31:06 +08:00
use embedded_hal::blocking::spi::Transfer;
use cortex_m_semihosting::hprintln;
use crate::Error;
2020-08-13 17:17:21 +08:00
construct_bitmask!(CFR1Mask; u32;
LSB_FIRST, 0, 1,
SDIO_IN_ONLY, 1, 1,
EXT_POWER_DOWN_CTRL, 3, 1,
AUX_DAC_POWER_DOWN, 4, 1,
REFCLK_IN_POWER_DOWN, 5, 1,
DAC_POWER_DOWN, 6, 1,
DIGITAL_POWER_DOWN, 7, 1,
SEL_AUTO_OSK, 8, 1,
OSK_ENABLE, 9, 1,
LOAD_ARR_IO_UPDATE, 10, 1,
CLEAR_PHASE_ACU, 11, 1,
CLEAR_DIGITAL_RAMP_ACU, 12, 1,
AUTOCLEAR_PHASE_ACU, 13, 1,
AUTOCLEAR_DIGITAL_RAMP_ACU, 14, 1,
LOAD_LRR_IO_UPDATE, 15, 1,
SEL_DDS_SIN_OUT, 16, 1,
PROFILE_CTRL, 17, 4,
INV_SINC_FILTER_ENABLE, 22, 1,
MANUAL_OSK_EXT_CTRL, 23, 1,
RAM_PLAYBACK_DST, 29, 2,
RAM_ENABLE, 31, 1
);
2020-08-14 14:14:14 +08:00
construct_bitmask!(CFR2Mask; u32;
FM_GAIN, 0, 4,
PARALLEL_DATA_PORT_ENABLE, 4, 1,
SYNC_TIM_VALIDATION_DISABLE, 5, 1,
DATA_ASSEM_HOLD_LAST_VALUE, 6, 1,
MATCHED_LATENCY_ENABLE, 7, 1,
TXENABLE_INV, 9, 1,
PDCLK_INV, 10, 1,
PDCLK_ENABLE, 11, 1,
IO_UPDATE_RATE_CTRL, 14, 2,
READ_EFFECTIVE_FTW, 16, 1,
DIGITAL_RAMP_NO_DWELL_LOW, 17, 1,
DIGITAL_RAMP_NO_DWELL_HIGH, 18, 1,
DIGITAL_RAMP_ENABLE, 19, 1,
DIGITAL_RAMP_DEST, 20, 2,
SYNC_CLK_ENABLE, 22, 1,
INT_IO_UPDATE_ACTIVE, 23, 1,
EN_AMP_SCALE_SINGLE_TONE_PRO, 24, 1
);
construct_bitmask!(CFR3Mask; u32;
N, 1, 7,
PLL_ENABLE, 8, 1,
PFD_RESET, 10, 1,
REFCLK_IN_DIV_RESETB, 14, 1,
REFCLK_IN_DIV_BYPASS, 15, 1,
I_CP, 19, 3,
VCO_SEL, 24, 3,
DRV0, 28, 2
2020-08-17 12:15:11 +08:00
);
2020-08-14 14:14:14 +08:00
2020-08-17 11:45:42 +08:00
const WRITE_MASK :u8 = 0x00;
const READ_MASK :u8 = 0x80;
2020-08-12 15:31:06 +08:00
pub struct DDS<SPI> {
spi: SPI,
}
impl<SPI, E> DDS<SPI>
where
2020-08-17 11:45:42 +08:00
SPI: Transfer<u8, Error = E>
2020-08-12 15:31:06 +08:00
{
pub fn new(spi: SPI) -> Self {
DDS {
spi
}
}
}
2020-08-17 12:15:11 +08:00
impl<SPI, E> Transfer<u8> for DDS<SPI>
2020-08-12 15:31:06 +08:00
where
SPI: Transfer<u8, Error = E>
{
type Error = Error<E>;
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
self.spi.transfer(words).map_err(Error::SPI)
}
}
2020-08-17 11:45:42 +08:00
macro_rules! impl_register_io {
($($reg_addr: expr, $reg_byte_size: expr),+) => {
impl<SPI, E> DDS<SPI>
where
SPI: Transfer<u8, Error = E>
{
pub fn write_register(&mut self, addr: u8, bytes: &mut[u8]) -> Result<(), Error<E>> {
match addr {
$(
$reg_addr => {
assert_eq!(bytes.len(), $reg_byte_size);
2020-08-17 12:15:11 +08:00
let mut arr: [u8; $reg_byte_size + 1] = [0; ($reg_byte_size + 1)];
arr[0] = addr | WRITE_MASK;
2020-08-17 11:45:42 +08:00
for i in 0..$reg_byte_size {
arr[i+1] = bytes[i];
}
2020-08-17 12:15:11 +08:00
match self.spi.transfer(&mut arr).map_err(Error::SPI) {
2020-08-17 11:45:42 +08:00
Ok(v) => Ok(()),
Err(e) => Err(e),
2020-08-17 12:15:11 +08:00
}
},
)*
_ => panic!("Bad address for DDS writing.")
}
}
pub fn read_register<'w>(&mut self, addr: u8, bytes: &'w mut[u8]) -> Result<&'w [u8], Error<E>> {
match addr {
$(
$reg_addr => {
assert_eq!(bytes.len(), $reg_byte_size);
let mut arr: [u8; $reg_byte_size + 1] = [0; ($reg_byte_size + 1)];
arr[0] = addr | READ_MASK;
match self.spi.transfer(&mut arr).map_err(Error::SPI) {
Ok(ret) => {
assert_eq!(ret.len(), $reg_byte_size + 1);
for i in 0..$reg_byte_size {
bytes[i] = ret[i+1];
}
Ok(bytes)
},
Err(e) => Err(e),
}
2020-08-17 11:45:42 +08:00
},
)*
2020-08-17 12:15:11 +08:00
_ => panic!("Bad address for DDS reading.")
2020-08-17 11:45:42 +08:00
}
}
}
}
}
impl_register_io!(
0x00, 4,
0x01, 4,
0x02, 4,
0x03, 4,
0x04, 4,
0x07, 4,
0x08, 2,
0x09, 4,
0x0A, 4,
0x0B, 8,
0x0C, 8,
0x0D, 4,
0x0E, 8,
0x0F, 8,
0x10, 8,
0x11, 8,
0x12, 8,
0x13, 8,
0x14, 8,
0x15, 8,
0x16, 4
);