diff --git a/Cargo.toml b/Cargo.toml index daa2bb9..55704f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,12 @@ pkg-url = "{ repo }/releases/download/v{ version }/sx127x-util-{ target }.tgz" bin-dir = "{ bin }-{ target }{ format }" [features] -util = [ "structopt", "driver-pal", "driver-pal/hal", "simplelog", "humantime" ] +util = [ "clap", "driver-pal", "driver-pal/hal", "simplelog", "humantime" ] default = [ "util", "serde", "driver-pal/hal-cp2130", "driver-pal/hal-linux" ] [dependencies] radio = "0.11.0" -embedded-hal = "1.0.0-alpha.7" +embedded-hal = "1.0.0-rc.1" libc = "0.2" log = { version = "0.4" } bitflags = "1.0" @@ -25,7 +25,7 @@ bitflags = "1.0" driver-pal = { version = "0.8.0-alpha.6", default_features = false, optional=true } serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } -structopt = { version = "0.3.21", optional = true } +clap = { version = "4.4.7", optional = true, features = [ "derive" ] } simplelog = { version = "0.8.0", optional = true } humantime = { version = "2.0.0", optional = true } @@ -45,3 +45,7 @@ path = "tests/integration.rs" required-features = ["utils"] [patch.crates-io] +linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal" } +radio = { git = "https://github.com/rust-iot/radio" } +driver-pal = { git = "https://github.com/ryankurte/rust-driver-pal" } +driver-cp2130 = { git = "https://github.com/rust-iot/rust-driver-cp2130" } diff --git a/src/base.rs b/src/base.rs index bc30034..e8bf795 100644 --- a/src/base.rs +++ b/src/base.rs @@ -5,9 +5,9 @@ use core::fmt::Debug; -use embedded_hal::delay::blocking::{DelayUs}; -use embedded_hal::digital::blocking::{OutputPin, InputPin}; -use embedded_hal::spi::blocking::{Transactional, TransferInplace, Write}; +use embedded_hal::delay::DelayUs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::{ErrorType, SpiDevice}; /// HAL trait for radio interaction, may be generic over SPI or UART connections pub trait Hal { @@ -20,10 +20,10 @@ pub trait Hal { fn wait_busy(&mut self) -> Result<(), Self::Error>; /// Delay for the specified time - fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error>; + fn delay_ms(&mut self, ms: u32); /// Delay for the specified time - fn delay_us(&mut self, us: u32) -> Result<(), Self::Error>; + fn delay_us(&mut self, us: u32); /// Read from radio with prefix fn prefix_read(&mut self, prefix: &[u8], data: &mut [u8]) -> Result<(), Self::Error>; @@ -31,19 +31,14 @@ pub trait Hal { /// Write to radio with prefix fn prefix_write(&mut self, prefix: &[u8], data: &[u8]) -> Result<(), Self::Error>; - /// Read from the specified register - fn read_regs<'a>( - &mut self, - reg: u8, - data: &mut [u8], - ) -> Result<(), Self::Error> { + /// Read from the specified register + fn read_regs<'a>(&mut self, reg: u8, data: &mut [u8]) -> Result<(), Self::Error> { // Setup register read - let out_buf: [u8; 1] = [reg as u8 & 0x7F]; + let out_buf: [u8; 1] = [reg & 0x7F]; self.wait_busy()?; let r = self .prefix_read(&out_buf, data) - .map(|_| ()) - .map_err(|e| e.into()); + .map(|_| ()); self.wait_busy()?; r } @@ -51,9 +46,9 @@ pub trait Hal { /// Write to the specified register fn write_regs(&mut self, reg: u8, data: &[u8]) -> Result<(), Self::Error> { // Setup register write - let out_buf: [u8; 1] = [reg as u8 | 0x80]; + let out_buf: [u8; 1] = [reg | 0x80]; self.wait_busy()?; - let r = self.prefix_write(&out_buf, data).map_err(|e| e.into()); + let r = self.prefix_write(&out_buf, data); self.wait_busy()?; r } @@ -61,9 +56,9 @@ pub trait Hal { /// Write to the specified buffer fn write_buff(&mut self, data: &[u8]) -> Result<(), Self::Error> { // Setup fifo buffer write - let out_buf: [u8; 1] = [0x00 | 0x80]; + let out_buf: [u8; 1] = [0x80]; self.wait_busy()?; - let r = self.prefix_write(&out_buf, data).map_err(|e| e.into()); + let r = self.prefix_write(&out_buf, data); self.wait_busy()?; r } @@ -75,8 +70,7 @@ pub trait Hal { self.wait_busy()?; let r = self .prefix_read(&out_buf, data) - .map(|_| ()) - .map_err(|e| e.into()); + .map(|_| ()); self.wait_busy()?; r } @@ -84,23 +78,18 @@ pub trait Hal { /// Read a single u8 value from the specified register fn read_reg(&mut self, reg: u8) -> Result { let mut incoming = [0u8; 1]; - self.read_regs(reg.into(), &mut incoming)?; + self.read_regs(reg, &mut incoming)?; Ok(incoming[0]) } /// Write a single u8 value to the specified register fn write_reg(&mut self, reg: u8, value: u8) -> Result<(), Self::Error> { - self.write_regs(reg.into(), &[value])?; + self.write_regs(reg, &[value])?; Ok(()) } /// Update the specified register with the provided value & mask - fn update_reg( - &mut self, - reg: u8, - mask: u8, - value: u8, - ) -> Result { + fn update_reg(&mut self, reg: u8, mask: u8, value: u8) -> Result { let existing = self.read_reg(reg)?; let updated = (existing & !mask) | (value & mask); self.write_reg(reg, updated)?; @@ -109,24 +98,21 @@ pub trait Hal { } #[derive(Debug, Clone, PartialEq)] -#[cfg_attr(feature="defmt", derive(defmt::Format))] -pub enum HalError { +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum HalError { Spi(Spi), Pin(Pin), - Delay(Delay), -} - -/// Helper SPI trait to tie errors together (no longer required next HAL release) -pub trait SpiBase: TransferInplace::Error> + Write::Error> + Transactional::Error> { - type Error; -} - -impl + Write + Transactional, E> SpiBase for T { - type Error = E; } /// Spi base object defined interface for interacting with radio via SPI -pub struct Base { +pub struct Base< + Spi: SpiDevice, + Cs: OutputPin, + Busy: InputPin, + Ready: InputPin, + Sdn: OutputPin, + Delay: DelayUs, +> { pub spi: Spi, pub cs: Cs, pub busy: Busy, @@ -138,29 +124,28 @@ pub struct Base Hal for Base where - Spi: SpiBase, - ::Error: Debug + 'static, - - Cs: OutputPin, - Busy: InputPin, - Ready: InputPin, - Sdn: OutputPin, + Spi: SpiDevice, + ::Error: Debug + 'static, + + Cs: OutputPin, + Busy: InputPin, + Ready: InputPin, + Sdn: OutputPin, PinError: Debug + 'static, Delay: DelayUs, - ::Error: Debug + 'static, { - type Error = HalError<::Error, PinError, ::Error>; + type Error = HalError<::Error, PinError>; /// Reset the radio fn reset(&mut self) -> Result<(), Self::Error> { self.sdn.set_low().map_err(HalError::Pin)?; - self.delay.delay_ms(1).map_err(HalError::Delay)?; + self.delay.delay_ms(1); self.sdn.set_high().map_err(HalError::Pin)?; - self.delay.delay_ms(10).map_err(HalError::Delay)?; + self.delay.delay_ms(10); Ok(()) } @@ -172,15 +157,13 @@ where } /// Delay for the specified time - fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> { - self.delay.delay_ms(ms).map_err(HalError::Delay)?; - Ok(()) + fn delay_ms(&mut self, ms: u32) { + self.delay.delay_ms(ms); } /// Delay for the specified time - fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> { - self.delay.delay_us(us).map_err(HalError::Delay)?; - Ok(()) + fn delay_us(&mut self, us: u32) { + self.delay.delay_us(us); } /// Write data with prefix, asserting CS as required @@ -201,7 +184,10 @@ where fn prefix_read(&mut self, prefix: &[u8], data: &mut [u8]) -> Result<(), Self::Error> { self.cs.set_low().map_err(HalError::Pin)?; - let r = self.spi.write(prefix).map(|_| self.spi.transfer_inplace(data)); + let r = self + .spi + .write(prefix) + .map(|_| self.spi.transfer_in_place(data)); self.cs.set_high().map_err(HalError::Pin)?; diff --git a/src/device/common.rs b/src/device/common.rs index 057deab..86ebf08 100644 --- a/src/device/common.rs +++ b/src/device/common.rs @@ -1,6 +1,6 @@ /// Payload length configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum PayloadLength { /// Constant length payloads use implicit headers Constant(u16), diff --git a/src/device/fsk.rs b/src/device/fsk.rs index d956f6c..78d6cfa 100644 --- a/src/device/fsk.rs +++ b/src/device/fsk.rs @@ -8,7 +8,7 @@ pub use super::common::*; /// FSK and OOK mode configuration #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct FskConfig { /// Preamble length in symbols (defaults to 0x8) @@ -93,7 +93,7 @@ impl Default for FskConfig { /// Fsk radio channel configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct FskChannel { /// (G)FSK frequency in Hz (defaults to 434 MHz) @@ -126,7 +126,7 @@ impl Default for FskChannel { // FSK bandwidth register values #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Bandwidth { Bw2600 = 0x17, Bw3100 = 0x0F, @@ -156,7 +156,7 @@ pub const OPMODE_LRMODE_MASK: u8 = 0x80; pub const OPMODE_SHAPING_MASK: u8 = 0b0001_1000; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Shaping { Sh00 = 0x00, Sh01 = 0x08, @@ -168,7 +168,7 @@ pub const OPMODE_MODULATION_MASK: u8 = 0b0010_0000; /// Modulation modes for the standard modem #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Modulation { /// Frequency Shift Keying Fsk = 0x00, @@ -183,7 +183,7 @@ pub const PACKETFORMAT_FIXED: u8 = 0x80; pub const DCFREE_MASK: u8 = 0x60; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum DcFree { Off = 0x00, Manchester = 0x20, @@ -193,7 +193,7 @@ pub enum DcFree { pub const CRC_MASK: u8 = 0x10; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Crc { Off = 0x00, On = 0x10, @@ -202,7 +202,7 @@ pub enum Crc { pub const CRC_AUTOCLEAR_MASK: u8 = 0x08; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum CrcAutoClear { Off = 0x08, On = 0x00, @@ -211,7 +211,7 @@ pub enum CrcAutoClear { pub const ADDRESS_FILTER_MASK: u8 = 0x08; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum AddressFilter { Off = 0x00, Node = 0x02, @@ -221,7 +221,7 @@ pub enum AddressFilter { pub const CRC_WHITENING_MASK: u8 = 0x01; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum CrcWhitening { Ccitt = 0x00, Ibm = 0x01, @@ -230,7 +230,7 @@ pub enum CrcWhitening { pub const WMBUS_CRC_MASK: u8 = 0x80; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum WmbusCrc { Off = 0x00, On = 0x80, @@ -239,7 +239,7 @@ pub enum WmbusCrc { pub const DATAMODE_MASK: u8 = 0x40; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum DataMode { Continuous = 0x00, Packet = 0x40, @@ -248,7 +248,7 @@ pub enum DataMode { pub const IOHOME_MASK: u8 = 0x20; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum IoHome { Off = 0x00, On = 0x20, @@ -257,7 +257,7 @@ pub enum IoHome { pub const BEACON_MASK: u8 = 0x08; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Beacon { Off = 0x00, On = 0x08, @@ -284,7 +284,7 @@ pub const RXCONFIG_RXTRIGER_MASK: u8 = 0xF8; /// Receive mode Auto Frequency Calibration (AFC) #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum RxAfc { On = 0x10, Off = 0x00, @@ -292,7 +292,7 @@ pub enum RxAfc { /// Receive mode Auto Gain Compensation (AGC) #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum RxAgc { On = 0x08, Off = 0x00, @@ -300,7 +300,7 @@ pub enum RxAgc { /// Receive mode trigger configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum RxTrigger { Off = 0x00, Rssi = 0x01, @@ -310,14 +310,14 @@ pub enum RxTrigger { /// Control preamble detector state #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum PreambleDetect { On = 0x80, Off = 0x00, } #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum PreambleDetectSize { /// Interrupt on one byte Ps1 = 0b0000_0000, diff --git a/src/device/lora.rs b/src/device/lora.rs index 59d26ef..5bbd015 100644 --- a/src/device/lora.rs +++ b/src/device/lora.rs @@ -8,7 +8,7 @@ pub use super::common::*; /// LoRa Radio Configuration Object #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct LoRaConfig { /// LoRa Frequency hopping configuration (defaults to disabled) @@ -41,7 +41,7 @@ impl Default for LoRaConfig { /// LoRa radio channel configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct LoRaChannel { /// LoRa frequency in Hz (defaults to 434 MHz) @@ -70,7 +70,7 @@ pub const BANDWIDTH_MASK: u8 = 0b1111_0000; /// LoRa channel bandwidth in kHz #[allow(non_snake_case)] #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Bandwidth { /// 62.5kHz bandwidth //Bandwidth62_5kHz = 0b0110_0000, @@ -86,7 +86,7 @@ pub const SPREADING_FACTOR_MASK: u8 = 0b1111_0000; /// LoRa spreading factor in chips / symbol #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum SpreadingFactor { /// Sf6: 64 chips / symbol Sf6 = 0b0110_0000, @@ -107,7 +107,7 @@ pub enum SpreadingFactor { pub const CODERATE_MASK: u8 = 0b0000_1110; #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum CodingRate { /// LoRa Coding rate 4/5 Cr4_5 = 0b0000_0010, @@ -127,7 +127,7 @@ pub const RXPAYLOADCRC_MASK: u8 = 0b0000_0100; /// Payload RX CRC configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum PayloadCrc { Disabled = 0x00, Enabled = 0x04, @@ -143,7 +143,7 @@ pub const LOWDATARATEOPTIMIZE_MASK: u8 = 0b0000_1000; /// Low datarate optimization state #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum LowDatarateOptimise { /// Low datarate optimizations disabled Disabled = 0x00, @@ -157,7 +157,7 @@ pub const PLLHOP_FASTHOP_OFF: u8 = 0b0000_0000; /// Frequency hopping configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum FrequencyHopping { Disabled, /// Enabled specifies the number of symbol periods between frequency hops @@ -174,7 +174,7 @@ pub const AUTOMATICIF_OFF: u8 = 0b0000_0000; /// LoRa detection optimization mode #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum DetectionOptimize { /// Optimised for Sf7 to Sf12 Sf7To12 = 0x03, diff --git a/src/device/mod.rs b/src/device/mod.rs index 6220f4d..e01ffd9 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -21,7 +21,7 @@ pub const OPMODE_STATE_MASK: u8 = 0b0000_0111; /// Sx127x radio configuration #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Config { /// Device modem configuration pub modem: Modem, @@ -53,7 +53,8 @@ impl Default for Config { /// LoRa Received packet information #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[derive(Default)] pub struct PacketInfo { /// Received Signal Strength Indication pub rssi: i16, @@ -61,11 +62,6 @@ pub struct PacketInfo { pub snr: Option, } -impl Default for PacketInfo { - fn default() -> Self { - Self { rssi: 0, snr: None } - } -} impl radio::ReceiveInfo for PacketInfo { @@ -76,7 +72,7 @@ impl radio::ReceiveInfo for PacketInfo { /// Radio modem configuration contains fields for each modem mode #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Modem { /// Modem not configured None, @@ -88,7 +84,7 @@ pub enum Modem { /// Radio channel configuration contains channel options for each mode #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum Channel { /// Channel not configured None, @@ -132,7 +128,7 @@ impl RadioState for State { /// Sx127x Power Amplifier (PA) configuration #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct PaConfig { /// Power amplifier output selection (defaults to PA_BOOST output) pub output: PaSelect, @@ -244,7 +240,7 @@ pub struct TxConfig { } /// Device frequency step -pub const FREQ_STEP: f32 = 61.03515625; +pub const FREQ_STEP: f32 = 61.035_156; pub const RX_BUFFER_SIZE: u32 = 256; @@ -296,7 +292,7 @@ pub const PASELECT_PA_BOOST: u8 = 0b1000_0000; /// Select the power amplifier output configuration #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum PaSelect { /// RFO pin, output power limited to +14dBm /// with specified maximum output value, defaults to 0x04 for 14dBm output diff --git a/src/device/regs.rs b/src/device/regs.rs index dd0798d..0059560 100644 --- a/src/device/regs.rs +++ b/src/device/regs.rs @@ -9,9 +9,9 @@ pub enum Register { LoRa(LoRa), } -impl Into for Register { - fn into(self) -> u8 { - match self { +impl From for u8 { + fn from(val: Register) -> Self { + match val { Register::Common(c) => c as u8, Register::Fsk(f) => f as u8, Register::LoRa(l) => l as u8, @@ -19,21 +19,21 @@ impl Into for Register { } } -impl Into for Common { - fn into(self) -> u8 { - self as u8 +impl From for u8 { + fn from(val: Common) -> Self { + val as u8 } } -impl Into for LoRa { - fn into(self) -> u8 { - self as u8 +impl From for u8 { + fn from(val: LoRa) -> Self { + val as u8 } } -impl Into for Fsk { - fn into(self) -> u8 { - self as u8 +impl From for u8 { + fn from(val: Fsk) -> Self { + val as u8 } } diff --git a/src/fsk.rs b/src/fsk.rs index 5fd7182..db1066b 100644 --- a/src/fsk.rs +++ b/src/fsk.rs @@ -4,10 +4,9 @@ //! //! Copyright 2019 Ryan Kurte - use radio::State as _; -use log::{trace, debug}; +use log::{debug, trace}; use crate::{Error, Mode, Sx127x}; @@ -83,10 +82,9 @@ where self.write_reg(regs::Fsk::PREAMBLELSB, config.preamble as u8)?; // Configure preamble detector - self.write_reg(regs::Fsk::PREAMBLEDETECT, - PreambleDetect::On as u8 | - PreambleDetectSize::Ps2 as u8 | - PREAMBLE_DETECTOR_TOL + self.write_reg( + regs::Fsk::PREAMBLEDETECT, + PreambleDetect::On as u8 | PreambleDetectSize::Ps2 as u8 | PREAMBLE_DETECTOR_TOL, )?; // Configure TXStart @@ -97,7 +95,7 @@ where self.mode = Mode::FskOok; self.config.modem = Modem::FskOok(config.clone()); - self.config.channel = Channel::FskOok(channel.clone()); + self.config.channel = Channel::FskOok(*channel); Ok(()) } @@ -119,16 +117,17 @@ where let irq1 = Irq1::from_bits(reg).unwrap(); if clear { - self.write_reg(regs::Fsk::IRQFLAGS1, - (irq1 & (Irq1::RSSI | Irq1::PREAMBLED_DETECT)).bits())?; + self.write_reg( + regs::Fsk::IRQFLAGS1, + (irq1 & (Irq1::RSSI | Irq1::PREAMBLED_DETECT)).bits(), + )?; } let reg = self.read_reg(regs::Fsk::IRQFLAGS2)?; let irq2 = Irq2::from_bits(reg).unwrap(); if clear { - self.write_reg(regs::Fsk::IRQFLAGS2, - (irq2 & (Irq2::LOW_BAT)).bits())?; + self.write_reg(regs::Fsk::IRQFLAGS2, (irq2 & (Irq2::LOW_BAT)).bits())?; } Ok((irq1, irq2)) @@ -146,12 +145,11 @@ where // f32::round let round = |x: f32| -> u32 { let integer = x as u32; - if (x - (integer as f32)) < 0.5 { - integer - } - else { - integer + 1 - } + if (x - (integer as f32)) < 0.5 { + integer + } else { + integer + 1 + } }; // Calculate channel configuration @@ -257,7 +255,9 @@ where trace!( "check receive (state: {:?}, irq1: {:?} irq2: {:?})", - s, i1, i2 + s, + i1, + i2 ); // Check for completion @@ -288,7 +288,6 @@ where &mut self, data: &mut [u8], ) -> Result<(usize, PacketInfo), Error<::Error>> { - let mut len = [0u8; 1]; // Read the length byte from the FIFO self.hal.read_buff(&mut len)?; @@ -302,7 +301,7 @@ where self.hal.read_buff(&mut data[..len])?; // Read the RSSI - let info = PacketInfo{ + let info = PacketInfo { rssi: self.fsk_poll_rssi()?, snr: None, }; diff --git a/src/lib.rs b/src/lib.rs index 29d4096..c112379 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,23 +8,22 @@ #![no_std] - use core::convert::TryFrom; use core::fmt::Debug; -use base::{Base, SpiBase, HalError}; -use log::{trace, debug, warn}; +use base::{Base, HalError}; +use log::{debug, trace, warn}; -use embedded_hal::spi::{Mode as SpiMode, Phase, Polarity}; -use embedded_hal::delay::blocking::{DelayUs}; -use embedded_hal::digital::blocking::{InputPin, OutputPin}; +use embedded_hal::delay::DelayUs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::{ErrorType, Mode as SpiMode, Phase, Polarity, SpiDevice}; use radio::{Power as _, State as _}; pub mod base; pub mod device; -use device::{regs, Channel, Interrupts, Config, Modem, ModemMode, PaConfig, PacketInfo, State}; +use device::{regs, Channel, Config, Interrupts, Modem, ModemMode, PaConfig, PacketInfo, State}; pub mod fsk; pub mod lora; @@ -97,15 +96,14 @@ impl Default for Settings { } } -pub type Sx127xSpi = Sx127x>; +pub type Sx127xSpi = + Sx127x>; impl - Sx127x< - Base, - > + Sx127x> where - Spi: SpiBase, - ::Error: Debug, + Spi: SpiDevice, + ::Error: Debug, CsPin: OutputPin, BusyPin: InputPin, @@ -114,7 +112,6 @@ where PinError: Debug, Delay: DelayUs, - ::Error: Debug, { /// Create an Sx127x with the provided SPI implementation and pins pub fn spi( @@ -125,9 +122,16 @@ where sdn: SdnPin, delay: Delay, config: &Config, - ) -> Result::Error, PinError, ::Error>>> { + ) -> Result::Error, PinError>>> { // Create SpiWrapper over spi/cs/busy/ready/reset - let base = Base{spi, cs, sdn, busy, ready, delay}; + let base = Base { + spi, + cs, + sdn, + busy, + ready, + delay, + }; // Create instance with new hal Self::new(base, config) @@ -199,7 +203,10 @@ where (Modem::FskOok(fsk_modem), Channel::FskOok(fsk_channel)) => { self.fsk_configure(fsk_modem, fsk_channel)?; } - _ => panic!("Invalid configuration, mismatch between Modem ({:?}) and Channel ({:?} modes", &config.modem, &config.channel), + _ => panic!( + "Invalid configuration, mismatch between Modem ({:?}) and Channel ({:?} modes", + &config.modem, &config.channel + ), } // Configure power amplifier @@ -263,11 +270,10 @@ where // Timeout eventually if ticks >= self.config.timeout_ms { warn!("Set state timeout"); - return Err(Error::Timeout) + return Err(Error::Timeout); } - - self.hal.delay_ms(1)?; + self.hal.delay_ms(1); ticks += 1; } Ok(()) @@ -314,13 +320,16 @@ where } // Set the channel by frequency - pub(crate) fn set_frequency(&mut self, freq: u32) -> Result<(), Error<::Error>> { + pub(crate) fn set_frequency( + &mut self, + freq: u32, + ) -> Result<(), Error<::Error>> { let channel = self.freq_to_channel_index(freq); let outgoing = [ (channel >> 16) as u8, (channel >> 8) as u8, - (channel >> 0) as u8, + channel as u8, ]; debug!("Set channel to index: {:?} (freq: {:?})", channel, freq); @@ -336,7 +345,7 @@ where self.hal .read_regs(regs::Common::FRFMSB as u8, &mut incoming)?; - let ch = (incoming[0] as u32) << 16 | (incoming[1] as u32) << 8 | (incoming[2] as u32) << 0; + let ch = (incoming[0] as u32) << 16 | (incoming[1] as u32) << 8 | (incoming[2] as u32); let freq = self.channel_index_to_freq(ch); @@ -358,13 +367,13 @@ where // Launch calibration for the LF band self.update_reg( regs::Fsk::IMAGECAL, - regs::RF_IMAGECAL_IMAGECAL_MASK as u8, - regs::RF_IMAGECAL_IMAGECAL_START as u8, + regs::RF_IMAGECAL_IMAGECAL_MASK, + regs::RF_IMAGECAL_IMAGECAL_START, )?; // Block on calibration complete // TODO: make this fallible with a timeout? - while self.read_reg(regs::Fsk::IMAGECAL)? & (regs::RF_IMAGECAL_IMAGECAL_RUNNING as u8) != 0 + while self.read_reg(regs::Fsk::IMAGECAL)? & regs::RF_IMAGECAL_IMAGECAL_RUNNING != 0 { } @@ -374,13 +383,13 @@ where // Launch calibration for the HF band self.update_reg( regs::Fsk::IMAGECAL, - regs::RF_IMAGECAL_IMAGECAL_MASK as u8, - regs::RF_IMAGECAL_IMAGECAL_START as u8, + regs::RF_IMAGECAL_IMAGECAL_MASK, + regs::RF_IMAGECAL_IMAGECAL_START, )?; // Block on calibration complete // TODO: make this fallible with a timeout? - while self.read_reg(regs::Fsk::IMAGECAL)? & (regs::RF_IMAGECAL_IMAGECAL_RUNNING as u8) != 0 + while self.read_reg(regs::Fsk::IMAGECAL)? & regs::RF_IMAGECAL_IMAGECAL_RUNNING != 0 { } @@ -411,10 +420,8 @@ impl DelayUs for Sx127x where Hal: base::Hal, { - type Error = Error<::Error>; - - fn delay_us(&mut self, t: u32) -> Result<(), Error<::Error>> { - self.hal.delay_us(t).map_err(Error::Hal) + fn delay_us(&mut self, t: u32) { + self.hal.delay_us(t); } } @@ -429,17 +436,31 @@ where { let value = self.hal.read_reg(reg.into())?; - trace!("Read reg: {:?} (0x{:02x}): 0x{:02x}", reg, reg.into(), value); + trace!( + "Read reg: {:?} (0x{:02x}): 0x{:02x}", + reg, + reg.into(), + value + ); Ok(value) } /// Write a u8 value to the specified register - pub fn write_reg(&mut self, reg: R, value: u8) -> Result<(), Error<::Error>> + pub fn write_reg( + &mut self, + reg: R, + value: u8, + ) -> Result<(), Error<::Error>> where R: Copy + Clone + Debug + Into, { - trace!("Write reg: {:?} (0x{:02x}): 0x{:02x}", reg, reg.into(), value); + trace!( + "Write reg: {:?} (0x{:02x}): 0x{:02x}", + reg, + reg.into(), + value + ); self.hal.write_reg(reg.into(), value).map_err(Error::Hal) } @@ -454,15 +475,23 @@ where where R: Copy + Clone + Debug + Into, { - trace!("Update reg: {:?} (0x{:02x}): 0x{:02x} (0x{:02x})", reg, reg.into(), value, mask); + trace!( + "Update reg: {:?} (0x{:02x}): 0x{:02x} (0x{:02x})", + reg, + reg.into(), + value, + mask + ); - self.hal.update_reg(reg.into(), mask, value).map_err(Error::Hal) + self.hal + .update_reg(reg.into(), mask, value) + .map_err(Error::Hal) } } impl radio::State for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type State = State; type Error = Error<::Error>; @@ -484,7 +513,7 @@ where impl radio::Power for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type Error = Error<::Error>; @@ -533,7 +562,7 @@ where impl radio::Interrupts for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type Irq = Interrupts; type Error = Error<::Error>; @@ -551,13 +580,16 @@ where impl radio::Channel for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type Channel = Channel; type Error = Error<::Error>; /// Set the LoRa mode channel for future receive or transmit operations - fn set_channel(&mut self, channel: &Self::Channel) -> Result<(), Error<::Error>> { + fn set_channel( + &mut self, + channel: &Self::Channel, + ) -> Result<(), Error<::Error>> { match (self.mode, channel) { (Mode::LoRa, Channel::LoRa(channel)) => self.lora_set_channel(channel), (Mode::FskOok, Channel::FskOok(channel)) => self.fsk_set_channel(channel), @@ -568,7 +600,7 @@ where impl radio::Transmit for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type Error = Error<::Error>; @@ -595,7 +627,7 @@ where impl radio::Receive for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type Info = PacketInfo; type Error = Error<::Error>; @@ -626,10 +658,7 @@ where /// /// This copies data into the provided slice, updates the provided information object, /// and returns the number of bytes received on success - fn get_received( - &mut self, - buff: &mut [u8], - ) -> Result<(usize, Self::Info), Self::Error> { + fn get_received(&mut self, buff: &mut [u8]) -> Result<(usize, Self::Info), Self::Error> { match self.mode { Mode::LoRa => self.lora_get_received(buff), Mode::FskOok => self.fsk_get_received(buff), @@ -640,7 +669,7 @@ where impl radio::Rssi for Sx127x where - Hal: base::Hal + Hal: base::Hal, { type Error = Error<::Error>; diff --git a/src/lora.rs b/src/lora.rs index aa92b25..b22a86d 100644 --- a/src/lora.rs +++ b/src/lora.rs @@ -4,7 +4,7 @@ //! //! Copyright 2019 Ryan Kurte -use log::{trace, debug, warn, error}; +use log::{debug, error, trace, warn}; use radio::State as _; @@ -26,8 +26,8 @@ where debug!("Configuring lora mode"); // Update internal config - self.config.channel = Channel::LoRa(channel.clone()); - self.config.modem = Modem::LoRa(config.clone()); + self.config.channel = Channel::LoRa(*channel); + self.config.modem = Modem::LoRa(*config); // Switch to sleep to change modem mode self.set_state(State::Sleep)?; @@ -64,8 +64,8 @@ where } self.mode = Mode::LoRa; - self.config.modem = Modem::LoRa(config.clone()); - self.config.channel = Channel::LoRa(channel.clone()); + self.config.modem = Modem::LoRa(*config); + self.config.channel = Channel::LoRa(*channel); Ok(()) } @@ -205,7 +205,7 @@ where } // Update internal channel state - self.config.channel = Channel::LoRa(channel.clone()); + self.config.channel = Channel::LoRa(*channel); Ok(()) } @@ -396,8 +396,9 @@ where let snr = self.read_reg(regs::LoRa::PKTSNRVALUE)? as i16; let (rssi, snr) = self.lora_process_rssi_snr(rssi, snr); - let info = PacketInfo{ - rssi, snr: Some(snr), + let info = PacketInfo { + rssi, + snr: Some(snr), }; trace!("FIFO RX {} bytes with fifo rx ptr: {}", n, r); diff --git a/src/util/main.rs b/src/util/main.rs index 17bd957..7cf6af1 100644 --- a/src/util/main.rs +++ b/src/util/main.rs @@ -4,17 +4,15 @@ //! //! Copyright 2019 Ryan Kurte -use log::{trace, debug, info, error}; -use simplelog::{TermLogger, TerminalMode, LevelFilter}; +use log::{debug, error, info, trace}; +use simplelog::{LevelFilter, TermLogger, TerminalMode}; -use structopt::StructOpt; +use clap::Parser; - -use driver_pal::hal::{HalInst, HalDelay}; +use driver_pal::hal::{HalDelay, HalInst}; use radio_sx127x::prelude::*; - mod options; use options::*; @@ -23,7 +21,7 @@ use operations::*; fn main() { // Load options - let opts = Options::from_args(); + let opts = Options::parse(); // Setup logging let mut log_config = simplelog::ConfigBuilder::new(); @@ -37,7 +35,7 @@ fn main() { // Connect to SPI peripheral debug!("Connecting to platform SPI"); trace!("with config: {:?}", opts.spi_config); - let HalInst{base: _, spi, pins} = match HalInst::load(&opts.spi_config) { + let HalInst { base: _, spi, pins } = match HalInst::load(&opts.spi_config) { Ok(v) => v, Err(e) => { error!("Error connecting to platform HAL: {:?}", e); @@ -70,13 +68,21 @@ fn main() { config.modem = Modem::FskOok(modem); config.channel = Channel::FskOok(channel); - }, + } _ => (), } debug!("Creating radio instance"); - let mut radio = - Sx127x::spi(spi, pins.cs, pins.busy, pins.ready, pins.reset, HalDelay {}, &config).expect("error creating device"); + let mut radio = Sx127x::spi( + spi, + pins.cs, + pins.busy, + pins.ready, + pins.reset, + HalDelay {}, + &config, + ) + .expect("error creating device"); debug!("Executing command"); match opts.command { @@ -85,7 +91,6 @@ fn main() { .silicon_version() .expect("error fetching chip version"); info!("Silicon version: 0x{:X}", version); - return; } Command::LoRa(lora_config) => { do_command(radio, lora_config.operation).expect("error executing command"); diff --git a/src/util/operations.rs b/src/util/operations.rs index 33d8366..c3f5227 100644 --- a/src/util/operations.rs +++ b/src/util/operations.rs @@ -29,13 +29,8 @@ where Operation::Receive(config) => { let mut buff = [0u8; 255]; - do_receive( - radio, - &mut buff, - config.continuous, - *config.poll_interval, - ) - .expect("Receive error"); + do_receive(radio, &mut buff, config.continuous, *config.poll_interval) + .expect("Receive error"); } Operation::Repeat(config) => { let mut buff = [0u8; 255]; @@ -52,8 +47,7 @@ where } Operation::Rssi(config) => { do_rssi(radio, config.continuous, *config.period).expect("RSSI error"); - } - //_ => warn!("unsuppored command: {:?}", opts.command), + } //_ => warn!("unsuppored command: {:?}", opts.command), } Ok(()) @@ -93,7 +87,7 @@ where pub fn do_receive( mut radio: T, - mut buff: &mut [u8], + buff: &mut [u8], continuous: bool, poll_interval: Duration, ) -> Result @@ -106,11 +100,11 @@ where loop { if radio.check_receive(true)? { - let (n, info) = radio.get_received(&mut buff)?; + let (n, info) = radio.get_received(buff)?; - match std::str::from_utf8(&buff[0..n as usize]) { + match std::str::from_utf8(&buff[0..n]) { Ok(s) => info!("Received: '{}' info: {:?}", s, info), - Err(_) => info!("Received: '{:?}' info: {:?}", &buff[0..n as usize], info), + Err(_) => info!("Received: '{:?}' info: {:?}", &buff[0..n], info), } if !continuous { @@ -150,7 +144,7 @@ where pub fn do_repeat( mut radio: T, - mut buff: &mut [u8], + buff: &mut [u8], power: i8, continuous: bool, delay: Duration, @@ -168,11 +162,11 @@ where loop { if radio.check_receive(true)? { - let (n, info) = radio.get_received(&mut buff)?; + let (n, info) = radio.get_received(buff)?; - match std::str::from_utf8(&buff[0..n as usize]) { + match std::str::from_utf8(&buff[0..n]) { Ok(s) => info!("Received: '{}' info: {:?}", s, info), - Err(_) => info!("Received: '{:?}' info: {:?}", &buff[0..n as usize], info), + Err(_) => info!("Received: '{:?}' info: {:?}", &buff[0..n], info), } std::thread::sleep(delay); diff --git a/src/util/options.rs b/src/util/options.rs index e2b8ebb..d9ae7b8 100644 --- a/src/util/options.rs +++ b/src/util/options.rs @@ -1,144 +1,144 @@ +use clap::Parser; +use driver_pal::hal::DeviceConfig; use humantime::Duration as HumanDuration; use simplelog::LevelFilter; -use structopt::StructOpt; -use driver_pal::hal::{DeviceConfig}; -#[derive(StructOpt)] -#[structopt(name = "Sx127x-util")] +#[derive(Parser)] +#[clap(name = "Sx127x-util")] /// A Command Line Interface (CLI) for interacting with a local Sx127x radio device pub struct Options { - #[structopt(subcommand)] + #[clap(subcommand)] /// Subcommand to execute pub command: Command, - - #[structopt(flatten)] + + #[clap(flatten)] pub spi_config: DeviceConfig, /// Log verbosity setting - #[structopt(long, default_value = "info")] + #[clap(long, default_value = "info")] pub log_level: LevelFilter, } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub enum Command { - #[structopt(name = "chip-version")] + #[clap(name = "chip-version")] /// Fetch the device silicon/firmware version SiliconVersion, - #[structopt(name = "lora")] + #[clap(name = "lora")] /// LoRa mode configuration and operations LoRa(LoRaCommand), - #[structopt(name = "gfsk")] + #[clap(name = "gfsk")] /// GFSK mode configuration and operations Gfsk(GfskCommand), } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub enum Operation { - #[structopt(name = "tx")] + #[clap(name = "tx")] /// Transmit a (string) packet Transmit(Transmit), - #[structopt(name = "rx")] + #[clap(name = "rx")] /// Receive a (string) packet Receive(Receive), - #[structopt(name = "rssi")] + #[clap(name = "rssi")] /// Poll for RSSI on the specified channel Rssi(Rssi), - #[structopt(name = "repeat")] + #[clap(name = "repeat")] /// Repeat received messages Repeat(Repeat), } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub struct LoRaCommand { /// LoRa frequency in MHz - #[structopt(long = "freq-mhz")] + #[clap(long = "freq-mhz")] pub freq_mhz: Option, - #[structopt(subcommand)] + #[clap(subcommand)] /// Operation to execute pub operation: Operation, } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub struct GfskCommand { /// GFSK frequency in MHz - #[structopt(long = "freq-mhz")] + #[clap(long = "freq-mhz")] pub freq_mhz: Option, - #[structopt(subcommand)] + #[clap(subcommand)] /// Operation to execute pub operation: Operation, } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub struct Transmit { /// Data to be transmitted - #[structopt(long = "data")] + #[clap(long = "data")] pub data: String, /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, /// Power in dBm - #[structopt(long = "power", default_value = "13")] + #[clap(long = "power", default_value = "13")] pub power: i8, /// Specify period for transmission - #[structopt(long = "period", default_value = "1s")] + #[clap(long = "period", default_value = "1s")] pub period: HumanDuration, /// Specify period for polling for device status - #[structopt(long = "poll-interval", default_value = "1ms")] + #[clap(long = "poll-interval", default_value = "1ms")] pub poll_interval: HumanDuration, } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub struct Receive { /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, /// Specify period for polling for device status - #[structopt(long = "poll-interval", default_value = "1ms")] + #[clap(long = "poll-interval", default_value = "1ms")] pub poll_interval: HumanDuration, } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub struct Rssi { /// Specify period for RSSI polling - #[structopt(long = "period", default_value = "1s")] + #[clap(long = "period", default_value = "1s")] pub period: HumanDuration, /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, } -#[derive(StructOpt, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] pub struct Repeat { /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, /// Power in dBm - #[structopt(long = "power", default_value = "13")] + #[clap(long = "power", default_value = "13")] pub power: i8, /// Specify period for polling for device status - #[structopt(long = "poll-interval", default_value = "1ms")] + #[clap(long = "poll-interval", default_value = "1ms")] pub poll_interval: HumanDuration, /// Specify delay for response message - #[structopt(long = "delay", default_value = "100ms")] + #[clap(long = "delay", default_value = "100ms")] pub delay: HumanDuration, /// Append RSSI and LQI to repeated message - #[structopt(long = "append-info")] + #[clap(long = "append-info")] pub append_info: bool, }