From 6d2ce9f42aae32f5c1289c334dcdea22542a27ff Mon Sep 17 00:00:00 2001 From: Noah Sprenger Date: Sun, 8 Dec 2024 20:18:54 -0500 Subject: [PATCH] Rework driver to avoid taking ownership of spi peripheral. --- Cargo.lock | 2 +- Cargo.toml | 3 +- boards/temperature/Cargo.toml | 1 + boards/temperature/src/adc_manager.rs | 80 +++++ boards/temperature/src/main.rs | 6 + crates/ads126x/src/lib.rs | 436 ++++++++++++++++---------- crates/ads126x/src/register.rs | 66 ++-- crates/ads126x/src/register/enums.rs | 258 +++++++-------- 8 files changed, 531 insertions(+), 321 deletions(-) create mode 100644 boards/temperature/src/adc_manager.rs diff --git a/Cargo.lock b/Cargo.lock index ff0ed16..d7de0cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -939,7 +939,6 @@ dependencies = [ [[package]] name = "stm32h7xx-hal" version = "0.16.0" -source = "git+https://github.com/uorocketry/stm32h7xx-hal#412160269f1729d55bc52de17463695db2c6bc6c" dependencies = [ "bare-metal 1.0.0", "cast", @@ -1006,6 +1005,7 @@ dependencies = [ name = "temperature" version = "0.1.0" dependencies = [ + "ads126x", "chrono", "common-arm", "cortex-m", diff --git a/Cargo.toml b/Cargo.toml index 8cb4cf7..7415b95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,9 @@ members = ["boards/*", "examples/*", "crates/*"] default-members = ["boards/*", "examples/*"] [workspace.dependencies.stm32h7xx-hal] -git = "https://github.com/uorocketry/stm32h7xx-hal" +# git = "https://github.com/uorocketry/stm32h7xx-hal" # We use 35 even though we have the 33. +path = "/home/bonjour/Rocketry/stm32h7xx-hal" features = ["defmt", "rt", "stm32h735", "can", "rtc"] [workspace.dependencies.serde] diff --git a/boards/temperature/Cargo.toml b/boards/temperature/Cargo.toml index 81939a3..494b916 100644 --- a/boards/temperature/Cargo.toml +++ b/boards/temperature/Cargo.toml @@ -22,6 +22,7 @@ defmt-rtt = { workspace = true } panic-probe = { workspace = true } chrono = { workspace = true } messages = {workspace = true} +ads126x = {path = "../../crates/ads126x"} [dev-dependencies] defmt-test = { workspace = true } diff --git a/boards/temperature/src/adc_manager.rs b/boards/temperature/src/adc_manager.rs new file mode 100644 index 0000000..cd9be5e --- /dev/null +++ b/boards/temperature/src/adc_manager.rs @@ -0,0 +1,80 @@ +use ads126x::{ + register::{DataRate, Mode1Register, Mode2Register}, + ADCCommand, Ads126x, +}; + +use common_arm::spawn; +use stm32h7xx_hal::{ + gpio::{Output, Pin, PushPull}, + spi::Spi, +}; + +use crate::app::delay; + +pub struct AdcManager { + pub spi: Spi, + pub adc1: Ads126x>>, + pub adc2: Ads126x>>, + pub adc1_cs: Pin<'A', 4, Output>, + pub adc2_cs: Pin<'A', 5, Output>, +} + +impl AdcManager { + pub fn new( + spi: Spi, + adc1_pin: Pin<'A', 0, Output>, + adc2_pin: Pin<'A', 1, Output>, + adc1_cs: Pin<'A', 4, Output>, + adc2_cs: Pin<'A', 5, Output>, + ) -> Self { + Self { + spi, + adc1: Ads126x::new(adc1_pin), + adc2: Ads126x::new(adc2_pin), + adc1_cs, + adc2_cs, + } + } + + pub fn init_adc1(&mut self) -> Result<(), ads126x::error::ADS126xError> { + self.adc2_cs.set_high(); + self.adc1_cs.set_low(); + self.adc1.reset()?; + + spawn!(delay, 1000); + + let mut mode1_cfg = Mode1Register::default(); + mode1_cfg.set_filter(ads126x::register::DigitalFilter::Sinc1); + self.adc1.set_mode1(&mode1_cfg, &mut self.spi)?; + + let mut mode2_cfg = Mode2Register::default(); + mode2_cfg.set_dr(DataRate::SPS1200); + self.adc1.set_mode2(&mode2_cfg, &mut self.spi)?; + + self.adc1.send_command(ADCCommand::START1, &mut self.spi)?; + self.adc1.send_command(ADCCommand::START2, &mut self.spi)?; + + Ok(()) + } + + pub fn init_adc2(&mut self) -> Result<(), ads126x::error::ADS126xError> { + self.adc1_cs.set_high(); + self.adc2_cs.set_low(); + self.adc2.reset()?; + + spawn!(delay, 1000); + + let mut mode1_cfg = Mode1Register::default(); + mode1_cfg.set_filter(ads126x::register::DigitalFilter::Sinc1); + self.adc1.set_mode1(&mode1_cfg, &mut self.spi)?; + + let mut mode2_cfg = Mode2Register::default(); + mode2_cfg.set_dr(DataRate::SPS1200); + self.adc1.set_mode2(&mode2_cfg, &mut self.spi)?; + + self.adc1.send_command(ADCCommand::START1, &mut self.spi)?; + self.adc1.send_command(ADCCommand::START2, &mut self.spi)?; + + Ok(()) + } +} diff --git a/boards/temperature/src/main.rs b/boards/temperature/src/main.rs index 2553651..d8ec809 100644 --- a/boards/temperature/src/main.rs +++ b/boards/temperature/src/main.rs @@ -1,6 +1,7 @@ #![no_std] #![no_main] +mod adc_manager; mod communication; mod data_manager; mod types; @@ -380,6 +381,11 @@ mod app { } } + #[task(priority = 3)] + async fn delay(_cx: delay::Context, delay: u32) { + Mono::delay(delay.millis()).await; + } + #[task(shared = [data_manager, &em, rtc])] async fn state_send(mut cx: state_send::Context) { let state_data = cx diff --git a/crates/ads126x/src/lib.rs b/crates/ads126x/src/lib.rs index 4330059..f918978 100644 --- a/crates/ads126x/src/lib.rs +++ b/crates/ads126x/src/lib.rs @@ -1,27 +1,28 @@ #![no_std] #![no_main] -mod error; -mod register; +pub mod error; +pub mod register; use error::ADS126xError; use register::{ - Adc2CfgRegister, Adc2MuxRegister, GpioConRegister, GpioDatRegister, GpioDirRegister, IdRegister, IdacMagRegister, IdacMuxRegister, InpMuxRegister, InterfaceRegister, Mode0Register, Mode1Register, Mode2Register, PowerRegister, RefMuxRegister, Register, TdacnRegister, TdacpRegister + Adc2CfgRegister, Adc2MuxRegister, GpioConRegister, GpioDatRegister, GpioDirRegister, + IdRegister, IdacMagRegister, IdacMuxRegister, InpMuxRegister, InterfaceRegister, Mode0Register, + Mode1Register, Mode2Register, PowerRegister, RefMuxRegister, Register, TdacnRegister, + TdacpRegister, }; -use embedded_hal::spi::FullDuplex; use embedded_hal::digital::v2::OutputPin; +use embedded_hal::spi::FullDuplex; use heapless::Vec; /// The [`Result`] type for ADS126x operations. pub type Result = core::result::Result; -pub struct ADS126x +pub struct Ads126x where - SPI: FullDuplex, - GpioPin: OutputPin, + GpioPin: OutputPin, { - spi: SPI, reset_pin: GpioPin, } @@ -50,34 +51,15 @@ fn delay(delay: u32) { } } -impl ADS126x +impl Ads126x where - SPI: FullDuplex, - GpioPin: OutputPin, + GpioPin: OutputPin, { - pub fn new(spi: SPI, reset_pin: GpioPin) -> Self { - Self { spi, reset_pin } + pub fn new(reset_pin: GpioPin) -> Self { + Self { reset_pin } } - pub fn init(&mut self) -> Result<()> { - self.reset()?; - // write configuration registers - delay(65536); // must wait 2^16 clock cycles, is this SPI clock? - let mut mode2_cfg = Mode2Register::default(); - mode2_cfg.set_dr(register::DataRate::SPS1200); - self.set_mode2(&mode2_cfg)?; - - // Set the rest of the registers below - // ... - - // start adc1 - self.send_command(ADCCommand::START1)?; - // start adc2 - self.send_command(ADCCommand::START2)?; - Ok(()) - } - - fn reset(&mut self) -> Result<()> { + pub fn reset(&mut self) -> Result<()> { self.reset_pin.set_high().map_err(|_| ADS126xError::IO)?; delay(1000); self.reset_pin.set_low().map_err(|_| ADS126xError::IO)?; @@ -87,7 +69,10 @@ where Ok(()) } - pub fn send_command(&mut self, command: ADCCommand) -> Result<()> { + pub fn send_command(&mut self, command: ADCCommand, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { let (opcode1, opcode2) = match command { ADCCommand::NOP => (0x00, None), ADCCommand::RESET => (0x06, None), @@ -107,64 +92,88 @@ where ADCCommand::WREG(addr, num) => (0x40 | addr as u8, Some(num)), }; - self.spi.send(opcode1).map_err(|_| ADS126xError::IO)?; + spi.send(opcode1).map_err(|_| ADS126xError::IO)?; if let Some(op2) = opcode2 { - self.spi.send(op2).map_err(|_| ADS126xError::IO)?; + spi.send(op2).map_err(|_| ADS126xError::IO)?; } Ok(()) } /// Reads data from multiple registers starting at the provided register. /// To read a single register, see [`ADS126x::read_register`]. - /// + /// /// Vector returns byte for each register read in order registers were read (increasing address). - pub fn read_multiple_registers(&mut self, reg: Register, num: u8) -> Result> { + pub fn read_multiple_registers( + &mut self, + reg: Register, + num: u8, + spi: &mut SPI, + ) -> Result> + where + SPI: FullDuplex, + { if num > 27 { return Err(ADS126xError::InvalidInputData); } - self.send_command(ADCCommand::RREG(reg, num - 1))?; + self.send_command(ADCCommand::RREG(reg, num - 1), spi)?; let mut buffer: Vec = Vec::new(); for _ in 0..num { buffer - .push(self.spi.read().map_err(|_| ADS126xError::IO)?) + .push(spi.read().map_err(|_| ADS126xError::IO)?) .map_err(|_| ADS126xError::InvalidInputData)?; } Ok(buffer) } - /// Reads data from only the single provided register. /// To read multiple registers, see [`ADS126x::read_multiple_registers`]. - pub fn read_register(&mut self, reg: Register) -> Result { - // zero since number of registers read - 1, so 1-1=0. - self.send_command(ADCCommand::RREG(reg, 0))?; - let data = self.spi.read().map_err(|_| ADS126xError::IO)?; + pub fn read_register(&mut self, reg: Register, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + // zero since number of registers read - 1, so 1-1=0. + self.send_command(ADCCommand::RREG(reg, 0), spi)?; + let data = spi.read().map_err(|_| ADS126xError::IO)?; Ok(data) } /// Writes data to multiple registers starting at the provided register. /// To write data to a single register, see [`ADS126x::write_register`]. - /// + /// /// Data has byte for each register in order registers are written to (increasing address). - pub fn write_multiple_registers(&mut self, reg: Register, data: &[u8]) -> Result<()> { + pub fn write_multiple_registers( + &mut self, + reg: Register, + data: &[u8], + spi: &mut SPI, + ) -> Result<()> + where + SPI: FullDuplex, + { if data.len() > 27 { return Err(ADS126xError::InvalidInputData); } - self.send_command(ADCCommand::WREG(reg, data.len() as u8 - 1))?; + self.send_command(ADCCommand::WREG(reg, data.len() as u8 - 1), spi)?; for &byte in data { - self.spi.send(byte).map_err(|_| ADS126xError::IO)?; + spi.send(byte).map_err(|_| ADS126xError::IO)?; } Ok(()) } /// Writes data to only the single provided register. /// To write data to multiple registers, see [`ADS126x::write_multiple_registers`]. - pub fn write_register(&mut self, reg: Register, data: u8) -> Result<()> { - self.send_command(ADCCommand::WREG(reg, 0))?; - self.spi.send(data).map_err(|_| ADS126xError::IO) - } - - pub fn get_id(&mut self) -> Result { - let bits = self.read_register(Register::ID)?; + pub fn write_register(&mut self, reg: Register, data: u8, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.send_command(ADCCommand::WREG(reg, 0), spi)?; + spi.send(data).map_err(|_| ADS126xError::IO) + } + + pub fn get_id(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::ID, spi)?; let data = IdRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -172,8 +181,11 @@ where } } - pub fn get_power(&mut self) -> Result { - let bits = self.read_register(Register::POWER)?; + pub fn get_power(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::POWER, spi)?; let data = PowerRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -181,12 +193,18 @@ where } } - pub fn set_power(&mut self, reg: &PowerRegister) -> Result<()> { - self.write_register(Register::POWER, reg.bits()) + pub fn set_power(&mut self, reg: &PowerRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::POWER, reg.bits(), spi) } - pub fn get_interface(&mut self) -> Result { - let bits = self.read_register(Register::INTERFACE)?; + pub fn get_interface(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::INTERFACE, spi)?; let data = InterfaceRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -194,12 +212,18 @@ where } } - pub fn set_interface(&mut self, reg: &InterfaceRegister) -> Result<()> { - self.write_register(Register::INTERFACE, reg.bits()) + pub fn set_interface(&mut self, reg: &InterfaceRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::INTERFACE, reg.bits(), spi) } - pub fn get_mode0(&mut self) -> Result { - let bits = self.read_register(Register::MODE0)?; + pub fn get_mode0(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::MODE0, spi)?; let data = Mode0Register::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -207,12 +231,18 @@ where } } - pub fn set_mode0(&mut self, reg: &Mode0Register) -> Result<()> { - self.write_register(Register::MODE0, reg.bits()) + pub fn set_mode0(&mut self, reg: &Mode0Register, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::MODE0, reg.bits(), spi) } - - pub fn get_mode1(&mut self) -> Result { - let bits = self.read_register(Register::MODE1)?; + + pub fn get_mode1(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::MODE1, spi)?; let data = Mode1Register::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -220,12 +250,18 @@ where } } - pub fn set_mode1(&mut self, reg: &Mode1Register) -> Result<()> { - self.write_register(Register::MODE1, reg.bits()) + pub fn set_mode1(&mut self, reg: &Mode1Register, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::MODE1, reg.bits(), spi) } - - pub fn get_mode2(&mut self) -> Result { - let bits = self.read_register(Register::MODE2)?; + + pub fn get_mode2(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::MODE2, spi)?; let data = Mode2Register::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -233,12 +269,18 @@ where } } - pub fn set_mode2(&mut self, reg: &Mode2Register) -> Result<()> { - self.write_register(Register::MODE2, reg.bits()) + pub fn set_mode2(&mut self, reg: &Mode2Register, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::MODE2, reg.bits(), spi) } - pub fn get_inpmux(&mut self) -> Result { - let bits = self.read_register(Register::INPMUX)?; + pub fn get_inpmux(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::INPMUX, spi)?; let data = InpMuxRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -246,48 +288,62 @@ where } } - pub fn set_inpmux(&mut self, reg: &InpMuxRegister) -> Result<()> { - self.write_register(Register::INPMUX, reg.bits()) + pub fn set_inpmux(&mut self, reg: &InpMuxRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::INPMUX, reg.bits(), spi) } - pub fn get_ofcal(&mut self) -> Result { - let bytes = self.read_multiple_registers(Register::OFCAL0, 3)?; // [OFCAL0, OFCAL1, OFCAL2] - let res = (bytes[2] as u32) << 16 | - (bytes[1] as u32) << 8 | - (bytes[0] as u32); + pub fn get_ofcal(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bytes = self.read_multiple_registers(Register::OFCAL0, 3, spi)?; // [OFCAL0, OFCAL1, OFCAL2] + let res = (bytes[2] as u32) << 16 | (bytes[1] as u32) << 8 | (bytes[0] as u32); Ok(res) } - - pub fn set_ofcal(&mut self, ofcal: u32) -> Result<()> { + + pub fn set_ofcal(&mut self, ofcal: u32, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { // Will not panic as & 0xFF ensures values are u8 let res: [u8; 3] = [ u8::try_from(ofcal & 0xFF).unwrap(), u8::try_from((ofcal >> 8) & 0xFF).unwrap(), u8::try_from((ofcal >> 16) & 0xFF).unwrap(), ]; - self.write_multiple_registers(Register::OFCAL0, &res) + self.write_multiple_registers(Register::OFCAL0, &res, spi) } - pub fn get_fscal(&mut self) -> Result { - let bytes = self.read_multiple_registers(Register::FSCAL0, 3)?; // [FSCAL0, FSCAL1, FSCAL2] - let res = (bytes[2] as u32) << 16 | - (bytes[1] as u32) << 8 | - (bytes[0] as u32); + pub fn get_fscal(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bytes = self.read_multiple_registers(Register::FSCAL0, 3, spi)?; // [FSCAL0, FSCAL1, FSCAL2] + let res = (bytes[2] as u32) << 16 | (bytes[1] as u32) << 8 | (bytes[0] as u32); Ok(res) } - - pub fn set_fscal(&mut self, fscal: u32) -> Result<()> { + + pub fn set_fscal(&mut self, fscal: u32, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { // Will not panic as & 0xFF ensures values are u8 let res: [u8; 3] = [ u8::try_from(fscal & 0xFF).unwrap(), u8::try_from((fscal >> 8) & 0xFF).unwrap(), u8::try_from((fscal >> 16) & 0xFF).unwrap(), ]; - self.write_multiple_registers(Register::FSCAL0, &res) + self.write_multiple_registers(Register::FSCAL0, &res, spi) } - pub fn get_idacmux(&mut self) -> Result { - let bits = self.read_register(Register::IDACMUX)?; + pub fn get_idacmux(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::IDACMUX, spi)?; let data = IdacMuxRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -295,12 +351,18 @@ where } } - pub fn set_idacmux(&mut self, reg: &IdacMuxRegister) -> Result<()> { - self.write_register(Register::IDACMUX, reg.bits()) + pub fn set_idacmux(&mut self, reg: &IdacMuxRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::IDACMUX, reg.bits(), spi) } - pub fn get_idacmag(&mut self) -> Result { - let bits = self.read_register(Register::IDACMAG)?; + pub fn get_idacmag(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::IDACMAG, spi)?; let data = IdacMagRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -308,12 +370,18 @@ where } } - pub fn set_idacmag(&mut self, reg: &IdacMagRegister) -> Result<()> { - self.write_register(Register::IDACMAG, reg.bits()) + pub fn set_idacmag(&mut self, reg: &IdacMagRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::IDACMAG, reg.bits(), spi) } - pub fn get_refmux(&mut self) -> Result { - let bits = self.read_register(Register::REFMUX)?; + pub fn get_refmux(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::REFMUX, spi)?; let data = RefMuxRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -321,12 +389,18 @@ where } } - pub fn set_refmux(&mut self, reg: &RefMuxRegister) -> Result<()> { - self.write_register(Register::REFMUX, reg.bits()) + pub fn set_refmux(&mut self, reg: &RefMuxRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::REFMUX, reg.bits(), spi) } - pub fn get_tdacp(&mut self) -> Result { - let bits = self.read_register(Register::TDACP)?; + pub fn get_tdacp(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::TDACP, spi)?; let data = TdacpRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -334,12 +408,18 @@ where } } - pub fn set_tdacp(&mut self, reg: &TdacpRegister) -> Result<()> { - self.write_register(Register::TDACP, reg.bits()) + pub fn set_tdacp(&mut self, reg: &TdacpRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::TDACP, reg.bits(), spi) } - pub fn get_tdacn(&mut self) -> Result { - let bits = self.read_register(Register::TDACN)?; + pub fn get_tdacn(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::TDACN, spi)?; let data = TdacnRegister::from_bits(bits); match data { Some(reg) => Ok(reg), @@ -347,105 +427,147 @@ where } } - pub fn set_tdacn(&mut self, reg: &TdacnRegister) -> Result<()> { - self.write_register(Register::TDACN, reg.bits()) + pub fn set_tdacn(&mut self, reg: &TdacnRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::TDACN, reg.bits(), spi) } - pub fn get_gpiocon(&mut self) -> Result { - let bits = self.read_register(Register::GPIOCON)?; + pub fn get_gpiocon(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::GPIOCON, spi)?; let data = GpioConRegister::from_bits(bits); match data { Some(reg) => Ok(reg), None => Err(ADS126xError::InvalidInputData), - } + } } - pub fn set_gpiocon(&mut self, reg: &GpioConRegister) -> Result<()> { - self.write_register(Register::GPIOCON, reg.bits()) + pub fn set_gpiocon(&mut self, reg: &GpioConRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::GPIOCON, reg.bits(), spi) } - pub fn get_gpiodir(&mut self) -> Result { - let bits = self.read_register(Register::GPIODIR)?; + pub fn get_gpiodir(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::GPIODIR, spi)?; let data = GpioDirRegister::from_bits(bits); match data { Some(reg) => Ok(reg), None => Err(ADS126xError::InvalidInputData), - } + } } - pub fn set_gpiodir(&mut self, reg: &GpioDirRegister) -> Result<()> { - self.write_register(Register::GPIODIR, reg.bits()) + pub fn set_gpiodir(&mut self, reg: &GpioDirRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::GPIODIR, reg.bits(), spi) } - pub fn get_gpiodat(&mut self) -> Result { - let bits = self.read_register(Register::GPIODAT)?; + pub fn get_gpiodat(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::GPIODAT, spi)?; let data = GpioDatRegister::from_bits(bits); match data { Some(reg) => Ok(reg), None => Err(ADS126xError::InvalidInputData), - } + } } - pub fn set_gpiodat(&mut self, reg: &GpioDatRegister) -> Result<()> { - self.write_register(Register::GPIODAT, reg.bits()) + pub fn set_gpiodat(&mut self, reg: &GpioDatRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::GPIODAT, reg.bits(), spi) } - pub fn get_adc2cfg(&mut self) -> Result { - let bits = self.read_register(Register::ADC2CFG)?; + pub fn get_adc2cfg(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::ADC2CFG, spi)?; let data = Adc2CfgRegister::from_bits(bits); match data { Some(reg) => Ok(reg), None => Err(ADS126xError::InvalidInputData), - } + } } - pub fn set_adc2cfg(&mut self, reg: &Adc2CfgRegister) -> Result<()> { - self.write_register(Register::ADC2CFG, reg.bits()) + pub fn set_adc2cfg(&mut self, reg: &Adc2CfgRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::ADC2CFG, reg.bits(), spi) } - - pub fn get_adc2mux(&mut self) -> Result { - let bits = self.read_register(Register::ADC2MUX)?; + pub fn get_adc2mux(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bits = self.read_register(Register::ADC2MUX, spi)?; let data = Adc2MuxRegister::from_bits(bits); match data { Some(reg) => Ok(reg), None => Err(ADS126xError::InvalidInputData), - } + } } - pub fn set_adc2mux(&mut self, reg: &Adc2MuxRegister) -> Result<()> { - self.write_register(Register::ADC2MUX, reg.bits()) + pub fn set_adc2mux(&mut self, reg: &Adc2MuxRegister, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { + self.write_register(Register::ADC2MUX, reg.bits(), spi) } - pub fn get_adc2ofc(&mut self) -> Result { - let bytes = self.read_multiple_registers(Register::ADC2OFC0, 2)?; // [ADC2OFC0, ADC2OFC1] - let res = (bytes[1] as u16) << 8 | - (bytes[0] as u16); + pub fn get_adc2ofc(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bytes = self.read_multiple_registers(Register::ADC2OFC0, 2, spi)?; // [ADC2OFC0, ADC2OFC1] + let res = (bytes[1] as u16) << 8 | (bytes[0] as u16); Ok(res) } - - pub fn set_adc2ofc(&mut self, ofc2: u16) -> Result<()> { + + pub fn set_adc2ofc(&mut self, ofc2: u16, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { // Will not panic as & 0xFF ensures values are u8 let res: [u8; 2] = [ u8::try_from(ofc2 & 0xFF).unwrap(), u8::try_from((ofc2 >> 8) & 0xFF).unwrap(), ]; - self.write_multiple_registers(Register::ADC2OFC0, &res) + self.write_multiple_registers(Register::ADC2OFC0, &res, spi) } - pub fn get_adc2fsc(&mut self) -> Result { - let bytes = self.read_multiple_registers(Register::ADC2FSC0, 2)?; // [ADC2FSC0, ADC2FSC1] - let res = (bytes[1] as u16) << 8 | - (bytes[0] as u16); + pub fn get_adc2fsc(&mut self, spi: &mut SPI) -> Result + where + SPI: FullDuplex, + { + let bytes = self.read_multiple_registers(Register::ADC2FSC0, 2, spi)?; // [ADC2FSC0, ADC2FSC1] + let res = (bytes[1] as u16) << 8 | (bytes[0] as u16); Ok(res) } - - pub fn set_adc2fsc(&mut self, fsc2: u32) -> Result<()> { + + pub fn set_adc2fsc(&mut self, fsc2: u32, spi: &mut SPI) -> Result<()> + where + SPI: FullDuplex, + { // Will not panic as & 0xFF ensures values are u8 let res: [u8; 2] = [ u8::try_from(fsc2 & 0xFF).unwrap(), u8::try_from((fsc2 >> 8) & 0xFF).unwrap(), ]; - self.write_multiple_registers(Register::ADC2FSC0, &res) + self.write_multiple_registers(Register::ADC2FSC0, &res, spi) } } diff --git a/crates/ads126x/src/register.rs b/crates/ads126x/src/register.rs index 4904043..56d5f35 100644 --- a/crates/ads126x/src/register.rs +++ b/crates/ads126x/src/register.rs @@ -1,37 +1,37 @@ mod enums; -pub use enums::*; use bitflags::bitflags; +pub use enums::*; #[repr(u8)] pub enum Register { - ID = 0x00, - POWER = 0x01, + ID = 0x00, + POWER = 0x01, INTERFACE = 0x02, - MODE0 = 0x03, - MODE1 = 0x04, - MODE2 = 0x05, - INPMUX = 0x06, - OFCAL0 = 0x07, - OFCAL1 = 0x08, - OFCAL2 = 0x09, - FSCAL0 = 0x0A, - FSCAL1 = 0x0B, - FSCAL2 = 0x0C, - IDACMUX = 0x0D, - IDACMAG = 0x0E, - REFMUX = 0x0F, - TDACP = 0x10, - TDACN = 0x11, - GPIOCON = 0x12, - GPIODIR = 0x13, - GPIODAT = 0x14, - ADC2CFG = 0x15, - ADC2MUX = 0x16, - ADC2OFC0 = 0x17, - ADC2OFC1 = 0x18, - ADC2FSC0 = 0x19, - ADC2FSC1 = 0x1A, + MODE0 = 0x03, + MODE1 = 0x04, + MODE2 = 0x05, + INPMUX = 0x06, + OFCAL0 = 0x07, + OFCAL1 = 0x08, + OFCAL2 = 0x09, + FSCAL0 = 0x0A, + FSCAL1 = 0x0B, + FSCAL2 = 0x0C, + IDACMUX = 0x0D, + IDACMAG = 0x0E, + REFMUX = 0x0F, + TDACP = 0x10, + TDACN = 0x11, + GPIOCON = 0x12, + GPIODIR = 0x13, + GPIODAT = 0x14, + ADC2CFG = 0x15, + ADC2MUX = 0x16, + ADC2OFC0 = 0x17, + ADC2OFC1 = 0x18, + ADC2FSC0 = 0x19, + ADC2FSC1 = 0x1A, } bitflags! { @@ -101,7 +101,7 @@ impl PowerRegister { self.contains(PowerRegister::RESET) } - // must be cleared if set to detect further resets. + // must be cleared if set to detect further resets. pub fn clear_reset(&mut self) { self.remove(PowerRegister::RESET); } @@ -557,7 +557,7 @@ impl RefMuxRegister { 0b100 => RefPositiveInp::IntAnlgSup, 0b101..=0b111 => panic!("Reserved Reference Positive Input"), - _ => unreachable!() + _ => unreachable!(), } } @@ -576,7 +576,7 @@ bitflags! { } impl TdacpRegister { - // there is no defined default values in the datasheet so just zeros. + // there is no defined default values in the datasheet so just zeros. pub fn default() -> Self { TdacpRegister::from_bits_truncate(0b0000_0000) } @@ -617,13 +617,13 @@ impl TdacpRegister { bitflags! { pub struct TdacnRegister: u8 { const OUTN = 0b1000_0000; - + const _ = 0b1001_1111; } } impl TdacnRegister { - // there is no defined default values in the datasheet so just zeros. + // there is no defined default values in the datasheet so just zeros. pub fn default() -> Self { TdacnRegister::from_bits_truncate(0b0000_0000) } @@ -718,7 +718,7 @@ bitflags! { } impl GpioDatRegister { - // there is no defined default values in the datasheet so just zeros. + // there is no defined default values in the datasheet so just zeros. pub fn default() -> Self { GpioDatRegister::from_bits_truncate(0b0000_0000) } diff --git a/crates/ads126x/src/register/enums.rs b/crates/ads126x/src/register/enums.rs index 48f8430..38ff242 100644 --- a/crates/ads126x/src/register/enums.rs +++ b/crates/ads126x/src/register/enums.rs @@ -6,15 +6,15 @@ pub enum DevId { /// Conversion delays follow the pattern `D`. /// - `len` is the length of time where _ is a substitute for a decimal point. /// - `units` are the units of time where us is microseconds and ms is milliseconds. -/// +/// /// D8_7us = delay of 8.7 microseconds. D8_8ms = delay of 8.8 milliseconds. #[repr(u8)] pub enum ConversionDelay { - DNone = 0b0000, + DNone = 0b0000, D8_7us = 0b0001, - D17us = 0b0010, - D35us = 0b0011, - D69us = 0b0100, + D17us = 0b0010, + D35us = 0b0011, + D69us = 0b0100, D139us = 0b0101, D278us = 0b0110, D555us = 0b0111, @@ -28,11 +28,11 @@ impl ConversionDelay { /// Returns the delay in nanoseconds. pub fn delay(&self) -> u32 { match self { - Self::DNone => 0, + Self::DNone => 0, Self::D8_7us => 8_700, - Self::D17us => 17_000, - Self::D35us => 35_000, - Self::D69us => 69_000, + Self::D17us => 17_000, + Self::D35us => 35_000, + Self::D69us => 69_000, Self::D139us => 139_000, Self::D278us => 278_000, Self::D555us => 555_000, @@ -46,25 +46,25 @@ impl ConversionDelay { #[repr(u8)] pub enum ChopMode { - Disabled = 0b00, - InChopEnabled = 0b01, - IdacEnabled = 0b10, + Disabled = 0b00, + InChopEnabled = 0b01, + IdacEnabled = 0b10, InChopAndIdacEnabled = 0b11, } /// SBMAGs follow the pattern `B` or `R`. /// - `mag` is the magnitude of current or resistance where _ is a substitute for a decimal point. /// - `units` are the units of current or resistance where uA is microamperes and MOhm is megaohms. -/// +/// /// B0_5uA = 0.5 microamps of current. R10MOhm = resistance of 10 megaohms. #[repr(u8)] pub enum SensorBiasMagnitude { - BNone = 0b000, - B0_5uA = 0b001, - B2uA = 0b010, - B10uA = 0b011, - B50uA = 0b100, - B200uA = 0b101, + BNone = 0b000, + B0_5uA = 0b001, + B2uA = 0b010, + B10uA = 0b011, + B50uA = 0b100, + B200uA = 0b101, R10MOhm = 0b110, } @@ -72,7 +72,7 @@ pub enum SensorBiasMagnitude { pub enum CrcMode { Disabled = 0b00, Checksum = 0b01, - CRC = 0b10, + CRC = 0b10, } #[repr(u8)] @@ -81,28 +81,28 @@ pub enum DigitalFilter { Sinc2 = 0b001, Sinc3 = 0b010, Sinc4 = 0b011, - FIR = 0b100, + FIR = 0b100, } /// Data rates follow the pattern `SPS`. /// - `num` is the SPS rate where _ is a substitute for a decimal point. -/// +/// /// SPS2_5 = 2.5 SPS. #[repr(u8)] pub enum DataRate { - SPS2_5 = 0b0000, - SPS5 = 0b0001, - SPS10 = 0b0010, - SPS16_6 = 0b0011, // 16.6666... = 50/3 - SPS20 = 0b0100, - SPS50 = 0b0101, - SPS60 = 0b0110, - SPS100 = 0b0111, - SPS400 = 0b1000, - SPS1200 = 0b1001, - SPS2400 = 0b1010, - SPS4800 = 0b1011, - SPS7200 = 0b1100, + SPS2_5 = 0b0000, + SPS5 = 0b0001, + SPS10 = 0b0010, + SPS16_6 = 0b0011, // 16.6666... = 50/3 + SPS20 = 0b0100, + SPS50 = 0b0101, + SPS60 = 0b0110, + SPS100 = 0b0111, + SPS400 = 0b1000, + SPS1200 = 0b1001, + SPS2400 = 0b1010, + SPS4800 = 0b1011, + SPS7200 = 0b1100, SPS14400 = 0b1101, SPS19200 = 0b1110, SPS38400 = 0b1111, @@ -110,160 +110,160 @@ pub enum DataRate { #[repr(u8)] pub enum PGAGain { - VV1 = 0b000, - VV2 = 0b001, - VV4 = 0b010, - VV8 = 0b011, + VV1 = 0b000, + VV2 = 0b001, + VV4 = 0b010, + VV8 = 0b011, VV16 = 0b100, VV32 = 0b101, } #[repr(u8)] pub enum NegativeInpMux { - AIN0 = 0b0000, - AIN1 = 0b0001, - AIN2 = 0b0010, - AIN3 = 0b0011, - AIN4 = 0b0100, - AIN5 = 0b0101, - AIN6 = 0b0110, - AIN7 = 0b0111, - AIN8 = 0b1000, - AIN9 = 0b1001, - AINCOM = 0b1010, - TempSensMonNeg = 0b1011, - AnlgPwrSupMonNeg = 0b1100, - DgtlPwrSubMonNeg = 0b1101, + AIN0 = 0b0000, + AIN1 = 0b0001, + AIN2 = 0b0010, + AIN3 = 0b0011, + AIN4 = 0b0100, + AIN5 = 0b0101, + AIN6 = 0b0110, + AIN7 = 0b0111, + AIN8 = 0b1000, + AIN9 = 0b1001, + AINCOM = 0b1010, + TempSensMonNeg = 0b1011, + AnlgPwrSupMonNeg = 0b1100, + DgtlPwrSubMonNeg = 0b1101, TDACTestSignalNeg = 0b1110, - Float = 0b1111, + Float = 0b1111, } #[repr(u8)] pub enum PositiveInpMux { - AIN0 = 0b0000, - AIN1 = 0b0001, - AIN2 = 0b0010, - AIN3 = 0b0011, - AIN4 = 0b0100, - AIN5 = 0b0101, - AIN6 = 0b0110, - AIN7 = 0b0111, - AIN8 = 0b1000, - AIN9 = 0b1001, - AINCOM = 0b1010, - TempSensMonPos = 0b1011, - AnlgPwrSupMonPos = 0b1100, - DgtlPwrSubMonPos = 0b1101, + AIN0 = 0b0000, + AIN1 = 0b0001, + AIN2 = 0b0010, + AIN3 = 0b0011, + AIN4 = 0b0100, + AIN5 = 0b0101, + AIN6 = 0b0110, + AIN7 = 0b0111, + AIN8 = 0b1000, + AIN9 = 0b1001, + AINCOM = 0b1010, + TempSensMonPos = 0b1011, + AnlgPwrSupMonPos = 0b1100, + DgtlPwrSubMonPos = 0b1101, TDACTestSignalPos = 0b1110, - Float = 0b1111, + Float = 0b1111, } #[repr(u8)] pub enum IdacOutMux { - AIN0 = 0b0000, - AIN1 = 0b0001, - AIN2 = 0b0010, - AIN3 = 0b0011, - AIN4 = 0b0100, - AIN5 = 0b0101, - AIN6 = 0b0110, - AIN7 = 0b0111, - AIN8 = 0b1000, - AIN9 = 0b1001, - AINCOM = 0b1010, + AIN0 = 0b0000, + AIN1 = 0b0001, + AIN2 = 0b0010, + AIN3 = 0b0011, + AIN4 = 0b0100, + AIN5 = 0b0101, + AIN6 = 0b0110, + AIN7 = 0b0111, + AIN8 = 0b1000, + AIN9 = 0b1001, + AINCOM = 0b1010, NoConnection = 0b1011, } /// Current magnitudes follow the pattern `I`. /// - `mag` is the magnitude of current. /// - `units` are uA meaning microamperes. -/// +/// /// I50uA = 50 microamps of current. #[repr(u8)] pub enum IdacCurMag { - I50uA = 0b0000, - I100uA = 0b0001, - I250uA = 0b0010, - I500uA = 0b0011, - I750uA = 0b0100, - I1000uA = 0b0101, - I1500uA = 0b0110, - I2000uA = 0b0111, - I2500uA = 0b1000, - I3000uA = 0b1001, + I50uA = 0b0000, + I100uA = 0b0001, + I250uA = 0b0010, + I500uA = 0b0011, + I750uA = 0b0100, + I1000uA = 0b0101, + I1500uA = 0b0110, + I2000uA = 0b0111, + I2500uA = 0b1000, + I3000uA = 0b1001, } #[repr(u8)] pub enum RefNegativeInp { Int2_5VRef = 0b000, - ExtAIN1 = 0b001, - ExtAIN3 = 0b010, - ExtAIN5 = 0b011, + ExtAIN1 = 0b001, + ExtAIN3 = 0b010, + ExtAIN5 = 0b011, IntAnlgSup = 0b100, } #[repr(u8)] pub enum RefPositiveInp { Int2_5VRef = 0b000, - ExtAIN0 = 0b001, - ExtAIN2 = 0b010, - ExtAIN4 = 0b011, + ExtAIN0 = 0b001, + ExtAIN2 = 0b010, + ExtAIN4 = 0b011, IntAnlgSup = 0b100, } /// Voltages are with respect to V_AVSS. /// Output magnitudes follow the pattern `V`. /// - `num` is the output magnitude in volts where _ is a substitute for a decimal point. -/// +/// /// V4_5 = 4.5 V. #[repr(u8)] pub enum TdacOutMag { - V4_5 = 0b01001, - V3_5 = 0b01000, - V3 = 0b00111, - V2_75 = 0b00110, - V2_625 = 0b00101, - V2_5625 = 0b00100, - V2_53125 = 0b00011, - V2_515625 = 0b00010, + V4_5 = 0b01001, + V3_5 = 0b01000, + V3 = 0b00111, + V2_75 = 0b00110, + V2_625 = 0b00101, + V2_5625 = 0b00100, + V2_53125 = 0b00011, + V2_515625 = 0b00010, V2_5078125 = 0b00001, - V2_5 = 0b00000, + V2_5 = 0b00000, V2_4921875 = 0b10001, - V2_484375 = 0b10010, - V2_46875 = 0b10011, - V2_4375 = 0b10100, - V2_375 = 0b10101, - V2_25 = 0b10110, - V2 = 0b10111, - V1_5 = 0b11000, - V0_5 = 0b11001, + V2_484375 = 0b10010, + V2_46875 = 0b10011, + V2_4375 = 0b10100, + V2_375 = 0b10101, + V2_25 = 0b10110, + V2 = 0b10111, + V1_5 = 0b11000, + V0_5 = 0b11001, } #[repr(u8)] pub enum Adc2Gain { - VV1 = 0b000, - VV2 = 0b001, - VV4 = 0b010, - VV8 = 0b011, - VV16 = 0b100, - VV32 = 0b101, - VV64 = 0b110, + VV1 = 0b000, + VV2 = 0b001, + VV4 = 0b010, + VV8 = 0b011, + VV16 = 0b100, + VV32 = 0b101, + VV64 = 0b110, VV128 = 0b111, } #[repr(u8)] pub enum Adc2RefInp { Int2_5VRef = 0b000, - ExtAIN0_1 = 0b001, - ExtAIN2_3 = 0b010, - ExtAIN4_5 = 0b011, + ExtAIN0_1 = 0b001, + ExtAIN2_3 = 0b010, + ExtAIN4_5 = 0b011, IntAnlgSup = 0b100, } #[repr(u8)] pub enum Adc2DataRate { - SPS10 = 0b00, - SPS100 = 0b01, - SPS400 = 0b10, - SPS800 = 0b11, + SPS10 = 0b00, + SPS100 = 0b01, + SPS400 = 0b10, + SPS800 = 0b11, }