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}