embassy/embassy-stm32/src/subghz/packet_params.rs
Ulf Lilleengen fb697a2657 Updates
2021-09-15 12:46:20 +02:00

538 lines
16 KiB
Rust

/// Preamble detection length for [`GenericPacketParams`].
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PreambleDetection {
/// Preamble detection disabled.
Disabled = 0x0,
/// 8-bit preamble detection.
Bit8 = 0x4,
/// 16-bit preamble detection.
Bit16 = 0x5,
/// 24-bit preamble detection.
Bit24 = 0x6,
/// 32-bit preamble detection.
Bit32 = 0x7,
}
/// Address comparison/filtering for [`GenericPacketParams`].
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AddrComp {
/// Address comparison/filtering disabled.
Disabled = 0x0,
/// Address comparison/filtering on node address.
Node = 0x1,
/// Address comparison/filtering on node and broadcast addresses.
Broadcast = 0x2,
}
/// Packet header type.
///
/// Argument of [`GenericPacketParams::set_header_type`] and
/// [`LoRaPacketParams::set_header_type`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HeaderType {
/// Fixed; payload length and header field not added to packet.
Fixed,
/// Variable; payload length and header field added to packet.
Variable,
}
impl HeaderType {
pub(crate) const fn to_bits_generic(self) -> u8 {
match self {
HeaderType::Fixed => 0,
HeaderType::Variable => 1,
}
}
pub(crate) const fn to_bits_lora(self) -> u8 {
match self {
HeaderType::Fixed => 1,
HeaderType::Variable => 0,
}
}
}
/// CRC type definition for [`GenericPacketParams`].
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CrcType {
/// 1-byte CRC.
Byte1 = 0x0,
/// CRC disabled.
Disabled = 0x1,
/// 2-byte CRC.
Byte2 = 0x2,
/// 1-byte inverted CRC.
Byte1Inverted = 0x4,
/// 2-byte inverted CRC.
Byte2Inverted = 0x6,
}
/// Packet parameters for [`set_packet_params`].
///
/// [`set_packet_params`]: super::SubGhz::set_packet_params
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct GenericPacketParams {
buf: [u8; 10],
}
impl GenericPacketParams {
/// Create a new `GenericPacketParams`.
///
/// This is the same as `default`, but in a `const` function.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::GenericPacketParams;
///
/// const PKT_PARAMS: GenericPacketParams = GenericPacketParams::new();
/// assert_eq!(PKT_PARAMS, GenericPacketParams::default());
/// ```
pub const fn new() -> GenericPacketParams {
const OPCODE: u8 = super::OpCode::SetPacketParams as u8;
// const variable ensure the compile always optimizes the methods
const NEW: GenericPacketParams = GenericPacketParams {
buf: [OPCODE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
}
.set_preamble_len(1)
.set_preamble_detection(PreambleDetection::Disabled)
.set_sync_word_len(0)
.set_addr_comp(AddrComp::Disabled)
.set_header_type(HeaderType::Fixed)
.set_payload_len(1);
NEW
}
/// Preamble length in number of symbols.
///
/// Values of zero are invalid, and will automatically be set to 1.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::GenericPacketParams;
///
/// const PKT_PARAMS: GenericPacketParams = GenericPacketParams::new().set_preamble_len(0x1234);
/// # assert_eq!(PKT_PARAMS.as_slice()[1], 0x12);
/// # assert_eq!(PKT_PARAMS.as_slice()[2], 0x34);
/// ```
#[must_use = "preamble_length returns a modified GenericPacketParams"]
pub const fn set_preamble_len(mut self, mut len: u16) -> GenericPacketParams {
if len == 0 {
len = 1
}
self.buf[1] = ((len >> 8) & 0xFF) as u8;
self.buf[2] = (len & 0xFF) as u8;
self
}
/// Preabmle detection length in number of bit symbols.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::{GenericPacketParams, PreambleDetection};
///
/// const PKT_PARAMS: GenericPacketParams =
/// GenericPacketParams::new().set_preamble_detection(PreambleDetection::Bit8);
/// # assert_eq!(PKT_PARAMS.as_slice()[3], 0x4);
/// ```
#[must_use = "set_preamble_detection returns a modified GenericPacketParams"]
pub const fn set_preamble_detection(
mut self,
pb_det: PreambleDetection,
) -> GenericPacketParams {
self.buf[3] = pb_det as u8;
self
}
/// Sync word length in number of bit symbols.
///
/// Valid values are `0x00` - `0x40` for 0 to 64-bits respectively.
/// Values that exceed the maximum will saturate at `0x40`.
///
/// # Example
///
/// Set the sync word length to 4 bytes (16 bits).
///
/// ```
/// use stm32wl_hal::subghz::GenericPacketParams;
///
/// const PKT_PARAMS: GenericPacketParams = GenericPacketParams::new().set_sync_word_len(16);
/// # assert_eq!(PKT_PARAMS.as_slice()[4], 0x10);
/// ```
#[must_use = "set_sync_word_len returns a modified GenericPacketParams"]
pub const fn set_sync_word_len(mut self, len: u8) -> GenericPacketParams {
const MAX: u8 = 0x40;
if len > MAX {
self.buf[4] = MAX;
} else {
self.buf[4] = len;
}
self
}
/// Address comparison/filtering.
///
/// # Example
///
/// Enable address on the node address.
///
/// ```
/// use stm32wl_hal::subghz::{AddrComp, GenericPacketParams};
///
/// const PKT_PARAMS: GenericPacketParams =
/// GenericPacketParams::new().set_addr_comp(AddrComp::Node);
/// # assert_eq!(PKT_PARAMS.as_slice()[5], 0x01);
/// ```
#[must_use = "set_addr_comp returns a modified GenericPacketParams"]
pub const fn set_addr_comp(mut self, addr_comp: AddrComp) -> GenericPacketParams {
self.buf[5] = addr_comp as u8;
self
}
/// Header type definition.
///
/// **Note:** The reference manual calls this packet type, but that results
/// in a conflicting variable name for the modulation scheme, which the
/// reference manual also calls packet type.
///
/// # Example
///
/// Set the header type to a variable length.
///
/// ```
/// use stm32wl_hal::subghz::{GenericPacketParams, HeaderType};
///
/// const PKT_PARAMS: GenericPacketParams =
/// GenericPacketParams::new().set_header_type(HeaderType::Variable);
/// # assert_eq!(PKT_PARAMS.as_slice()[6], 0x01);
/// ```
#[must_use = "set_header_type returns a modified GenericPacketParams"]
pub const fn set_header_type(mut self, header_type: HeaderType) -> GenericPacketParams {
self.buf[6] = header_type.to_bits_generic();
self
}
/// Set the payload length in bytes.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::GenericPacketParams;
///
/// const PKT_PARAMS: GenericPacketParams = GenericPacketParams::new().set_payload_len(12);
/// # assert_eq!(PKT_PARAMS.as_slice()[7], 12);
/// ```
#[must_use = "set_payload_len returns a modified GenericPacketParams"]
pub const fn set_payload_len(mut self, len: u8) -> GenericPacketParams {
self.buf[7] = len;
self
}
/// CRC type definition.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::{CrcType, GenericPacketParams};
///
/// const PKT_PARAMS: GenericPacketParams =
/// GenericPacketParams::new().set_crc_type(CrcType::Byte2Inverted);
/// # assert_eq!(PKT_PARAMS.as_slice()[8], 0x6);
/// ```
#[must_use = "set_payload_len returns a modified GenericPacketParams"]
pub const fn set_crc_type(mut self, crc_type: CrcType) -> GenericPacketParams {
self.buf[8] = crc_type as u8;
self
}
/// Whitening enable.
///
/// # Example
///
/// Enable whitening.
///
/// ```
/// use stm32wl_hal::subghz::GenericPacketParams;
///
/// const PKT_PARAMS: GenericPacketParams = GenericPacketParams::new().set_whitening_enable(true);
/// # assert_eq!(PKT_PARAMS.as_slice()[9], 1);
/// ```
#[must_use = "set_whitening_enable returns a modified GenericPacketParams"]
pub const fn set_whitening_enable(mut self, en: bool) -> GenericPacketParams {
self.buf[9] = en as u8;
self
}
/// Extracts a slice containing the packet.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::{
/// AddrComp, CrcType, GenericPacketParams, HeaderType, PreambleDetection,
/// };
///
/// const PKT_PARAMS: GenericPacketParams = GenericPacketParams::new()
/// .set_preamble_len(8)
/// .set_preamble_detection(PreambleDetection::Disabled)
/// .set_sync_word_len(2)
/// .set_addr_comp(AddrComp::Disabled)
/// .set_header_type(HeaderType::Fixed)
/// .set_payload_len(128)
/// .set_crc_type(CrcType::Byte2)
/// .set_whitening_enable(true);
///
/// assert_eq!(
/// PKT_PARAMS.as_slice(),
/// &[0x8C, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x02, 0x01]
/// );
/// ```
pub const fn as_slice(&self) -> &[u8] {
&self.buf
}
}
impl Default for GenericPacketParams {
fn default() -> Self {
Self::new()
}
}
/// Packet parameters for [`set_lora_packet_params`].
///
/// [`set_lora_packet_params`]: super::SubGhz::set_lora_packet_params
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LoRaPacketParams {
buf: [u8; 7],
}
impl LoRaPacketParams {
/// Create a new `GenericPacketParams`.
///
/// This is the same as `default`, but in a `const` function.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::LoRaPacketParams;
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new();
/// assert_eq!(PKT_PARAMS, LoRaPacketParams::default());
/// ```
pub const fn new() -> LoRaPacketParams {
const OPCODE: u8 = super::OpCode::SetPacketParams as u8;
// const variable ensure the compile always optimizes the methods
const NEW: LoRaPacketParams = LoRaPacketParams {
buf: [OPCODE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
}
.set_preamble_len(1)
.set_header_type(HeaderType::Fixed)
.set_payload_len(1)
.set_crc_en(true)
.set_invert_iq(false);
NEW
}
/// Preamble length in number of symbols.
///
/// Values of zero are invalid, and will automatically be set to 1.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::LoRaPacketParams;
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new().set_preamble_len(0x1234);
/// # assert_eq!(PKT_PARAMS.as_slice()[1], 0x12);
/// # assert_eq!(PKT_PARAMS.as_slice()[2], 0x34);
/// ```
#[must_use = "preamble_length returns a modified LoRaPacketParams"]
pub const fn set_preamble_len(mut self, mut len: u16) -> LoRaPacketParams {
if len == 0 {
len = 1
}
self.buf[1] = ((len >> 8) & 0xFF) as u8;
self.buf[2] = (len & 0xFF) as u8;
self
}
/// Header type (fixed or variable).
///
/// # Example
///
/// Set the payload type to a fixed length.
///
/// ```
/// use stm32wl_hal::subghz::{HeaderType, LoRaPacketParams};
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new().set_header_type(HeaderType::Fixed);
/// # assert_eq!(PKT_PARAMS.as_slice()[3], 0x01);
/// ```
#[must_use = "set_header_type returns a modified LoRaPacketParams"]
pub const fn set_header_type(mut self, header_type: HeaderType) -> LoRaPacketParams {
self.buf[3] = header_type.to_bits_lora();
self
}
/// Set the payload length in bytes.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::LoRaPacketParams;
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new().set_payload_len(12);
/// # assert_eq!(PKT_PARAMS.as_slice()[4], 12);
/// ```
#[must_use = "set_payload_len returns a modified LoRaPacketParams"]
pub const fn set_payload_len(mut self, len: u8) -> LoRaPacketParams {
self.buf[4] = len;
self
}
/// CRC enable.
///
/// # Example
///
/// Enable CRC.
///
/// ```
/// use stm32wl_hal::subghz::LoRaPacketParams;
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new().set_crc_en(true);
/// # assert_eq!(PKT_PARAMS.as_slice()[5], 0x1);
/// ```
#[must_use = "set_crc_en returns a modified LoRaPacketParams"]
pub const fn set_crc_en(mut self, en: bool) -> LoRaPacketParams {
self.buf[5] = en as u8;
self
}
/// IQ setup.
///
/// # Example
///
/// Use an inverted IQ setup.
///
/// ```
/// use stm32wl_hal::subghz::LoRaPacketParams;
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new().set_invert_iq(true);
/// # assert_eq!(PKT_PARAMS.as_slice()[6], 0x1);
/// ```
#[must_use = "set_invert_iq returns a modified LoRaPacketParams"]
pub const fn set_invert_iq(mut self, invert: bool) -> LoRaPacketParams {
self.buf[6] = invert as u8;
self
}
/// Extracts a slice containing the packet.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::{HeaderType, LoRaPacketParams};
///
/// const PKT_PARAMS: LoRaPacketParams = LoRaPacketParams::new()
/// .set_preamble_len(5 * 8)
/// .set_header_type(HeaderType::Fixed)
/// .set_payload_len(64)
/// .set_crc_en(true)
/// .set_invert_iq(true);
///
/// assert_eq!(
/// PKT_PARAMS.as_slice(),
/// &[0x8C, 0x00, 0x28, 0x01, 0x40, 0x01, 0x01]
/// );
/// ```
pub const fn as_slice(&self) -> &[u8] {
&self.buf
}
}
impl Default for LoRaPacketParams {
fn default() -> Self {
Self::new()
}
}
/// Packet parameters for [`set_lora_packet_params`].
///
/// [`set_lora_packet_params`]: super::SubGhz::set_lora_packet_params
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct BpskPacketParams {
buf: [u8; 2],
}
impl BpskPacketParams {
/// Create a new `BpskPacketParams`.
///
/// This is the same as `default`, but in a `const` function.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::BpskPacketParams;
///
/// const PKT_PARAMS: BpskPacketParams = BpskPacketParams::new();
/// assert_eq!(PKT_PARAMS, BpskPacketParams::default());
/// ```
pub const fn new() -> BpskPacketParams {
BpskPacketParams {
buf: [super::OpCode::SetPacketParams as u8, 0x00],
}
}
/// Set the payload length in bytes.
///
/// The length includes preamble, sync word, device ID, and CRC.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::BpskPacketParams;
///
/// const PKT_PARAMS: BpskPacketParams = BpskPacketParams::new().set_payload_len(12);
/// # assert_eq!(PKT_PARAMS.as_slice()[1], 12);
/// ```
#[must_use = "set_payload_len returns a modified BpskPacketParams"]
pub const fn set_payload_len(mut self, len: u8) -> BpskPacketParams {
self.buf[1] = len;
self
}
/// Extracts a slice containing the packet.
///
/// # Example
///
/// ```
/// use stm32wl_hal::subghz::{BpskPacketParams, HeaderType};
///
/// const PKT_PARAMS: BpskPacketParams = BpskPacketParams::new().set_payload_len(24);
///
/// assert_eq!(PKT_PARAMS.as_slice(), &[0x8C, 24]);
/// ```
pub const fn as_slice(&self) -> &[u8] {
&self.buf
}
}
impl Default for BpskPacketParams {
fn default() -> Self {
Self::new()
}
}