use core::{
marker::PhantomData,
ops::{Deref, DerefMut},
};
use cc2538_pac as pac;
use cortex_m::peripheral::NVIC;
use pac::{
ana_regs, rfcore_ffsm, rfcore_sfr, rfcore_xreg, AnaRegs, Interrupt, RfcoreFfsm, RfcoreSfr,
RfcoreXreg,
};
use crate::dma::{self, Dma, Enabled, TransferMode};
use crate::time::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorEvent {
NoLock,
RxAbo,
RxOverf,
RxUnderf,
TxOverf,
TxUnderf,
StrobeErr,
All,
}
impl ErrorEvent {
pub(crate) const fn mask(&self) -> u32 {
match self {
ErrorEvent::NoLock => 1 << 0,
ErrorEvent::RxAbo => 1 << 1,
ErrorEvent::RxOverf => 1 << 2,
ErrorEvent::RxUnderf => 1 << 3,
ErrorEvent::TxOverf => 1 << 4,
ErrorEvent::TxUnderf => 1 << 5,
ErrorEvent::StrobeErr => 1 << 6,
ErrorEvent::All => !0u32,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Event {
TxAckDone,
TxDone,
RfIdle,
CspManInt,
CspStop,
CspWait,
Sfd,
Fifop,
SrcMatchDone,
SrcMatchFound,
FrameAccepted,
RxPktDone,
RxMaskZero,
All,
}
impl Event {
#[inline]
pub(crate) const fn mask(&self) -> u32 {
match self {
Event::TxAckDone => 0b1,
Event::TxDone => 0b10,
Event::RfIdle => 0b100,
Event::CspManInt => 0b1000,
Event::CspStop => 0b10000,
Event::CspWait => 0b100000,
Event::Sfd => 0b10,
Event::Fifop => 0b100,
Event::SrcMatchDone => 0b1000,
Event::SrcMatchFound => 0b10000,
Event::FrameAccepted => 0b100000,
Event::RxPktDone => 0b1000000,
Event::RxMaskZero => 0b10000000,
Event::All => !0u32,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RadioError {
PayloadTooBig,
ChannelNotClear,
UnableToStartTx,
Collision,
FailedTransmission,
IncorrectFrame,
}
pub enum Radio<'p> {
Off(RadioDriver<'p, RadioOff>),
On(RadioDriver<'p, RadioOn>),
Undefined,
}
const CHECKSUM_LEN: usize = 2;
const MAX_PACKET_LEN: usize = 127;
const MAX_PAYLOAD_LEN: usize = MAX_PACKET_LEN - CHECKSUM_LEN;
const CCA_THRES: usize = 0xF8;
#[derive(Debug, Copy, Clone)]
pub struct RadioConfig {
pub channel: Channel,
pub src_pan_id: u32,
pub dst_pan_id: u32,
pub short_addr: u16,
pub ext_addr: [u8; 8],
}
impl Default for RadioConfig {
fn default() -> Self {
Self {
channel: Channel::Channel26,
src_pan_id: 0xabcd,
dst_pan_id: 0xabcd,
short_addr: 0,
ext_addr: [0; 8],
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum RxMode {
Normal = 0x0,
InfiniteRx = 0x1,
InfiniteReception = 0x10,
SymbolSearchDisabled = 0x11,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Channel {
Channel11 = 11,
Channel12,
Channel13,
Channel14,
Channel15,
Channel16,
Channel17,
Channel18,
Channel19,
Channel20,
Channel21,
Channel22,
Channel23,
Channel24,
Channel25,
Channel26,
}
#[inline]
pub(crate) const fn channel_frequency(channel: Channel) -> u32 {
(2405 + 5 * (channel as u32 - 11)) * 1_000_000
}
#[inline]
pub(crate) const fn channel_freq_reg_val(channel: Channel) -> u32 {
11 + 5 * (channel as u32 - 11)
}
#[repr(u8)]
#[derive(Debug, Copy, Clone)]
pub enum CspOpCode {
DecZ = 0xC5,
DecY = 0xC4,
DecX = 0xC3,
IncZ = 0xC2,
IncY = 0xC1,
IncX = 0xC0,
IncMaxY = 0xC8,
RandXY = 0xBD,
Int = 0xBA,
WaitX = 0xBC,
SetCmp1 = 0xBE,
WaitW = 0x80,
WEvent1 = 0xB8,
WEvent2 = 0xB9,
Label = 0xBB,
RptC = 0xA0,
SkipSC = 0x00,
Stop = 0xD2,
SNop = 0xD0,
SRXOn = 0xD3,
STXOn = 0xD9,
STXOnCca = 0xDA,
SSampleCca = 0xDB,
SRFOff = 0xDF,
SFlushRX = 0xDD,
SFlushTX = 0xDE,
SAck = 0xD6,
SAckPend = 0xD7,
SNack = 0xD8,
SRXMaskBitSet = 0xD4,
SRXMaskBitClr = 0xD5,
IsStop = 0xE2,
IsStart = 0xE1,
IsRXon = 0xE3,
IsRXMaskBitSet = 0xE4,
IsRXMaskBitClr = 0xE5,
IsTXOn = 0xE9,
IsTXOnCca = 0xEA,
IsSampleCca = 0xEB,
IsRFOff = 0xEF,
IsFlushRx = 0xED,
IsFlushTX = 0xEE,
IsAck = 0xE6,
IsAckPend = 0xE7,
IsNack = 0xE8,
IsClear = 0xFF,
}
pub struct RadioOn;
pub struct RadioOff;
pub struct RadioDriver<'p, State> {
_ffsm: PhantomData<&'p mut RfcoreFfsm>,
_xreg: PhantomData<&'p mut RfcoreXreg>,
_sfr: PhantomData<&'p mut RfcoreSfr>,
_ana: PhantomData<&'p mut AnaRegs>,
tx_channel: dma::Channel,
rx_channel: dma::Channel,
_state: PhantomData<State>,
}
impl<State> RadioDriver<'_, State> {
#[inline]
fn ffsm_regs() -> &'static rfcore_ffsm::RegisterBlock {
unsafe { &*RfcoreFfsm::ptr() }
}
#[inline]
fn xreg_regs() -> &'static rfcore_xreg::RegisterBlock {
unsafe { &*RfcoreXreg::ptr() }
}
#[inline]
fn sfr_regs() -> &'static rfcore_sfr::RegisterBlock {
unsafe { &*RfcoreSfr::ptr() }
}
#[inline]
fn ana_regs() -> &'static ana_regs::RegisterBlock {
unsafe { &*AnaRegs::ptr() }
}
#[inline]
pub fn set_pan_id(&self, id: u32) {
Self::ffsm_regs()
.pan_id0()
.modify(|_, w| unsafe { w.bits(id & 0xFF) });
Self::ffsm_regs()
.pan_id1()
.modify(|_, w| unsafe { w.bits(id >> 8) });
}
#[inline]
pub fn get_pan_id(&mut self) -> u16 {
(Self::ffsm_regs().pan_id1().read().bits() << 8) as u16
| (Self::ffsm_regs().pan_id0().read().bits() & 0xFF) as u16
}
#[inline]
pub fn set_short_address(&mut self, addr: u16) {
Self::ffsm_regs()
.short_addr0()
.modify(|_, w| unsafe { w.bits(addr as u32 & 0xFF) });
Self::ffsm_regs()
.short_addr1()
.modify(|_, w| unsafe { w.bits(addr as u32 >> 8) });
}
#[inline]
pub fn get_short_address(&mut self) -> u16 {
(Self::ffsm_regs().short_addr1().read().bits() << 8) as u16
| (Self::ffsm_regs().short_addr0().read().bits() & 0xFF) as u16
}
#[inline]
pub fn set_extended_address(&mut self, addr: &[u8]) {
let ffsm = Self::ffsm_regs();
ffsm.ext_addr0()
.write(|w| unsafe { w.ext_addr0().bits(addr[7]) });
ffsm.ext_addr1()
.write(|w| unsafe { w.ext_addr1().bits(addr[6]) });
ffsm.ext_addr2()
.write(|w| unsafe { w.ext_addr2().bits(addr[5]) });
ffsm.ext_addr3()
.write(|w| unsafe { w.ext_addr3().bits(addr[4]) });
ffsm.ext_addr4()
.write(|w| unsafe { w.ext_addr4().bits(addr[3]) });
ffsm.ext_addr5()
.write(|w| unsafe { w.ext_addr5().bits(addr[2]) });
ffsm.ext_addr6()
.write(|w| unsafe { w.ext_addr6().bits(addr[1]) });
ffsm.ext_addr7()
.write(|w| unsafe { w.ext_addr7().bits(addr[0]) });
}
#[inline]
pub fn get_cca_threshold(&mut self) -> i32 {
let cca_thr = Self::xreg_regs().ccactrl0().read().cca_thr().bits() as i32;
cca_thr - 73
}
#[inline]
pub fn set_cca_threshold(&mut self, threshold: i32) {
Self::xreg_regs()
.ccactrl0()
.modify(|_, w| unsafe { w.bits((threshold + 73) as u32) });
}
pub fn get_tx_power(&mut self) -> i32 {
todo!();
}
pub fn set_tx_power(&mut self, _power: i32) {
todo!();
}
#[inline]
pub fn enable_frame_filtering(&mut self) {
Self::xreg_regs()
.frmfilt0()
.modify(|_, w| w.frame_filter_en().set_bit());
}
#[inline]
pub fn disable_frame_filtering(&mut self) {
Self::xreg_regs()
.frmfilt0()
.modify(|_, w| w.frame_filter_en().clear_bit());
}
#[inline]
pub fn enable_shr_search(&mut self) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| unsafe { w.rx_mode().bits(0b00) });
}
#[inline]
pub fn disable_shr_search(&mut self) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| unsafe { w.rx_mode().bits(0b11) });
}
#[inline]
fn enable_autocrc(&mut self) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| w.autocrc().set_bit());
}
#[inline]
fn disable_autocrc(&mut self) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| w.autocrc().clear_bit());
}
#[inline]
fn enable_autoack(&mut self) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| w.autoack().set_bit());
}
#[inline]
fn disable_autoack(&mut self) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| w.autoack().clear_bit());
}
pub fn get_sfd_timestamp(&mut self) -> u32 {
todo!();
}
#[inline]
pub fn set_rx_mode(&mut self, rx_mode: RxMode) {
Self::xreg_regs()
.frmctrl0()
.modify(|_, w| unsafe { w.rx_mode().bits(rx_mode as u8) });
}
#[inline]
pub fn send_csp_op_code(&self, op_code: CspOpCode) {
Self::sfr_regs()
.rfst()
.modify(|_, w| unsafe { w.instr().bits(op_code as u8) });
}
#[inline]
pub fn listen(&mut self, event: Event) {
match event {
Event::Sfd
| Event::Fifop
| Event::SrcMatchDone
| Event::SrcMatchFound
| Event::FrameAccepted
| Event::RxPktDone
| Event::RxMaskZero => {
Self::xreg_regs()
.rfirqm0()
.modify(|r, w| unsafe { w.bits(r.bits() | event.mask()) });
}
Event::TxAckDone
| Event::TxDone
| Event::RfIdle
| Event::CspManInt
| Event::CspStop
| Event::CspWait => {
Self::xreg_regs()
.rfirqm1()
.modify(|r, w| unsafe { w.bits(r.bits() | event.mask()) });
}
Event::All => {
Self::xreg_regs()
.rfirqm0()
.write(|w| unsafe { w.bits(event.mask()) });
Self::xreg_regs()
.rfirqm1()
.write(|w| unsafe { w.bits(event.mask()) });
}
};
}
#[inline]
pub fn unlisten(&mut self, event: Event) {
match event {
Event::Sfd
| Event::Fifop
| Event::SrcMatchDone
| Event::SrcMatchFound
| Event::FrameAccepted
| Event::RxPktDone
| Event::RxMaskZero => {
Self::xreg_regs()
.rfirqm0()
.modify(|r, w| unsafe { w.bits(r.bits() & !event.mask()) });
}
Event::TxAckDone
| Event::TxDone
| Event::RfIdle
| Event::CspManInt
| Event::CspStop
| Event::CspWait => {
Self::xreg_regs()
.rfirqm1()
.modify(|r, w| unsafe { w.bits(r.bits() & !event.mask()) });
}
Event::All => {
Self::xreg_regs().rfirqm0().write(|w| unsafe { w.bits(0) });
Self::xreg_regs().rfirqm1().write(|w| unsafe { w.bits(0) });
}
};
}
#[inline]
pub fn clear_event(&mut self, event: Event) {
match event {
Event::Sfd
| Event::Fifop
| Event::SrcMatchDone
| Event::SrcMatchFound
| Event::FrameAccepted
| Event::RxPktDone
| Event::RxMaskZero => {
Self::sfr_regs()
.rfirqf0()
.modify(|r, w| unsafe { w.bits(r.bits() & !event.mask()) });
}
Event::TxAckDone
| Event::TxDone
| Event::RfIdle
| Event::CspManInt
| Event::CspStop
| Event::CspWait => {
Self::sfr_regs()
.rfirqf1()
.modify(|r, w| unsafe { w.bits(r.bits() & !event.mask()) });
}
Event::All => {
Self::sfr_regs().rfirqf0().write(|w| unsafe { w.bits(0) });
Self::sfr_regs().rfirqf1().write(|w| unsafe { w.bits(0) });
}
};
}
#[inline]
pub fn is_interrupt_pending(&self, event: Event) -> bool {
match event {
Event::Sfd
| Event::Fifop
| Event::SrcMatchDone
| Event::SrcMatchFound
| Event::FrameAccepted
| Event::RxPktDone
| Event::RxMaskZero => (Self::sfr_regs().rfirqf0().read().bits() & event.mask()) != 0,
Event::TxAckDone
| Event::TxDone
| Event::RfIdle
| Event::CspManInt
| Event::CspStop
| Event::CspWait => (Self::sfr_regs().rfirqf1().read().bits() & event.mask()) != 0,
Event::All => {
(Self::sfr_regs().rfirqf0().read().bits()
| Self::sfr_regs().rfirqf1().read().bits())
!= 0
}
}
}
#[inline]
pub fn listen_error(&mut self, event: ErrorEvent) {
Self::xreg_regs()
.rferrm()
.modify(|r, w| unsafe { w.bits(r.bits() | event.mask()) });
}
#[inline]
pub fn unlisten_error(&mut self, event: ErrorEvent) {
Self::xreg_regs()
.rferrm()
.modify(|r, w| unsafe { w.bits(r.bits() & !event.mask()) });
}
#[inline]
pub fn clear_err(&mut self, event: ErrorEvent) {
Self::sfr_regs()
.rferrf()
.modify(|r, w| unsafe { w.bits(r.bits() & !event.mask()) });
}
#[inline]
pub fn is_error_interrupt(&self, event: ErrorEvent) -> bool {
match event {
ErrorEvent::NoLock => Self::sfr_regs().rferrf().read().nlock().bit_is_set(),
ErrorEvent::RxAbo => Self::sfr_regs().rferrf().read().rxabo().bit_is_set(),
ErrorEvent::RxOverf => Self::sfr_regs().rferrf().read().rxoverf().bit_is_set(),
ErrorEvent::RxUnderf => Self::sfr_regs().rferrf().read().rxunderf().bit_is_set(),
ErrorEvent::TxOverf => Self::sfr_regs().rferrf().read().txoverf().bit_is_set(),
ErrorEvent::TxUnderf => Self::sfr_regs().rferrf().read().txunderf().bit_is_set(),
ErrorEvent::StrobeErr => Self::sfr_regs().rferrf().read().strobeerr().bit_is_set(),
ErrorEvent::All => Self::sfr_regs().rferrf().read().bits() != 0,
}
}
}
impl<'p> RadioDriver<'p, RadioOff> {
pub fn new(
#[allow(unused_variables)] rfcore_ffsm: &'p mut RfcoreFfsm,
#[allow(unused_variables)] rfcore_xreg: &'p mut RfcoreXreg,
#[allow(unused_variables)] rfcore_sfr: &'p mut RfcoreSfr,
#[allow(unused_variables)] ana_regs: &'p mut AnaRegs,
tx_channel: dma::Channel,
rx_channel: dma::Channel,
) -> RadioDriver<'p, RadioOff> {
RadioDriver {
_ffsm: PhantomData,
_xreg: PhantomData,
_sfr: PhantomData,
_ana: PhantomData,
tx_channel,
rx_channel,
_state: PhantomData,
}
}
#[inline]
pub fn enable(mut self, config: Option<RadioConfig>) -> RadioDriver<'p, RadioOn> {
let xreg = Self::xreg_regs();
let ana = Self::ana_regs();
xreg.ccactrl0()
.modify(|_, w| unsafe { w.cca_thr().bits(CCA_THRES as u8) });
if let Some(config) = config {
self.set_pan_id(config.dst_pan_id);
self.set_short_address(config.short_addr);
self.set_extended_address(&config.ext_addr);
}
self.send_csp_op_code(CspOpCode::IsFlushRx);
xreg.txfiltcfg().modify(|_, w| unsafe { w.bits(0x09) }); xreg.agcctrl1().modify(|_, w| unsafe { w.bits(0x15) }); ana.ivctrl().modify(|_, w| unsafe { w.bits(0x0B) }); xreg.fscal1().modify(|_, w| unsafe { w.bits(0x01) });
self.enable_autocrc();
self.enable_autoack();
xreg.srcmatch().modify(|_, w| unsafe { w.bits(0) });
xreg.fifopctrl()
.modify(|_, w| unsafe { w.fifop_thr().bits(MAX_PACKET_LEN as u8) });
xreg.txpower().modify(|_, w| unsafe { w.bits(0xD5) });
self.set_channel(Channel::Channel26);
self.enable_shr_search();
self.tx_channel.allow_periph_requests(false);
self.tx_channel
.set_destination_end_address(Self::sfr_regs().rfdata().as_ptr() as u32);
self.tx_channel
.set_arbitration_size(dma::Arbitration::Transfer128);
self.tx_channel
.set_transfer_mode(dma::TransferMode::AutoRequest);
self.tx_channel.set_source_size(dma::DataSize::Data8bit);
self.tx_channel
.set_destination_size(dma::DataSize::Data8bit);
self.tx_channel
.set_source_increment(dma::AddressIncrement::Increment8bit);
self.tx_channel
.set_destination_increment(dma::AddressIncrement::None);
self.rx_channel.allow_periph_requests(true);
self.rx_channel
.set_source_end_address(Self::sfr_regs().rfdata().as_ptr() as u32);
self.rx_channel
.set_arbitration_size(dma::Arbitration::Transfer128);
self.rx_channel
.set_transfer_mode(dma::TransferMode::AutoRequest);
self.rx_channel.set_source_size(dma::DataSize::Data8bit);
self.rx_channel
.set_destination_size(dma::DataSize::Data8bit);
self.rx_channel
.set_source_increment(dma::AddressIncrement::None);
self.rx_channel
.set_destination_increment(dma::AddressIncrement::Increment8bit);
self.clear_event(Event::All);
self.clear_err(ErrorEvent::All);
self.listen(Event::Fifop);
self.listen(Event::TxDone);
self.listen_error(ErrorEvent::All);
unsafe { NVIC::unmask(Interrupt::RF_TXRX) };
self.enable_rx()
}
#[inline]
pub fn set_channel(&mut self, channel: Channel) {
Self::xreg_regs()
.freqctrl()
.modify(|_, w| unsafe { w.bits(channel_freq_reg_val(channel)) });
}
#[inline]
pub fn get_rssi(&mut self) -> i32 {
let mut rssi;
loop {
rssi = Self::xreg_regs().rssi().read().rssi_val().bits();
if rssi != 0x80 {
break;
}
}
rssi as i32 - 73
}
#[inline]
fn enable_rx(self) -> RadioDriver<'p, RadioOn> {
self.send_csp_op_code(CspOpCode::IsRXon);
RadioDriver {
_ffsm: PhantomData,
_xreg: PhantomData,
_sfr: PhantomData,
_ana: PhantomData,
tx_channel: self.tx_channel,
rx_channel: self.rx_channel,
_state: PhantomData,
}
}
#[inline]
fn start_mac_timer(&mut self) {
Self::sfr_regs().mtctrl().write(|w| w.sync().set_bit());
Self::sfr_regs().mtctrl().write(|w| w.run().set_bit());
while Self::sfr_regs().mtctrl().read().state().bit_is_clear() {}
}
#[inline]
fn set_poll_mode(&mut self) {
self.start_mac_timer();
}
}
impl<'p> RadioDriver<'p, RadioOn> {
pub fn disable(self) -> RadioDriver<'p, RadioOff> {
while Self::xreg_regs().fsmstat1().read().tx_active().bit_is_set() {}
if Self::xreg_regs().fsmstat1().read().fifop().bit_is_set() {
self.send_csp_op_code(CspOpCode::IsFlushRx);
}
self.disable_rx()
}
#[inline]
fn enable_tx(self) {
self.send_csp_op_code(CspOpCode::IsTXOn);
}
fn disable_rx(self) -> RadioDriver<'p, RadioOff> {
self.send_csp_op_code(CspOpCode::IsRFOff);
RadioDriver {
_ffsm: PhantomData,
_xreg: PhantomData,
_sfr: PhantomData,
_ana: PhantomData,
tx_channel: self.tx_channel,
rx_channel: self.rx_channel,
_state: PhantomData,
}
}
#[inline]
pub fn prepare(&mut self, payload: &[u8]) -> Result<(), RadioError> {
if payload.len() > MAX_PAYLOAD_LEN {
return Err(RadioError::PayloadTooBig);
}
while Self::xreg_regs().fsmstat1().read().tx_active().bit() {}
self.send_csp_op_code(CspOpCode::IsFlushTX);
Self::sfr_regs()
.rfdata()
.write(|w| unsafe { w.bits((payload.len() + CHECKSUM_LEN) as u32) });
for b in payload.iter() {
Self::sfr_regs()
.rfdata()
.write(|w| unsafe { w.bits((*b) as u32) });
}
Ok(())
}
#[inline]
pub fn transmit(&mut self) -> Result<(), RadioError> {
if !self.is_channel_clear() || self.receiving_packet() {
return Err(RadioError::Collision);
}
self.send_csp_op_code(CspOpCode::IsTXOn);
let mut counter = 0;
while Self::xreg_regs().fsmstat1().read().tx_active().bit_is_set() && counter < 3 {
counter += 1;
}
if Self::xreg_regs()
.fsmstat1()
.read()
.tx_active()
.bit_is_clear()
{
self.send_csp_op_code(CspOpCode::IsFlushTX);
return Err(RadioError::UnableToStartTx);
}
Ok(())
}
#[inline]
pub fn send(&mut self, payload: &[u8]) -> Result<(), RadioError> {
self.prepare(payload).expect("unable to prepare");
self.transmit()
}
#[inline]
pub fn sending(&self) -> bool {
Self::xreg_regs().fsmstat1().read().tx_active().bit_is_set()
}
#[inline]
pub fn read(&mut self, buffer: &mut [u8]) -> u32 {
let len: u32 = Self::sfr_regs().rfdata().read().bits();
if len > 127 {
self.send_csp_op_code(CspOpCode::IsFlushRx);
return 0;
}
if len <= 4 {
self.send_csp_op_code(CspOpCode::IsFlushRx);
return 0;
}
if len - 2 > buffer.len() as u32 {
self.send_csp_op_code(CspOpCode::IsFlushRx);
return 0;
}
for i in 0..len {
buffer[i as usize] = Self::sfr_regs().rfdata().read().bits() as u8;
}
if Self::xreg_regs().fsmstat1().read().fifop().bit_is_set() {
if Self::xreg_regs().fsmstat1().read().fifo().bit_is_set() {
cortex_m::asm::sev();
} else {
self.send_csp_op_code(CspOpCode::IsFlushRx);
}
}
len - 2
}
#[inline]
pub fn receiving_packet(&self) -> bool {
Self::xreg_regs().fsmstat1().read().sfd().bit()
& Self::xreg_regs().fsmstat1().read().tx_active().bit()
}
#[inline]
pub fn received_packet(&self) -> bool {
Self::xreg_regs().fsmstat1().read().fifop().bit()
}
#[inline]
pub fn is_rssi_valid(&self) -> bool {
Self::xreg_regs()
.rssistat()
.read()
.rssi_valid()
.bit_is_set()
}
#[inline]
pub fn is_channel_clear(&self) -> bool {
while !self.is_rssi_valid() {}
Self::xreg_regs().fsmstat1().read().cca().bit_is_set()
}
#[inline]
pub fn random_data(&self) -> u8 {
Self::xreg_regs().rfrnd().read().irnd().bit() as u8
}
}