diff --git a/Cargo.toml b/Cargo.toml index 3b306f8..266f716 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,9 +12,10 @@ description = "A generic rust driver to support RFM69 family wireless chips" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -embedded-hal = "0.2" +embedded-hal = "1.0.0" [dev-dependencies] anyhow = "1.0" -linux-embedded-hal = "^0.3.2" +embedded-hal-bus = { version = "0.1.0", features = ["std"] } +linux-embedded-hal = "0.4.0" utilities = { path = "utilities" } diff --git a/examples/low_power_lab_receive.rs b/examples/low_power_lab_receive.rs index efd7271..d2e6d68 100644 --- a/examples/low_power_lab_receive.rs +++ b/examples/low_power_lab_receive.rs @@ -1,7 +1,8 @@ use anyhow::Result; +use embedded_hal_bus::spi::ExclusiveDevice; use linux_embedded_hal::spidev::{SpiModeFlags, SpidevOptions}; use linux_embedded_hal::sysfs_gpio::Direction; -use linux_embedded_hal::{Spidev, SysfsPin}; +use linux_embedded_hal::{Delay, SpidevBus, SysfsPin}; use rfm69::{low_power_lab_defaults, Rfm69}; use utilities::{rfm_error, Packet}; @@ -12,20 +13,18 @@ fn main() -> Result<()> { cs.set_direction(Direction::High)?; // Configure SPI 8 bits, Mode 0 - let mut spi = Spidev::open("/dev/spidev0.0")?; + let mut spi_bus = SpidevBus::open("/dev/spidev0.0")?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(1_000_000) .mode(SpiModeFlags::SPI_MODE_0) .build(); - spi.configure(&options)?; + spi_bus.configure(&options)?; + + let spi = ExclusiveDevice::new(spi_bus, cs, Delay); // Create rfm struct with default compatible with LowPowerLabs - let mut rfm = rfm_error!(low_power_lab_defaults( - Rfm69::new(spi, cs), - 100, - 433_000_000 - ))?; + let mut rfm = rfm_error!(low_power_lab_defaults(Rfm69::new(spi), 100, 433_000_000))?; // Print content of all RFM registers for (index, val) in rfm_error!(rfm.read_all_regs())?.iter().enumerate() { diff --git a/examples/low_power_lab_send.rs b/examples/low_power_lab_send.rs index 3420205..16ee621 100644 --- a/examples/low_power_lab_send.rs +++ b/examples/low_power_lab_send.rs @@ -1,7 +1,8 @@ use anyhow::Result; +use embedded_hal_bus::spi::ExclusiveDevice; use linux_embedded_hal::spidev::{SpiModeFlags, SpidevOptions}; use linux_embedded_hal::sysfs_gpio::Direction; -use linux_embedded_hal::{Spidev, SysfsPin}; +use linux_embedded_hal::{Delay, SpidevBus, SysfsPin}; use rfm69::{low_power_lab_defaults, Rfm69}; use utilities::{rfm_error, Packet}; @@ -12,20 +13,18 @@ fn main() -> Result<()> { cs.set_direction(Direction::High)?; // Configure SPI 8 bits, Mode 0 - let mut spi = Spidev::open("/dev/spidev0.0")?; + let mut spi_bus = SpidevBus::open("/dev/spidev0.0")?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(1_000_000) .mode(SpiModeFlags::SPI_MODE_0) .build(); - spi.configure(&options)?; + spi_bus.configure(&options)?; + + let spi = ExclusiveDevice::new(spi_bus, cs, Delay); // Create rfm struct with default compatible with LowPowerLabs - let mut rfm = rfm_error!(low_power_lab_defaults( - Rfm69::new(spi, cs), - 100, - 433_000_000 - ))?; + let mut rfm = rfm_error!(low_power_lab_defaults(Rfm69::new(spi), 100, 433_000_000))?; // Print content of all RFM registers for (index, val) in rfm_error!(rfm.read_all_regs())?.iter().enumerate() { diff --git a/examples/receive.rs b/examples/receive.rs index fc81848..6fb52e5 100644 --- a/examples/receive.rs +++ b/examples/receive.rs @@ -1,18 +1,12 @@ use anyhow::Result; use linux_embedded_hal::spidev::{SpiModeFlags, SpidevOptions}; -use linux_embedded_hal::sysfs_gpio::Direction; -use linux_embedded_hal::{Spidev, SysfsPin}; +use linux_embedded_hal::SpidevDevice; use rfm69::Rfm69; use utilities::rfm_error; fn main() -> Result<()> { - // Configure CS pin - let cs = SysfsPin::new(25); - cs.export()?; - cs.set_direction(Direction::High)?; - // Configure SPI 8 bits, Mode 0 - let mut spi = Spidev::open("/dev/spidev0.0")?; + let mut spi = SpidevDevice::open("/dev/spidev0.0")?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(1_000_000) @@ -21,7 +15,7 @@ fn main() -> Result<()> { spi.configure(&options)?; // Create rfm struct with defaults that are set after reset - let mut rfm = Rfm69::new(spi, cs); + let mut rfm = Rfm69::new(spi); // Print content of all RFM registers for (index, val) in rfm_error!(rfm.read_all_regs())?.iter().enumerate() { @@ -36,8 +30,5 @@ fn main() -> Result<()> { println!("Value at {} = {}", index, val) } - // Un-export the CS pin - SysfsPin::new(25).unexport()?; - Ok(()) } diff --git a/examples/send.rs b/examples/send.rs index eada078..e620818 100644 --- a/examples/send.rs +++ b/examples/send.rs @@ -1,18 +1,12 @@ use anyhow::Result; use linux_embedded_hal::spidev::{SpiModeFlags, SpidevOptions}; -use linux_embedded_hal::sysfs_gpio::Direction; -use linux_embedded_hal::{Spidev, SysfsPin}; +use linux_embedded_hal::SpidevDevice; use rfm69::Rfm69; use utilities::rfm_error; fn main() -> Result<()> { - // Configure CS pin - let cs = SysfsPin::new(25); - cs.export()?; - cs.set_direction(Direction::High)?; - // Configure SPI 8 bits, Mode 0 - let mut spi = Spidev::open("/dev/spidev0.0")?; + let mut spi = SpidevDevice::open("/dev/spidev0.0")?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(1_000_000) @@ -21,7 +15,7 @@ fn main() -> Result<()> { spi.configure(&options)?; // Create rfm struct with defaults that are set after reset - let mut rfm = Rfm69::new(spi, cs); + let mut rfm = Rfm69::new(spi); // Print content of all RFM registers for (index, val) in rfm_error!(rfm.read_all_regs())?.iter().enumerate() { @@ -32,8 +26,5 @@ fn main() -> Result<()> { let buffer = Vec::from(b"Hello, world!".as_ref()); rfm_error!(rfm.send(&buffer))?; - // Un-export the CS pin - SysfsPin::new(25).unexport()?; - Ok(()) } diff --git a/src/cs.rs b/src/cs.rs deleted file mode 100644 index 06fc2f2..0000000 --- a/src/cs.rs +++ /dev/null @@ -1,62 +0,0 @@ -use core::marker::PhantomData; - -use embedded_hal::digital::v2::OutputPin; - -use crate::error::{Error, Result}; - -/// An implementation of [`OutputPin`] which does nothing. This can be used for the CS line where it -/// is not needed. -pub struct NoCs; - -impl OutputPin for NoCs { - type Error = (); - - fn set_low(&mut self) -> core::result::Result<(), Self::Error> { - Ok(()) - } - - fn set_high(&mut self) -> core::result::Result<(), Self::Error> { - Ok(()) - } -} - -pub(crate) struct CsGuard<'a, T, Ecs, Espi> -where - T: OutputPin, -{ - cs: &'a mut T, - _phantom: PhantomData, -} - -impl<'a, T, Ecs, Espi> CsGuard<'a, T, Ecs, Espi> -where - T: OutputPin, -{ - pub(crate) fn new(pin: &'a mut T) -> Result { - let mut guard = CsGuard { - cs: pin, - _phantom: PhantomData, - }; - guard.select()?; - Ok(guard) - } - - fn select(&mut self) -> Result<(), Ecs, Espi> { - self.cs.set_low().map_err(Error::Cs) - } - - fn unselect(&mut self) -> Result<(), Ecs, Espi> { - self.cs.set_high().map_err(Error::Cs) - } -} - -impl<'a, T, Ecs, Espi> Drop for CsGuard<'a, T, Ecs, Espi> -where - T: OutputPin, -{ - fn drop(&mut self) { - if self.unselect().is_err() { - panic!("Cannot clear CS guard"); - } - } -} diff --git a/src/defaults.rs b/src/defaults.rs index 91e4845..9ea7576 100644 --- a/src/defaults.rs +++ b/src/defaults.rs @@ -1,5 +1,3 @@ -use embedded_hal::digital::v2::OutputPin; - use crate::error::Result; use crate::registers::{ ContinuousDagc, DataMode, DccCutoff, FifoMode, InterPacketRxDelay, LnaConfig, LnaGain, @@ -11,13 +9,12 @@ use crate::Rfm69; /// Configures RFM69 according to [LowPowerLab](https://github.com/LowPowerLab/RFM69) Arduino /// library -pub fn low_power_lab_defaults( - mut rfm: Rfm69, +pub fn low_power_lab_defaults( + mut rfm: Rfm69, network_id: u8, frequency: u32, -) -> Result, Ecs, Espi> +) -> Result, Espi> where - T: OutputPin, S: ReadWrite, { rfm.mode(Mode::Standby)?; diff --git a/src/error.rs b/src/error.rs index c867f2a..c663cff 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,7 @@ -pub(crate) type Result = core::result::Result>; +pub(crate) type Result = core::result::Result>; #[derive(Debug)] -pub enum Error { - /// Chip select pin error - Cs(Ecs), +pub enum Error { /// SPI bus error Spi(Espi), /// Timeout exceeded diff --git a/src/lib.rs b/src/lib.rs index 5eb2a41..48b8a97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,13 +27,11 @@ #![cfg_attr(not(test), no_std)] -pub use crate::cs::NoCs; pub use crate::defaults::low_power_lab_defaults; pub use crate::error::Error; pub use crate::rfm::Rfm69; -pub use crate::rw::{ReadWrite, SpiTransactional}; +pub use crate::rw::ReadWrite; -mod cs; mod defaults; mod error; mod rfm; diff --git a/src/rfm.rs b/src/rfm.rs index 83ff5a0..d3ff355 100644 --- a/src/rfm.rs +++ b/src/rfm.rs @@ -1,16 +1,12 @@ use core::convert::TryInto; -use embedded_hal::blocking::spi::Transactional; -use embedded_hal::digital::v2::OutputPin; - -use crate::cs::{CsGuard, NoCs}; use crate::error::{Error, Result}; use crate::registers::{ ContinuousDagc, DioMapping, DioPin, FifoMode, IrqFlags1, IrqFlags2, LnaConfig, Mode, Modulation, Pa13dBm1, Pa13dBm2, PacketConfig, PacketFormat, Registers, RxBw, RxBwFreq, SensitivityBoost, }; -use crate::rw::{ReadWrite, SpiTransactional}; +use crate::rw::ReadWrite; // 1_000_000 larger for better precision. const F_SCALE: u64 = 1_000_000; @@ -24,36 +20,21 @@ macro_rules! _f_scale { } /// Main struct to interact with RFM69 chip. -pub struct Rfm69 { +pub struct Rfm69 { pub(crate) spi: S, - cs: T, mode: Mode, dio: [Option; 6], rssi: i16, } -impl Rfm69> -where - S: Transactional, -{ - /// Creates a new instance with everything set to default values after restart, and no explicit - /// chip select line. This should be used when the chip select line is managed automatically by - /// the [`Transactional`] implementation, such as when using `linux_embedded_hal`. - pub fn new_without_cs(spi: S) -> Self { - Self::new(SpiTransactional(spi), NoCs) - } -} - -impl Rfm69 +impl Rfm69 where - T: OutputPin, S: ReadWrite, { /// Creates a new instance with everything set to default values after restart. - pub fn new(spi: S, cs: T) -> Self { + pub fn new(spi: S) -> Self { Rfm69 { spi, - cs, mode: Mode::Standby, dio: [None; 6], rssi: 0, @@ -61,14 +42,14 @@ where } /// Reads content of all registers that are available. - pub fn read_all_regs(&mut self) -> Result<[u8; 0x4f], Ecs, Espi> { + pub fn read_all_regs(&mut self) -> Result<[u8; 0x4f], Espi> { let mut buffer = [0u8; 0x4f]; self.read_many(Registers::OpMode, &mut buffer)?; Ok(buffer) } /// Sets the mode in corresponding register `RegOpMode (0x01)`. - pub fn mode(&mut self, mode: Mode) -> Result<(), Ecs, Espi> { + pub fn mode(&mut self, mode: Mode) -> Result<(), Espi> { if self.mode == mode { return Ok(()); } @@ -79,34 +60,34 @@ where } /// Sets the modulation in corresponding register `RegDataModul (0x02)`. - pub fn modulation(&mut self, modulation: Modulation) -> Result<(), Ecs, Espi> { + pub fn modulation(&mut self, modulation: Modulation) -> Result<(), Espi> { self.write(Registers::DataModul, modulation.value()) } /// Computes the bitrate, according to `Fosc / bit_rate` and stores it in /// `RegBitrateMsb (0x03), RegBitrateLsb (0x04)`. - pub fn bit_rate(&mut self, bit_rate: u32) -> Result<(), Ecs, Espi> { + pub fn bit_rate(&mut self, bit_rate: u32) -> Result<(), Espi> { let reg = (FOSC / _f_scale!(bit_rate)) as u16; self.write_many(Registers::BitrateMsb, ®.to_be_bytes()) } /// Computes the frequency deviation, according to `fdev / Fstep` and stores it in /// `RegFdevMsb (0x05), RegFdevLsb (0x06)`. - pub fn fdev(&mut self, fdev: u32) -> Result<(), Ecs, Espi> { + pub fn fdev(&mut self, fdev: u32) -> Result<(), Espi> { let reg = (_f_scale!(fdev) / FSTEP) as u16; self.write_many(Registers::FdevMsb, ®.to_be_bytes()) } /// Computes the radio frequency, according to `frequency / Fstep` and stores it in /// `RegFrfMsb (0x07), RegFrfMid (0x08), RegFrfLsb (0x09)`. - pub fn frequency(&mut self, frequency: u32) -> Result<(), Ecs, Espi> { + pub fn frequency(&mut self, frequency: u32) -> Result<(), Espi> { let reg = (_f_scale!(frequency) / FSTEP) as u32; self.write_many(Registers::FrfMsb, ®.to_be_bytes()[1..]) } /// Stores DIO mapping for different RFM69 modes. For DIO behavior between modes /// please refer to the corresponding table in RFM69 datasheet. - pub fn dio_mapping(&mut self, mapping: DioMapping) -> Result<(), Ecs, Espi> { + pub fn dio_mapping(&mut self, mapping: DioMapping) -> Result<(), Espi> { let pin = mapping.pin; let dio = Some(mapping); match pin { @@ -121,7 +102,7 @@ where } /// Clears stored DIO mapping for specified pin. - pub fn clear_dio(&mut self, pin: DioPin) -> Result<(), Ecs, Espi> { + pub fn clear_dio(&mut self, pin: DioPin) -> Result<(), Espi> { match pin { DioPin::Dio0 => self.dio[0] = None, DioPin::Dio1 => self.dio[1] = None, @@ -135,13 +116,13 @@ where /// Sets preamble length in corresponding registers `RegPreambleMsb (0x2C), /// RegPreambleLsb (0x2D)`. - pub fn preamble(&mut self, reg: u16) -> Result<(), Ecs, Espi> { + pub fn preamble(&mut self, reg: u16) -> Result<(), Espi> { self.write_many(Registers::PreambleMsb, ®.to_be_bytes()) } /// Sets sync config and sync words in `RegSyncConfig (0x2E), RegSyncValue1-8(0x2F-0x36)`. /// Maximal sync length is 8, pass empty buffer to clear the sync flag. - pub fn sync(&mut self, sync: &[u8]) -> Result<(), Ecs, Espi> { + pub fn sync(&mut self, sync: &[u8]) -> Result<(), Espi> { let len = sync.len(); if len == 0 { return self.update(Registers::SyncConfig, |r| r & 0x7f); @@ -155,7 +136,7 @@ where /// Sets packet settings in corresponding registers `RegPacketConfig1 (0x37), /// RegPayloadLength (0x38), RegPacketConfig2 (0x3D)`. - pub fn packet(&mut self, packet_config: PacketConfig) -> Result<(), Ecs, Espi> { + pub fn packet(&mut self, packet_config: PacketConfig) -> Result<(), Espi> { let len: u8; let mut reg = 0x00; match packet_config.format { @@ -173,17 +154,17 @@ where } /// Sets node address in corresponding register `RegNodeAdrs (0x39)`. - pub fn node_address(&mut self, a: u8) -> Result<(), Ecs, Espi> { + pub fn node_address(&mut self, a: u8) -> Result<(), Espi> { self.write(Registers::NodeAddrs, a) } /// Sets broadcast address in corresponding register `RegBroadcastAdrs (0x3A)`. - pub fn broadcast_address(&mut self, a: u8) -> Result<(), Ecs, Espi> { + pub fn broadcast_address(&mut self, a: u8) -> Result<(), Espi> { self.write(Registers::BroadcastAddrs, a) } /// Sets FIFO mode in corresponding register `RegFifoThresh (0x3C)`. - pub fn fifo_mode(&mut self, mode: FifoMode) -> Result<(), Ecs, Espi> { + pub fn fifo_mode(&mut self, mode: FifoMode) -> Result<(), Espi> { match mode { FifoMode::NotEmpty => self.update(Registers::FifoThresh, |r| r | 0x80), FifoMode::Level(level) => self.write(Registers::FifoThresh, level & 0x7f), @@ -193,7 +174,7 @@ where /// Sets AES encryption in corresponding registers `RegPacketConfig2 (0x3D), /// RegAesKey1-16 (0x3E-0x4D)`. The key must be 16 bytes long, pass empty buffer to disable /// the AES encryption. - pub fn aes(&mut self, key: &[u8]) -> Result<(), Ecs, Espi> { + pub fn aes(&mut self, key: &[u8]) -> Result<(), Espi> { let len = key.len(); if len == 0 { return self.update(Registers::PacketConfig2, |r| r & 0xfe); @@ -225,7 +206,7 @@ where /// } /// /// ``` - pub fn recv(&mut self, buffer: &mut [u8]) -> Result<(), Ecs, Espi> { + pub fn recv(&mut self, buffer: &mut [u8]) -> Result<(), Espi> { if buffer.is_empty() { return Ok(()); } @@ -252,7 +233,7 @@ where /// /// ## Note /// This function does not detect FIFO overruns. - pub fn recv_large(&mut self, buffer: &mut [u8]) -> Result { + pub fn recv_large(&mut self, buffer: &mut [u8]) -> Result { self.mode(Mode::Receiver)?; while self.is_fifo_empty()? {} @@ -280,7 +261,7 @@ where } /// Send bytes to another RFM69. This can block until all data are sent. - pub fn send(&mut self, buffer: &[u8]) -> Result<(), Ecs, Espi> { + pub fn send(&mut self, buffer: &[u8]) -> Result<(), Espi> { if buffer.is_empty() { return Ok(()); } @@ -305,7 +286,7 @@ where /// /// ## Note /// This function does not detect FIFO underruns. - pub fn send_large(&mut self, buffer: &[u8]) -> Result<(), Ecs, Espi> { + pub fn send_large(&mut self, buffer: &[u8]) -> Result<(), Espi> { let packet_size: u8 = buffer.len().try_into().or(Err(Error::PacketTooLarge))?; self.mode(Mode::Standby)?; @@ -327,68 +308,68 @@ where } /// Check if IRQ flag SyncAddressMatch is set. - pub fn is_sync_address_match(&mut self) -> Result { + pub fn is_sync_address_match(&mut self) -> Result { Ok(self.read(Registers::IrqFlags1)? & IrqFlags1::SyncAddressMatch != 0) } /// Check if IRQ flag FifoNotEmpty is cleared. - pub fn is_fifo_empty(&mut self) -> Result { + pub fn is_fifo_empty(&mut self) -> Result { Ok(self.read(Registers::IrqFlags2)? & IrqFlags2::FifoNotEmpty == 0) } /// Check if IRQ flag FifoFull is set. - pub fn is_fifo_full(&mut self) -> Result { + pub fn is_fifo_full(&mut self) -> Result { Ok(self.read(Registers::IrqFlags2)? & IrqFlags2::FifoFull != 0) } /// Check if IRQ flag PacketReady is set. - pub fn is_packet_ready(&mut self) -> Result { + pub fn is_packet_ready(&mut self) -> Result { Ok(self.read(Registers::IrqFlags2)? & IrqFlags2::PayloadReady != 0) } /// Check if IRQ flag ModeReady is set. - pub fn is_mode_ready(&mut self) -> Result { + pub fn is_mode_ready(&mut self) -> Result { Ok((self.read(Registers::IrqFlags1)? & IrqFlags1::ModeReady) != 0) } /// Check if IRQ flag PacketSent is set. - pub fn is_packet_sent(&mut self) -> Result { + pub fn is_packet_sent(&mut self) -> Result { Ok((self.read(Registers::IrqFlags2)? & IrqFlags2::PacketSent) != 0) } /// Configure LNA in corresponding register `RegLna (0x18)`. - pub fn lna(&mut self, lna: LnaConfig) -> Result<(), Ecs, Espi> { + pub fn lna(&mut self, lna: LnaConfig) -> Result<(), Espi> { let reg = (lna.zin as u8) | (lna.gain_select as u8); self.update(Registers::Lna, |r| (r & 0x78) | reg) } /// Configure RSSI Threshold in corresponding register `RegRssiThresh (0x29)`. - pub fn rssi_threshold(&mut self, threshold: u8) -> Result<(), Ecs, Espi> { + pub fn rssi_threshold(&mut self, threshold: u8) -> Result<(), Espi> { self.write(Registers::RssiThresh, threshold) } /// Configure Sensitivity Boost in corresponding register `RegTestLna (0x58)`. - pub fn sensitivity_boost(&mut self, boost: SensitivityBoost) -> Result<(), Ecs, Espi> { + pub fn sensitivity_boost(&mut self, boost: SensitivityBoost) -> Result<(), Espi> { self.write(Registers::TestLna, boost as u8) } /// Configure Pa13 dBm 1 in corresponding register `RegTestPa1 (0x5A)`. - pub fn pa13_dbm1(&mut self, pa13: Pa13dBm1) -> Result<(), Ecs, Espi> { + pub fn pa13_dbm1(&mut self, pa13: Pa13dBm1) -> Result<(), Espi> { self.write(Registers::TestPa1, pa13 as u8) } /// Configure Pa13 dBm 2 in corresponding register `RegTestPa2 (0x5C)`. - pub fn pa13_dbm2(&mut self, pa13: Pa13dBm2) -> Result<(), Ecs, Espi> { + pub fn pa13_dbm2(&mut self, pa13: Pa13dBm2) -> Result<(), Espi> { self.write(Registers::TestPa2, pa13 as u8) } /// Configure Continuous Dagc in corresponding register `RegTestDagc (0x6F)`. - pub fn continuous_dagc(&mut self, cdagc: ContinuousDagc) -> Result<(), Ecs, Espi> { + pub fn continuous_dagc(&mut self, cdagc: ContinuousDagc) -> Result<(), Espi> { self.write(Registers::TestDagc, cdagc as u8) } /// Configure Rx Bandwidth in corresponding register `RegRxBw (0x19)`. - pub fn rx_bw(&mut self, rx_bw: RxBw) -> Result<(), Ecs, Espi> + pub fn rx_bw(&mut self, rx_bw: RxBw) -> Result<(), Espi> where RxBwT: RxBwFreq, { @@ -399,7 +380,7 @@ where } /// Configure Rx AFC Bandwidth in corresponding register `RegAfcBw (0x1A)`. - pub fn rx_afc_bw(&mut self, rx_bw: RxBw) -> Result<(), Ecs, Espi> + pub fn rx_afc_bw(&mut self, rx_bw: RxBw) -> Result<(), Espi> where RxBwT: RxBwFreq, { @@ -410,30 +391,28 @@ where } /// Direct write to RFM69 registers. - pub fn write(&mut self, reg: Registers, val: u8) -> Result<(), Ecs, Espi> { + pub fn write(&mut self, reg: Registers, val: u8) -> Result<(), Espi> { self.write_many(reg, &[val]) } /// Direct write to RFM69 registers. - pub fn write_many(&mut self, reg: Registers, data: &[u8]) -> Result<(), Ecs, Espi> { - let _guard = CsGuard::new(&mut self.cs)?; + pub fn write_many(&mut self, reg: Registers, data: &[u8]) -> Result<(), Espi> { self.spi.write_many(reg, data).map_err(Error::Spi) } /// Direct read from RFM69 registers. - pub fn read(&mut self, reg: Registers) -> Result { + pub fn read(&mut self, reg: Registers) -> Result { let mut buffer = [0u8; 1]; self.read_many(reg, &mut buffer)?; Ok(buffer[0]) } /// Direct read from RFM69 registers. - pub fn read_many(&mut self, reg: Registers, buffer: &mut [u8]) -> Result<(), Ecs, Espi> { - let _guard = CsGuard::new(&mut self.cs)?; + pub fn read_many(&mut self, reg: Registers, buffer: &mut [u8]) -> Result<(), Espi> { self.spi.read_many(reg, buffer).map_err(Error::Spi) } - fn dio(&mut self) -> Result<(), Ecs, Espi> { + fn dio(&mut self) -> Result<(), Espi> { let mut reg = 0x07; for mapping in self.dio.iter().flatten() { if mapping.dio_mode.eq(self.mode) { @@ -443,15 +422,15 @@ where self.write_many(Registers::DioMapping1, ®.to_be_bytes()) } - fn read_rssi(&mut self) -> Result { + fn read_rssi(&mut self) -> Result { Ok(-i16::from(self.read(Registers::RssiValue)?) >> 1) } - fn reset_fifo(&mut self) -> Result<(), Ecs, Espi> { + fn reset_fifo(&mut self) -> Result<(), Espi> { self.write(Registers::IrqFlags2, IrqFlags2::FifoOverrun as u8) } - fn update(&mut self, reg: Registers, f: F) -> Result<(), Ecs, Espi> + fn update(&mut self, reg: Registers, f: F) -> Result<(), Espi> where F: FnOnce(u8) -> u8, { diff --git a/src/rw.rs b/src/rw.rs index 29afe4d..a57f5a0 100644 --- a/src/rw.rs +++ b/src/rw.rs @@ -1,4 +1,4 @@ -use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write}; +use embedded_hal::spi::{Operation, SpiDevice}; use crate::registers::Registers; @@ -16,43 +16,21 @@ pub trait ReadWrite { ) -> core::result::Result<(), Self::Error>; } -pub struct SpiTransactional(pub(crate) S); - -impl ReadWrite for SpiTransactional +impl ReadWrite for S where - S: Transactional, + S: SpiDevice, { type Error = E; fn write_many(&mut self, reg: Registers, data: &[u8]) -> core::result::Result<(), E> { let write = [reg.write()]; let mut operations = [Operation::Write(&write), Operation::Write(data)]; - self.0.exec(&mut operations) + self.transaction(&mut operations) } fn read_many(&mut self, reg: Registers, buffer: &mut [u8]) -> core::result::Result<(), E> { let read = [reg.read()]; - let mut operations = [Operation::Write(&read), Operation::Transfer(buffer)]; - self.0.exec(&mut operations) - } -} - -impl ReadWrite for S -where - S: Transfer, - S: Write, -{ - type Error = E; - - fn write_many(&mut self, reg: Registers, data: &[u8]) -> core::result::Result<(), E> { - self.write(&[reg.write()])?; - self.write(data)?; - Ok(()) - } - - fn read_many(&mut self, reg: Registers, buffer: &mut [u8]) -> core::result::Result<(), E> { - self.write(&[reg.read()])?; - self.transfer(buffer)?; - Ok(()) + let mut operations = [Operation::Write(&read), Operation::TransferInPlace(buffer)]; + self.transaction(&mut operations) } } diff --git a/src/tests.rs b/src/tests.rs index d922b2c..c318355 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,8 +1,10 @@ #![allow(clippy::unusual_byte_groupings)] +use core::convert::Infallible; +use core::iter::repeat; use std::prelude::v1::*; -use embedded_hal::blocking::spi::{Operation, Transactional, Transfer, Write}; +use embedded_hal::spi::{ErrorType, Operation, SpiDevice}; use crate::registers::*; use crate::*; @@ -12,54 +14,50 @@ struct SpiMock { tx_buffer: Vec, } -impl Transfer for SpiMock { - type Error = (); - - fn transfer<'w>(&mut self, words: &'w mut [u8]) -> std::result::Result<&'w [u8], Self::Error> { - self.rx_buffer.extend_from_slice(words); - for (index, val) in words.iter_mut().enumerate() { - *val = self.tx_buffer[index]; - } - Ok(words) - } +impl ErrorType for SpiMock { + type Error = Infallible; } -impl Write for SpiMock { - type Error = (); - - fn write(&mut self, words: &[u8]) -> std::result::Result<(), Self::Error> { - self.rx_buffer.extend_from_slice(words); - Ok(()) - } -} - -impl Transactional for SpiMock { - type Error = (); - - fn exec<'a>( +impl SpiDevice for SpiMock { + fn transaction( &mut self, - operations: &mut [Operation<'a, u8>], + operations: &mut [Operation], ) -> std::result::Result<(), Self::Error> { for operation in operations { match operation { - Operation::Write(buffer) => self.write(buffer)?, - Operation::Transfer(buffer) => { - self.transfer(buffer)?; + Operation::Read(buffer) => { + self.rx_buffer.extend(repeat(0xff).take(buffer.len())); + for (index, val) in buffer.iter_mut().enumerate() { + *val = self.tx_buffer[index]; + } } + Operation::Write(buffer) => { + self.rx_buffer.extend_from_slice(buffer); + } + Operation::Transfer(rx_buffer, tx_buffer) => { + self.rx_buffer.extend_from_slice(tx_buffer); + for (index, val) in rx_buffer.iter_mut().enumerate() { + *val = self.tx_buffer[index]; + } + } + Operation::TransferInPlace(buffer) => { + self.rx_buffer.extend_from_slice(buffer); + for (index, val) in buffer.iter_mut().enumerate() { + *val = self.tx_buffer[index]; + } + } + Operation::DelayNs(_) => {} } } Ok(()) } } -fn setup_rfm(rx_buffer: Vec, tx_buffer: Vec) -> Rfm69 { - Rfm69::new( - SpiMock { - rx_buffer, - tx_buffer, - }, - NoCs, - ) +fn setup_rfm(rx_buffer: Vec, tx_buffer: Vec) -> Rfm69 { + Rfm69::new(SpiMock { + rx_buffer, + tx_buffer, + }) } #[test] @@ -71,18 +69,6 @@ fn test_read_all_regs() { assert_eq!(result.as_ref(), rfm.spi.tx_buffer.as_slice()); } -#[test] -fn test_read_all_regs_transactional() { - let mut rfm = Rfm69::new_without_cs(SpiMock { - rx_buffer: Vec::new(), - tx_buffer: (1..=0x4f).collect(), - }); - - let result = rfm.read_all_regs().unwrap_or([0; 0x4f]); - assert_eq!(rfm.spi.0.rx_buffer[0], Registers::OpMode.read()); - assert_eq!(result.as_ref(), rfm.spi.0.tx_buffer.as_slice()); -} - #[test] fn test_mode() { let mut rfm = setup_rfm(Vec::new(), vec![0b111_001_11, 0]);