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) {
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
748 NRF_RADIO->EVENTS_RXREADY = 0;
749 NRF_RADIO->EVENTS_CRCOK = 0;
750 NRF_RADIO->TASKS_RXEN = 1;
751 if (!waitForEvent(NRF_RADIO->EVENTS_RXREADY))
752 return;
753
754 NRF_RADIO->TASKS_START = 1;
755 inRxMode = true;
756}
757
758/**********************************************************************************************************/
759
760void nrf_to_nrf::stopListening(bool setWritingPipe, bool resetAddresses)
761{
762 NRF_RADIO->EVENTS_DISABLED = 0;
763 NRF_RADIO->TASKS_DISABLE = 1;
764 if (!waitForEvent(NRF_RADIO->EVENTS_DISABLED))
765 return;
766 NRF_RADIO->EVENTS_DISABLED = 0;
767
768 if (resetAddresses) {
769 NRF_RADIO->BASE0 = txBase;
770 NRF_RADIO->PREFIX0 = txPrefix;
771 }
772 if (setWritingPipe) {
773 NRF_RADIO->TXADDRESS = 0x00;
774 NRF_RADIO->TIFS = interframeSpacing;
775#ifndef ARDUINO_NRF54L15
776 NRF_RADIO->MODECNF0 = 0x200;
777#else
778 NRF_RADIO->TIMING = 0x0;
779#endif
780 }
781#ifndef ARDUINO_NRF54L15
782 NRF_RADIO->SHORTS = 0x6;
783#else
784 NRF_RADIO->SHORTS = 0x80004;
785#endif
786 if (NRF_RADIO->STATE < 9) {
787 NRF_RADIO->EVENTS_TXREADY = 0;
788 NRF_RADIO->TASKS_TXEN = 1;
789 if (!waitForEvent(NRF_RADIO->EVENTS_TXREADY))
790 return;
791 NRF_RADIO->EVENTS_TXREADY = 0;
792 }
793
794 inRxMode = false;
795}
796
797/**********************************************************************************************************/
798
799void nrf_to_nrf::stopListening(const uint8_t* txAddress, bool setWritingPipe, bool resetAddresses)
800{
801 stopListening(setWritingPipe, resetAddresses);
802 openWritingPipe(txAddress);
803}
804
805/**********************************************************************************************************/
806
808{
809 uint8_t size = min(staticPayloadSize, rxBuffer[0]);
810 return size;
811}
812
813/**********************************************************************************************************/
814
816{
817
818 uint32_t freq = NRF_RADIO->FREQUENCY;
819 NRF_RADIO->FREQUENCY = 0x4C;
820 if (NRF_RADIO->FREQUENCY == 0x4C) {
821 NRF_RADIO->FREQUENCY = freq;
822 return 1;
823 }
824 return 0;
825}
826
827/**********************************************************************************************************/
828
829void nrf_to_nrf::setChannel(uint8_t channel, bool map) { NRF_RADIO->FREQUENCY = channel | map << RADIO_FREQUENCY_MAP_Pos; }
830
831/**********************************************************************************************************/
832
833uint8_t nrf_to_nrf::getChannel() { return (uint8_t)NRF_RADIO->FREQUENCY; }
834
835/**********************************************************************************************************/
836
837void nrf_to_nrf::setAutoAck(bool enable)
838{
839
840 for (int i = 0; i < 8; i++) {
841 acksPerPipe[i] = enable;
842 }
843 if (!DPL) {
844 disableDynamicPayloads(); // Called to re-configure the PCNF0 register
845 }
846}
847
848/**********************************************************************************************************/
849
850void nrf_to_nrf::setAutoAck(uint8_t pipe, bool enable)
851{
852
853 acksPerPipe[pipe] = enable;
854 if (!DPL) {
855 disableDynamicPayloads(); // Called to re-configure the PCNF0 register
856 }
857}
858
859/**********************************************************************************************************/
860
861void nrf_to_nrf::enableDynamicPayloads(uint8_t payloadSize)
862{
863
864 if (!DPL) {
865 DPL = true;
866 staticPayloadSize = payloadSize;
867
868 if (payloadSize <= 63) {
869 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (6 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);
870 }
871 else {
872 // Using 8 bits for length
873 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (8 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos);
874 }
875
876 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_MAXLEN_Pos | 0xFF << RADIO_PCNF1_STATLEN_Pos);
877 NRF_RADIO->PCNF1 |= payloadSize << RADIO_PCNF1_MAXLEN_Pos;
878 }
879}
880
881/**********************************************************************************************************/
882
884{
885 DPL = false;
886
887 uint8_t lenConfig = 0;
888 if (acksEnabled(0)) {
889 lenConfig = 1;
890 }
891 NRF_RADIO->PCNF0 = (lenConfig << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (lenConfig << RADIO_PCNF0_S1LEN_Pos);
892
893 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_MAXLEN_Pos | 0xFF << RADIO_PCNF1_STATLEN_Pos);
894 NRF_RADIO->PCNF1 |= staticPayloadSize << RADIO_PCNF1_STATLEN_Pos | staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos;
895}
896
897/**********************************************************************************************************/
898
900{
901 staticPayloadSize = size;
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 return staticPayloadSize;
919}
920
921/**********************************************************************************************************/
922
923void nrf_to_nrf::setRetries(uint8_t retryVar, uint8_t attempts)
924{
925
926 retries = attempts;
927 retryDuration = retryVar;
928}
929
930/**********************************************************************************************************/
931
932void nrf_to_nrf::openReadingPipe(uint8_t child, uint64_t address)
933{
934 uint32_t base = addrConv32(address >> 8);
935 uint32_t prefix = addrConv32(address & 0xFF) >> 24;
936
937 openReadingPipe(child, base, prefix);
938}
939
940/**********************************************************************************************************/
941
942void nrf_to_nrf::openWritingPipe(uint64_t address)
943{
944 uint32_t base = addrConv32(address >> 8);
945 uint32_t prefix = addrConv32(address & 0xFF) >> 24;
946
947 openWritingPipe(base, prefix);
948}
949
950/**********************************************************************************************************/
951
952void nrf_to_nrf::openReadingPipe(uint8_t child, const uint8_t* address)
953{
954 uint32_t base = addr_conv(&address[1]);
955 uint32_t prefix = addr_conv(&address[0]) >> 24;
956
957 openReadingPipe(child, base, prefix);
958}
959
960/**********************************************************************************************************/
961
962void nrf_to_nrf::openReadingPipe(uint8_t child, uint32_t base, uint32_t prefix)
963{
964
965 // Using pipes 1-7 for reading pipes, leaving pipe0 for a tx pipe
966 if (!child) {
967 NRF_RADIO->PREFIX0 = rxPrefix;
968 NRF_RADIO->BASE0 = base;
969 NRF_RADIO->PREFIX0 &= ~(0xFF);
970 NRF_RADIO->PREFIX0 |= prefix;
971 rxBase = NRF_RADIO->BASE0;
972 rxPrefix = NRF_RADIO->PREFIX0;
973 }
974 else if (child < 4) { // prefixes AP1-3 are in prefix0
975 NRF_RADIO->PREFIX0 = rxPrefix;
976 NRF_RADIO->BASE1 = base;
977 NRF_RADIO->PREFIX0 &= ~(0xFF << (8 * child));
978 NRF_RADIO->PREFIX0 |= prefix << (8 * child);
979 rxPrefix = NRF_RADIO->PREFIX0;
980 }
981 else {
982 NRF_RADIO->BASE1 = base;
983 NRF_RADIO->PREFIX1 &= ~(0xFF << (8 * (child - 4)));
984 NRF_RADIO->PREFIX1 |= prefix << (8 * (child - 4));
985 }
986 NRF_RADIO->RXADDRESSES |= 1 << child;
987}
988
989/**********************************************************************************************************/
990
991void nrf_to_nrf::openWritingPipe(const uint8_t* address)
992{
993
994 uint32_t base = addr_conv(&address[1]);
995 uint32_t prefix = addr_conv(&address[0]) >> 24;
996
997 openWritingPipe(base, prefix);
998}
999
1000/**********************************************************************************************************/
1001
1002void nrf_to_nrf::openWritingPipe(uint32_t base, uint32_t prefix)
1003{
1004
1005 NRF_RADIO->BASE0 = base;
1006 NRF_RADIO->PREFIX0 &= ~(0xFF);
1007 NRF_RADIO->PREFIX0 |= prefix;
1008 NRF_RADIO->TXADDRESS = 0x00;
1009 txBase = NRF_RADIO->BASE0;
1010 txPrefix = NRF_RADIO->PREFIX0;
1011}
1012/**********************************************************************************************************/
1013
1015{
1016 return lastTxResult;
1017}
1018
1019/**********************************************************************************************************/
1020
1021bool nrf_to_nrf::txStandBy(uint32_t timeout, bool startTx)
1022{
1023 return lastTxResult;
1024}
1025
1026/**********************************************************************************************************/
1027
1028bool nrf_to_nrf::writeFast(void* buf, uint8_t len, bool multicast)
1029{
1030 lastTxResult = write(buf, len, multicast);
1031 return lastTxResult;
1032}
1033
1034/**********************************************************************************************************/
1035
1036bool nrf_to_nrf::acksEnabled(uint8_t pipe)
1037{
1038
1039 if (acksPerPipe[pipe]) {
1040 return 1;
1041 }
1042 return 0;
1043}
1044
1045/**********************************************************************************************************/
1046
1048
1049/**********************************************************************************************************/
1050
1051bool nrf_to_nrf::setDataRate(uint8_t speed)
1052{
1053
1054 if (speed == NRF_1MBPS) {
1055 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_1Mbit << RADIO_MODE_MODE_Pos);
1056 ackTimeout = ACK_TIMEOUT_1MBPS;
1057 }
1058 else if (speed == NRF_250KBPS) {
1059 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_250Kbit << RADIO_MODE_MODE_Pos);
1060 ackTimeout = ACK_TIMEOUT_250KBPS;
1061 }
1062 else if (speed == NRF_2MBPS) { // NRF_2MBPS
1063 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_2Mbit << RADIO_MODE_MODE_Pos);
1064 ackTimeout = ACK_TIMEOUT_2MBPS;
1065 }
1066#ifdef ARDUINO_NRF54L15
1067 else if (speed == NRF_4MBPS_OBT4) {
1068 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_4Mbit_OBT4 << RADIO_MODE_MODE_Pos);
1069 ackTimeout = ACK_TIMEOUT_2MBPS;
1070 }
1071 else {
1072 NRF_RADIO->MODE = (RADIO_MODE_MODE_Nrf_4Mbit_OBT6 << RADIO_MODE_MODE_Pos);
1073 ackTimeout = ACK_TIMEOUT_2MBPS;
1074 }
1075#endif
1076
1077 return 1;
1078}
1079
1080/**********************************************************************************************************/
1081
1082void nrf_to_nrf::setPALevel(uint8_t level, bool lnaEnable)
1083{
1084
1085 uint8_t paLevel = 0x00;
1086
1087 if (level == NRF_PA_MIN) {
1088 paLevel = TXPOWER_PA_MIN;
1089 }
1090 else if (level == NRF_PA_LOW) {
1091 paLevel = TXPOWER_PA_LOW;
1092 }
1093 else if (level == NRF_PA_HIGH) {
1094 paLevel = TXPOWER_PA_HIGH;
1095 }
1096 else if (level == NRF_PA_MAX) {
1097 paLevel = TXPOWER_PA_MAX;
1098 }
1099 NRF_RADIO->TXPOWER = paLevel;
1100}
1101
1102/**********************************************************************************************************/
1103
1105{
1106
1107 uint8_t paLevel = NRF_RADIO->TXPOWER;
1108
1109 if (paLevel == TXPOWER_PA_MIN) {
1110 return NRF_PA_MIN;
1111 }
1112 else if (paLevel == TXPOWER_PA_LOW) {
1113 return NRF_PA_LOW;
1114 }
1115 else if (paLevel == TXPOWER_PA_HIGH) {
1116 return NRF_PA_HIGH;
1117 }
1118 else if (paLevel == TXPOWER_PA_MAX) {
1119 return NRF_PA_MAX;
1120 }
1121 else {
1122 return NRF_PA_ERROR;
1123 }
1124}
1125
1126/**********************************************************************************************************/
1127
1129{
1130 return arcCounter;
1131}
1132
1133/**********************************************************************************************************/
1134
1136{
1137 if (length == NRF_CRC_24) {
1138 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Three; /* CRC configuration: 24bit */
1139 NRF_RADIO->CRCINIT = 0x555555UL; // Initial value
1140 NRF_RADIO->CRCPOLY = 0x65BUL;
1141 }
1142 else if (length == NRF_CRC_16) {
1143 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_Two; /* CRC configuration: 16bit */
1144 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
1145 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
1146 }
1147 else if (length == NRF_CRC_8) {
1148 NRF_RADIO->CRCCNF = RADIO_CRCCNF_LEN_One; /* CRC configuration: 8bit */
1149 NRF_RADIO->CRCINIT = 0xFFUL;
1150 NRF_RADIO->CRCPOLY = 0x107UL;
1151 }
1152 else {
1153 NRF_RADIO->CRCCNF = 0; /* CRC configuration: Disabled */
1154 NRF_RADIO->CRCINIT = 0x00L;
1155 NRF_RADIO->CRCPOLY = 0x00UL;
1156 }
1157}
1158
1159/**********************************************************************************************************/
1160
1162{
1163 if (NRF_RADIO->CRCCNF == 0) {
1164 return NRF_CRC_DISABLED;
1165 }
1166 else if (NRF_RADIO->CRCCNF == RADIO_CRCCNF_LEN_One) {
1167 return NRF_CRC_8;
1168 }
1169 if (NRF_RADIO->CRCCNF == RADIO_CRCCNF_LEN_Two) {
1170 return NRF_CRC_16;
1171 }
1172 else {
1173 return NRF_CRC_24;
1174 }
1175}
1176
1177/**********************************************************************************************************/
1178
1179bool nrf_to_nrf::testCarrier(uint8_t RSSI)
1180{
1181#ifndef ARDUINO_NRF54L15
1182 NRF_RADIO->EVENTS_RSSIEND = 0;
1183 NRF_RADIO->TASKS_RSSISTART = 1;
1184 if (!waitForEvent(NRF_RADIO->EVENTS_RSSIEND))
1185 return false;
1186
1187 if (NRF_RADIO->RSSISAMPLE < RSSI) {
1188 return 1;
1189 }
1190#endif
1191 return 0;
1192}
1193
1194/**********************************************************************************************************/
1195
1196bool nrf_to_nrf::testRPD(uint8_t RSSI)
1197{
1198 return testCarrier(RSSI);
1199}
1200
1201/**********************************************************************************************************/
1202
1204{
1205#ifndef ARDUINO_NRF54L15
1206 NRF_RADIO->EVENTS_RSSIEND = 0;
1207 NRF_RADIO->TASKS_RSSISTART = 1;
1208 if (!waitForEvent(NRF_RADIO->EVENTS_RSSIEND))
1209 return 0;
1210
1211 return (uint8_t)NRF_RADIO->RSSISAMPLE;
1212#endif
1213 return 0;
1214}
1215
1216/**********************************************************************************************************/
1217
1219{
1220 return 0;
1221}
1222
1223/**********************************************************************************************************/
1224
1226{
1227#ifndef ARDUINO_NRF54L15
1228 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
1229 NRF_CLOCK->TASKS_HFCLKSTART = 1;
1230
1231 /* Wait for the external oscillator to start up */
1232 waitForEvent(NRF_CLOCK->EVENTS_HFCLKSTARTED);
1233
1234 NRF_RADIO->POWER = 1;
1235#else
1236 NRF_POWER->TASKS_CONSTLAT = 1;
1237 NRF_CLOCK->EVENTS_XOSTARTED = 0;
1238 NRF_CLOCK->TASKS_XOSTART = 1;
1239
1240 waitForEvent(NRF_CLOCK->EVENTS_XOSTARTED);
1241#endif
1242
1243#ifdef CCM_ENCRYPTION_ENABLED
1244 if (enableEncryption) {
1245 NRF_RNG->CONFIG = 1;
1246 NRF_RNG->TASKS_START = 1;
1247 NRF_CCM->ENABLE = 2;
1248 }
1249#endif
1250}
1251
1252/**********************************************************************************************************/
1253
1255{
1256#ifndef ARDUINO_NRF54L15
1257 NRF_RADIO->POWER = 0;
1258 NRF_CLOCK->TASKS_HFCLKSTOP = 1;
1259#else
1260 NRF_CLOCK->TASKS_XOSTOP = 1;
1261#endif
1262
1263#ifdef CCM_ENCRYPTION_ENABLED
1264 if (enableEncryption) {
1265 NRF_RNG->TASKS_STOP = 1;
1266 NRF_RNG->CONFIG = 0;
1267 NRF_CCM->ENABLE = 0;
1268 }
1269#endif
1270}
1271
1272/**********************************************************************************************************/
1273void nrf_to_nrf::setAddressWidth(uint8_t a_width)
1274{
1275 NRF_RADIO->PCNF1 &= ~(0xFF << RADIO_PCNF1_BALEN_Pos);
1276 NRF_RADIO->PCNF1 |= (a_width - 1) << RADIO_PCNF1_BALEN_Pos;
1277}
1278
1279/**********************************************************************************************************/
1280
1282{
1283 uint8_t addressWidth = ((NRF_RADIO->PCNF1 >> 16) & 0xFF) + 1;
1284
1285 Serial.println("================ Radio Configuration ================");
1286 Serial.print("STATUS\t\t= ");
1287 Serial.println(NRF_RADIO->STATE);
1288
1289 // Serial.println(addrConv32(NRF_RADIO->PREFIX0);
1290 Serial.print("RX_ADDR_P0-1\t= 0x");
1291 uint32_t base = addrConv32(NRF_RADIO->BASE0);
1292 for (int i = addressWidth - 2; i > -1; i--) {
1293 Serial.print((base >> (i * 8)) & 0xFF, HEX);
1294 }
1295 uint32_t prefixes = addrConv32(NRF_RADIO->PREFIX0);
1296 uint8_t prefix = (prefixes >> 24) & 0xFF;
1297 Serial.print(prefix, HEX);
1298 Serial.print(" 0x");
1299 base = addrConv32(NRF_RADIO->BASE1);
1300 for (int i = addressWidth - 2; i > -1; i--) {
1301 Serial.print((base >> (i * 8)) & 0xFF, HEX);
1302 }
1303 prefix = (prefixes >> 16) & 0xFF;
1304 Serial.println(prefix, HEX);
1305
1306 Serial.print("RX_ADDR_P2-7\t= 0x");
1307 prefix = (prefixes >> 8) & 0xFF;
1308 Serial.print(prefix, HEX);
1309 Serial.print(" 0x");
1310 prefix = (prefixes) & 0xFF;
1311 Serial.print(prefix, HEX);
1312 Serial.print(" 0x");
1313 prefixes = addrConv32(NRF_RADIO->PREFIX1);
1314 prefix = (prefixes >> 24) & 0xFF;
1315 Serial.print(prefix, HEX);
1316 Serial.print(" 0x");
1317 prefix = (prefixes >> 16) & 0xFF;
1318 Serial.print(prefix, HEX);
1319 Serial.print(" 0x");
1320 prefix = (prefixes >> 8) & 0xFF;
1321 Serial.print(prefix, HEX);
1322 Serial.print(" 0x");
1323 prefix = (prefixes) & 0xFF;
1324 Serial.println(prefix, HEX);
1325
1326 uint8_t enAA = 0;
1327 for (int i = 0; i < 6; i++) {
1328 enAA |= acksPerPipe[i] << i;
1329 }
1330 Serial.print("EN_AA\t\t= 0x");
1331 Serial.println(enAA, HEX);
1332 Serial.print("EN_RXADDR\t= 0x");
1333 Serial.println(NRF_RADIO->RXADDRESSES, HEX);
1334 Serial.print("RF_CH\t\t= 0x");
1335 Serial.println(NRF_RADIO->FREQUENCY, HEX);
1336 Serial.println("DYNPD/FEATURE\t= 0x");
1337 Serial.print("Data Rate\t= ");
1338 Serial.println(NRF_RADIO->MODE ? "2 MBPS" : "1MBPS");
1339 Serial.println("Model\t\t= NRF52");
1340 Serial.print("CRC Length\t= ");
1341 uint8_t crcLen = getCRCLength();
1342 if (crcLen == NRF_CRC_16) {
1343 Serial.println("16 bits");
1344 }
1345 else if (crcLen == NRF_CRC_8) {
1346 Serial.println("8 bits");
1347 }
1348 else {
1349 Serial.println("Disabled");
1350 }
1351 Serial.print("PA Power\t= ");
1352 uint8_t paLevel = getPALevel();
1353 if (paLevel == NRF_PA_MAX) {
1354 Serial.println("PA_MAX");
1355 }
1356 else if (paLevel == NRF_PA_HIGH) {
1357 Serial.println("PA_HIGH");
1358 }
1359 else if (paLevel == NRF_PA_LOW) {
1360 Serial.println("PA_LOW");
1361 }
1362 else if (paLevel == NRF_PA_MIN) {
1363 Serial.println("PA_MIN");
1364 }
1365 else {
1366 Serial.println("?");
1367 }
1368 Serial.print("ARC\t\t= ");
1369 Serial.println(arcCounter);
1370}
1371
1372/**********************************************************************************************************/
1373
1374#if defined CCM_ENCRYPTION_ENABLED
1375
1376uint8_t nrf_to_nrf::encrypt(void* bufferIn, uint8_t size)
1377{
1378 NRF_CCM->MODE = 0 | 1 << 24 | 1 << 16;
1379
1380 if (!size) {
1381 return 0;
1382 }
1383 if (size > MAX_PACKET_SIZE) {
1384 return 0;
1385 }
1386
1387 inBuffer[0] = 0;
1388 inBuffer[1] = size;
1389 inBuffer[2] = 0;
1390
1391 memcpy(&inBuffer[CCM_START_SIZE], bufferIn, size);
1392 memset(outBuffer, 0, sizeof(outBuffer));
1393
1394 NRF_CCM->EVENTS_ENDKSGEN = 0;
1395 NRF_CCM->EVENTS_ENDCRYPT = 0;
1396 NRF_CCM->TASKS_KSGEN = 1;
1397 if (!waitForEvent(NRF_CCM->EVENTS_ENDCRYPT))
1398 return 0;
1399
1400 if (NRF_CCM->EVENTS_ERROR) {
1401 return 0;
1402 }
1403 return outBuffer[1];
1404}
1405
1406/**********************************************************************************************************/
1407
1408uint8_t nrf_to_nrf::decrypt(void* bufferIn, uint8_t size)
1409{
1410 NRF_CCM->MODE = 1 | 1 << 24 | 1 << 16;
1411
1412 if (!size) {
1413 return 0;
1414 }
1415 if (size > MAX_PACKET_SIZE) {
1416 return 0;
1417 }
1418
1419 memcpy(&inBuffer[CCM_START_SIZE], bufferIn, size);
1420
1421 inBuffer[0] = 0;
1422 inBuffer[1] = size;
1423 inBuffer[2] = 0;
1424
1425 memset(outBuffer, 0, sizeof(outBuffer));
1426
1427 NRF_CCM->EVENTS_ENDKSGEN = 0;
1428 NRF_CCM->EVENTS_ENDCRYPT = 0;
1429 NRF_CCM->TASKS_KSGEN = 1;
1430
1431 if (!waitForEvent(NRF_CCM->EVENTS_ENDCRYPT))
1432 return 0;
1433
1434 if (NRF_CCM->EVENTS_ERROR) {
1435 return 0;
1436 }
1437
1438 if (NRF_CCM->MICSTATUS == (CCM_MICSTATUS_MICSTATUS_CheckFailed << CCM_MICSTATUS_MICSTATUS_Pos)) {
1439 return 0;
1440 }
1441
1442 return outBuffer[1];
1443}
1444
1445/**********************************************************************************************************/
1446
1448{
1449
1450 NRF_CCM->MODE = 1 << 24 | 1 << 16;
1451 NRF_CCM->MAXPACKETSIZE = MAX_PACKET_SIZE;
1452 NRF_CCM->SHORTS = 1;
1453 NRF_CCM->ENABLE = 2;
1454
1455 NRF_RNG->CONFIG = 1;
1456 NRF_RNG->TASKS_START = 1;
1457
1458 memcpy(ccmData.key, key, CCM_KEY_SIZE);
1459}
1460
1461/**********************************************************************************************************/
1462
1463void nrf_to_nrf::setCounter(uint64_t counter)
1464{
1465
1466 ccmData.counter = counter;
1467 packetCounter = counter;
1468}
1469/**********************************************************************************************************/
1470
1472{
1473
1474 for (int i = 0; i < CCM_IV_SIZE; i++) {
1475 ccmData.iv[i] = IV[i];
1476 }
1477}
1478
1479#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
#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
static bool waitForEvent(volatile uint32_t &event, uint32_t timeout=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