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