52 #include "hal_clocks.h" 55 #include "tinyprintf.h" 58 #include "hal_clocks.h" 59 #include "profiler_timer.h" 63 #include "isr_manager.h" 67 #define ADV_ACCESS_ADRS 0x8E89BED6 70 #define ADV_CRC_INIT 0x555555 72 #define ADV_HEADER_PDU_OFFSET 0 73 #define ADV_HEADER_LEN_OFFSET 1 74 #define ADV_ADRS_OFFSET 2 75 #define ADV_PAYLOAD_OFFSET 8 77 #define ADV_TX_ADRS_TYPE_BIT_POS 6 78 #define ADV_RX_ADRS_TYPE_BIT_POS 7 80 #define MAX_PAYLOAD_LEN 37 81 #define MAX_RADIO_PDU 39 83 #define ADV_IDX_CH_37 0 84 #define ADV_IDX_CH_38 1 85 #define ADV_IDX_CH_39 2 86 #define ADV_IDX_CH_MAX 3 88 #define TIME_TO_RX_ACCESS_ADRS 200 90 #define SHORT_READY_START \ 91 (RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos) 92 #define SHORT_END_DIS \ 93 (RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos) 94 #define SHORT_DIS_TXEN \ 95 (RADIO_SHORTS_DISABLED_TXEN_Enabled << RADIO_SHORTS_DISABLED_TXEN_Pos) 96 #define SHORT_DIS_RXEN \ 97 (RADIO_SHORTS_DISABLED_RXEN_Enabled << RADIO_SHORTS_DISABLED_RXEN_Pos) 99 const int8_t radio_pwr_levels[] = {4, 3, 0, -4, -8, -12, -16, -20, -40};
101 const uint8_t adv_channels[] = {37, 38, 39};
102 const uint8_t adv_freq[] = {2, 26, 80};
104 void irq_null_end(
void);
105 void irq_scan_end(
void);
107 void irq_null_dis(
void);
108 void irq_adv_nc_dis(
void);
109 void irq_adv_tx_dis(
void);
110 void irq_adv_rx_dis(
void);
111 void irq_scan_dis(
void);
132 void (*end_handler[])(void) = {
140 void (*dis_handler[])(void) = {
148 static struct radio_context {
150 volatile radio_states state;
151 uint8_t adv_txbuf[MAX_RADIO_PDU];
152 uint8_t adv_rxbuf[MAX_RADIO_PDU];
153 uint8_t scan_rsp[MAX_RADIO_PDU];
161 uint8_t adv_ch_map[3];
163 volatile uint8_t adv_idx;
164 volatile bool is_scan;
169 void add_log(
const char* func_name);
170 volatile uint32_t log_cnt = LOG_BUFFER_SIZE-1;
171 volatile log_t log_buf[LOG_BUFFER_SIZE];
173 void add_log(
const char * func_name){
176 log_buf[log_cnt].func_name = func_name;
177 log_buf[log_cnt].radio_state = NRF_RADIO->STATE;
178 log_buf[log_cnt].radio_ctx_state = radio_ctx.state;
179 log_buf[log_cnt].freq = radio_ctx.adv_idx;
186 for(i = LOG_BUFFER_SIZE-1; i>log_cnt;i--){
189 tfp_printf(
"; Hw:%d; Sw:%d; Fq:%d F:%s\n",
190 log_buf[i].radio_state, log_buf[i].radio_ctx_state,
191 log_buf[i].freq, log_buf[i].func_name);
193 log_cnt = LOG_BUFFER_SIZE-1;
197 void add_log(
const char* func_name);
198 void add_log(
const char* func_name){}
199 void dump_log(
void){}
205 radio_ctx.adv_type = ADV_IND;
207 case ADV_DIRECT_IND_PARAM:
208 radio_ctx.adv_type = ADV_DIRECT_IND;
210 case ADV_SCAN_IND_PARAM:
211 radio_ctx.adv_type = ADV_SCAN_IND;
213 case ADV_NONCONN_IND_PARAM:
214 radio_ctx.adv_type = ADV_NONCONN_IND;
218 radio_ctx.adv_intvl = adv_param->
adv_intvl;
219 radio_ctx.adv_ch_map[ADV_IDX_CH_37] = (adv_param->
adv_ch_map & 0x01);
220 radio_ctx.adv_ch_map[ADV_IDX_CH_38] = (adv_param->
adv_ch_map>>1) & 0x01;
221 radio_ctx.adv_ch_map[ADV_IDX_CH_39] = (adv_param->
adv_ch_map>>2) & 0x01;
226 return radio_ctx.adv_pwr;
231 for(i = (
sizeof(radio_pwr_levels)-1); i; i--){
232 if(radio_pwr_levels[i] >= pwr){
233 radio_ctx.adv_pwr = radio_pwr_levels[i];
238 radio_ctx.adv_pwr = radio_pwr_levels[0];
243 memcpy(radio_ctx.MAC_adrs, rand_adrs ,
ADRS_LEN);
247 memcpy(radio_ctx.adv_txbuf + ADV_PAYLOAD_OFFSET, data_ptr, len);
248 radio_ctx.adv_txbuf[ADV_HEADER_LEN_OFFSET] = len +
ADRS_LEN;
252 memcpy(radio_ctx.scan_rsp + ADV_PAYLOAD_OFFSET, data_ptr, len);
253 radio_ctx.scan_rsp[ADV_HEADER_LEN_OFFSET] = len +
ADRS_LEN;
256 static inline void adv_set_ch_freq(){
257 NRF_RADIO->DATAWHITEIV = adv_channels[radio_ctx.adv_idx];
258 NRF_RADIO->FREQUENCY = adv_freq[radio_ctx.adv_idx];
261 void radio_prepare_adv(
void)
263 if(radio_ctx.adv_ch_map[ADV_IDX_CH_37]){
264 radio_ctx.adv_idx = ADV_IDX_CH_37;
265 }
else if(radio_ctx.adv_ch_map[ADV_IDX_CH_38]){
266 radio_ctx.adv_idx = ADV_IDX_CH_38;
267 }
else if(radio_ctx.adv_ch_map[ADV_IDX_CH_39]){
268 radio_ctx.adv_idx = ADV_IDX_CH_39;
273 NRF_RADIO->BASE0 = (ADV_ACCESS_ADRS << 8) & 0xFFFFFF00;
274 NRF_RADIO->PREFIX0 = (ADV_ACCESS_ADRS >> 24) & RADIO_PREFIX0_AP0_Msk;
275 NRF_RADIO->CRCINIT = ADV_CRC_INIT;
276 NRF_RADIO->TXPOWER = radio_ctx.adv_pwr;
278 radio_ctx.adv_txbuf[ADV_HEADER_PDU_OFFSET] = radio_ctx.adv_type;
279 radio_ctx.adv_txbuf[ADV_HEADER_PDU_OFFSET] |=
280 (radio_ctx.adrs_type & 0x01) << ADV_TX_ADRS_TYPE_BIT_POS;
282 memcpy(radio_ctx.adv_txbuf + ADV_ADRS_OFFSET, radio_ctx.MAC_adrs,
ADRS_LEN);
284 radio_ctx.scan_rsp[ADV_HEADER_PDU_OFFSET] = SCAN_RSP;
285 radio_ctx.scan_rsp[ADV_HEADER_PDU_OFFSET] |=
286 (radio_ctx.adrs_type & 0x01) << ADV_TX_ADRS_TYPE_BIT_POS;
288 memcpy(radio_ctx.scan_rsp + ADV_ADRS_OFFSET, radio_ctx.MAC_adrs,
ADRS_LEN);
290 radio_ctx.state = STOP;
293 void radio_send_adv(
void){
294 switch(radio_ctx.adv_type){
298 radio_ctx.state = ADV_TX;
299 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_RXEN;
301 case ADV_NONCONN_IND:
302 radio_ctx.state = ADV_NC;
312 NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_txbuf;
314 NRF_RADIO->TASKS_TXEN = 1UL;
317 void radio_init(
void){
318 NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled;
322 NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos)
323 | (RADIO_MODECNF0_RU_Fast);
331 if ((NRF_FICR->OVERRIDEEN & FICR_OVERRIDEEN_BLE_1MBIT_Msk)
332 == (FICR_OVERRIDEEN_BLE_1MBIT_Override
333 << FICR_OVERRIDEEN_BLE_1MBIT_Pos)) {
334 NRF_RADIO->OVERRIDE0 = NRF_FICR->BLE_1MBIT[0];
335 NRF_RADIO->OVERRIDE1 = NRF_FICR->BLE_1MBIT[1];
336 NRF_RADIO->OVERRIDE2 = NRF_FICR->BLE_1MBIT[2];
337 NRF_RADIO->OVERRIDE3 = NRF_FICR->BLE_1MBIT[3];
338 NRF_RADIO->OVERRIDE4 = NRF_FICR->BLE_1MBIT[4] | 0x80000000;
343 NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos;
350 NRF_RADIO->TIFS = 150;
358 (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
359 (MAX_PAYLOAD_LEN << RADIO_PCNF1_MAXLEN_Pos) |
360 (3UL << RADIO_PCNF1_BALEN_Pos);
369 NRF_RADIO->RXADDRESSES = 1UL;
370 NRF_RADIO->TXADDRESS = 0UL;
379 (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |
380 (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos);
381 NRF_RADIO->CRCPOLY = 0x100065B;
392 NRF_RADIO->PCNF0 = (1UL << RADIO_PCNF0_S0LEN_Pos)
393 | (8UL << RADIO_PCNF0_LFLEN_Pos)
394 | (0UL << RADIO_PCNF0_S1LEN_Pos);
406 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
409 NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk | RADIO_INTENSET_DISABLED_Msk;
412 NVIC_SetPriority(RADIO_IRQn, APP_IRQ_PRIORITY_HIGHEST);
413 NVIC_ClearPendingIRQ(RADIO_IRQn);
414 NVIC_EnableIRQ(RADIO_IRQn);
417 void radio_deinit(
void){
418 radio_ctx.state = STOP;
419 NRF_RADIO->TASKS_DISABLE = 1;
423 bool check_set_ch_idx(){
426 while(ADV_IDX_CH_MAX != radio_ctx.adv_idx){
427 if(radio_ctx.adv_ch_map[radio_ctx.adv_idx]){
438 void rx_timer_handler(
void){
440 if(NRF_RADIO->EVENTS_ADDRESS){
442 if((SCAN_REQ == (radio_ctx.adv_rxbuf[ADV_HEADER_PDU_OFFSET] & ADV_PDU_MASK))
445 radio_ctx.is_scan =
true;
446 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_TXEN;
449 NRF_RADIO->TASKS_DISABLE = 1;
453 void irq_null_end(
void){}
454 void irq_null_dis(
void){}
456 void irq_scan_end(
void){
457 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
460 void irq_adv_tx_dis(
void){
464 TIME_TO_RX_ACCESS_ADRS, rx_timer_handler);
466 NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_rxbuf;
467 NRF_RADIO->EVENTS_ADDRESS = 0;
469 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
470 radio_ctx.state = ADV_RX;
472 memset(radio_ctx.adv_rxbuf,0,MAX_RADIO_PDU);
474 radio_ctx.is_scan =
false;
477 void irq_adv_rx_dis(
void){
479 if(radio_ctx.is_scan){
480 radio_ctx.state = SCAN;
481 NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.scan_rsp;
483 if(check_set_ch_idx()){
486 radio_ctx.state = ADV_TX;
487 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_RXEN;
489 NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_txbuf;
490 NRF_RADIO->TASKS_TXEN = 1UL;
495 void irq_scan_dis(
void){
496 if(check_set_ch_idx()){
499 radio_ctx.state = ADV_TX;
500 NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_RXEN;
502 NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_txbuf;
503 NRF_RADIO->TASKS_TXEN = 1UL;
507 void irq_adv_nc_dis(
void){
510 if(check_set_ch_idx()){
512 NRF_RADIO->TASKS_TXEN = 1UL;
516 void irq_scan_ready(
void){
520 void irq_adv_tx_ready(
void){
525 void ble_adv_radio_Handler ()
527 void RADIO_IRQHandler(
void)
531 if(1 == NRF_RADIO->EVENTS_END){
532 NRF_RADIO->EVENTS_END = 0;
533 (void) NRF_RADIO->EVENTS_END;
534 end_handler[radio_ctx.state]();
537 if((1 == NRF_RADIO->EVENTS_DISABLED) && (0 == NRF_RADIO->EVENTS_END)){
538 NRF_RADIO->EVENTS_DISABLED = 0;
539 (void) NRF_RADIO->EVENTS_DISABLED;
540 dis_handler[radio_ctx.state]();
544 void adv_intvl_handler(
void){
void us_timer_start(us_timer_num id, us_timer_mode mode, uint32_t time_us, void(*handler)(void))
void ble_adv_start(void)
Start advertising based on the parameters set.
ble_adv_ch_map_t adv_ch_map
void ble_adv_set_tx_power(int8_t pwr)
Set the advertising transmission power in dBm.
#define ADRS_LEN
length of MAC address in BLE
Repeated call of the timer.
void ble_adv_set_adv_param(ble_adv_param_t *adv_param)
Set the advertising parameters to be used.
adrs_type_t own_adrs_type
One shot call of the timer.
int8_t ble_adv_get_tx_power(void)
Get the advertising transmission power in dBm.
void ble_adv_stop(void)
Stop advertising.
void ble_adv_set_scan_rsp_data(uint8_t len, uint8_t *data_ptr)
Set the scan response data.
#define LFCLK_TICKS_625(ms)
void ms_timer_start(ms_timer_num id, ms_timer_mode mode, uint64_t ticks, void(*handler)(void))
void ble_adv_set_random_adrs(uint8_t *rand_adrs)
Set the random address to be used.
void printfcomma(uint32_t num)
The structure format for setting the advertisement parameters.
void ble_adv_set_adv_data(uint8_t len, uint8_t *data_ptr)
Set the advertising data.
void ms_timer_stop(ms_timer_num id)
uint32_t read_time_us(void)