nrf_to_nrf - NRF52 Radio Driver v1.2.2
TMRh20 2023 - OSI Layer 2 radio driver using RF24 API
Loading...
Searching...
No Matches
nrf_to_nrf.cpp
Go to the documentation of this file.
1
2
3#include "nrf_to_nrf.h"
4
5#if defined NRF54_CCM_ENCRYPTION
6 #include <nrf54l15_hal.h>
7static xiao_nrf54l15::Ccm nrf54Ccm;
8static xiao_nrf54l15::CracenRng nrf54Rng;
9#endif
10
11#ifndef __REV
12 #define __REV(x) __builtin_bswap32(x);
13#endif
14
15#if defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || defined(NRF52811_XXAA) || defined(NRF52810_XXAA) || defined(NRF52805_XXAA)
16 // TX power range (Product Specification): -20 .. +4dbm, configurable in 4 dB steps
17 #define TXPOWER_PA_MIN 0xF4 // -12dBm
18 #define TXPOWER_PA_LOW 0xFC // -4dBm
19 #define TXPOWER_PA_HIGH 0x00 // 0dBm
20 #define TXPOWER_PA_MAX 0x04 // 4dBm
21#elif !defined(ARDUINO_NRF54L15) // nRF52840, nRF52833, nRF52820
22 // TX power range (Product Specification): -20 .. +8dbm, configurable in 4 dB steps
23 #define TXPOWER_PA_MIN 0xF4 // -12dBm
24 #define TXPOWER_PA_LOW 0x02 // 2dBm
25 #define TXPOWER_PA_HIGH 0x06 // 6dBm
26 #define TXPOWER_PA_MAX 0x08 // 8dBm
27#else
28 #define TXPOWER_PA_MIN 0x6 // -12dBm
29 #define TXPOWER_PA_LOW 0x1F // 2dBm
30 #define TXPOWER_PA_HIGH 0x33 // 6dBm
31 #define TXPOWER_PA_MAX 0x3F // 8dBm
32#endif
33// Note that 250Kbit mode is deprecated and might not work reliably on all devices.
34// See: https://devzone.nordicsemi.com/f/nordic-q-a/78469/250-kbit-s-nordic-proprietary-radio-mode-on-nrf52840
35#ifndef RADIO_MODE_MODE_Nrf_250Kbit
36 #define RADIO_MODE_MODE_Nrf_250Kbit (2UL)
37#endif
38#ifdef ARDUINO_NRF54L15
39 #define RADIO_MODE_MODE_Nrf_4Mbit_OBT4 (10UL)
40 #define RADIO_MODE_MODE_Nrf_4Mbit_OBT6 (9UL)
41#endif
42
43#define DEFAULT_TIMEOUT 250
44
45/**********************************************************************************************************/
46
47static bool waitForEvent(volatile uint32_t* event, uint32_t timeout = DEFAULT_TIMEOUT)
48{
49 uint32_t start = millis();
50 while (*event == 0) {
51 if (millis() - start > timeout) {
52 return false;
53 }
54 }
55 return true;
56}
57
58/**********************************************************************************************************/
59
60// Function to do bytewise bit-swap on an unsigned 32-bit value
61static uint32_t bytewise_bit_swap(uint8_t const* p_inp)
62{
63 uint32_t inp = (p_inp[3] << 24) | (p_inp[2] << 16) | (p_inp[1] << 8) | (p_inp[0]);
64 inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4;
65 inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2;
66 inp = (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1;
67 return inp;
68}
69
70/**********************************************************************************************************/
71
72// Convert a base address from nRF24L format to nRF5 format
73static uint32_t addr_conv(uint8_t const* p_addr)
74{
75 return __REV(
76 bytewise_bit_swap(p_addr)); // lint -esym(628, __rev) -esym(526, __rev) */
77}
78
79/**********************************************************************************************************/
80
81uint32_t nrf_to_nrf::addrConv32(uint32_t addr)
82{
83
84 uint8_t buffer[4];
85 buffer[0] = addr & 0xFF;
86 buffer[1] = (addr >> 8) & 0xFF;
87 buffer[2] = (addr >> 16) & 0xFF;
88 buffer[3] = (addr >> 24) & 0xFF;
89
90 return addr_conv(buffer);
91}
92
93/**********************************************************************************************************/
94
96{
97 DPL = false;
98 staticPayloadSize = 32;
99 retries = 5;
100 retryDuration = 5;
101 ackPayloadsEnabled = false;
102 ackPipe = 0;
103 inRxMode = false;
104 arcCounter = 0;
105 ackTimeout = ACK_TIMEOUT_1MBPS;
106 payloadAvailable = false;
107#ifndef ARDUINO_NRF54L15
108 interframeSpacing = 115;
109#else
110 interframeSpacing = 130;
111#endif
112
113#if defined CCM_ENCRYPTION_ENABLED
114 #if !defined NRF54_CCM_ENCRYPTION
115 NRF_CCM->INPTR = (uint32_t)inBuffer;
116 NRF_CCM->OUTPTR = (uint32_t)outBuffer;
117 NRF_CCM->CNFPTR = (uint32_t)&ccmData;
118 NRF_CCM->SCRATCHPTR = (uint32_t)scratchPTR;
119 #endif
120 ccmData.counter = 12345;
121 enableEncryption = false;
122#endif
123};
124
125/**********************************************************************************************************/
126
128{
129
130#ifndef ARDUINO_NRF54L15
131 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
132 NRF_CLOCK->TASKS_HFCLKSTART = 1;
133
134 /* Wait for the external oscillator to start up */
135 if (!waitForEvent(&NRF_CLOCK->EVENTS_HFCLKSTARTED))
136 return false;
137#else
138 NRF_POWER->TASKS_CONSTLAT = 1;
139 NRF_CLOCK->EVENTS_XOSTARTED = 0;
140 NRF_CLOCK->TASKS_XOSTART = 1;
141
142 if (!waitForEvent(&NRF_CLOCK->EVENTS_XOSTARTED))
143 return false;
144#endif
145
146 NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
147 NRF_CLOCK->TASKS_LFCLKSTART = 1;
148
149 /* Wait for the low frequency clock to start up */
150 if (!waitForEvent(&NRF_CLOCK->EVENTS_LFCLKSTARTED))
151 return false;
152
153#ifndef ARDUINO_NRF54L15
154 NRF_RADIO->POWER = 1;
155#endif
156
157 NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (1 << RADIO_PCNF0_S1LEN_Pos);
158
159 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | (4 << RADIO_PCNF1_BALEN_Pos) | (staticPayloadSize << RADIO_PCNF1_STATLEN_Pos) | (staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos);
160
161 NRF_RADIO->BASE0 = 0xE7E7E7E7; /* Base address 0 */
162 NRF_RADIO->BASE1 = 0x43434343;
163 NRF_RADIO->PREFIX0 = 0x23C343E7; /* Prefixes bytes for logical addresses 0 */
164 NRF_RADIO->PREFIX1 = 0x13E363A3;
165 NRF_RADIO->RXADDRESSES = 0x01;
166 NRF_RADIO->TXADDRESS = 0x00;
167 /* Receive address select */
168 txBase = NRF_RADIO->BASE0;
169 txPrefix = NRF_RADIO->PREFIX0;
170 rxBase = NRF_RADIO->BASE0;
171 rxPrefix = NRF_RADIO->PREFIX0;
172 // Configure CRC for 16-bit
173 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Two; /* CRC configuration: 16bit */
174 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
175 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
176
177 NRF_RADIO->PACKETPTR = (uint32_t)radioData;
178 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
179
180#ifndef ARDUINO_NRF54L15
181 NRF_RADIO->MODECNF0 = 0x201;
182#else
183 NRF_RADIO->TIMING = 0x1;
184#endif
185 NRF_RADIO->TXPOWER = (TXPOWER_PA_MAX << RADIO_TXPOWER_TXPOWER_Pos);
186 NRF_RADIO->FREQUENCY = 0x4C;
187
188 DPL = false;
189 // Enable auto ack on all pipes by default
190 setAutoAck(1);
191
192#ifdef ARDUINO_NRF54L15
193 NRF_RADIO->TASKS_START = 1;
194#endif
195
196 return 1;
197}
198
199/**********************************************************************************************************/
200
201#ifdef NRF_HAS_ENERGY_DETECT
202 #define ED_RSSISCALE 4 // From electrical specifications
203uint8_t nrf_to_nrf::sample_ed(void)
204{
205 int val;
206 NRF_RADIO->TASKS_EDSTART = 1; // Start
207 if (!waitForEvent(&NRF_RADIO->EVENTS_EDEND))
208 return 0;
209
210 val = NRF_RADIO->EDSAMPLE; // Read level
211 return (uint8_t)(val > 63
212 ? 255
213 : val * ED_RSSISCALE); // Convert to IEEE 802.15.4 scale
214}
215#endif
216
217/**********************************************************************************************************/
218
220{
221 uint8_t pipe_num = 0;
222 return available(&pipe_num);
223}
224
225/**********************************************************************************************************/
226
227bool nrf_to_nrf::available(uint8_t* pipe_num)
228{
229
230 if (payloadAvailable) {
231 *pipe_num = (uint8_t)NRF_RADIO->RXMATCH;
232 return true;
233 }
234
235 if (!inRxMode) {
236 if (ackPayloadAvailable) {
237 *pipe_num = ackAvailablePipeNo;
238 return true;
239 }
240 }
241 if (NRF_RADIO->EVENTS_CRCOK) {
242 NRF_RADIO->EVENTS_CRCOK = 0;
243 if (DPL) {
244 if (radioData[0] > ACTUAL_MAX_PAYLOAD_SIZE - (2 + NRF_RADIO->CRCCNF) || radioData[0] == 0) {
245 return restartReturnRx();
246 }
247 }
248
249 *pipe_num = (uint8_t)NRF_RADIO->RXMATCH;
250 if (!DPL && acksEnabled(*pipe_num) == false) {
251#if defined CCM_ENCRYPTION_ENABLED
252 if (enableEncryption) {
253 memcpy(&rxBuffer[1], &radioData[CCM_IV_SIZE + CCM_COUNTER_SIZE], staticPayloadSize - CCM_IV_SIZE - CCM_COUNTER_SIZE);
254 memcpy(ccmData.iv, &radioData[0], CCM_IV_SIZE);
255 memcpy(&ccmData.counter, &radioData[CCM_IV_SIZE], CCM_COUNTER_SIZE);
256 }
257 else {
258#endif
259 memcpy(&rxBuffer[1], &radioData[0], staticPayloadSize);
260#if defined CCM_ENCRYPTION_ENABLED
261 }
262#endif
263 }
264 else {
265#if defined CCM_ENCRYPTION_ENABLED
266 if (enableEncryption) {
267 if (DPL) {
268 memcpy(&rxBuffer[1], &radioData[2 + CCM_IV_SIZE + CCM_COUNTER_SIZE], max(0, (int8_t)radioData[0] - CCM_IV_SIZE - CCM_COUNTER_SIZE));
269 }
270 else {
271 memcpy(&rxBuffer[1], &radioData[CCM_IV_SIZE + CCM_COUNTER_SIZE], max(0, (int8_t)staticPayloadSize - CCM_IV_SIZE - CCM_COUNTER_SIZE));
272 }
273 memcpy(ccmData.iv, &radioData[2], CCM_IV_SIZE);
274 memcpy(&ccmData.counter, &radioData[2 + CCM_IV_SIZE], CCM_COUNTER_SIZE);
275 }
276 else {
277#endif
278 if (DPL) {
279 memcpy(&rxBuffer[1], &radioData[2], radioData[0]);
280 }
281 else {
282 memcpy(&rxBuffer[1], &radioData[2], staticPayloadSize);
283 }
284#if defined CCM_ENCRYPTION_ENABLED
285 }
286#endif
287 }
288
289 rxFifoAvailable = true;
290 uint8_t packetCtr = 0;
291 if (DPL) {
292 packetCtr = radioData[1];
293 rxBuffer[0] = radioData[0];
294 }
295 else {
296 packetCtr = radioData[0];
297 rxBuffer[0] = staticPayloadSize;
298 }
299
300 ackPID = packetCtr;
301 uint16_t packetData = NRF_RADIO->RXCRC;
302 // If ack is enabled on this receiving pipe
303 if (acksEnabled(NRF_RADIO->RXMATCH)) {
304 stopListening(false, false);
305 uint32_t txAddress = NRF_RADIO->TXADDRESS;
306 NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH;
307 delayMicroseconds(75);
308 if (ackPayloadsEnabled) {
309 if (*pipe_num == ackPipe) {
310 write(&ackBuffer[1], ackBuffer[0], 1, 0);
311 }
312 else {
313 write(0, 0, 1, 0);
314 }
315 }
316 else {
317 uint8_t payloadSize = 0;
318 if (!DPL) {
319 payloadSize = getPayloadSize();
321 }
322 write(0, 0, 1, 0); // Send an ACK
323 if (!DPL) {
324 setPayloadSize(payloadSize);
325 }
326 }
327 NRF_RADIO->TXADDRESS = txAddress;
328 startListening(false);
329
330 // If the packet has the same ID number and data, it is most likely a
331 // duplicate
332 if (NRF_RADIO->CRCCNF != 0) { // If CRC enabled, check this data
333 if (packetCtr == lastPacketCounter && packetData == lastData) {
334 return restartReturnRx();
335 }
336 }
337 }
338
339#if defined CCM_ENCRYPTION_ENABLED
340 if (enableEncryption) {
341 uint8_t bufferLength = 0;
342 if (DPL) {
343 bufferLength = rxBuffer[0] - CCM_IV_SIZE - CCM_COUNTER_SIZE;
344 }
345 else {
346 bufferLength = staticPayloadSize - CCM_IV_SIZE - CCM_COUNTER_SIZE;
347 }
348 if (!decrypt(&rxBuffer[1], bufferLength)) {
349 Serial.println("DECRYPT FAIL");
350 return restartReturnRx();
351 }
352
353 memset(&rxBuffer[1], 0, sizeof(rxBuffer) - 1);
354
355 if (DPL) {
356 rxBuffer[0] -= (CCM_MIC_SIZE + CCM_IV_SIZE + CCM_COUNTER_SIZE);
357 memcpy(&rxBuffer[1], &outBuffer[CCM_START_SIZE], rxBuffer[0]);
358 }
359 else {
360 memcpy(&rxBuffer[1], &outBuffer[CCM_START_SIZE], staticPayloadSize - (CCM_MIC_SIZE - CCM_IV_SIZE - CCM_COUNTER_SIZE));
361 }
362 }
363#endif
364 lastPacketCounter = packetCtr;
365 lastData = packetData;
366
367 if (inRxMode && !acksEnabled(NRF_RADIO->RXMATCH)) {
368 NRF_RADIO->TASKS_START = 1;
369 }
370 if ((DPL && rxBuffer[0]) || !DPL) {
371 payloadAvailable = true;
372 return 1;
373 }
374 }
375 if (NRF_RADIO->EVENTS_CRCERROR) {
376 NRF_RADIO->EVENTS_CRCERROR = 0;
377 NRF_RADIO->TASKS_START = 1;
378 }
379 return 0;
380}
381
382/**********************************************************************************************************/
383
384bool nrf_to_nrf::restartReturnRx()
385{
386 if (inRxMode) {
387 NRF_RADIO->TASKS_START = 1;
388 }
389 return 0;
390}
391
392/**********************************************************************************************************/
393
394void nrf_to_nrf::read(void* buf, uint8_t len)
395{
396 memcpy(buf, &rxBuffer[1], len);
397 ackPayloadAvailable = false;
398 payloadAvailable = false;
399}
400
401/**********************************************************************************************************/
402
403bool nrf_to_nrf::write(void* buf, uint8_t len, bool multicast, bool doEncryption)
404{
405
406 uint8_t PID = ackPID;
407 if (DPL) {
408 PID = ((ackPID += 1) % 7) << 1;
409 }
410 else {
411 PID = ackPID++;
412 }
413 uint8_t payloadSize = 0;
414
415#if defined CCM_ENCRYPTION_ENABLED
416
417 if (enableEncryption && doEncryption) {
418 if (len) {
419
420 if (!generateIV(ccmData.iv)) {
421 return 0;
422 }
423 ccmData.counter = packetCounter;
424
425 if (!encrypt(buf, len)) {
426 return 0;
427 }
428
430 packetCounter++;
431 if (packetCounter > 200000) {
432 packetCounter = 0;
433 }
434 }
435 }
436#endif
437
438 for (int i = 0; i < (retries + 1); i++) {
439 arcCounter = i;
440 if (DPL) {
441 radioData[0] = len;
442 radioData[1] = PID;
443 }
444 else {
445 radioData[1] = 0;
446 radioData[0] = PID;
447 }
448
449 uint8_t dataStart = 0;
450
451#if defined CCM_ENCRYPTION_ENABLED
452
453 if (enableEncryption && doEncryption) {
454 dataStart = (!DPL && acksEnabled(0) == false) ? CCM_IV_SIZE + CCM_COUNTER_SIZE : CCM_IV_SIZE + CCM_COUNTER_SIZE + 2;
455 }
456 else {
457#endif
458 dataStart = (!DPL && acksEnabled(0) == false) ? 0 : 2;
459#if defined CCM_ENCRYPTION_ENABLED
460 }
461#endif
462
463#if defined CCM_ENCRYPTION_ENABLED
464 if (enableEncryption && doEncryption) {
465 memcpy(&radioData[dataStart - CCM_COUNTER_SIZE], &ccmData.counter, CCM_COUNTER_SIZE);
466 memcpy(&radioData[dataStart - CCM_IV_SIZE - CCM_COUNTER_SIZE], ccmData.iv, CCM_IV_SIZE);
467 memcpy(&radioData[dataStart], &outBuffer[CCM_START_SIZE], len - (CCM_IV_SIZE + CCM_COUNTER_SIZE));
468 }
469 else {
470#endif
471 memcpy(&radioData[dataStart], buf, len);
472#if defined CCM_ENCRYPTION_ENABLED
473 }
474#endif
475#ifdef ARDUINO_NRF54L15
476 uint32_t timeout = millis();
477 while (NRF_RADIO->STATE != 10) {
478 yield();
479 if (millis() - timeout > 250) {
480 return 0;
481 }
482 }
483#endif
484 NRF_RADIO->EVENTS_END = 0;
485 NRF_RADIO->TASKS_START = 1;
486 if (!waitForEvent(&NRF_RADIO->EVENTS_END))
487 return false;
488
489 NRF_RADIO->EVENTS_END = 0;
490 if (!multicast && acksPerPipe[NRF_RADIO->TXADDRESS] == true) {
491 uint32_t rxAddress = NRF_RADIO->RXADDRESSES;
492 NRF_RADIO->RXADDRESSES = 1 << NRF_RADIO->TXADDRESS;
493 if (!DPL) {
494 payloadSize = getPayloadSize();
496 }
497 startListening(false);
498
499 int32_t realAckTimeout = (int32_t)ackTimeout;
500 if (!DPL) {
501 if (NRF_RADIO->MODE == (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos)) {
502 realAckTimeout -= ACK_TIMEOUT_1MBPS_OFFSET;
503 }
504 else if (NRF_RADIO->MODE == (RADIO_MODE_MODE_Nrf_250Kbit << RADIO_MODE_MODE_Pos)) {
505 realAckTimeout -= ACK_TIMEOUT_250KBPS_OFFSET;
506 }
507 else {
508 realAckTimeout -= ACK_TIMEOUT_2MBPS_OFFSET;
509 }
510 }
511 else {
512 if (ackPayloadsEnabled && staticPayloadSize <= DEFAULT_MAX_PAYLOAD_SIZE) {
513 realAckTimeout += 200;
514 }
515 else {
516 realAckTimeout += ACK_PAYLOAD_TIMEOUT_OFFSET;
517 }
518 }
519 if (realAckTimeout < 0) {
520 realAckTimeout = 0;
521 }
522
523 uint32_t ack_timeout = micros();
524 while (!NRF_RADIO->EVENTS_CRCOK && !NRF_RADIO->EVENTS_CRCERROR) {
525 if (micros() - ack_timeout > realAckTimeout) {
526 break;
527 }
528 }
529 if (NRF_RADIO->EVENTS_CRCOK) {
530 if (ackPayloadsEnabled && radioData[0] > 0) {
531#if defined CCM_ENCRYPTION_ENABLED
532 if (enableEncryption && doEncryption) {
533 memcpy(&rxBuffer[1], &radioData[2 + CCM_COUNTER_SIZE + CCM_IV_SIZE], max(0, radioData[0] - CCM_COUNTER_SIZE - CCM_IV_SIZE));
534 }
535 else {
536 memcpy(&rxBuffer[1], &radioData[2], radioData[0]);
537 }
538#else
539 memcpy(&rxBuffer[1], &radioData[2], radioData[0]);
540#endif
541
542#if defined CCM_ENCRYPTION_ENABLED
543 if (enableEncryption && radioData[0] > 0) {
544 memcpy(ccmData.iv, &radioData[2], CCM_IV_SIZE);
545 memcpy(&ccmData.counter, &radioData[2 + CCM_IV_SIZE], CCM_COUNTER_SIZE);
546
547 if (!decrypt(&rxBuffer[1], radioData[0])) {
548 Serial.println("DECRYPT FAIL");
549 return 0;
550 }
553 }
554 memcpy(&rxBuffer[1], &outBuffer[CCM_START_SIZE], radioData[0]);
555 }
556#endif
557 rxBuffer[0] = radioData[0];
558 ackPayloadAvailable = true;
559 ackAvailablePipeNo = NRF_RADIO->RXMATCH;
560 }
561 NRF_RADIO->EVENTS_CRCOK = 0;
562 stopListening(false, false);
563 if (!DPL) {
564 setPayloadSize(payloadSize);
565 }
566 NRF_RADIO->RXADDRESSES = rxAddress;
567 lastTxResult = true;
568 return 1;
569 }
570 else if (NRF_RADIO->EVENTS_CRCERROR) {
571 NRF_RADIO->EVENTS_CRCERROR = 0;
572 }
573 uint32_t duration = 258 * retryDuration;
574 delayMicroseconds(duration);
575 stopListening(false, false);
576 if (!DPL) {
577 setPayloadSize(payloadSize);
578 }
579 NRF_RADIO->RXADDRESSES = rxAddress;
580 }
581 else {
582 lastTxResult = true;
583 return 1;
584 }
585 }
586 lastTxResult = false;
587 return 0;
588}
589
590/**********************************************************************************************************/
591
592bool nrf_to_nrf::startWrite(void* buf, uint8_t len, bool multicast, bool doEncryption)
593{
594
595 uint8_t PID = ackPID;
596 if (DPL) {
597 PID = ((ackPID += 1) % 7) << 1;
598 }
599 else {
600 PID = ackPID++;
601 }
602
603#if defined CCM_ENCRYPTION_ENABLED
604 uint8_t tmpIV[CCM_IV_SIZE];
605 uint32_t tmpCounter = 0;
606
607 if (enableEncryption && doEncryption) {
608 if (len) {
609
610 if (!generateIV(tmpIV)) {
611 return 0;
612 }
613 memcpy(ccmData.iv, tmpIV, CCM_IV_SIZE);
614 tmpCounter = packetCounter;
615 ccmData.counter = tmpCounter;
616
617 if (!encrypt(buf, len)) {
618 return 0;
619 }
620
622 packetCounter++;
623 if (packetCounter > 200000) {
624 packetCounter = 0;
625 }
626 }
627 }
628#endif
629
630 // for (int i = 0; i < retries; i++) {
631 arcCounter = 0;
632 if (DPL) {
633 radioData[0] = len;
634 radioData[1] = PID;
635 }
636 else {
637 radioData[1] = 0;
638 radioData[0] = PID;
639 }
640
641 uint8_t dataStart = 0;
642
643#if defined CCM_ENCRYPTION_ENABLED
644
645 if (enableEncryption && doEncryption) {
646 dataStart = (!DPL && acksEnabled(0) == false) ? CCM_IV_SIZE + CCM_COUNTER_SIZE : CCM_IV_SIZE + CCM_COUNTER_SIZE + 2;
647 }
648 else {
649#endif
650 dataStart = (!DPL && acksEnabled(0) == false) ? 0 : 2;
651#if defined CCM_ENCRYPTION_ENABLED
652 }
653#endif
654
655#if defined CCM_ENCRYPTION_ENABLED
656 if (enableEncryption && doEncryption) {
657 memcpy(&radioData[dataStart - CCM_COUNTER_SIZE], &tmpCounter, CCM_COUNTER_SIZE);
658 memcpy(&radioData[dataStart - CCM_IV_SIZE - CCM_COUNTER_SIZE], &tmpIV[0], CCM_IV_SIZE);
659 memcpy(&radioData[dataStart], &outBuffer[CCM_START_SIZE], len - (CCM_IV_SIZE + CCM_COUNTER_SIZE));
660 }
661 else {
662#endif
663 memcpy(&radioData[dataStart], buf, len);
664#if defined CCM_ENCRYPTION_ENABLED
665 }
666#endif
667
668 NRF_RADIO->EVENTS_END = 0;
669 NRF_RADIO->TASKS_START = 1;
670 lastTxResult = true;
671
672 return true;
673}
674
675/**********************************************************************************************************/
676
677bool nrf_to_nrf::writeAckPayload(uint8_t pipe, void* buf, uint8_t len)
678{
679
680#if defined CCM_ENCRYPTION_ENABLED
681 if (enableEncryption) {
682 if (len) {
683
684 if (!generateIV(ccmData.iv)) {
685 return 0;
686 }
687 memcpy(&ackBuffer[1], ccmData.iv, CCM_IV_SIZE);
688
689 ccmData.counter = packetCounter;
690 memcpy(&ackBuffer[1 + CCM_IV_SIZE], &ccmData.counter, CCM_COUNTER_SIZE);
691
692 if (!encrypt(buf, len)) {
693 return 0;
694 }
695
698 packetCounter++;
699 if (packetCounter > 200000) {
700 packetCounter = 0;
701 }
702 }
703 }
704 else {
705#endif
706 memcpy(&ackBuffer[1], buf, len);
707#if defined CCM_ENCRYPTION_ENABLED
708 }
709#endif
710 ackBuffer[0] = len;
711 ackPipe = pipe;
712 return true;
713}
714
715/**********************************************************************************************************/
716
717void nrf_to_nrf::enableAckPayload() { ackPayloadsEnabled = true; }
718
719/**********************************************************************************************************/
720
721void nrf_to_nrf::disableAckPayload() { ackPayloadsEnabled = false; }
722
723/**********************************************************************************************************/
724
725void nrf_to_nrf::startListening(bool resetAddresses)
726{
727
728 NRF_RADIO->EVENTS_DISABLED = 0;
729 NRF_RADIO->TASKS_DISABLE = 1;
730 if (!waitForEvent(&NRF_RADIO->EVENTS_DISABLED))
731 return;
732 NRF_RADIO->EVENTS_DISABLED = 0;
733
734 if (resetAddresses == true) {
735 NRF_RADIO->BASE0 = rxBase;
736 NRF_RADIO->PREFIX0 = rxPrefix;
737#ifndef ARDUINO_NRF54L15
738 NRF_RADIO->MODECNF0 = 0x201;
739#else
740 NRF_RADIO->TIMING = 0x1;
741#endif
742 // NRF_RADIO->MODECNF0 = 0x201;
743 NRF_RADIO->TIFS = 0;
744 }
745 NRF_RADIO->SHORTS = 0x0;
746#if defined(NRF52832_XXAA)
747 NRF_RADIO->EVENTS_READY = 0;
748#else
749 NRF_RADIO->EVENTS_RXREADY = 0;
750#endif
751 NRF_RADIO->EVENTS_CRCOK = 0;
752 NRF_RADIO->TASKS_RXEN = 1;
753#if defined(NRF52832_XXAA)
754 if (!waitForEvent(&NRF_RADIO->EVENTS_READY))
755 return;
756#else
757 if (!waitForEvent(&NRF_RADIO->EVENTS_RXREADY))
758 return;
759#endif
760 NRF_RADIO->TASKS_START = 1;
761 inRxMode = true;
762}
763
764/**********************************************************************************************************/
765
766void nrf_to_nrf::stopListening(bool setWritingPipe, bool resetAddresses)
767{
768 NRF_RADIO->EVENTS_DISABLED = 0;
769 NRF_RADIO->TASKS_DISABLE = 1;
770 if (!waitForEvent(&NRF_RADIO->EVENTS_DISABLED))
771 return;
772 NRF_RADIO->EVENTS_DISABLED = 0;
773
774 if (resetAddresses) {
775 NRF_RADIO->BASE0 = txBase;
776 NRF_RADIO->PREFIX0 = txPrefix;
777 }
778 if (setWritingPipe) {
779 NRF_RADIO->TXADDRESS = 0x00;
780 NRF_RADIO->TIFS = interframeSpacing;
781#ifndef ARDUINO_NRF54L15
782 NRF_RADIO->MODECNF0 = 0x200;
783#else
784 NRF_RADIO->TIMING = 0x0;
785#endif
786 }
787#ifndef ARDUINO_NRF54L15
788 NRF_RADIO->SHORTS = 0x6;
789#else
790 NRF_RADIO->SHORTS = 0x80004;
791#endif
792 if (NRF_RADIO->STATE < 9) {
793#if defined(NRF52832_XXAA)
794 NRF_RADIO->EVENTS_READY = 0;
795#else
796 NRF_RADIO->EVENTS_TXREADY = 0;
797#endif
798 NRF_RADIO->TASKS_TXEN = 1;
799#if defined(NRF52832_XXAA)
800 if (!waitForEvent(&NRF_RADIO->EVENTS_READY))
801 return;
802 NRF_RADIO->EVENTS_READY = 0;
803#else
804 if (!waitForEvent(&NRF_RADIO->EVENTS_TXREADY))
805 return;
806 NRF_RADIO->EVENTS_TXREADY = 0;
807#endif
808 }
809
810 inRxMode = false;
811}
812
813/**********************************************************************************************************/
814
815void nrf_to_nrf::stopListening(const uint8_t* txAddress, bool setWritingPipe, bool resetAddresses)
816{
817 stopListening(setWritingPipe, resetAddresses);
818 openWritingPipe(txAddress);
819}
820
821/**********************************************************************************************************/
822
824{
825 uint8_t size = min(staticPayloadSize, rxBuffer[0]);
826 return size;
827}
828
829/**********************************************************************************************************/
830
832{
833
834 uint32_t freq = NRF_RADIO->FREQUENCY;
835 NRF_RADIO->FREQUENCY = 0x4C;
836 if (NRF_RADIO->FREQUENCY == 0x4C) {
837 NRF_RADIO->FREQUENCY = freq;
838 return 1;
839 }
840 return 0;
841}
842
843/**********************************************************************************************************/
844
845void nrf_to_nrf::setChannel(uint8_t channel, bool map) { NRF_RADIO->FREQUENCY = channel | map << RADIO_FREQUENCY_MAP_Pos; }
846
847/**********************************************************************************************************/
848
849uint8_t nrf_to_nrf::getChannel() { return (uint8_t)NRF_RADIO->FREQUENCY; }
850
851/**********************************************************************************************************/
852
853void nrf_to_nrf::setAutoAck(bool enable)
854{
855
856 for (int i = 0; i < 8; i++) {
857 acksPerPipe[i] = enable;
858 }
859 if (!DPL) {
860 disableDynamicPayloads(); // Called to re-configure the PCNF0 register
861 }
862}
863
864/**********************************************************************************************************/
865
866void nrf_to_nrf::setAutoAck(uint8_t pipe, bool enable)
867{
868
869 acksPerPipe[pipe] = enable;
870 if (!DPL) {
871 disableDynamicPayloads(); // Called to re-configure the PCNF0 register
872 }
873}
874
875/**********************************************************************************************************/
876
877void nrf_to_nrf::enableDynamicPayloads(uint8_t payloadSize)
878{
879
880 if (!DPL) {
881 DPL = true;
882 staticPayloadSize = payloadSize;
883
884 if (payloadSize <= 63) {
885 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (6 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);
886 }
887 else {
888 // Using 8 bits for length
889 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (8 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);
890 }
891
892 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_MAXLEN_Pos | 0xFF << RADIO_PCNF1_STATLEN_Pos);
893 NRF_RADIO->PCNF1 |= payloadSize << RADIO_PCNF1_MAXLEN_Pos;
894 }
895}
896
897/**********************************************************************************************************/
898
900{
901 DPL = false;
902
903 uint8_t lenConfig = 0;
904 if (acksEnabled(0)) {
905 lenConfig = 1;
906 }
907 NRF_RADIO->PCNF0 = (lenConfig << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (lenConfig << RADIO_PCNF0_S1LEN_Pos);
908
909 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_MAXLEN_Pos | 0xFF << RADIO_PCNF1_STATLEN_Pos);
910 NRF_RADIO->PCNF1 |= staticPayloadSize << RADIO_PCNF1_STATLEN_Pos | staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos;
911}
912
913/**********************************************************************************************************/
914
916{
917 staticPayloadSize = size;
918 DPL = false;
919
920 uint8_t lenConfig = 0;
921 if (acksEnabled(0)) {
922 lenConfig = 1;
923 }
924 NRF_RADIO->PCNF0 = (lenConfig << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (lenConfig << RADIO_PCNF0_S1LEN_Pos);
925
926 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_MAXLEN_Pos | 0xFF << RADIO_PCNF1_STATLEN_Pos);
927 NRF_RADIO->PCNF1 |= staticPayloadSize << RADIO_PCNF1_STATLEN_Pos | staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos;
928}
929
930/**********************************************************************************************************/
931
933{
934 return staticPayloadSize;
935}
936
937/**********************************************************************************************************/
938
939void nrf_to_nrf::setRetries(uint8_t retryVar, uint8_t attempts)
940{
941
942 retries = attempts;
943 retryDuration = retryVar;
944}
945
946/**********************************************************************************************************/
947
948void nrf_to_nrf::openReadingPipe(uint8_t child, uint64_t address)
949{
950 uint32_t base = addrConv32(address >> 8);
951 uint32_t prefix = addrConv32(address & 0xFF) >> 24;
952
953 openReadingPipe(child, base, prefix);
954}
955
956/**********************************************************************************************************/
957
958void nrf_to_nrf::openWritingPipe(uint64_t address)
959{
960 uint32_t base = addrConv32(address >> 8);
961 uint32_t prefix = addrConv32(address & 0xFF) >> 24;
962
963 openWritingPipe(base, prefix);
964}
965
966/**********************************************************************************************************/
967
968void nrf_to_nrf::openReadingPipe(uint8_t child, const uint8_t* address)
969{
970 uint32_t base = addr_conv(&address[1]);
971 uint32_t prefix = addr_conv(&address[0]) >> 24;
972
973 openReadingPipe(child, base, prefix);
974}
975
976/**********************************************************************************************************/
977
978void nrf_to_nrf::openReadingPipe(uint8_t child, uint32_t base, uint32_t prefix)
979{
980
981 // Using pipes 1-7 for reading pipes, leaving pipe0 for a tx pipe
982 if (!child) {
983 NRF_RADIO->PREFIX0 = rxPrefix;
984 NRF_RADIO->BASE0 = base;
985 NRF_RADIO->PREFIX0 &= ~(0xFF);
986 NRF_RADIO->PREFIX0 |= prefix;
987 rxBase = NRF_RADIO->BASE0;
988 rxPrefix = NRF_RADIO->PREFIX0;
989 }
990 else if (child < 4) { // prefixes AP1-3 are in prefix0
991 NRF_RADIO->PREFIX0 = rxPrefix;
992 NRF_RADIO->BASE1 = base;
993 NRF_RADIO->PREFIX0 &= ~(0xFF << (8 * child));
994 NRF_RADIO->PREFIX0 |= prefix << (8 * child);
995 rxPrefix = NRF_RADIO->PREFIX0;
996 }
997 else {
998 NRF_RADIO->BASE1 = base;
999 NRF_RADIO->PREFIX1 &= ~(0xFF << (8 * (child - 4)));
1000 NRF_RADIO->PREFIX1 |= prefix << (8 * (child - 4));
1001 }
1002 NRF_RADIO->RXADDRESSES |= 1 << child;
1003}
1004
1005/**********************************************************************************************************/
1006
1007void nrf_to_nrf::openWritingPipe(const uint8_t* address)
1008{
1009
1010 uint32_t base = addr_conv(&address[1]);
1011 uint32_t prefix = addr_conv(&address[0]) >> 24;
1012
1013 openWritingPipe(base, prefix);
1014}
1015
1016/**********************************************************************************************************/
1017
1018void nrf_to_nrf::openWritingPipe(uint32_t base, uint32_t prefix)
1019{
1020
1021 NRF_RADIO->BASE0 = base;
1022 NRF_RADIO->PREFIX0 &= ~(0xFF);
1023 NRF_RADIO->PREFIX0 |= prefix;
1024 NRF_RADIO->TXADDRESS = 0x00;
1025 txBase = NRF_RADIO->BASE0;
1026 txPrefix = NRF_RADIO->PREFIX0;
1027}
1028/**********************************************************************************************************/
1029
1031{
1032 return lastTxResult;
1033}
1034
1035/**********************************************************************************************************/
1036
1037bool nrf_to_nrf::txStandBy(uint32_t timeout, bool startTx)
1038{
1039 return lastTxResult;
1040}
1041
1042/**********************************************************************************************************/
1043
1044bool nrf_to_nrf::writeFast(void* buf, uint8_t len, bool multicast)
1045{
1046 lastTxResult = write(buf, len, multicast);
1047 return lastTxResult;
1048}
1049
1050/**********************************************************************************************************/
1051
1052bool nrf_to_nrf::acksEnabled(uint8_t pipe)
1053{
1054
1055 if (acksPerPipe[pipe]) {
1056 return 1;
1057 }
1058 return 0;
1059}
1060
1061/**********************************************************************************************************/
1062
1064
1065/**********************************************************************************************************/
1066
1067bool nrf_to_nrf::setDataRate(uint8_t speed)
1068{
1069
1070 if (speed == NRF_1MBPS) {
1071 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
1072 ackTimeout = ACK_TIMEOUT_1MBPS;
1073 }
1074 else if (speed == NRF_250KBPS) {
1075 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_250Kbit << RADIO_MODE_MODE_Pos);
1076 ackTimeout = ACK_TIMEOUT_250KBPS;
1077 }
1078 else if (speed == NRF_2MBPS) { // NRF_2MBPS
1079 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_2Mbit << RADIO_MODE_MODE_Pos);
1080 ackTimeout = ACK_TIMEOUT_2MBPS;
1081 }
1082#ifdef ARDUINO_NRF54L15
1083 else if (speed == NRF_4MBPS_OBT4) {
1084 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_4Mbit_OBT4 << RADIO_MODE_MODE_Pos);
1085 ackTimeout = ACK_TIMEOUT_2MBPS;
1086 }
1087 else {
1088 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_4Mbit_OBT6 << RADIO_MODE_MODE_Pos);
1089 ackTimeout = ACK_TIMEOUT_2MBPS;
1090 }
1091#endif
1092
1093 return 1;
1094}
1095
1096/**********************************************************************************************************/
1097
1098void nrf_to_nrf::setPALevel(uint8_t level, bool lnaEnable)
1099{
1100
1101 uint8_t paLevel = 0x00;
1102
1103 if (level == NRF_PA_MIN) {
1104 paLevel = TXPOWER_PA_MIN;
1105 }
1106 else if (level == NRF_PA_LOW) {
1107 paLevel = TXPOWER_PA_LOW;
1108 }
1109 else if (level == NRF_PA_HIGH) {
1110 paLevel = TXPOWER_PA_HIGH;
1111 }
1112 else if (level == NRF_PA_MAX) {
1113 paLevel = TXPOWER_PA_MAX;
1114 }
1115 NRF_RADIO->TXPOWER = paLevel;
1116}
1117
1118/**********************************************************************************************************/
1119
1121{
1122
1123 uint8_t paLevel = NRF_RADIO->TXPOWER;
1124
1125 if (paLevel == TXPOWER_PA_MIN) {
1126 return NRF_PA_MIN;
1127 }
1128 else if (paLevel == TXPOWER_PA_LOW) {
1129 return NRF_PA_LOW;
1130 }
1131 else if (paLevel == TXPOWER_PA_HIGH) {
1132 return NRF_PA_HIGH;
1133 }
1134 else if (paLevel == TXPOWER_PA_MAX) {
1135 return NRF_PA_MAX;
1136 }
1137 else {
1138 return NRF_PA_ERROR;
1139 }
1140}
1141
1142/**********************************************************************************************************/
1143
1145{
1146 return arcCounter;
1147}
1148
1149/**********************************************************************************************************/
1150
1152{
1153 if (length == NRF_CRC_24) {
1154 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Three; /* CRC configuration: 24bit */
1155 NRF_RADIO->CRCINIT = 0x555555UL; // Initial value
1156 NRF_RADIO->CRCPOLY = 0x65BUL;
1157 }
1158 else if (length == NRF_CRC_16) {
1159 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Two; /* CRC configuration: 16bit */
1160 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
1161 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
1162 }
1163 else if (length == NRF_CRC_8) {
1164 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_One; /* CRC configuration: 8bit */
1165 NRF_RADIO->CRCINIT = 0xFFUL;
1166 NRF_RADIO->CRCPOLY = 0x107UL;
1167 }
1168 else {
1169 NRF_RADIO->CRCCNF = 0; /* CRC configuration: Disabled */
1170 NRF_RADIO->CRCINIT = 0x00L;
1171 NRF_RADIO->CRCPOLY = 0x00UL;
1172 }
1173}
1174
1175/**********************************************************************************************************/
1176
1178{
1179 if (NRF_RADIO->CRCCNF == 0) {
1180 return NRF_CRC_DISABLED;
1181 }
1182 else if (NRF_RADIO->CRCCNF == RADIO_CRCCNF_LEN_One) {
1183 return NRF_CRC_8;
1184 }
1185 if (NRF_RADIO->CRCCNF == RADIO_CRCCNF_LEN_Two) {
1186 return NRF_CRC_16;
1187 }
1188 else {
1189 return NRF_CRC_24;
1190 }
1191}
1192
1193/**********************************************************************************************************/
1194
1195bool nrf_to_nrf::testCarrier(uint8_t RSSI)
1196{
1197#ifndef ARDUINO_NRF54L15
1198 NRF_RADIO->EVENTS_RSSIEND = 0;
1199 NRF_RADIO->TASKS_RSSISTART = 1;
1200 if (!waitForEvent(&NRF_RADIO->EVENTS_RSSIEND))
1201 return false;
1202
1203 if (NRF_RADIO->RSSISAMPLE < RSSI) {
1204 return 1;
1205 }
1206#endif
1207 return 0;
1208}
1209
1210/**********************************************************************************************************/
1211
1212bool nrf_to_nrf::testRPD(uint8_t RSSI)
1213{
1214 return testCarrier(RSSI);
1215}
1216
1217/**********************************************************************************************************/
1218
1220{
1221#ifndef ARDUINO_NRF54L15
1222 NRF_RADIO->EVENTS_RSSIEND = 0;
1223 NRF_RADIO->TASKS_RSSISTART = 1;
1224 if (!waitForEvent(&NRF_RADIO->EVENTS_RSSIEND))
1225 return 0;
1226
1227 return (uint8_t)NRF_RADIO->RSSISAMPLE;
1228#endif
1229 return 0;
1230}
1231
1232/**********************************************************************************************************/
1233
1235{
1236 return 0;
1237}
1238
1239/**********************************************************************************************************/
1240
1242{
1243#ifndef ARDUINO_NRF54L15
1244 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
1245 NRF_CLOCK->TASKS_HFCLKSTART = 1;
1246
1247 /* Wait for the external oscillator to start up */
1248 waitForEvent(&NRF_CLOCK->EVENTS_HFCLKSTARTED);
1249
1250 NRF_RADIO->POWER = 1;
1251#else
1252 NRF_POWER->TASKS_CONSTLAT = 1;
1253 NRF_CLOCK->EVENTS_XOSTARTED = 0;
1254 NRF_CLOCK->TASKS_XOSTART = 1;
1255
1256 waitForEvent(&NRF_CLOCK->EVENTS_XOSTARTED);
1257#endif
1258
1259#ifdef CCM_ENCRYPTION_ENABLED
1260 if (enableEncryption) {
1261 #if defined NRF54_CCM_ENCRYPTION
1262 nrf54Rng.begin(); // The Ccm class enables CCM00 for each operation
1263 #else
1264 NRF_RNG->CONFIG = 1;
1265 NRF_RNG->TASKS_START = 1;
1266 NRF_CCM->ENABLE = 2;
1267 #endif
1268 }
1269#endif
1270}
1271
1272/**********************************************************************************************************/
1273
1275{
1276#ifndef ARDUINO_NRF54L15
1277 NRF_RADIO->POWER = 0;
1278 NRF_CLOCK->TASKS_HFCLKSTOP = 1;
1279#else
1280 NRF_CLOCK->TASKS_XOSTOP = 1;
1281#endif
1282
1283#ifdef CCM_ENCRYPTION_ENABLED
1284 if (enableEncryption) {
1285 #if defined NRF54_CCM_ENCRYPTION
1286 nrf54Rng.end();
1287 #else
1288 NRF_RNG->TASKS_STOP = 1;
1289 NRF_RNG->CONFIG = 0;
1290 NRF_CCM->ENABLE = 0;
1291 #endif
1292 }
1293#endif
1294}
1295
1296/**********************************************************************************************************/
1297void nrf_to_nrf::setAddressWidth(uint8_t a_width)
1298{
1299 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_BALEN_Pos);
1300 NRF_RADIO->PCNF1 |= (a_width - 1) << RADIO_PCNF1_BALEN_Pos;
1301}
1302
1303/**********************************************************************************************************/
1304
1306{
1307 uint8_t addressWidth = ((NRF_RADIO->PCNF1 >> 16) & 0xFF) + 1;
1308
1309 Serial.println("================ Radio Configuration ================");
1310 Serial.print("STATUS\t\t= ");
1311 Serial.println(NRF_RADIO->STATE);
1312
1313 // Serial.println(addrConv32(NRF_RADIO->PREFIX0);
1314 Serial.print("RX_ADDR_P0-1\t= 0x");
1315 uint32_t base = addrConv32(NRF_RADIO->BASE0);
1316 for (int i = addressWidth - 2; i > -1; i--) {
1317 Serial.print((base >> (i * 8)) & 0xFF, HEX);
1318 }
1319 uint32_t prefixes = addrConv32(NRF_RADIO->PREFIX0);
1320 uint8_t prefix = (prefixes >> 24) & 0xFF;
1321 Serial.print(prefix, HEX);
1322 Serial.print(" 0x");
1323 base = addrConv32(NRF_RADIO->BASE1);
1324 for (int i = addressWidth - 2; i > -1; i--) {
1325 Serial.print((base >> (i * 8)) & 0xFF, HEX);
1326 }
1327 prefix = (prefixes >> 16) & 0xFF;
1328 Serial.println(prefix, HEX);
1329
1330 Serial.print("RX_ADDR_P2-7\t= 0x");
1331 prefix = (prefixes >> 8) & 0xFF;
1332 Serial.print(prefix, HEX);
1333 Serial.print(" 0x");
1334 prefix = (prefixes) & 0xFF;
1335 Serial.print(prefix, HEX);
1336 Serial.print(" 0x");
1337 prefixes = addrConv32(NRF_RADIO->PREFIX1);
1338 prefix = (prefixes >> 24) & 0xFF;
1339 Serial.print(prefix, HEX);
1340 Serial.print(" 0x");
1341 prefix = (prefixes >> 16) & 0xFF;
1342 Serial.print(prefix, HEX);
1343 Serial.print(" 0x");
1344 prefix = (prefixes >> 8) & 0xFF;
1345 Serial.print(prefix, HEX);
1346 Serial.print(" 0x");
1347 prefix = (prefixes) & 0xFF;
1348 Serial.println(prefix, HEX);
1349
1350 uint8_t enAA = 0;
1351 for (int i = 0; i < 6; i++) {
1352 enAA |= acksPerPipe[i] << i;
1353 }
1354 Serial.print("EN_AA\t\t= 0x");
1355 Serial.println(enAA, HEX);
1356 Serial.print("EN_RXADDR\t= 0x");
1357 Serial.println(NRF_RADIO->RXADDRESSES, HEX);
1358 Serial.print("RF_CH\t\t= 0x");
1359 Serial.println(NRF_RADIO->FREQUENCY, HEX);
1360 Serial.println("DYNPD/FEATURE\t= 0x");
1361 Serial.print("Data Rate\t= ");
1362 Serial.println(NRF_RADIO->MODE ? "2 MBPS" : "1MBPS");
1363 Serial.println("Model\t\t= NRF52");
1364 Serial.print("CRC Length\t= ");
1365 uint8_t crcLen = getCRCLength();
1366 if (crcLen == NRF_CRC_16) {
1367 Serial.println("16 bits");
1368 }
1369 else if (crcLen == NRF_CRC_8) {
1370 Serial.println("8 bits");
1371 }
1372 else {
1373 Serial.println("Disabled");
1374 }
1375 Serial.print("PA Power\t= ");
1376 uint8_t paLevel = getPALevel();
1377 if (paLevel == NRF_PA_MAX) {
1378 Serial.println("PA_MAX");
1379 }
1380 else if (paLevel == NRF_PA_HIGH) {
1381 Serial.println("PA_HIGH");
1382 }
1383 else if (paLevel == NRF_PA_LOW) {
1384 Serial.println("PA_LOW");
1385 }
1386 else if (paLevel == NRF_PA_MIN) {
1387 Serial.println("PA_MIN");
1388 }
1389 else {
1390 Serial.println("?");
1391 }
1392 Serial.print("ARC\t\t= ");
1393 Serial.println(arcCounter);
1394}
1395
1396/**********************************************************************************************************/
1397
1398#if defined CCM_ENCRYPTION_ENABLED
1399
1400 #if defined NRF54_CCM_ENCRYPTION
1401
1402// The nRF54L15 CCM takes the key and nonce in registers and the data through EasyDMA job lists.
1403// The core's Ccm class handles that and builds the same Bluetooth LE nonce (packet counter,
1404// direction bit, IV) as the nRF52 CCM, so frames are compatible with nRF52 nodes and RF24CCM.
1405// The result goes to outBuffer[CCM_START_SIZE] and its length to outBuffer[1], as on the nRF52.
1406
1407uint8_t nrf_to_nrf::encrypt(void* bufferIn, uint8_t size)
1408{
1409 if (!size || size > MAX_PACKET_SIZE) {
1410 return 0;
1411 }
1412 memset(outBuffer, 0, sizeof(outBuffer));
1413
1414 uint8_t length = 0;
1415 if (!nrf54Ccm.encryptBlePacket(ccmData.key, ccmData.iv, ccmData.counter, ccmData.direction, 0, static_cast<const uint8_t*>(bufferIn), size,
1416 &outBuffer[CCM_START_SIZE], &length, xiao_nrf54l15::CcmBleDataRate::k2Mbit)) {
1417 return 0;
1418 }
1419 outBuffer[1] = length;
1420 return length;
1421}
1422
1423/**********************************************************************************************************/
1424
1425uint8_t nrf_to_nrf::decrypt(void* bufferIn, uint8_t size)
1426{
1427 if (!size || size > MAX_PACKET_SIZE) {
1428 return 0;
1429 }
1430 memset(outBuffer, 0, sizeof(outBuffer));
1431
1432 // Decryption runs at the pace of the data rate, so use the fastest BLE rate
1433 uint8_t length = 0;
1434 bool macValid = false;
1435 if (!nrf54Ccm.decryptBlePacket(ccmData.key, ccmData.iv, ccmData.counter, ccmData.direction, 0, static_cast<const uint8_t*>(bufferIn), size,
1436 &outBuffer[CCM_START_SIZE], &length, &macValid, xiao_nrf54l15::CcmBleDataRate::k2Mbit)
1437 || !macValid) {
1438 return 0;
1439 }
1440 outBuffer[1] = length;
1441 return length;
1442}
1443
1444/**********************************************************************************************************/
1445
1446void nrf_to_nrf::setKey(uint8_t key[CCM_KEY_SIZE])
1447{
1448 nrf54Rng.begin();
1449 memcpy(ccmData.key, key, CCM_KEY_SIZE);
1450}
1451
1452/**********************************************************************************************************/
1453
1454 #else
1455
1456uint8_t nrf_to_nrf::encrypt(void* bufferIn, uint8_t size)
1457{
1458 NRF_CCM->MODE = 0 | 1 << 24 | 1 << 16;
1459
1460 if (!size) {
1461 return 0;
1462 }
1463 if (size > MAX_PACKET_SIZE) {
1464 return 0;
1465 }
1466
1467 inBuffer[0] = 0;
1468 inBuffer[1] = size;
1469 inBuffer[2] = 0;
1470
1471 memcpy(&inBuffer[CCM_START_SIZE], bufferIn, size);
1472 memset(outBuffer, 0, sizeof(outBuffer));
1473
1474 NRF_CCM->EVENTS_ENDKSGEN = 0;
1475 NRF_CCM->EVENTS_ENDCRYPT = 0;
1476 NRF_CCM->TASKS_KSGEN = 1;
1477 if (!waitForEvent(&NRF_CCM->EVENTS_ENDCRYPT))
1478 return 0;
1479
1480 if (NRF_CCM->EVENTS_ERROR) {
1481 return 0;
1482 }
1483 return outBuffer[1];
1484}
1485
1486/**********************************************************************************************************/
1487
1488uint8_t nrf_to_nrf::decrypt(void* bufferIn, uint8_t size)
1489{
1490 NRF_CCM->MODE = 1 | 1 << 24 | 1 << 16;
1491
1492 if (!size) {
1493 return 0;
1494 }
1495 if (size > MAX_PACKET_SIZE) {
1496 return 0;
1497 }
1498
1499 memcpy(&inBuffer[CCM_START_SIZE], bufferIn, size);
1500
1501 inBuffer[0] = 0;
1502 inBuffer[1] = size;
1503 inBuffer[2] = 0;
1504
1505 memset(outBuffer, 0, sizeof(outBuffer));
1506
1507 NRF_CCM->EVENTS_ENDKSGEN = 0;
1508 NRF_CCM->EVENTS_ENDCRYPT = 0;
1509 NRF_CCM->TASKS_KSGEN = 1;
1510
1511 if (!waitForEvent(&NRF_CCM->EVENTS_ENDCRYPT))
1512 return 0;
1513
1514 if (NRF_CCM->EVENTS_ERROR) {
1515 return 0;
1516 }
1517
1518 if (NRF_CCM->MICSTATUS == (CCM_MICSTATUS_MICSTATUS_CheckFailed << CCM_MICSTATUS_MICSTATUS_Pos)) {
1519 return 0;
1520 }
1521
1522 return outBuffer[1];
1523}
1524
1525/**********************************************************************************************************/
1526
1528{
1529
1530 NRF_CCM->MODE = 1 << 24 | 1 << 16;
1531#ifndef NRF52832_XXAA
1532 NRF_CCM->MAXPACKETSIZE = MAX_PACKET_SIZE > 251 ? 251 : MAX_PACKET_SIZE;
1533#endif
1534 NRF_CCM->SHORTS = 1;
1535 NRF_CCM->ENABLE = 2;
1536
1537 NRF_RNG->CONFIG = 1;
1538 NRF_RNG->TASKS_START = 1;
1539
1540 memcpy(ccmData.key, key, CCM_KEY_SIZE);
1541}
1542
1543 #endif // defined NRF54_CCM_ENCRYPTION
1544
1545/**********************************************************************************************************/
1546
1547void nrf_to_nrf::setCounter(uint64_t counter)
1548{
1549
1550 ccmData.counter = counter;
1551 packetCounter = counter;
1552}
1553/**********************************************************************************************************/
1554
1556{
1557
1558 for (int i = 0; i < CCM_IV_SIZE; i++) {
1559 ccmData.iv[i] = IV[i];
1560 }
1561}
1562
1563/**********************************************************************************************************/
1564
1565bool nrf_to_nrf::generateIV(uint8_t iv[CCM_IV_SIZE])
1566{
1567 #if defined NRF54_CCM_ENCRYPTION
1568 return nrf54Rng.fill(iv, CCM_IV_SIZE);
1569 #else
1570 for (int i = 0; i < CCM_IV_SIZE; i++) {
1571 if (!waitForEvent(&NRF_RNG->EVENTS_VALRDY, 100)) {
1572 return false;
1573 }
1574 NRF_RNG->EVENTS_VALRDY = 0;
1575 iv[i] = NRF_RNG->VALUE;
1576 }
1577 return true;
1578 #endif
1579}
1580
1581#endif // defined CCM_ENCRYPTION_ENABLED
void startListening(bool resetAddresses=true)
void openReadingPipe(uint8_t child, const uint8_t *address)
bool available()
void setPALevel(uint8_t level, bool lnaEnable=true)
bool testCarrier(uint8_t RSSI=65)
bool txStandBy()
uint8_t decrypt(void *bufferIn, uint8_t size)
uint8_t radioData[ACTUAL_MAX_PAYLOAD_SIZE+2]
Definition nrf_to_nrf.h:220
uint32_t addrConv32(uint32_t addr)
void disableDynamicPayloads()
bool write(void *buf, uint8_t len, bool multicast=false, bool doEncryption=true)
bool testRPD(uint8_t RSSI=65)
void setCounter(uint64_t counter)
bool isChipConnected()
void setAddressWidth(uint8_t a_width)
void setChannel(uint8_t channel, bool map=0)
uint8_t getDynamicPayloadSize()
bool setDataRate(uint8_t speed)
bool isValid()
void setKey(uint8_t key[CCM_KEY_SIZE])
bool writeAckPayload(uint8_t pipe, void *buf, uint8_t len)
bool enableEncryption
Definition nrf_to_nrf.h:528
void enableDynamicPayloads(uint8_t payloadSize=DEFAULT_MAX_PAYLOAD_SIZE)
void disableAckPayload()
void powerDown()
uint8_t getARC()
uint8_t flush_rx()
uint8_t encrypt(void *bufferIn, uint8_t size)
void printDetails()
uint8_t getChannel()
bool startWrite(void *buf, uint8_t len, bool multicast, bool doEncryption=true)
uint8_t getRSSI()
uint16_t interframeSpacing
Definition nrf_to_nrf.h:458
uint8_t outBuffer[MAX_PACKET_SIZE+CCM_MIC_SIZE+CCM_START_SIZE]
Definition nrf_to_nrf.h:495
void setRetries(uint8_t retryVar, uint8_t attempts)
void enableAckPayload()
void openWritingPipe(const uint8_t *address)
void setCRCLength(nrf_crclength_e length)
bool writeFast(void *buf, uint8_t len, bool multicast=0)
uint8_t getPALevel()
void setAutoAck(bool enable)
void read(void *buf, uint8_t len)
void stopListening(bool setWritingPipe=true, bool resetAddresses=true)
void setIV(uint8_t IV[CCM_IV_SIZE])
void setPayloadSize(uint8_t size)
nrf_crclength_e getCRCLength()
uint8_t getPayloadSize()
#define RADIO_MODE_MODE_Nrf_250Kbit
#define TXPOWER_PA_MIN
#define __REV(x)
#define TXPOWER_PA_MAX
#define TXPOWER_PA_HIGH
static bool waitForEvent(volatile uint32_t *event, uint32_t timeout=DEFAULT_TIMEOUT)
#define TXPOWER_PA_LOW
static uint32_t bytewise_bit_swap(uint8_t const *p_inp)
static uint32_t addr_conv(uint8_t const *p_addr)
#define DEFAULT_TIMEOUT
#define ACK_TIMEOUT_1MBPS_OFFSET
Definition nrf_to_nrf.h:25
#define DEFAULT_MAX_PAYLOAD_SIZE
Definition nrf_to_nrf.h:20
#define ACK_PAYLOAD_TIMEOUT_OFFSET
Definition nrf_to_nrf.h:28
@ NRF_PA_MAX
Definition nrf_to_nrf.h:67
@ NRF_PA_HIGH
Definition nrf_to_nrf.h:63
@ NRF_PA_LOW
Definition nrf_to_nrf.h:59
@ NRF_PA_MIN
Definition nrf_to_nrf.h:55
@ NRF_PA_ERROR
Definition nrf_to_nrf.h:71
#define CCM_COUNTER_SIZE
Definition nrf_to_nrf.h:44
#define ACK_TIMEOUT_250KBPS_OFFSET
Definition nrf_to_nrf.h:27
nrf_crclength_e
Definition nrf_to_nrf.h:112
@ NRF_CRC_8
Definition nrf_to_nrf.h:116
@ NRF_CRC_24
Definition nrf_to_nrf.h:120
@ NRF_CRC_DISABLED
Definition nrf_to_nrf.h:114
@ NRF_CRC_16
Definition nrf_to_nrf.h:118
#define ACK_TIMEOUT_250KBPS
Definition nrf_to_nrf.h:24
@ NRF_1MBPS
Definition nrf_to_nrf.h:86
@ NRF_2MBPS
Definition nrf_to_nrf.h:88
@ NRF_250KBPS
Definition nrf_to_nrf.h:90
#define ACK_TIMEOUT_2MBPS
Definition nrf_to_nrf.h:23
#define CCM_START_SIZE
Definition nrf_to_nrf.h:46
#define ACTUAL_MAX_PAYLOAD_SIZE
Definition nrf_to_nrf.h:21
#define MAX_PACKET_SIZE
Definition nrf_to_nrf.h:40
#define CCM_MIC_SIZE
Definition nrf_to_nrf.h:45
#define CCM_KEY_SIZE
Definition nrf_to_nrf.h:41
#define ACK_TIMEOUT_2MBPS_OFFSET
Definition nrf_to_nrf.h:26
#define ACK_TIMEOUT_1MBPS
Definition nrf_to_nrf.h:22
#define CCM_IV_SIZE
Definition nrf_to_nrf.h:42