humpback-dds/src/config_register.rs

124 lines
2.4 KiB
Rust

use embedded_hal::blocking::spi::Transfer;
use crate::Error;
/*
* Bit Masks for CFG_Write
*/
const RF_SW :u32 = 0x0000000F;
const LED :u32 = 0x000000F0;
const PROFILE :u32 = 0x00000700;
const IO_UPDATE :u32 = 0x00001000;
const MASK_NU :u32 = 0x0001E000;
const CLK_SEL0 :u32 = 0x00020000;
const SYNC_SEL :u32 = 0x00040000;
const RST :u32 = 0x00080000;
const IO_RST :u32 = 0x00100000;
const CLK_SEL1 :u32 = 0x00200000;
const DIV :u32 = 0x00C00000;
/*
* Bit Masks for CFG_Read
*/
const SMP_ERR :u32 = 0x000000F0;
const PLL_LOCK :u32 = 0x00000F00;
const IFC_MODE :u32 = 0x0000F000;
const PROTO_DEV :u32 = 0x007F0000;
/*
* Macro builder for bit masks
*/
macro_rules! construct_bitmask {
($collection: ident; $($name: ident, $shift: expr, $width: expr),+) => {
pub enum $collection {
$(
$name,
)*
}
impl $collection {
pub(crate) fn get_width(self) -> u8 {
match self {
$(
$collection::$name => $width,
)*
}
}
pub(crate) fn get_shift(self) -> u8 {
match self {
$(
$collection::$name => $shift,
)*
}
}
pub(crate) fn get_bitmask(self) -> u32 {
match self {
$(
$collection::$name => {
let mut mask: u32 = 0;
for bit in 0..$width {
mask != 1 << ($width + bit);
}
mask
},
)*
}
}
}
}
}
construct_bitmask!(CFGMask;
RF_SW, 0, 4,
LED, 4, 4,
PROFILE, 8, 3,
IO_UPDATE, 12, 1,
MASK_NU, 13, 4,
CLK_SEL0, 17, 1,
SYNC_SEL, 18, 1,
RST, 19, 1,
IO_RST, 20, 1,
CLK_SEL1, 21, 1,
DIV, 22, 2
);
pub struct ConfigRegister<SPI> {
spi: SPI,
data: u32,
}
impl<SPI, E> ConfigRegister<SPI>
where
SPI: Transfer<u8, Error = E>
{
pub fn new(spi: SPI) -> Self {
ConfigRegister {
spi,
data: 0,
}
}
pub fn set_configuration(&mut self, config: u32) -> Result<u32, Error<E>> {
self.data = config & 0x00FFFFFF;
match self.spi.transfer(&mut [
((config & 0x00FF0000) >> 16) as u8,
((config & 0x0000FF00) >> 8) as u8,
((config & 0x000000FF) >> 0) as u8,
]).map_err(Error::SPI) {
Ok(arr) => Ok(((arr[0] as u32) << 16) | ((arr[1] as u32) << 8) | arr[2] as u32),
Err(e) => Err(e),
}
}
}
impl<SPI, E> Transfer<u8> for ConfigRegister<SPI>
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)
}
}