esp_ieee802154/
hal.rs

1use core::ops::{BitAnd, BitOr};
2
3use esp_hal::peripherals::IEEE802154;
4
5use crate::pib::CcaMode;
6
7#[allow(unused)]
8#[derive(Debug, Clone, Copy)]
9pub(crate) enum Event {
10    TxDone          = 1 << 0,
11    RxDone          = 1 << 1,
12    AckTxDone       = 1 << 2,
13    AckRxDone       = 1 << 3,
14    RxAbort         = 1 << 4,
15    TxAbort         = 1 << 5,
16    EdDone          = 1 << 6,
17    Timer0Overflow  = 1 << 8,
18    Timer1Overflow  = 1 << 9,
19    ClockCountMatch = 1 << 10,
20    TxSfdDone       = 1 << 11,
21    RxSfdDone       = 1 << 12,
22}
23
24impl Event {
25    pub(crate) fn mask() -> u16 {
26        0x0000_1FFF
27    }
28}
29
30impl BitAnd<Event> for u16 {
31    type Output = u16;
32
33    fn bitand(self, rhs: Event) -> Self::Output {
34        self & rhs as u16
35    }
36}
37
38impl BitOr for Event {
39    type Output = u16;
40
41    fn bitor(self, rhs: Self) -> Self::Output {
42        self as u16 | rhs as u16
43    }
44}
45
46impl BitOr<Event> for u16 {
47    type Output = u16;
48
49    fn bitor(self, rhs: Event) -> Self::Output {
50        self | rhs as u16
51    }
52}
53
54#[allow(unused)]
55#[derive(Debug, Clone, Copy)]
56pub(crate) enum TxAbortReason {
57    RxAckStop       = 1,
58    RxAckSfdTimeout = 2,
59    RxAckCrcError   = 3,
60    RxAckInvalidLen = 4,
61    RxAckFilterFail = 5,
62    RxAckNoRss      = 6,
63    RxAckCoexBreak  = 7,
64    RxAckTypeNotAck = 8,
65    RxAckRestart    = 9,
66    RxAckTimeout    = 16,
67    TxStop          = 17,
68    TxCoexBreak     = 18,
69    TxSecurityError = 19,
70    CcaFailed       = 24,
71    CcaBusy         = 25,
72}
73
74impl TxAbortReason {
75    pub fn bit(&self) -> u32 {
76        1 << (*self as u32 - 1)
77    }
78}
79
80impl BitOr for TxAbortReason {
81    type Output = u32;
82
83    fn bitor(self, rhs: Self) -> Self::Output {
84        self.bit() | rhs.bit()
85    }
86}
87
88impl BitOr<TxAbortReason> for u32 {
89    type Output = u32;
90
91    fn bitor(self, rhs: TxAbortReason) -> Self::Output {
92        self | rhs.bit()
93    }
94}
95
96#[allow(unused)]
97#[derive(Debug, Clone, Copy)]
98pub(crate) enum RxAbortReason {
99    RxStop              = 1,
100    SfdTimeout          = 2,
101    CrcError            = 3,
102    InvalidLen          = 4,
103    FilterFail          = 5,
104    NoRss               = 6,
105    CoexBreak           = 7,
106    UnexpectedAck       = 8,
107    RxRestart           = 9,
108    TxAckTimeout        = 16,
109    TxAckStop           = 17,
110    TxAckCoexBreak      = 18,
111    EnhackSecurityError = 19,
112    EdAbort             = 24,
113    EdStop              = 25,
114    EdCoexReject        = 26,
115}
116
117impl RxAbortReason {
118    pub fn bit(&self) -> u32 {
119        1 << (*self as u32 - 1)
120    }
121}
122
123impl BitOr for RxAbortReason {
124    type Output = u32;
125
126    fn bitor(self, rhs: Self) -> Self::Output {
127        self.bit() | rhs.bit()
128    }
129}
130
131impl BitOr<RxAbortReason> for u32 {
132    type Output = u32;
133
134    fn bitor(self, rhs: RxAbortReason) -> Self::Output {
135        self | rhs.bit()
136    }
137}
138
139#[allow(unused)]
140#[derive(Debug, Clone, Copy)]
141pub(crate) enum EdSampleMode {
142    Max = 0,
143    Avg = 1,
144}
145
146#[allow(unused)]
147#[derive(Debug, Clone, Copy)]
148pub(crate) enum Command {
149    TxStart     = 0x41,
150    RxStart     = 0x42,
151    CcaTxStart  = 0x43,
152    EdStart     = 0x44,
153    Stop        = 0x45,
154    DtmTxStart  = 0x46,
155    DtmRxStart  = 0x47,
156    DtmStop     = 0x48,
157    Timer0Start = 0x4C,
158    Timer0Stop  = 0x4D,
159    Timer1Start = 0x4E,
160    Timer1Stop  = 0x4F,
161}
162
163#[derive(Debug, Clone, Copy)]
164pub(crate) enum MultipanIndex {
165    Multipan0 = 0,
166    Multipan1 = 1,
167    Multipan2 = 2,
168    Multipan3 = 3,
169}
170
171impl From<usize> for MultipanIndex {
172    fn from(value: usize) -> Self {
173        match value {
174            0 => MultipanIndex::Multipan0,
175            1 => MultipanIndex::Multipan1,
176            2 => MultipanIndex::Multipan2,
177            3 => MultipanIndex::Multipan3,
178            _ => panic!(),
179        }
180    }
181}
182
183#[inline(always)]
184pub(crate) fn mac_date() -> u32 {
185    IEEE802154::regs().mac_date().read().bits()
186}
187
188#[inline(always)]
189pub(crate) fn set_rx_on_delay(delay: u16) {
190    IEEE802154::regs()
191        .rxon_delay()
192        .modify(|_, w| unsafe { w.rxon_delay().bits(delay) });
193}
194
195#[inline(always)]
196pub(crate) fn enable_events(events: u16) {
197    IEEE802154::regs()
198        .event_en()
199        .modify(|r, w| unsafe { w.event_en().bits(r.event_en().bits() | events) });
200}
201
202#[inline(always)]
203pub(crate) fn disable_events(events: u16) {
204    IEEE802154::regs()
205        .event_en()
206        .modify(|r, w| unsafe { w.event_en().bits(r.event_en().bits() & !events) });
207}
208
209#[inline(always)]
210pub(crate) fn enable_tx_abort_events(events: u32) {
211    IEEE802154::regs()
212        .tx_abort_interrupt_control()
213        .modify(|r, w| unsafe {
214            w.tx_abort_interrupt_control()
215                .bits(r.tx_abort_interrupt_control().bits() | events)
216        });
217}
218
219#[inline(always)]
220pub(crate) fn enable_rx_abort_events(events: u32) {
221    IEEE802154::regs()
222        .rx_abort_intr_ctrl()
223        .modify(|r, w| unsafe {
224            w.rx_abort_intr_ctrl()
225                .bits(r.rx_abort_intr_ctrl().bits() | events)
226        });
227}
228
229#[inline(always)]
230pub(crate) fn set_ed_sample_mode(ed_sample_mode: EdSampleMode) {
231    IEEE802154::regs()
232        .ed_scan_cfg()
233        .modify(|_, w| unsafe { w.ed_sample_mode().bits(ed_sample_mode as u8) });
234}
235
236#[inline(always)]
237pub(crate) fn set_tx_addr(addr: *const u8) {
238    IEEE802154::regs()
239        .txdma_addr()
240        .modify(|_, w| unsafe { w.txdma_addr().bits(addr as u32) });
241}
242
243#[inline(always)]
244pub(crate) fn set_cmd(cmd: Command) {
245    IEEE802154::regs()
246        .command()
247        .modify(|_, w| unsafe { w.opcode().bits(cmd as u8) });
248}
249
250#[inline(always)]
251pub(crate) fn set_freq(freq: u8) {
252    IEEE802154::regs()
253        .channel()
254        .modify(|_, w| unsafe { w.hop().bits(freq) });
255}
256
257#[inline(always)]
258pub(crate) fn freq() -> u8 {
259    IEEE802154::regs().channel().read().hop().bits()
260}
261
262#[inline(always)]
263pub(crate) fn set_power(power: u8) {
264    IEEE802154::regs()
265        .tx_power()
266        .modify(|_, w| unsafe { w.tx_power().bits(power) });
267}
268
269#[inline(always)]
270pub(crate) fn set_multipan_enable_mask(mask: u8) {
271    // apparently the REGS are garbage and the struct is right?
272    IEEE802154::regs()
273        .ctrl_cfg()
274        .modify(|r, w| unsafe { w.bits(r.bits() & !(0b1111 << 29) | ((mask as u32) << 29)) });
275}
276
277#[inline(always)]
278pub(crate) fn set_multipan_panid(index: MultipanIndex, panid: u16) {
279    unsafe {
280        let pan_id = IEEE802154::regs()
281            .inf0_pan_id()
282            .as_ptr()
283            .offset(4 * index as isize);
284        pan_id.write_volatile(panid as u32);
285    }
286}
287
288#[inline(always)]
289pub(crate) fn set_multipan_short_addr(index: MultipanIndex, value: u16) {
290    unsafe {
291        let short_addr = IEEE802154::regs()
292            .inf0_short_addr()
293            .as_ptr()
294            .offset(4 * index as isize);
295        short_addr.write_volatile(value as u32);
296    }
297}
298
299#[inline(always)]
300pub(crate) fn set_multipan_ext_addr(index: MultipanIndex, ext_addr: *const u8) {
301    unsafe {
302        let mut ext_addr_ptr = IEEE802154::regs()
303            .inf0_extend_addr0()
304            .as_ptr()
305            .offset(4 * index as isize);
306
307        ext_addr_ptr.write_volatile(
308            (ext_addr.offset(0).read_volatile() as u32)
309                | ((ext_addr.offset(1).read_volatile() as u32) << 8)
310                | ((ext_addr.offset(2).read_volatile() as u32) << 16)
311                | ((ext_addr.offset(3).read_volatile() as u32) << 24),
312        );
313
314        ext_addr_ptr = ext_addr_ptr.offset(1);
315
316        ext_addr_ptr.write_volatile(
317            (ext_addr.offset(4).read_volatile() as u32)
318                | ((ext_addr.offset(5).read_volatile() as u32) << 8)
319                | ((ext_addr.offset(6).read_volatile() as u32) << 16)
320                | ((ext_addr.offset(7).read_volatile() as u32) << 24),
321        );
322    }
323}
324
325#[inline(always)]
326pub(crate) fn set_cca_mode(cca_mode: CcaMode) {
327    IEEE802154::regs()
328        .ed_scan_cfg()
329        .modify(|_, w| unsafe { w.cca_mode().bits(cca_mode as u8) });
330}
331
332#[inline(always)]
333pub(crate) fn set_cca_threshold(cca_threshold: i8) {
334    IEEE802154::regs()
335        .ed_scan_cfg()
336        .modify(|_, w| unsafe { w.cca_ed_threshold().bits(cca_threshold as u8) });
337}
338
339#[inline(always)]
340pub(crate) fn set_tx_auto_ack(enable: bool) {
341    IEEE802154::regs()
342        .ctrl_cfg()
343        .modify(|_, w| w.hw_auto_ack_tx_en().bit(enable));
344}
345
346#[inline(always)]
347pub(crate) fn tx_auto_ack() -> bool {
348    IEEE802154::regs()
349        .ctrl_cfg()
350        .read()
351        .hw_auto_ack_tx_en()
352        .bit_is_set()
353}
354
355#[inline(always)]
356pub(crate) fn set_rx_auto_ack(enable: bool) {
357    IEEE802154::regs()
358        .ctrl_cfg()
359        .modify(|_, w| w.hw_auto_ack_rx_en().bit(enable));
360}
361
362#[inline(always)]
363pub(crate) fn set_tx_enhance_ack(enable: bool) {
364    IEEE802154::regs()
365        .ctrl_cfg()
366        .modify(|_, w| w.hw_enhance_ack_tx_en().bit(enable));
367}
368
369#[inline(always)]
370pub(crate) fn tx_enhance_ack() -> bool {
371    IEEE802154::regs()
372        .ctrl_cfg()
373        .read()
374        .hw_enhance_ack_tx_en()
375        .bit_is_set()
376}
377
378#[inline(always)]
379pub(crate) fn set_coordinator(enable: bool) {
380    IEEE802154::regs()
381        .ctrl_cfg()
382        .modify(|_, w| w.pan_coordinator().bit(enable));
383}
384
385#[inline(always)]
386pub(crate) fn set_promiscuous(enable: bool) {
387    IEEE802154::regs()
388        .ctrl_cfg()
389        .modify(|_, w| w.promiscuous_mode().bit(enable));
390}
391
392#[inline(always)]
393pub(crate) fn set_pending_mode(enable: bool) {
394    IEEE802154::regs()
395        .ctrl_cfg()
396        .modify(|_, w| w.autopend_enhance().bit(enable));
397}
398
399#[inline(always)]
400pub(crate) fn events() -> u16 {
401    IEEE802154::regs().event_status().read().bits() as u16
402}
403
404#[inline(always)]
405pub(crate) fn clear_events(events: u16) {
406    IEEE802154::regs()
407        .event_status()
408        .modify(|r, w| unsafe { w.event_status().bits(r.event_status().bits() & events) });
409}
410
411#[inline(always)]
412pub(crate) fn set_transmit_security(enable: bool) {
413    IEEE802154::regs()
414        .sec_ctrl()
415        .modify(|_, w| w.sec_en().bit(enable));
416}
417
418#[inline(always)]
419pub(crate) fn set_rx_addr(addr: *mut u8) {
420    IEEE802154::regs()
421        .rxdma_addr()
422        .modify(|_, w| unsafe { w.rxdma_addr().bits(addr as u32) });
423}
424
425#[inline(always)]
426pub(crate) fn abort_tx() {
427    IEEE802154::regs()
428        .tx_status()
429        .modify(|_, w| unsafe { w.tx_abort_status().bits(0) });
430}
431
432#[inline(always)]
433pub(crate) fn abort_rx() {
434    IEEE802154::regs()
435        .rx_status()
436        .modify(|_, w| unsafe { w.rx_abort_status().bits(0) });
437}