From 0df7ff71cfdb55d66181792e73bace515b54c15a Mon Sep 17 00:00:00 2001 From: occheung Date: Tue, 11 Aug 2020 16:51:17 +0800 Subject: [PATCH] cfg_reg: add bitmask macro --- src/config_register.rs | 96 +++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 3 +- src/main.rs | 4 ++ 3 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/config_register.rs b/src/config_register.rs index 7a8d962..27f176c 100644 --- a/src/config_register.rs +++ b/src/config_register.rs @@ -1,4 +1,5 @@ -use embedded_hal::blocking::spi::Transfer +use embedded_hal::blocking::spi::Transfer; +use crate::Error; /* * Bit Masks for CFG_Write @@ -23,7 +24,100 @@ 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) + } +} + diff --git a/src/lib.rs b/src/lib.rs index 32d30e8..5c5acb9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,7 @@ use cortex_m_semihosting::hprintln; pub mod spi_slave; use crate::spi_slave::Parts; -//pub mod generic_spi_device; - +pub mod config_register; pub mod attenuator; /* diff --git a/src/main.rs b/src/main.rs index 97ac942..7f39442 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ use firmware; use firmware::{ CPLD, attenuator::Attenuator, + config_register::ConfigRegister, }; #[entry] @@ -90,6 +91,9 @@ fn main() -> ! { attenuator.set_attenuation(attenuation); attenuator.set_channel_attenuation(2, 15.3); + let mut config = ConfigRegister::new(parts.spi1); + hprintln!("{}", config.set_configuration(0xDEADBEEF).unwrap()).unwrap(); + loop { nop(); }