nrf52/
ble_radio.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Radio driver, Bluetooth Low Energy, NRF52
6//!
7//! The generic radio configuration i.e., not specific to Bluetooth are functions and similar which
8//! do not start with `ble`. Moreover, Bluetooth Low Energy specific radio configuration
9//! starts with `ble`
10//!
11//! For more readability the Bluetooth specific configuration may be moved to separate trait
12//!
13//! ### Author
14//! * Niklas Adolfsson <niklasadolfsson1@gmail.com>
15//! * Date: July 18, 2017
16//!
17//! ### Packet Configuration
18//! ```txt
19//! +----------+------+--------+----+--------+----+---------+-----+
20//! | Preamble | Base | Prefix | S0 | Length | S1 | Payload | CRC |
21//! +----------+------+--------+----+--------+----+---------+-----+
22//! ```
23//!
24//! * Preamble - 1 byte
25//!
26//! * Base and prefix forms together the access address
27//!
28//! * S0, an optional parameter that is configured to indicate how many bytes of
29//! the payload is the PDU Type. Configured as 1 byte!
30//!
31//! * Length, an optional parameter that is configured to indicate how many bits of the
32//! payload is the length field. Configured as 8 bits!
33//!
34//! * S1, Not used
35//!
36//! * Payload - 2 to 255 bytes
37//!
38//! * CRC - 3 bytes
39
40use core::cell::Cell;
41use core::ptr::addr_of;
42use core::ptr::addr_of_mut;
43use kernel::hil::ble_advertising;
44use kernel::hil::ble_advertising::RadioChannel;
45use kernel::utilities::cells::OptionalCell;
46use kernel::utilities::cells::TakeCell;
47use kernel::utilities::registers::interfaces::{Readable, Writeable};
48use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
49use kernel::utilities::StaticRef;
50use kernel::ErrorCode;
51use nrf5x::constants::TxPower;
52
53const RADIO_BASE: StaticRef<RadioRegisters> =
54    unsafe { StaticRef::new(0x40001000 as *const RadioRegisters) };
55
56#[repr(C)]
57struct RadioRegisters {
58    /// Enable Radio in TX mode
59    /// - Address: 0x000 - 0x004
60    task_txen: WriteOnly<u32, Task::Register>,
61    /// Enable Radio in RX mode
62    /// - Address: 0x004 - 0x008
63    task_rxen: WriteOnly<u32, Task::Register>,
64    /// Start Radio
65    /// - Address: 0x008 - 0x00c
66    task_start: WriteOnly<u32, Task::Register>,
67    /// Stop Radio
68    /// - Address: 0x00c - 0x010
69    task_stop: WriteOnly<u32, Task::Register>,
70    /// Disable Radio
71    /// - Address: 0x010 - 0x014
72    task_disable: WriteOnly<u32, Task::Register>,
73    /// Start the RSSI and take one single sample of the receive signal strength
74    /// - Address: 0x014- 0x018
75    task_rssistart: WriteOnly<u32, Task::Register>,
76    /// Stop the RSSI measurement
77    /// - Address: 0x018 - 0x01c
78    task_rssistop: WriteOnly<u32, Task::Register>,
79    /// Start the bit counter
80    /// - Address: 0x01c - 0x020
81    task_bcstart: WriteOnly<u32, Task::Register>,
82    /// Stop the bit counter
83    /// - Address: 0x020 - 0x024
84    task_bcstop: WriteOnly<u32, Task::Register>,
85    /// Reserved
86    _reserved1: [u32; 55],
87    /// Radio has ramped up and is ready to be started
88    /// - Address: 0x100 - 0x104
89    event_ready: ReadWrite<u32, Event::Register>,
90    /// Address sent or received
91    /// - Address: 0x104 - 0x108
92    event_address: ReadWrite<u32, Event::Register>,
93    /// Packet payload sent or received
94    /// - Address: 0x108 - 0x10c
95    event_payload: ReadWrite<u32, Event::Register>,
96    /// Packet sent or received
97    /// - Address: 0x10c - 0x110
98    event_end: ReadWrite<u32, Event::Register>,
99    /// Radio has been disabled
100    /// - Address: 0x110 - 0x114
101    event_disabled: ReadWrite<u32, Event::Register>,
102    /// A device address match occurred on the last received packet
103    /// - Address: 0x114 - 0x118
104    event_devmatch: ReadWrite<u32>,
105    /// No device address match occurred on the last received packet
106    /// - Address: 0x118 - 0x11c
107    event_devmiss: ReadWrite<u32, Event::Register>,
108    /// Sampling of receive signal strength complete
109    /// - Address: 0x11c - 0x120
110    event_rssiend: ReadWrite<u32, Event::Register>,
111    /// Reserved
112    _reserved2: [u32; 2],
113    /// Bit counter reached bit count value
114    /// - Address: 0x128 - 0x12c
115    event_bcmatch: ReadWrite<u32, Event::Register>,
116    /// Reserved
117    _reserved3: [u32; 1],
118    /// Packet received with CRC ok
119    /// - Address: 0x130 - 0x134
120    event_crcok: ReadWrite<u32, Event::Register>,
121    /// Packet received with CRC error
122    /// - Address: 0x134 - 0x138
123    crcerror: ReadWrite<u32, Event::Register>,
124    /// Reserved
125    _reserved4: [u32; 50],
126    /// Shortcut register
127    /// - Address: 0x200 - 0x204
128    shorts: ReadWrite<u32, Shortcut::Register>,
129    /// Reserved
130    _reserved5: [u32; 64],
131    /// Enable interrupt
132    /// - Address: 0x304 - 0x308
133    intenset: ReadWrite<u32, Interrupt::Register>,
134    /// Disable interrupt
135    /// - Address: 0x308 - 0x30c
136    intenclr: ReadWrite<u32, Interrupt::Register>,
137    /// Reserved
138    _reserved6: [u32; 61],
139    /// CRC status
140    /// - Address: 0x400 - 0x404
141    crcstatus: ReadOnly<u32, Event::Register>,
142    /// Reserved
143    _reserved7: [u32; 1],
144    /// Received address
145    /// - Address: 0x408 - 0x40c
146    rxmatch: ReadOnly<u32, ReceiveMatch::Register>,
147    /// CRC field of previously received packet
148    /// - Address: 0x40c - 0x410
149    rxcrc: ReadOnly<u32, ReceiveCrc::Register>,
150    /// Device address match index
151    /// - Address: 0x410 - 0x414
152    dai: ReadOnly<u32, DeviceAddressIndex::Register>,
153    /// Reserved
154    _reserved8: [u32; 60],
155    /// Packet pointer
156    /// - Address: 0x504 - 0x508
157    packetptr: ReadWrite<u32, PacketPointer::Register>,
158    /// Frequency
159    /// - Address: 0x508 - 0x50c
160    frequency: ReadWrite<u32, Frequency::Register>,
161    /// Output power
162    /// - Address: 0x50c - 0x510
163    txpower: ReadWrite<u32, TransmitPower::Register>,
164    /// Data rate and modulation
165    /// - Address: 0x510 - 0x514
166    mode: ReadWrite<u32, Mode::Register>,
167    /// Packet configuration register 0
168    /// - Address 0x514 - 0x518
169    pcnf0: ReadWrite<u32, PacketConfiguration0::Register>,
170    /// Packet configuration register 1
171    /// - Address: 0x518 - 0x51c
172    pcnf1: ReadWrite<u32, PacketConfiguration1::Register>,
173    /// Base address 0
174    /// - Address: 0x51c - 0x520
175    base0: ReadWrite<u32, BaseAddress::Register>,
176    /// Base address 1
177    /// - Address: 0x520 - 0x524
178    base1: ReadWrite<u32, BaseAddress::Register>,
179    /// Prefix bytes for logical addresses 0-3
180    /// - Address: 0x524 - 0x528
181    prefix0: ReadWrite<u32, Prefix0::Register>,
182    /// Prefix bytes for logical addresses 4-7
183    /// - Address: 0x528 - 0x52c
184    prefix1: ReadWrite<u32, Prefix1::Register>,
185    /// Transmit address select
186    /// - Address: 0x52c - 0x530
187    txaddress: ReadWrite<u32, TransmitAddress::Register>,
188    /// Receive address select
189    /// - Address: 0x530 - 0x534
190    rxaddresses: ReadWrite<u32, ReceiveAddresses::Register>,
191    /// CRC configuration
192    /// - Address: 0x534 - 0x538
193    crccnf: ReadWrite<u32, CrcConfiguration::Register>,
194    /// CRC polynomial
195    /// - Address: 0x538 - 0x53c
196    crcpoly: ReadWrite<u32, CrcPolynomial::Register>,
197    /// CRC initial value
198    /// - Address: 0x53c - 0x540
199    crcinit: ReadWrite<u32, CrcInitialValue::Register>,
200    /// Reserved
201    _reserved9: [u32; 1],
202    /// Interframe spacing in microseconds
203    /// - Address: 0x544 - 0x548
204    tifs: ReadWrite<u32, InterFrameSpacing::Register>,
205    /// RSSI sample
206    /// - Address: 0x548 - 0x54c
207    rssisample: ReadWrite<u32, RssiSample::Register>,
208    /// Reserved
209    _reserved10: [u32; 1],
210    /// Current radio state
211    /// - Address: 0x550 - 0x554
212    state: ReadOnly<u32, State::Register>,
213    /// Data whitening initial value
214    /// - Address: 0x554 - 0x558
215    datawhiteiv: ReadWrite<u32, DataWhiteIv::Register>,
216    /// Reserved
217    _reserved11: [u32; 2],
218    /// Bit counter compare
219    /// - Address: 0x560 - 0x564
220    bcc: ReadWrite<u32, BitCounterCompare::Register>,
221    /// Reserved
222    _reserved12: [u32; 39],
223    /// Device address base segments
224    /// - Address: 0x600 - 0x620
225    dab: [ReadWrite<u32, DeviceAddressBase::Register>; 8],
226    /// Device address prefix
227    /// - Address: 0x620 - 0x640
228    dap: [ReadWrite<u32, DeviceAddressPrefix::Register>; 8],
229    /// Device address match configuration
230    /// - Address: 0x640 - 0x644
231    dacnf: ReadWrite<u32, DeviceAddressMatch::Register>,
232    /// Reserved
233    _reserved13: [u32; 3],
234    /// Radio mode configuration register
235    /// - Address: 0x650 - 0x654
236    modecnf0: ReadWrite<u32, RadioModeConfig::Register>,
237    /// Reserved
238    _reserved14: [u32; 618],
239    /// Peripheral power control
240    /// - Address: 0xFFC - 0x1000
241    power: ReadWrite<u32, Task::Register>,
242}
243
244register_bitfields! [u32,
245    /// Task register
246    Task [
247        /// Enable task
248        ENABLE OFFSET(0) NUMBITS(1)
249    ],
250    /// Event register
251    Event [
252        /// Ready event
253        READY OFFSET(0) NUMBITS(1)
254    ],
255    /// Shortcut register
256    Shortcut [
257        /// Shortcut between READY event and START task
258        READY_START OFFSET(0) NUMBITS(1),
259        /// Shortcut between END event and DISABLE task
260        END_DISABLE OFFSET(1) NUMBITS(1),
261        /// Shortcut between DISABLED event and TXEN task
262        DISABLED_TXEN OFFSET(2) NUMBITS(1),
263        /// Shortcut between DISABLED event and RXEN task
264        DISABLED_RXEN OFFSET(3) NUMBITS(1),
265        /// Shortcut between ADDRESS event and RSSISTART task
266        ADDRESS_RSSISTART OFFSET(4) NUMBITS(1),
267        /// Shortcut between END event and START task
268        END_START OFFSET(5) NUMBITS(1),
269        /// Shortcut between ADDRESS event and BCSTART task
270        ADDRESS_BCSTART OFFSET(6) NUMBITS(1),
271        /// Shortcut between DISABLED event and RSSISTOP task
272        DISABLED_RSSISTOP OFFSET(8) NUMBITS(1)
273    ],
274    /// Interrupt register
275    Interrupt [
276        /// READY event
277        READY OFFSET(0) NUMBITS(1),
278        /// ADDRESS event
279        ADDRESS OFFSET(1) NUMBITS(1),
280        /// PAYLOAD event
281        PAYLOAD OFFSET(2) NUMBITS(1),
282        /// END event
283        END OFFSET(3) NUMBITS(1),
284        /// DISABLED event
285        DISABLED OFFSET(4) NUMBITS(1),
286        /// DEVMATCH event
287        DEVMATCH OFFSET(5) NUMBITS(1),
288        /// DEVMISS event
289        DEVMISS OFFSET(6) NUMBITS(1),
290        /// RSSIEND event
291        RSSIEND OFFSET(7) NUMBITS(1),
292        /// BCMATCH event
293        BCMATCH OFFSET(10) NUMBITS(1),
294        /// CRCOK event
295        CRCOK OFFSET(12) NUMBITS(1),
296        /// CRCERROR event
297        CRCERROR OFFSET(13) NUMBITS(1)
298    ],
299    /// Receive match register
300    ReceiveMatch [
301        /// Logical address of which previous packet was received
302        MATCH OFFSET(0) NUMBITS(3)
303    ],
304    /// Received CRC register
305    ReceiveCrc [
306        /// CRC field of previously received packet
307        CRC OFFSET(0) NUMBITS(24)
308    ],
309    /// Device address match index register
310    DeviceAddressIndex [
311        /// Device address match index
312        /// Index (n) of device address, see DAB\[n\] and DAP\[n\], that got an
313        /// address match
314        INDEX OFFSET(0) NUMBITS(3)
315    ],
316    /// Packet pointer register
317    PacketPointer [
318        /// Packet address to be used for the next transmission or reception. When transmitting, the packet pointed to by this
319        /// address will be transmitted and when receiving, the received packet will be written to this address. This address is a byte
320        /// aligned ram address.
321        POINTER OFFSET(0) NUMBITS(32)
322    ],
323    /// Frequency register
324    Frequency [
325        /// Radio channel frequency
326        /// Frequency = 2400 + FREQUENCY (MHz)
327        FREQUENCY OFFSET(0) NUMBITS(7) [],
328        /// Channel map selection.
329        /// Channel map between 2400 MHZ .. 2500 MHZ
330        MAP OFFSET(8) NUMBITS(1) [
331            DEFAULT = 0,
332            LOW = 1
333        ]
334    ],
335    /// Transmitting power register
336    TransmitPower [
337        /// Radio output power
338        POWER OFFSET(0) NUMBITS(8) [
339            POS4DBM = 4,
340            POS3DBM = 3,
341            ODBM = 0,
342            NEG4DBM = 0xfc,
343            NEG8DBM = 0xf8,
344            NEG12DBM = 0xf4,
345            NEG16DBM = 0xf0,
346            NEG20DBM = 0xec,
347            NEG40DBM = 0xd8
348        ]
349    ],
350    /// Data rate and modulation register
351    Mode [
352        /// Radio data rate and modulation setting.
353        /// The radio supports Frequency-shift Keying (FSK) modulation
354        MODE OFFSET(0) NUMBITS(4) [
355            NRF_1MBIT = 0,
356            NRF_2MBIT = 1,
357            NRF_250KBIT = 2,
358            BLE_1MBIT = 3
359        ]
360    ],
361    /// Packet configuration register 0
362    PacketConfiguration0 [
363        /// Length on air of LENGTH field in number of bits
364        LFLEN OFFSET(0) NUMBITS(4) [],
365        /// Length on air of S0 field in number of bytes
366        S0LEN OFFSET(8) NUMBITS(1) [],
367        /// Length on air of S1 field in number of bits.
368        S1LEN OFFSET(16) NUMBITS(4) [],
369        /// Include or exclude S1 field in RAM
370        S1INCL OFFSET(20) NUMBITS(1) [
371            AUTOMATIC = 0,
372            INCLUDE = 1
373        ],
374        /// Length of preamble on air. Decision point: TASKS_START task
375        PLEN OFFSET(24) NUMBITS(1) [
376            EIGHT = 0,
377            SIXTEEN = 1
378        ]
379    ],
380    /// Packet configuration register 1
381    PacketConfiguration1 [
382        /// Maximum length of packet payload
383        MAXLEN OFFSET(0) NUMBITS(8) [],
384        /// Static length in number of bytes
385        STATLEN OFFSET(8) NUMBITS(8) [],
386        /// Base address length in number of bytes
387        BALEN OFFSET(16) NUMBITS(3) [],
388        /// On air endianness
389        ENDIAN OFFSET(24) NUMBITS(1) [
390            LITTLE = 0,
391            BIG = 1
392        ],
393        /// Enable or disable packet whitening
394        WHITEEN OFFSET(25) NUMBITS(1) [
395            DISABLED = 0,
396            ENABLED = 1
397        ]
398    ],
399    /// Radio base address register
400    BaseAddress [
401        /// BASE0 or BASE1
402        BASE OFFSET(0) NUMBITS(32)
403    ],
404    /// Radio prefix0 registers
405    Prefix0 [
406        /// Address prefix 0
407        AP0 OFFSET(0) NUMBITS(8),
408        /// Address prefix 1
409        AP1 OFFSET(8) NUMBITS(8),
410        /// Address prefix 2
411        AP2 OFFSET(16) NUMBITS(8),
412        /// Address prefix 3
413        AP3 OFFSET(24) NUMBITS(8)
414    ],
415    /// Radio prefix0 registers
416    Prefix1 [
417        /// Address prefix 4
418        AP4 OFFSET(0) NUMBITS(8),
419        /// Address prefix 5
420        AP5 OFFSET(8) NUMBITS(8),
421        /// Address prefix 6
422        AP6 OFFSET(16) NUMBITS(8),
423        /// Address prefix 7
424        AP7 OFFSET(24) NUMBITS(8)
425    ],
426    /// Transmit address register
427    TransmitAddress [
428        /// Logical address to be used when transmitting a packet
429        ADDRESS OFFSET(0) NUMBITS(3)
430    ],
431    /// Receive addresses register
432    ReceiveAddresses [
433        /// Enable or disable reception on logical address 0-7
434        ADDRESS OFFSET(0) NUMBITS(8)
435    ],
436    /// CRC configuration register
437    CrcConfiguration [
438        /// CRC length in bytes
439        LEN OFFSET(0) NUMBITS(2) [
440            DISABLED = 0,
441            ONE = 1,
442            TWO = 2,
443            THREE = 3
444        ],
445        /// Include or exclude packet field from CRC calculation
446        SKIPADDR OFFSET(8) NUMBITS(1) [
447            INCLUDE = 0,
448            EXCLUDE = 1
449        ]
450    ],
451    /// CRC polynomial register
452    CrcPolynomial [
453        /// CRC polynomial
454        CRCPOLY OFFSET(0) NUMBITS(24)
455    ],
456    /// CRC initial value register
457    CrcInitialValue [
458       /// Initial value for CRC calculation
459       CRCINIT OFFSET(0) NUMBITS(24)
460    ],
461    /// Inter Frame Spacing in us register
462    InterFrameSpacing [
463        /// Inter Frame Spacing in us
464        /// Inter frame space is the time interval between two consecutive packets. It is defined as the time, in micro seconds, from the
465        /// end of the last bit of the previous packet to the start of the first bit of the subsequent packet
466        TIFS OFFSET(0) NUMBITS(8)
467    ],
468    /// RSSI sample register
469    RssiSample [
470        /// RSSI sample result
471        RSSISAMPLE OFFSET(0) NUMBITS(7)
472    ],
473    /// Radio state register
474    State [
475        /// Current radio state
476        STATE OFFSET(0) NUMBITS(4) [
477            DISABLED = 0,
478            RXRU = 1,
479            RXIDLE = 2,
480            RX = 3,
481            RXDISABLED = 4,
482            TXRU = 9,
483            TXIDLE = 10,
484            TX = 11,
485            TXDISABLED = 12
486        ]
487    ],
488    /// Data whitening initial value register
489    DataWhiteIv [
490        /// Data whitening initial value. Bit 6 is hard-wired to '1', writing '0'
491        /// to it has no effect, and it will always be read back and used by the device as '1'
492        DATEWHITEIV OFFSET(0) NUMBITS(7)
493    ],
494    /// Bit counter compare register
495    BitCounterCompare [
496        /// Bit counter compare
497        BCC OFFSET(0) NUMBITS(32)
498    ],
499    /// Device address base register
500    DeviceAddressBase [
501        /// Device address base 0-7
502        DAB OFFSET(0) NUMBITS(32)
503    ],
504    /// Device address prefix register
505    DeviceAddressPrefix [
506        /// Device address prefix 0-7
507        DAP OFFSET(0) NUMBITS(32)
508    ],
509    /// Device address match configuration register
510    DeviceAddressMatch [
511        /// Enable or disable device address matching on 0-7
512        ENA OFFSET(0) NUMBITS(8),
513        /// TxAdd for device address 0-7
514        TXADD OFFSET(8) NUMBITS(8)
515    ],
516    /// Radio mode configuration register
517    RadioModeConfig [
518        /// Radio ramp-up time
519        RU OFFSET(0) NUMBITS(1) [
520            DEFAULT = 0,
521            FAST = 1
522        ],
523        /// Default TX value
524        /// Specifies what the RADIO will transmit when it is not started, i.e. between:
525        /// RADIO.EVENTS_READY and RADIO.TASKS_START
526        /// RADIO.EVENTS_END and RADIO.TASKS_START
527        DTX OFFSET(8) NUMBITS(2) [
528            B1 = 0,
529            B0 = 1,
530            CENTER = 2
531        ]
532    ]
533];
534
535static mut PAYLOAD: [u8; nrf5x::constants::RADIO_PAYLOAD_LENGTH] =
536    [0x00; nrf5x::constants::RADIO_PAYLOAD_LENGTH];
537
538pub struct Radio<'a> {
539    registers: StaticRef<RadioRegisters>,
540    tx_power: Cell<TxPower>,
541    rx_client: OptionalCell<&'a dyn ble_advertising::RxClient>,
542    tx_client: OptionalCell<&'a dyn ble_advertising::TxClient>,
543    buffer: TakeCell<'static, [u8]>,
544}
545
546impl<'a> Radio<'a> {
547    pub const fn new() -> Radio<'a> {
548        Radio {
549            registers: RADIO_BASE,
550            tx_power: Cell::new(TxPower::ZerodBm),
551            rx_client: OptionalCell::empty(),
552            tx_client: OptionalCell::empty(),
553            buffer: TakeCell::empty(),
554        }
555    }
556
557    pub fn is_enabled(&self) -> bool {
558        self.registers.mode.matches_all(Mode::MODE::BLE_1MBIT)
559    }
560
561    fn tx(&self) {
562        self.registers.event_ready.write(Event::READY::CLEAR);
563        self.registers.task_txen.write(Task::ENABLE::SET);
564    }
565
566    fn rx(&self) {
567        self.registers.event_ready.write(Event::READY::CLEAR);
568        self.registers.task_rxen.write(Task::ENABLE::SET);
569    }
570
571    fn set_rx_address(&self) {
572        self.registers
573            .rxaddresses
574            .write(ReceiveAddresses::ADDRESS.val(1));
575    }
576
577    fn set_tx_address(&self) {
578        self.registers
579            .txaddress
580            .write(TransmitAddress::ADDRESS.val(0));
581    }
582
583    fn radio_on(&self) {
584        // reset and enable power
585        self.registers.power.write(Task::ENABLE::CLEAR);
586        self.registers.power.write(Task::ENABLE::SET);
587    }
588
589    fn radio_off(&self) {
590        self.registers.power.write(Task::ENABLE::CLEAR);
591    }
592
593    fn set_tx_power(&self) {
594        self.registers.txpower.set(self.tx_power.get() as u32);
595    }
596
597    fn set_dma_ptr(&self) {
598        self.registers.packetptr.set(addr_of!(PAYLOAD) as u32);
599    }
600
601    #[inline(never)]
602    pub fn handle_interrupt(&self) {
603        self.disable_all_interrupts();
604
605        if self.registers.event_ready.is_set(Event::READY) {
606            self.registers.event_ready.write(Event::READY::CLEAR);
607            self.registers.event_end.write(Event::READY::CLEAR);
608            self.registers.task_start.write(Task::ENABLE::SET);
609        }
610
611        if self.registers.event_address.is_set(Event::READY) {
612            self.registers.event_address.write(Event::READY::CLEAR);
613        }
614        if self.registers.event_payload.is_set(Event::READY) {
615            self.registers.event_payload.write(Event::READY::CLEAR);
616        }
617
618        // tx or rx finished!
619        if self.registers.event_end.is_set(Event::READY) {
620            self.registers.event_end.write(Event::READY::CLEAR);
621
622            let result = if self.registers.crcstatus.is_set(Event::READY) {
623                Ok(())
624            } else {
625                Err(ErrorCode::FAIL)
626            };
627
628            match self.registers.state.get() {
629                nrf5x::constants::RADIO_STATE_TXRU
630                | nrf5x::constants::RADIO_STATE_TXIDLE
631                | nrf5x::constants::RADIO_STATE_TXDISABLE
632                | nrf5x::constants::RADIO_STATE_TX => {
633                    self.radio_off();
634                    self.tx_client
635                        .map(|client| client.transmit_event(self.buffer.take().unwrap(), result));
636                }
637                nrf5x::constants::RADIO_STATE_RXRU
638                | nrf5x::constants::RADIO_STATE_RXIDLE
639                | nrf5x::constants::RADIO_STATE_RXDISABLE
640                | nrf5x::constants::RADIO_STATE_RX => {
641                    self.radio_off();
642                    unsafe {
643                        self.rx_client.map(|client| {
644                            // Length is: S0 (1 Byte) + Length (1 Byte) + S1 (0 Bytes) + Payload
645                            // And because the length field is directly read from the packet
646                            // We need to add 2 to length to get the total length
647                            client.receive_event(
648                                &mut *addr_of_mut!(PAYLOAD),
649                                PAYLOAD[1] + 2,
650                                result,
651                            )
652                        });
653                    }
654                }
655                // Radio state - Disabled
656                _ => (),
657            }
658        }
659        self.enable_interrupts();
660    }
661
662    pub fn enable_interrupts(&self) {
663        self.registers.intenset.write(
664            Interrupt::READY::SET
665                + Interrupt::ADDRESS::SET
666                + Interrupt::PAYLOAD::SET
667                + Interrupt::END::SET,
668        );
669    }
670
671    pub fn enable_interrupt(&self, intr: u32) {
672        self.registers.intenset.set(intr);
673    }
674
675    pub fn clear_interrupt(&self, intr: u32) {
676        self.registers.intenclr.set(intr);
677    }
678
679    pub fn disable_all_interrupts(&self) {
680        // disable all possible interrupts
681        self.registers.intenclr.set(0xffffffff);
682    }
683
684    fn replace_radio_buffer(&self, buf: &'static mut [u8]) -> &'static mut [u8] {
685        // set payload
686        for (i, c) in buf.as_ref().iter().enumerate() {
687            unsafe {
688                PAYLOAD[i] = *c;
689            }
690        }
691        buf
692    }
693
694    fn ble_initialize(&self, channel: RadioChannel) {
695        self.radio_on();
696
697        self.ble_set_tx_power();
698
699        self.ble_set_channel_rate();
700
701        self.ble_set_channel_freq(channel);
702        self.ble_set_data_whitening(channel);
703
704        self.set_tx_address();
705        self.set_rx_address();
706
707        self.ble_set_packet_config();
708        self.ble_set_advertising_access_address();
709
710        self.ble_set_crc_config();
711
712        self.set_dma_ptr();
713    }
714
715    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B], section 3.1.1 CRC Generation
716    fn ble_set_crc_config(&self) {
717        self.registers
718            .crccnf
719            .write(CrcConfiguration::LEN::THREE + CrcConfiguration::SKIPADDR::EXCLUDE);
720        self.registers
721            .crcinit
722            .set(nrf5x::constants::RADIO_CRCINIT_BLE);
723        self.registers
724            .crcpoly
725            .set(nrf5x::constants::RADIO_CRCPOLY_BLE);
726    }
727
728    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B], section 2.1.2 Access Address
729    // Set access address to 0x8E89BED6
730    fn ble_set_advertising_access_address(&self) {
731        self.registers.prefix0.set(0x0000008e);
732        self.registers.base0.set(0x89bed600);
733    }
734
735    // Packet configuration
736    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B], section 2.1 Packet Format
737    //
738    // LSB                                                      MSB
739    // +----------+   +----------------+   +---------------+   +------------+
740    // | Preamble | - | Access Address | - | PDU           | - | CRC        |
741    // | (1 byte) |   | (4 bytes)      |   | (2-255 bytes) |   | (3 bytes)  |
742    // +----------+   +----------------+   +---------------+   +------------+
743    //
744    fn ble_set_packet_config(&self) {
745        // sets the header of PDU TYPE to 1 byte
746        // sets the header length to 1 byte
747        self.registers.pcnf0.write(
748            PacketConfiguration0::LFLEN.val(8)
749                + PacketConfiguration0::S0LEN.val(1)
750                + PacketConfiguration0::S1LEN::CLEAR
751                + PacketConfiguration0::S1INCL::CLEAR
752                + PacketConfiguration0::PLEN::EIGHT,
753        );
754
755        self.registers.pcnf1.write(
756            PacketConfiguration1::WHITEEN::ENABLED
757                + PacketConfiguration1::ENDIAN::LITTLE
758                + PacketConfiguration1::BALEN.val(3)
759                + PacketConfiguration1::STATLEN::CLEAR
760                + PacketConfiguration1::MAXLEN.val(255),
761        );
762    }
763
764    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part A], 4.6 REFERENCE SIGNAL DEFINITION
765    // Bit Rate = 1 Mb/s ±1 ppm
766    fn ble_set_channel_rate(&self) {
767        self.registers.mode.write(Mode::MODE::BLE_1MBIT);
768    }
769
770    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B], section 3.2 Data Whitening
771    // Configure channel index to the LFSR and the hardware solves the rest
772    fn ble_set_data_whitening(&self, channel: RadioChannel) {
773        self.registers.datawhiteiv.set(channel.get_channel_index());
774    }
775
776    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B], section 1.4.1
777    // RF Channels:     0 - 39
778    // Data:            0 - 36
779    // Advertising:     37, 38, 39
780    fn ble_set_channel_freq(&self, channel: RadioChannel) {
781        self.registers
782            .frequency
783            .write(Frequency::FREQUENCY.val(channel as u32));
784    }
785
786    // BLUETOOTH SPECIFICATION Version 4.2 [Vol 6, Part B], section 3 TRANSMITTER CHARACTERISTICS
787    // Minimum Output Power : -20dBm
788    // Maximum Output Power : +10dBm
789    //
790    // no check is required because the BleConfig::set_tx_power() method ensures that only
791    // valid tranmitting power is configured!
792    fn ble_set_tx_power(&self) {
793        self.set_tx_power();
794    }
795}
796
797impl<'a> ble_advertising::BleAdvertisementDriver<'a> for Radio<'a> {
798    fn transmit_advertisement(&self, buf: &'static mut [u8], _len: usize, channel: RadioChannel) {
799        let res = self.replace_radio_buffer(buf);
800        self.buffer.replace(res);
801        self.ble_initialize(channel);
802        self.tx();
803        self.enable_interrupts();
804    }
805
806    fn receive_advertisement(&self, channel: RadioChannel) {
807        self.ble_initialize(channel);
808        self.rx();
809        self.enable_interrupts();
810    }
811
812    fn set_receive_client(&self, client: &'a dyn ble_advertising::RxClient) {
813        self.rx_client.set(client);
814    }
815
816    fn set_transmit_client(&self, client: &'a dyn ble_advertising::TxClient) {
817        self.tx_client.set(client);
818    }
819}
820
821impl ble_advertising::BleConfig for Radio<'_> {
822    // The BLE Advertising Driver validates that the `tx_power` is between -20 to 10 dBm but then
823    // underlying chip must validate if the current `tx_power` is supported as well
824    fn set_tx_power(&self, tx_power: u8) -> Result<(), ErrorCode> {
825        // Convert u8 to TxPower
826        match nrf5x::constants::TxPower::try_from(tx_power) {
827            // Invalid transmitting power, propogate error
828            Err(()) => Err(ErrorCode::NOSUPPORT),
829            // Valid transmitting power, propogate success
830            Ok(res) => {
831                self.tx_power.set(res);
832                Ok(())
833            }
834        }
835    }
836}