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, data: u32, } impl ConfigRegister where SPI: Transfer { pub fn new(spi: SPI) -> Self { ConfigRegister { spi, data: 0, } } pub fn set_configuration(&mut self, config: u32) -> Result> { 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 Transfer for ConfigRegister where SPI: Transfer { type Error = Error; fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { self.spi.transfer(words).map_err(Error::SPI) } }