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