1 /*
2 * Copyright (C) 2021 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "radio_nrf5.c"
39
40 #include "radio.h"
41 #include "btstack_debug.h"
42 #include <inttypes.h>
43 #include "nrf.h"
44 #include "nrf52.h"
45 #include "nrf_gpio.h"
46 #include "nrf_gpiote.h"
47
48 #define MAXLEN 37
49
50 static enum {
51 RADIO_OFF,
52 RADIO_DISABLED,
53 RADIO_W2_TX,
54 RADIO_W4_TX_DONE,
55 RADIO_W4_TX_TO_RX,
56 RADIO_W2_RX,
57 RADIO_W4_RX_DONE,
58 RADIO_W4_RX_TIMEOUT,
59 RADIO_W4_DISABLED,
60 } volatile radio_state;
61
62 static radio_callback_t radio_callback;
63 static int8_t * rssi_buffer;
64
65 // channel table: freq in hertz and whitening seed
66 static const struct {
67 uint8_t freq_index;
68 uint8_t whitening;
69 } channel_table[] = {
70 { 4, 0x01 /* 00000001 */ },
71 { 6, 0x41 /* 01000001 */ },
72 { 8, 0x21 /* 00100001 */ },
73 { 10, 0x61 /* 01100001 */ },
74 { 12, 0x11 /* 00010001 */ },
75 { 14, 0x51 /* 01010001 */ },
76 { 16, 0x31 /* 00110001 */ },
77 { 18, 0x71 /* 01110001 */ },
78 { 20, 0x09 /* 00001001 */ },
79 { 22, 0x49 /* 01001001 */ },
80 { 24, 0x29 /* 00101001 */ },
81 { 28, 0x69 /* 01101001 */ },
82 { 30, 0x19 /* 00011001 */ },
83 { 32, 0x59 /* 01011001 */ },
84 { 34, 0x39 /* 00111001 */ },
85 { 36, 0x79 /* 01111001 */ },
86 { 38, 0x05 /* 00000101 */ },
87 { 40, 0x45 /* 01000101 */ },
88 { 42, 0x25 /* 00100101 */ },
89 { 44, 0x65 /* 01100101 */ },
90 { 46, 0x15 /* 00010101 */ },
91 { 48, 0x55 /* 01010101 */ },
92 { 50, 0x35 /* 00110101 */ },
93 { 52, 0x75 /* 01110101 */ },
94 { 54, 0x0d /* 00001101 */ },
95 { 56, 0x4d /* 01001101 */ },
96 { 58, 0x2d /* 00101101 */ },
97 { 60, 0x6d /* 01101101 */ },
98 { 62, 0x1d /* 00011101 */ },
99 { 64, 0x5d /* 01011101 */ },
100 { 66, 0x3d /* 00111101 */ },
101 { 68, 0x7d /* 01111101 */ },
102 { 70, 0x03 /* 00000011 */ },
103 { 72, 0x43 /* 01000011 */ },
104 { 74, 0x23 /* 00100011 */ },
105 { 76, 0x63 /* 01100011 */ },
106 { 78, 0x13 /* 00010011 */ },
107 { 2, 0x53 /* 01010011 */ },
108 { 26, 0x33 /* 00110011 */ },
109 { 80, 0x73 /* 01110011 */ },
110 };
111
radio_init(void)112 void radio_init(void){
113
114 radio_state = RADIO_OFF;
115
116 /* TIMER0 setup */
117 NRF_TIMER0->TASKS_STOP = 1;
118 NRF_TIMER0->TASKS_SHUTDOWN = 1;
119 NRF_TIMER0->BITMODE = 3; /* 32-bit timer */
120 NRF_TIMER0->MODE = 0; /* Timer mode */
121 NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */
122
123 // PPI setup
124 // Channel 0: RADIO END -> TIMER0 Start
125 NRF_PPI->CH[0].EEP = (uint32_t)&(NRF_RADIO->EVENTS_END);
126 NRF_PPI->CH[0].TEP = (uint32_t)&(NRF_TIMER0->TASKS_START);
127 // Channel 1: RADIO ADDRESS -> TIMER0 Stop
128 NRF_PPI->CH[1].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
129 NRF_PPI->CH[1].TEP = (uint32_t)&(NRF_TIMER0->TASKS_STOP);
130
131 #ifdef NRF51
132 // Handle BLE Radio tuning parameters from production if required.
133 // Does not exist on NRF52
134 // See PCN-083.
135 if (NRF_FICR->OVERRIDEEN & FICR_OVERRIDEEN_BLE_1MBIT_Msk){
136 NRF_RADIO->OVERRIDE0 = NRF_FICR->BLE_1MBIT[0];
137 NRF_RADIO->OVERRIDE1 = NRF_FICR->BLE_1MBIT[1];
138 NRF_RADIO->OVERRIDE2 = NRF_FICR->BLE_1MBIT[2];
139 NRF_RADIO->OVERRIDE3 = NRF_FICR->BLE_1MBIT[3];
140 NRF_RADIO->OVERRIDE4 = NRF_FICR->BLE_1MBIT[4] | 0x80000000;
141 }
142 #endif // NRF51
143
144 // Mode: BLE 1 Mbps
145 NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos;
146
147 // PacketConfig 0:
148 // ---
149 // LENGTH field in bits = 8
150 // S0 field in bytes = 1
151 // S1 field not used
152 // 8 bit preamble
153 NRF_RADIO->PCNF0 =
154 ( 8 << RADIO_PCNF0_LFLEN_Pos ) |
155 ( 1 << RADIO_PCNF0_S0LEN_Pos ) |
156 ( 0 << RADIO_PCNF0_S1LEN_Pos );
157
158 // PacketConfig 1:
159 // ---
160 // Payload MAXLEN = MAXLEN
161 // No additional bytes
162 // 4 address bytes (1 + 3)
163 // S0, LENGTH, S1, PAYLOAD in little endian
164 // Packet whitening enabled
165 NRF_RADIO->PCNF1 =
166 ( MAXLEN << RADIO_PCNF1_MAXLEN_Pos) |
167 ( 0 << RADIO_PCNF1_STATLEN_Pos ) |
168 ( 3 << RADIO_PCNF1_BALEN_Pos ) |
169 ( RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos ) |
170 ( RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos );
171
172 // Use logical address 0 for sending and receiving
173 NRF_RADIO->TXADDRESS = 0;
174 NRF_RADIO->RXADDRESSES = 1 << 0;
175
176 // 24 bit CRC, skip address field
177 NRF_RADIO->CRCCNF =
178 ( RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos ) |
179 ( RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos );
180
181 // The polynomial has the form of x^24 +x^10 +x^9 +x^6 +x^4 +x^3 +x+1
182 NRF_RADIO->CRCPOLY = 0x100065B;
183
184 // Inter frame spacing 150 us
185 NRF_RADIO->TIFS = 150;
186
187 // Transmit with max power
188 NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_Pos4dBm << RADIO_TXPOWER_TXPOWER_Pos);
189
190 // Disable all interrupts
191 NRF_RADIO->INTENCLR = 0xffffffff;
192
193 // enable Radio IRQs
194 NVIC_SetPriority( RADIO_IRQn, 0 );
195 NVIC_ClearPendingIRQ( RADIO_IRQn );
196 NVIC_EnableIRQ( RADIO_IRQn );
197
198 #ifdef DEBUG_PIN_HF_CLOCK
199 // debug pins
200 nrf_gpio_cfg_output(DEBUG_PIN_HF_CLOCK);
201 nrf_gpio_cfg_output(DEBUG_PIN_ADDRESS);
202 nrf_gpio_cfg_output(DEBUG_PIN_RX);
203 nrf_gpio_cfg_output(DEBUG_PIN_TX);
204 nrf_gpio_cfg_output(DEBUG_PIN_RADIO_IRQ);
205 // toggle DEBUG_PIN_ADDRESS on RADIO ADDRESS event. Use PPI Channel 19 and GPIOT[0]
206 // NOTE: unclear how pin could be cleared after set on address.
207 nrf_gpiote_task_configure(0, DEBUG_PIN_ADDRESS, GPIOTE_CONFIG_POLARITY_Toggle, NRF_GPIOTE_INITIAL_VALUE_LOW);
208 nrf_gpiote_task_enable(0);
209 NRF_PPI->CH[19].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
210 NRF_PPI->CH[19].TEP = nrf_gpiote_task_addr_get(0);
211 NRF_PPI->CHENSET = PPI_CHEN_CH19_Msk;
212 #endif
213 }
214
215 // Enable the High Frequency clock on the processor.
radio_hf_clock_enable_reset(radio_result_t result)216 static void radio_hf_clock_enable_reset(radio_result_t result){
217 UNUSED(result);
218 }
radio_hf_clock_enable(bool wait_until_ready)219 void radio_hf_clock_enable(bool wait_until_ready){
220
221 // Work around for incomplete RX
222 if (radio_state == RADIO_W4_RX_DONE){
223 #ifdef DEBUG_PIN_HF_CLOCK
224 nrf_gpio_pin_clear(DEBUG_PIN_HF_CLOCK);
225 nrf_gpio_pin_set(DEBUG_PIN_HF_CLOCK);
226 #endif
227 #if 0
228 // state = RX, PAYLOAD = 1, END = 0, DISABLED = 0
229 printf("Enable: STATE %u\n", (int) NRF_RADIO->STATE);
230 printf("Enable: PAYLOAD %u\n", (int) NRF_RADIO->EVENTS_PAYLOAD);
231 printf("Enable: END %u\n", (int) NRF_RADIO->EVENTS_END);
232 printf("Enable: DISABLED %u\n", (int) NRF_RADIO->EVENTS_DISABLED);
233 btstack_assert(false);
234 #else
235 printf("\n\nRADIO_W4_RX_DONE hang\n\n\n");
236 radio_stop(&radio_hf_clock_enable_reset);
237 radio_state = RADIO_DISABLED;
238 return;
239 #endif
240 }
241
242 #ifdef DEBUG_PIN_HF_CLOCK
243 nrf_gpio_pin_set(DEBUG_PIN_HF_CLOCK);
244 #endif
245
246
247 // the RADIO module. Without this clock, no communication is possible.
248 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
249 NRF_CLOCK->TASKS_HFCLKSTART = 1;
250 if (wait_until_ready){
251 while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
252 }
253
254 radio_state = RADIO_DISABLED;
255 }
256
radio_hf_clock_disable(void)257 void radio_hf_clock_disable(void) {
258 #ifdef DEBUG_PIN_HF_CLOCK
259 nrf_gpio_pin_clear(DEBUG_PIN_HF_CLOCK);
260 #endif
261
262 NRF_CLOCK->TASKS_HFCLKSTOP = 1;
263 radio_state = RADIO_OFF;
264 }
265
radio_set_access_address(uint32_t access_address)266 void radio_set_access_address(uint32_t access_address) {
267 NRF_RADIO->BASE0 = ( access_address << 8 ) & 0xFFFFFF00;
268 NRF_RADIO->PREFIX0 = ( access_address >> 24 ) & RADIO_PREFIX0_AP0_Msk;
269 }
270
radio_set_crc_init(uint32_t crc_init)271 void radio_set_crc_init(uint32_t crc_init){
272 NRF_RADIO->CRCINIT = crc_init;
273 }
274
radio_set_channel(uint8_t channel)275 void radio_set_channel(uint8_t channel){
276 // set frequency based on channel
277 NRF_RADIO->FREQUENCY = channel_table[channel].freq_index;
278
279 // initializes data whitening with channel index
280 NRF_RADIO->DATAWHITEIV = channel & 0x3F;
281 }
282
radio_transmit(radio_callback_t callback,radio_transition_t transition,const uint8_t * packet,uint16_t len)283 void radio_transmit(radio_callback_t callback, radio_transition_t transition, const uint8_t * packet, uint16_t len){
284
285 #ifdef DEBUG_PIN_TX
286 nrf_gpio_pin_set(DEBUG_PIN_TX);
287 #endif
288
289 uint16_t state = (uint16_t) NRF_RADIO->STATE;
290
291 switch (radio_state){
292 case RADIO_W2_TX:
293 // already in transition to tx
294 if (state != RADIO_STATE_STATE_TxRu){
295 log_info("TX Start after RX, transition %u, state 0x%04x", (int) transition, state);
296 btstack_assert(false);
297 }
298 break;
299 case RADIO_DISABLED:
300 if (state != RADIO_STATE_STATE_Disabled){
301 log_info("TX Start after Disabled, transition %u, state 0x%04x", (int) transition, state);
302 btstack_assert(false);
303 }
304 // start tx
305 NRF_RADIO->TASKS_TXEN = 1;
306 break;
307 default:
308 log_info("TX Start unexpected state: our state %u, transition %u, state 0x%04x", radio_state, (int) transition, state);
309 btstack_assert(false);
310 break;
311 }
312
313 radio_callback = callback;
314
315 // set data to send (assume it's valid until tx done)
316 NRF_RADIO->PACKETPTR = (uint32_t) packet;
317
318 switch (transition){
319 case RADIO_TRANSITION_TX_ONLY:
320 radio_state = RADIO_W4_TX_DONE;
321 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk;
322 break;
323 case RADIO_TRANSITION_TX_TO_RX:
324 radio_state = RADIO_W4_TX_TO_RX;
325 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_RXEN_Msk;
326 // - Clear Timer0
327 NRF_TIMER0->TASKS_CLEAR = 1;
328 // - Set CC for receive (ca. 300 us)
329 NRF_TIMER0->CC[1] = 300; // 300 us
330 NRF_TIMER0->EVENTS_COMPARE[1] = 0;
331 // - END -> Start Timer0
332 NRF_PPI->CHENSET = PPI_CHEN_CH0_Msk;
333 // - Timer0 CC[1] -> Radio END
334 NRF_PPI->CHENSET = PPI_CHEN_CH22_Msk;
335 // - Disable address->stop
336 NRF_PPI->CHENCLR = PPI_CHEN_CH1_Msk;
337 break;
338 default:
339 btstack_assert(false);
340 break;
341 }
342
343 NRF_RADIO->INTENCLR = 0xffffffff;
344 NRF_RADIO->EVENTS_END = 0;
345 NRF_RADIO->EVENTS_DISABLED = 0;
346
347 NVIC_ClearPendingIRQ(RADIO_IRQn);
348 NVIC_EnableIRQ(RADIO_IRQn);
349
350 // Interrupt on DISABLED
351 NRF_RADIO->INTENSET = 0x00000010;
352 }
353
radio_setup_rx(void)354 static void radio_setup_rx(void){
355 NRF_RADIO->EVENTS_ADDRESS = 0;
356 NRF_RADIO->EVENTS_END = 0;
357 NRF_RADIO->EVENTS_DISABLED = 0;
358 // PPI0: END -> Start Timer0
359 NRF_PPI->CHENCLR = PPI_CHEN_CH0_Msk;
360 // PPI1: Radio Address -> Stop Timer
361 NRF_PPI->CHENSET = PPI_CHEN_CH1_Msk;
362 // Update Shortcuts
363 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk;
364 }
365
radio_receive(radio_callback_t callback,uint32_t timeout_us,uint8_t * buffer,uint16_t len,int8_t * rssi)366 void radio_receive(radio_callback_t callback, uint32_t timeout_us, uint8_t * buffer, uint16_t len, int8_t * rssi){
367
368 #ifdef DEBUG_PIN_RX
369 nrf_gpio_pin_set(DEBUG_PIN_RX);
370 #endif
371
372 uint16_t state = (uint16_t) NRF_RADIO->STATE;
373
374 // log_info("RX Start: our state = 0x%0x, radio_state 0x%04x", radio_state, state);
375
376 radio_callback = callback;
377 rssi_buffer = rssi;
378
379 NRF_RADIO->PACKETPTR = (uint32_t) buffer;
380 buffer[0] = 0;
381 buffer[1] = 0;
382
383 switch (radio_state){
384 case RADIO_W2_RX:
385 // radio setup as part of TX->RX transition
386 switch (state){
387 case RADIO_STATE_STATE_RxRu:
388 case RADIO_STATE_STATE_RxIdle:
389 case RADIO_STATE_STATE_Rx:
390 break;
391 default:
392 btstack_assert(false);
393 break;
394 }
395 break;
396 case RADIO_DISABLED:
397 btstack_assert(state == RADIO_STATE_STATE_Disabled);
398 // - Stop Timer0
399 NRF_TIMER0->TASKS_STOP = 1;
400 // - Clear Timer0
401 NRF_TIMER0->TASKS_CLEAR = 1;
402 // - Set CC for receive
403 NRF_TIMER0->CC[1] = timeout_us;
404 NRF_TIMER0->EVENTS_COMPARE[1] = 0;
405 // - Timer0 CC[1] -> Radio Disable
406 NRF_PPI->CHENSET = PPI_CHEN_CH22_Msk;
407 // - Start Timer0
408 NRF_TIMER0->TASKS_START = 1;
409 // Start Receive
410 radio_setup_rx();
411 NRF_RADIO->TASKS_RXEN = 1;
412 break;
413 default:
414 log_info("RX unexpected radio_state: state 0x%04x / phy state state 0x%04x", radio_state, state);
415 log_info("cc[1] %" PRIu32 "events_compare[1] %u", NRF_TIMER0->CC[1], (int) NRF_TIMER0->EVENTS_COMPARE[1]);
416 btstack_assert(false);
417 break;
418 }
419
420 // Disable all interrupts
421 NRF_RADIO->INTENCLR = 0xffffffff;
422
423 NVIC_ClearPendingIRQ(RADIO_IRQn);
424 NVIC_EnableIRQ(RADIO_IRQn);
425
426 // Interrupt on DISABLED
427 NRF_RADIO->INTENSET = 0x00000010;
428
429 radio_state = RADIO_W4_RX_DONE;
430 }
431
radio_stop(radio_callback_t callback)432 void radio_stop(radio_callback_t callback){
433
434 // log_info("Disable, state 0x%04x", (uint16_t) NRF_RADIO->STATE);
435
436 radio_callback = callback;
437
438 NRF_RADIO->SHORTS = 0;
439
440 uint16_t state = (uint16_t) NRF_RADIO->STATE;
441 switch (state){
442 case RADIO_STATE_STATE_Disabled:
443 (*callback)(RADIO_RESULT_OK);
444 break;
445 default:
446 radio_state = RADIO_W4_DISABLED;
447 NRF_RADIO->TASKS_DISABLE = 1;
448 break;
449 }
450 }
451
RADIO_IRQHandler(void)452 void RADIO_IRQHandler(void){
453 uint16_t state = (uint16_t) NRF_RADIO->STATE;
454
455 #ifdef DEBUG_PIN_RADIO_IRQ
456 nrf_gpio_pin_toggle(DEBUG_PIN_RADIO_IRQ);
457 #endif
458 #ifdef DEBUG_PIN_RX
459 nrf_gpio_pin_clear(DEBUG_PIN_RX);
460 #endif
461 #ifdef DEBUG_PIN_TX
462 nrf_gpio_pin_clear(DEBUG_PIN_TX);
463 #endif
464
465 switch (radio_state){
466 case RADIO_W4_TX_DONE:
467 // TX Done, no transition to rx requested
468 btstack_assert(state == RADIO_STATE_STATE_Disabled);
469 NRF_RADIO->EVENTS_DISABLED = 0;
470 radio_state = RADIO_DISABLED;
471 (*radio_callback)(RADIO_RESULT_OK);
472 break;
473 case RADIO_W4_TX_TO_RX:
474 // TX Done, transition to rx
475 btstack_assert(state == RADIO_STATE_STATE_RxRu);
476 NRF_RADIO->EVENTS_DISABLED = 0;
477 radio_state = RADIO_W2_RX;
478 radio_setup_rx();
479 (*radio_callback)(RADIO_RESULT_OK);
480 break;
481 case RADIO_W4_RX_DONE:
482 // RX Done
483 btstack_assert(state == RADIO_STATE_STATE_TxRu);
484 NRF_RADIO->EVENTS_DISABLED = 0;
485 NRF_TIMER0->TASKS_STOP = 1;
486 // check EVENTS_COMPARE[1]
487 if (NRF_TIMER0->EVENTS_COMPARE[1]){
488 // compare event -> timeout
489 radio_state = RADIO_W4_RX_TIMEOUT;
490 NRF_RADIO->SHORTS = 0;
491 NRF_RADIO->TASKS_DISABLE = 1;
492 #ifdef DEBUG_PIN_RX
493 // toggle twice for timeout
494 nrf_gpio_pin_toggle(DEBUG_PIN_RX);
495 nrf_gpio_pin_toggle(DEBUG_PIN_RX);
496 nrf_gpio_pin_toggle(DEBUG_PIN_RX);
497 nrf_gpio_pin_toggle(DEBUG_PIN_RX);
498 #endif
499 } else {
500 // no compare event -> packet with address received
501 radio_state = RADIO_W2_TX;
502 // RSSI is stored without sign but is negative (range: 0..127)
503 if (rssi_buffer != NULL){
504 uint32_t rssi_sample = NRF_RADIO->RSSISAMPLE;
505 int8_t rssi;
506 if (rssi_sample < 128){
507 rssi = -rssi_sample;
508 } else {
509 rssi = -128;
510 }
511 *rssi_buffer = rssi;
512 }
513 // check CRC
514 radio_result_t result = ((NRF_RADIO->CRCSTATUS & RADIO_CRCSTATUS_CRCSTATUS_Msk) != 0) ? RADIO_RESULT_OK : RADIO_RESULT_CRC_ERROR;
515 #ifdef DEBUG_PIN_RX
516 // toggle once for crc error
517 if (result == RADIO_RESULT_CRC_ERROR){
518 nrf_gpio_pin_toggle(DEBUG_PIN_RX);
519 nrf_gpio_pin_toggle(DEBUG_PIN_RX);
520 }
521 #endif
522 (*radio_callback)(result);
523 }
524 break;
525 case RADIO_W4_RX_TIMEOUT:
526 // after RX Timeout, RX was started and stopped again
527 btstack_assert(state == RADIO_STATE_STATE_Disabled);
528 NRF_RADIO->EVENTS_DISABLED = 0;
529 radio_state = RADIO_DISABLED;
530 (*radio_callback)(RADIO_RESULT_TIMEOUT);
531 break;
532 case RADIO_W4_DISABLED:
533 NRF_RADIO->EVENTS_DISABLED = 0;
534 NRF_RADIO->INTENCLR = 0xffffffff;
535 radio_state = RADIO_DISABLED;
536 (*radio_callback)(RADIO_RESULT_OK);
537 break;
538 default:
539 log_info("IRQ: our state = 0x%0x, radio_state 0x%04x", radio_state, state);
540 btstack_assert(false);
541 break;
542 }
543 #ifdef DEBUG_PIN_RADIO_IRQ
544 nrf_gpio_pin_toggle(DEBUG_PIN_RADIO_IRQ);
545 #endif
546 }
547