1use nrf_pac::{
17 self as pac,
18 radio::{
19 regs::{Int as RadioInt, Prefix0, Prefix1, Rxaddresses},
20 vals::{Crcstatus, Endian, Len, Mode},
21 },
22 timer::{regs::Int as TimerInt, vals::Bitmode},
23 TIMER0, TIMER1, TIMER2,
24};
25
26use core::sync::atomic::{compiler_fence, Ordering};
27
28use crate::{
29 app::{Addresses, FramedConsumer},
30 payload::{PayloadR, PayloadW},
31 Error,
32};
33pub(crate) use pac::{radio::vals::Txpower, radio::Radio, Interrupt};
34pub use pac::RADIO;
36
37const CRC_INIT: u32 = 0x0000_FFFF;
38const CRC_POLY: u32 = 0x0001_1021;
39const NUM_PIPES: usize = 8;
40
41#[inline]
42fn bytewise_bit_swap(value: u32) -> u32 {
43 value.reverse_bits().swap_bytes()
44}
45
46#[inline]
47fn address_conversion(value: u32) -> u32 {
48 value.reverse_bits()
49}
50
51#[derive(Copy, Clone, PartialEq, Debug)]
52pub(crate) enum RxPayloadState {
53 Ack,
54 NoAck,
55 RepeatedAck,
56 RepeatedNoAck,
57 BadCRC,
58}
59
60pub struct EsbRadio<const OUT: usize, const IN: usize>
61{
62 radio: Radio,
63 tx_grant: Option<PayloadR<OUT>>,
64 rx_grant: Option<PayloadW<IN>>,
65 last_crc: [u16; NUM_PIPES],
66 last_pid: [u8; NUM_PIPES],
67 cached_pipe: u8,
68}
69
70impl<const OUT: usize, const IN: usize> EsbRadio<OUT, IN>
71{
72 pub(crate) fn new(radio: Radio) -> Self {
73 EsbRadio {
74 radio,
75 tx_grant: None,
76 rx_grant: None,
77 last_crc: [0; NUM_PIPES],
78 last_pid: [0; NUM_PIPES],
79 cached_pipe: 0,
80 }
81 }
82
83 pub(crate) fn init(&mut self, max_payload: u8, tx_power: Txpower, addresses: &Addresses) {
84 self.radio.intenclr().write_value(RadioInt(0xFFFF_FFFF));
86 self.radio.mode().write(|w| w.set_mode(Mode::NRF_2MBIT));
87 let len_bits = if max_payload <= 32 { 6 } else { 8 };
88 let base0 = address_conversion(u32::from_le_bytes(addresses.base0));
90 let base1 = address_conversion(u32::from_le_bytes(addresses.base1));
91 let prefix0 = bytewise_bit_swap(u32::from_le_bytes(addresses.prefixes0));
92 let prefix1 = bytewise_bit_swap(u32::from_le_bytes(addresses.prefixes1));
93
94 self.radio.shorts().write(|w| {
95 w.set_ready_start(true);
96 w.set_end_disable(true);
97 w.set_address_rssistart(true);
98 w.set_disabled_rssistop(true);
99 });
100
101 #[cfg(feature = "fast-ru")]
103 self.radio.modecnf0.modify(|w| w.ru().fast());
104
105 self.radio.txpower().write(|w| w.set_txpower(tx_power));
106
107 self.radio.pcnf0().write(|w| {
108 w.set_lflen(len_bits);
109 w.set_s1len(3);
110 });
111
112 self.radio.pcnf1().write(|w| {
113 w.set_maxlen(max_payload);
114 w.set_balen(4);
116 w.set_statlen(0);
119 w.set_endian(Endian::BIG);
120 });
121
122 self.radio
123 .crcinit()
124 .write(|w| w.set_crcinit(CRC_INIT & 0x00FF_FFFF));
125
126 self.radio
127 .crcpoly()
128 .write(|w| w.set_crcpoly(CRC_POLY & 0x00FF_FFFF));
129
130 self.radio.crccnf().write(|w| w.set_len(Len::TWO));
131
132 self.radio.base0().write_value(base0);
133 self.radio.base1().write_value(base1);
134
135 self.radio.prefix0().write_value(Prefix0(prefix0));
136 self.radio.prefix1().write_value(Prefix1(prefix1));
137
138 self.radio
141 .frequency()
142 .write(|w| w.set_frequency(addresses.rf_channel));
143 }
144
145 #[inline]
147 pub(crate) fn clear_disabled_event(&mut self) {
148 self.radio.events_disabled().write_value(0);
149 }
150
151 #[inline]
153 pub(crate) fn check_disabled_event(&mut self) -> bool {
154 self.radio.events_disabled().read() == 1
155 }
156
157 #[inline]
159 pub(crate) fn clear_end_event(&mut self) {
160 self.radio.events_end().write_value(0);
161 }
162
163 #[inline]
165 pub(crate) fn check_ready_event(&self) -> bool {
166 self.radio.events_ready().read() == 1
167 }
168
169 #[inline]
171 pub(crate) fn clear_ready_event(&mut self) {
172 self.radio.events_ready().write_value(0);
173 }
174
175 #[inline]
177 pub(crate) fn disable_disabled_interrupt(&mut self) {
178 self.radio.intenclr().write(|w| w.set_disabled(true));
179 }
180
181 pub(crate) fn stop(&mut self, drop_grants: bool) {
183 self.radio.shorts().modify(|w| {
184 w.set_disabled_rxen(false);
185 w.set_disabled_txen(false);
186 });
187 self.disable_disabled_interrupt();
188 self.radio.tasks_disable().write_value(1);
189
190 while self.radio.events_disabled().read() == 0 {}
193 self.clear_disabled_event();
194
195 compiler_fence(Ordering::Acquire);
197
198 if drop_grants {
199 self.tx_grant.take();
201 self.rx_grant.take();
202 }
203 }
204
205 pub(crate) fn transmit(&mut self, payload: PayloadR<OUT>, ack: bool) {
209 if ack {
210 self.radio.shorts().modify(|w| w.set_disabled_rxen(true));
212 }
213 self.radio.intenset().write(|w| w.set_disabled(true));
214 self.radio
216 .txaddress()
217 .write(|w| w.set_txaddress(payload.pipe()));
218 self.radio
220 .rxaddresses()
221 .write_value(Rxaddresses(1 << payload.pipe()));
222
223 self.radio
224 .packetptr()
225 .write_value(payload.dma_pointer() as u32);
226 self.radio.events_address().write_value(0);
227 self.clear_disabled_event();
228 self.clear_ready_event();
229 self.clear_end_event();
230 self.radio.events_payload().write_value(0); compiler_fence(Ordering::Release);
234
235 self.radio.tasks_txen().write_value(1);
236 self.tx_grant = Some(payload);
237 }
238
239 pub(crate) fn finish_tx_no_ack(&mut self) {
241 compiler_fence(Ordering::SeqCst);
244
245 if let Some(grant) = self.tx_grant.take() {
247 grant.release();
248 }
249
250 self.disable_disabled_interrupt();
252 }
253
254 pub(crate) fn prepare_for_ack(&mut self, mut rx_buf: PayloadW<IN>) {
257 self.clear_ready_event();
258 compiler_fence(Ordering::Release);
262 self.radio
263 .packetptr()
264 .write_value(rx_buf.dma_pointer() as u32);
265
266 debug_assert!(!self.check_ready_event(), "Missed window (PTX)");
268
269 self.rx_grant = Some(rx_buf);
270 self.radio.shorts().modify(|w| w.set_disabled_rxen(false));
272
273 }
275
276 #[inline]
279 pub(crate) fn check_ack(&mut self) -> Result<bool, Error> {
280 let ret = self.radio.crcstatus().read().crcstatus() == Crcstatus::CRCOK;
281 compiler_fence(Ordering::Acquire);
283
284 if ret {
285 let (tx_grant, mut rx_grant) = (
286 self.tx_grant.take().ok_or(Error::InternalError)?,
287 self.rx_grant.take().ok_or(Error::InternalError)?,
288 );
289
290 let pipe = tx_grant.pipe();
291 tx_grant.release();
292
293 let rssi = self.radio.rssisample().read().rssisample();
294 rx_grant.set_pipe(pipe);
295 rx_grant.set_rssi(rssi);
296 rx_grant.commit_all();
297 } else {
298 self.tx_grant.take();
301 self.rx_grant.take();
302 }
303 Ok(ret)
304 }
305
306 pub(crate) fn start_receiving(&mut self, mut rx_buf: PayloadW<IN>, enabled_pipes: u8) {
310 self.radio.shorts().modify(|w| w.set_disabled_txen(true));
312
313 self.radio.intenset().write(|w| w.set_disabled(true));
314 self.radio
315 .rxaddresses()
316 .write_value(Rxaddresses(enabled_pipes as u32));
317
318 self.radio
319 .packetptr()
320 .write_value(rx_buf.dma_pointer() as u32);
321 self.radio.events_address().write_value(0);
322 self.clear_disabled_event();
323 self.clear_ready_event();
324 self.clear_end_event();
325 self.radio.events_payload().write_value(0); compiler_fence(Ordering::Release);
329
330 self.radio.tasks_rxen().write_value(1);
331
332 self.rx_grant = Some(rx_buf);
333 }
334
335 #[inline]
337 pub(crate) fn check_packet(
338 &mut self,
339 consumer: &mut FramedConsumer<OUT>,
340 ) -> Result<RxPayloadState, Error> {
341 static FALLBACK_ACK: [u8; 2] = [0, 0];
343
344 if self.radio.crcstatus().read().crcstatus() == Crcstatus::CRCERROR {
345 self.stop(false);
347 self.radio.shorts().modify(|w| w.set_disabled_txen(true));
348 self.radio.intenset().write(|w| w.set_disabled(true));
349 compiler_fence(Ordering::Release);
351
352 self.radio.tasks_rxen().write_value(1);
354 return Ok(RxPayloadState::BadCRC);
355 }
356 compiler_fence(Ordering::Acquire);
358 self.clear_ready_event();
359
360 let pipe = self.radio.rxmatch().read().rxmatch() as usize;
361 let crc = self.radio.rxcrc().read().rxcrc() as u16;
362 let rx_grant = self.rx_grant.as_ref().ok_or(Error::InternalError)?;
363 let (pid, ack) = (rx_grant.pid(), !rx_grant.no_ack());
364 let repeated = (self.last_crc[pipe] == crc) && (self.last_pid[pipe] == pid);
365
366 if ack {
367 self.radio.txaddress().write(|w| {
374 w.set_txaddress(pipe as u8);
375 });
376
377 let mut dma_pointer = FALLBACK_ACK.as_ptr() as u32;
378
379 if repeated {
380 if pipe == self.cached_pipe as usize {
381 if let Some(grant) = &self.tx_grant {
382 dma_pointer = grant.dma_pointer() as u32;
383 }
384 }
385 } else {
386 if let Some(grant) = self.tx_grant.take() {
388 grant.release();
389 }
390
391 compiler_fence(Ordering::SeqCst);
393
394 if let Ok(payload) = consumer.read().map(PayloadR::new) {
395 dma_pointer = payload.dma_pointer() as u32;
396 self.tx_grant = Some(payload);
397 }
398 }
399
400 compiler_fence(Ordering::Release);
402
403 self.radio.packetptr().write_value(dma_pointer);
405
406 debug_assert!(!self.check_ready_event(), "Missed window (PRX)");
408
409 self.radio.shorts().modify(|w| {
413 w.set_disabled_txen(false);
414 w.set_disabled_rxen(true);
415 });
416 } else {
417 self.stop(false);
419 }
420
421 if repeated {
422 if ack {
423 return Ok(RxPayloadState::RepeatedAck);
424 } else {
425 return Ok(RxPayloadState::RepeatedNoAck);
426 }
427 }
428 self.last_crc[pipe] = crc;
429 self.last_pid[pipe] = pid;
430 self.cached_pipe = pipe as u8;
431
432 let mut grant = self.rx_grant.take().ok_or(Error::InternalError)?;
433 let rssi = self.radio.rssisample().read().rssisample();
434 grant.set_rssi(rssi);
435 grant.set_pipe(pipe as u8);
436 grant.commit_all();
437 if ack {
438 Ok(RxPayloadState::Ack)
439 } else {
440 Ok(RxPayloadState::NoAck)
441 }
442 }
443
444 pub(crate) fn complete_rx_ack(
447 &mut self,
448 mut rx_buf: Option<PayloadW<IN>>,
449 ) -> Result<(), Error> {
450 let dma_pointer = if let Some(mut grant) = rx_buf.take() {
451 let pointer = grant.dma_pointer() as u32;
452 self.rx_grant = Some(grant);
453 pointer
454 } else {
455 self.rx_grant
456 .as_mut()
457 .ok_or(Error::InternalError)?
458 .dma_pointer() as u32
459 };
460
461 compiler_fence(Ordering::SeqCst);
463
464 self.radio.packetptr().write_value(dma_pointer);
465
466 self.radio.shorts().modify(|w| {
472 w.set_disabled_rxen(false);
473 w.set_disabled_txen(true);
474 });
475 Ok(())
476 }
477
478 pub(crate) fn complete_rx_no_ack(&mut self, mut rx_buf: Option<PayloadW<IN>>) {
481 if let Some(mut grant) = rx_buf.take() {
485 self.radio
486 .packetptr()
487 .write_value(grant.dma_pointer() as u32);
488 self.rx_grant = Some(grant);
489 }
490
491 self.radio.shorts().modify(|w| w.set_disabled_txen(true));
492 self.radio.intenset().write(|w| w.set_disabled(true));
493 compiler_fence(Ordering::Release);
495
496 self.radio.tasks_rxen().write_value(1);
497 }
498}
499
500mod sealed {
501 pub trait Sealed {}
502}
503
504pub trait EsbTimer: sealed::Sealed {
506 fn init(&mut self);
508
509 fn set_interrupt_retransmit(&mut self, micros: u16);
512
513 fn clear_interrupt_retransmit();
515
516 fn is_retransmit_pending() -> bool;
518
519 fn set_interrupt_ack(&mut self, micros: u16);
522
523 fn clear_interrupt_ack();
525
526 fn is_ack_pending() -> bool;
528
529 fn stop();
531}
532
533use pac::timer::Timer;
534
535pub trait PtrTimer {
536 const ME: Timer;
537 fn timer(&mut self) -> &mut Timer;
538 unsafe fn take() -> Self;
542}
543
544pub struct Timer0 {
545 timer: Timer,
546}
547pub struct Timer1 {
548 timer: Timer,
549}
550pub struct Timer2 {
551 timer: Timer,
552}
553
554impl PtrTimer for Timer0 {
555 const ME: Timer = TIMER0;
556
557 fn timer(&mut self) -> &mut Timer {
558 &mut self.timer
559 }
560
561 unsafe fn take() -> Self {
562 Self { timer: Self::ME }
563 }
564}
565
566impl PtrTimer for Timer1 {
567 const ME: Timer = TIMER1;
568
569 fn timer(&mut self) -> &mut Timer {
570 &mut self.timer
571 }
572
573 unsafe fn take() -> Self {
574 Self { timer: Self::ME }
575 }
576}
577
578impl PtrTimer for Timer2 {
579 const ME: Timer = TIMER2;
580
581 fn timer(&mut self) -> &mut Timer {
582 &mut self.timer
583 }
584
585 unsafe fn take() -> Self {
586 Self { timer: Self::ME }
587 }
588}
589
590impl<T: PtrTimer + sealed::Sealed> EsbTimer for T {
591 #[inline]
592 fn init(&mut self) {
593 self.timer().intenclr().write_value(TimerInt(0xFFFF_FFFF));
595 Self::stop();
596 self.timer()
597 .bitmode()
598 .write(|w| w.set_bitmode(Bitmode::_32BIT));
599 self.timer().prescaler().write(|w| w.set_prescaler(4));
602 }
603
604 #[inline]
608 fn set_interrupt_retransmit(&mut self, micros: u16) {
609 self.timer().cc(0).write_value(micros as u32);
610 self.timer().events_compare(0).write_value(0);
611 self.timer().intenset().write(|w| w.set_compare(0, true));
612
613 self.timer().tasks_clear().write_value(1);
615 self.timer().tasks_start().write_value(1);
616 }
617
618 #[inline]
619 fn clear_interrupt_retransmit() {
620 let timer = Self::ME;
622
623 timer.intenclr().write(|w| w.set_compare(0, false));
624 timer.events_compare(0).write_value(0);
625
626 Self::stop();
627 }
628
629 #[inline]
630 fn is_retransmit_pending() -> bool {
631 let timer = Self::ME;
633
634 timer.events_compare(0).read() == 1u32
635 }
636
637 fn set_interrupt_ack(&mut self, micros: u16) {
638 self.timer().tasks_capture(1).write_value(1);
640 let current_counter = self.timer().cc(1).read();
641
642 self.timer()
643 .cc(1)
644 .write_value(current_counter + micros as u32);
645 self.timer().events_compare(1).write_value(0);
646 self.timer().intenset().write(|w| w.set_compare(1, true));
647 }
648
649 #[inline]
650 fn clear_interrupt_ack() {
651 let timer = Self::ME;
653
654 timer.intenclr().write(|w| w.set_compare(1, false));
655 timer.events_compare(1).write_value(0);
656 }
657
658 #[inline]
659 fn is_ack_pending() -> bool {
660 let timer = Self::ME;
662
663 timer.events_compare(1).read() == 1u32
664 }
665
666 #[inline]
667 fn stop() {
668 let timer = Self::ME;
670
671 timer.tasks_stop().write_value(1);
672 }
673}
674
675impl sealed::Sealed for Timer0 {}
676impl sealed::Sealed for Timer1 {}
677impl sealed::Sealed for Timer2 {}
678
679