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