1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
use super::Status;
typestate!(LoRaStats, "LoRa stats");
typestate!(FskStats, "FSK stats");
/// Packet statistics.
///
/// Returned by [`fsk_stats`] and [`lora_stats`].
///
/// [`fsk_stats`]: super::SubGhz::fsk_stats
/// [`lora_stats`]: super::SubGhz::lora_stats
#[derive(Eq, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Stats<ModType> {
status: Status,
pkt_rx: u16,
pkt_crc: u16,
pkt_len_or_hdr_err: u16,
ty: ModType,
}
impl<ModType> Stats<ModType> {
const fn from_buf(buf: [u8; 7], ty: ModType) -> Stats<ModType> {
Stats {
status: Status::from_raw(buf[0]),
pkt_rx: u16::from_be_bytes([buf[1], buf[2]]),
pkt_crc: u16::from_be_bytes([buf[3], buf[4]]),
pkt_len_or_hdr_err: u16::from_be_bytes([buf[5], buf[6]]),
ty,
}
}
/// Get the radio status returned with the packet statistics.
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{CmdStatus, FskStats, Stats, StatusMode};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 0, 0, 0, 0, 0];
/// let stats: Stats<FskStats> = Stats::from_raw_fsk(example_data_from_radio);
/// assert_eq!(stats.status().mode(), Ok(StatusMode::Rx));
/// assert_eq!(stats.status().cmd(), Ok(CmdStatus::Available));
/// ```
pub const fn status(&self) -> Status {
self.status
}
/// Number of packets received.
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{FskStats, Stats};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 3, 0, 0, 0, 0];
/// let stats: Stats<FskStats> = Stats::from_raw_fsk(example_data_from_radio);
/// assert_eq!(stats.pkt_rx(), 3);
/// ```
pub const fn pkt_rx(&self) -> u16 {
self.pkt_rx
}
/// Number of packets received with a payload CRC error
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{LoRaStats, Stats};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 0, 0, 1, 0, 0];
/// let stats: Stats<LoRaStats> = Stats::from_raw_lora(example_data_from_radio);
/// assert_eq!(stats.pkt_crc(), 1);
/// ```
pub const fn pkt_crc(&self) -> u16 {
self.pkt_crc
}
}
impl Stats<FskStats> {
/// Create a new FSK packet statistics structure from a raw buffer.
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{FskStats, Stats};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 0, 0, 0, 0, 0];
/// let stats: Stats<FskStats> = Stats::from_raw_fsk(example_data_from_radio);
/// ```
pub const fn from_raw_fsk(buf: [u8; 7]) -> Stats<FskStats> {
Self::from_buf(buf, FskStats::new())
}
/// Number of packets received with a payload length error.
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{FskStats, Stats};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 0, 0, 0, 0, 1];
/// let stats: Stats<FskStats> = Stats::from_raw_fsk(example_data_from_radio);
/// assert_eq!(stats.pkt_len_err(), 1);
/// ```
pub const fn pkt_len_err(&self) -> u16 {
self.pkt_len_or_hdr_err
}
}
impl Stats<LoRaStats> {
/// Create a new LoRa packet statistics structure from a raw buffer.
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{LoRaStats, Stats};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 0, 0, 0, 0, 0];
/// let stats: Stats<LoRaStats> = Stats::from_raw_lora(example_data_from_radio);
/// ```
pub const fn from_raw_lora(buf: [u8; 7]) -> Stats<LoRaStats> {
Self::from_buf(buf, LoRaStats::new())
}
/// Number of packets received with a header CRC error.
///
/// # Example
///
/// ```
/// use stm32wlxx_hal::subghz::{LoRaStats, Stats};
///
/// let example_data_from_radio: [u8; 7] = [0x54, 0, 0, 0, 0, 0, 1];
/// let stats: Stats<LoRaStats> = Stats::from_raw_lora(example_data_from_radio);
/// assert_eq!(stats.pkt_hdr_err(), 1);
/// ```
pub const fn pkt_hdr_err(&self) -> u16 {
self.pkt_len_or_hdr_err
}
}
impl core::fmt::Debug for Stats<FskStats> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Stats")
.field("status", &self.status())
.field("pkt_rx", &self.pkt_rx())
.field("pkt_crc", &self.pkt_crc())
.field("pkt_len_err", &self.pkt_len_err())
.finish()
}
}
#[cfg(test)]
mod test {
use super::super::{CmdStatus, LoRaStats, Stats, StatusMode};
#[test]
fn mixed() {
let example_data_from_radio: [u8; 7] = [0x54, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
let stats: Stats<LoRaStats> = Stats::from_raw_lora(example_data_from_radio);
assert_eq!(stats.status().mode(), Ok(StatusMode::Rx));
assert_eq!(stats.status().cmd(), Ok(CmdStatus::Available));
assert_eq!(stats.pkt_rx(), 0x0102);
assert_eq!(stats.pkt_crc(), 0x0304);
assert_eq!(stats.pkt_hdr_err(), 0x0506);
}
}