Appiko
ble_adv.c
1 
19 /* Copyright (c) 2015, Prithvi Raj Narendra
20  * Copyright (c) 2013 Paulo B. de Oliveira Filho <pauloborgesfilho@gmail.com>
21  * Copyright (c) 2013 Claudio Takahasi <claudio.takahasi@gmail.com>
22  * Copyright (c) 2013 João Paulo Rechi Vita <jprvita@gmail.com>
23  * All rights reserved.
24  *
25  * Redistribution and use in source and binary forms, with or without modification,
26  * are permitted provided that the following conditions are met:
27  *
28  * 1. Redistributions of source code must retain the above copyright notice,
29  * this list of conditions and the following disclaimer.
30  *
31  * 2. Redistributions in binary form must reproduce the above copyright notice,
32  * this list of conditions and the following disclaimer in the documentation
33  * and/or other materials provided with the distribution.
34  *
35  * 3. Neither the name of the copyright holder nor the names of its contributors
36  * may be used to endorse or promote products derived from this software without
37  * specific prior written permission.
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
40  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
41  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
43  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
44  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
45  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
46  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #include "ble_adv.h"
52 #include "hal_clocks.h"
53 #include "us_timer.h"
54 #include "ms_timer.h"
55 #include "tinyprintf.h"
56 #include "nrf.h"
57 #include "nrf_util.h"
58 #include "hal_clocks.h"
59 #include "profiler_timer.h"
60 #include <string.h>
61 
62 #if ISR_MANAGER == 1
63 #include "isr_manager.h"
64 #endif
65 
66 /* Link Layer specification Section 2.1.2, Core 4.1 page 2503 */
67 #define ADV_ACCESS_ADRS 0x8E89BED6
68 
69 /* Link Layer specification Section 3.1.1, Core 4.1 page 2522 */
70 #define ADV_CRC_INIT 0x555555
71 
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
76 
77 #define ADV_TX_ADRS_TYPE_BIT_POS 6
78 #define ADV_RX_ADRS_TYPE_BIT_POS 7
79 
80 #define MAX_PAYLOAD_LEN 37
81 #define MAX_RADIO_PDU 39
82 
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
87 
88 #define TIME_TO_RX_ACCESS_ADRS 200
89 
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)
98 
99 const int8_t radio_pwr_levels[] = {4, 3, 0, -4, -8, -12, -16, -20, -40};
100 
101 const uint8_t adv_channels[] = {37, 38, 39};
102 const uint8_t adv_freq[] = {2, 26, 80};
103 
104 void irq_null_end(void);
105 void irq_scan_end(void);
106 
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);
112 
113 typedef enum{
114  ADV_IND, // Connectable undirected advertising
115  ADV_DIRECT_IND, // Connectable high duty cycle directed advertising (high duty cycle)
116  ADV_NONCONN_IND, // Non connectable undirected advertising
117  SCAN_REQ, // Scan request from scanner
118  SCAN_RSP, // Scan response from advertiser
119  CONNECT_REQ, // Connect request from initiator
120  ADV_SCAN_IND, // Scannable undirected advertising
121  ADV_PDU_MASK
122 }adv_pdu_types_t;
123 
124 typedef enum{
125  STOP,
126  ADV_NC,
127  ADV_TX,
128  ADV_RX,
129  SCAN
130 }radio_states;
131 
132 void (*end_handler[])(void) = {
133  irq_null_end, //IDLE
134  irq_null_end, //ADV_NC
135  irq_null_end, //ADV_TX
136  irq_null_end, //ADV_RX
137  irq_scan_end //SCAN
138 };
139 
140 void (*dis_handler[])(void) = {
141  irq_null_dis, //IDLE
142  irq_adv_nc_dis, //ADV_NC
143  irq_adv_tx_dis, //ADV_TX
144  irq_adv_rx_dis, //ADV_RX
145  irq_scan_dis //SCAN
146 };
147 
148 static struct radio_context {
150  volatile radio_states state; //4 bytes
151  uint8_t adv_txbuf[MAX_RADIO_PDU]; //39 bytes
152  uint8_t adv_rxbuf[MAX_RADIO_PDU]; //39 bytes
153  uint8_t scan_rsp[MAX_RADIO_PDU]; //39 bytes
154 
156  uint8_t adrs_type; //1 byte
157  uint8_t MAC_adrs[ADRS_LEN]; //6 bytes
158 
160  uint8_t adv_type; //1 byte
161  uint8_t adv_ch_map[3]; //3 bytes
162  int8_t adv_pwr; //1 byte
163  volatile uint8_t adv_idx; //1 byte
164  volatile bool is_scan; //1 byte
165  uint16_t adv_intvl; //2 byte
166 } radio_ctx;
167 
168 #ifdef DEBUG
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];
172 
173 void add_log(const char * func_name){
174  if(log_cnt){
175  log_buf[log_cnt].time =read_time_us();
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;
180  log_cnt--;
181  }
182 }
183 
184 void dump_log(){
185  uint32_t i;
186  for(i = LOG_BUFFER_SIZE-1; i>log_cnt;i--){
187  tfp_printf("T:");
188  printfcomma(log_buf[i].time);
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);
192  }
193  log_cnt = LOG_BUFFER_SIZE-1;
194 }
195 
196 #else
197 void add_log(const char* func_name);
198 void add_log(const char* func_name){}
199 void dump_log(void){}
200 #endif
201 
203  switch(adv_param->adv_type){
204  case ADV_IND_PARAM:
205  radio_ctx.adv_type = ADV_IND;
206  break;
207  case ADV_DIRECT_IND_PARAM:
208  radio_ctx.adv_type = ADV_DIRECT_IND;
209  break;
210  case ADV_SCAN_IND_PARAM:
211  radio_ctx.adv_type = ADV_SCAN_IND;
212  break;
213  case ADV_NONCONN_IND_PARAM:
214  radio_ctx.adv_type = ADV_NONCONN_IND;
215  break;
216  }
217 
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;
222  radio_ctx.adrs_type = adv_param->own_adrs_type;
223 }
224 
225 int8_t ble_adv_get_tx_power(void){
226  return radio_ctx.adv_pwr;
227 }
228 
229 void ble_adv_set_tx_power(int8_t pwr){
230  uint32_t i;
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];
234  break;
235  }
236  }
237  if(0 == i){
238  radio_ctx.adv_pwr = radio_pwr_levels[0];
239  }
240 }
241 
242 void ble_adv_set_random_adrs(uint8_t * rand_adrs){
243  memcpy(radio_ctx.MAC_adrs, rand_adrs , ADRS_LEN);
244 }
245 
246 void ble_adv_set_adv_data(uint8_t len, uint8_t* data_ptr){
247  memcpy(radio_ctx.adv_txbuf + ADV_PAYLOAD_OFFSET, data_ptr, len);
248  radio_ctx.adv_txbuf[ADV_HEADER_LEN_OFFSET] = len + ADRS_LEN;
249 }
250 
251 void ble_adv_set_scan_rsp_data(uint8_t len, uint8_t* data_ptr){
252  memcpy(radio_ctx.scan_rsp + ADV_PAYLOAD_OFFSET, data_ptr, len);
253  radio_ctx.scan_rsp[ADV_HEADER_LEN_OFFSET] = len + ADRS_LEN;
254 }
255 
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];
259 }
260 
261 void radio_prepare_adv(void)
262 {
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;
269  }
270 
271  adv_set_ch_freq();
272 
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;
277 
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;
281 
282  memcpy(radio_ctx.adv_txbuf + ADV_ADRS_OFFSET, radio_ctx.MAC_adrs, ADRS_LEN);
283 
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;
287 
288  memcpy(radio_ctx.scan_rsp + ADV_ADRS_OFFSET, radio_ctx.MAC_adrs, ADRS_LEN);
289 
290  radio_ctx.state = STOP;
291 }
292 
293 void radio_send_adv(void){
294  switch(radio_ctx.adv_type){
295  case ADV_IND:
296  case ADV_DIRECT_IND:
297  case ADV_SCAN_IND:
298  radio_ctx.state = ADV_TX;
299  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_RXEN;
300  break;
301  case ADV_NONCONN_IND:
302  radio_ctx.state = ADV_NC;
303  break;
304  case SCAN_REQ:
305  case SCAN_RSP:
306  case CONNECT_REQ:
307  default:
308  break;
309  }
310 
311 
312  NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_txbuf;
313 
314  NRF_RADIO->TASKS_TXEN = 1UL;
315 }
316 
317 void radio_init(void){
318  NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled;
319 
320 #ifdef NRF52
321  /* Enable the fast startup (nrf52 only)*/
322  NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos)
323  | (RADIO_MODECNF0_RU_Fast);
324 #endif
325 
326 #ifdef NRF51
327  /* nRF51 Series Reference Manual v2.1, section 6.1.1, page 18
328  * PCN-083 rev.1.1
329  *
330  * Fine tune BLE deviation parameters. Not required for nrf52. */
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;
339  }
340 #endif
341 
342  /* nRF51 Series Reference Manual v2.1, section 16.2.7, page 86 */
343  NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos;
344 
345  /* Link Layer specification section 4.1, Core 4.1, page 2524
346  * nRF51 Series Reference Manual v2.1, section 16.2.7, page 92
347  *
348  * Set the inter frame space (T_IFS) to 150 us.
349  */
350  NRF_RADIO->TIFS = 150;
351 
352  /* nRF51 Series Reference Manual v2.1, section 16.2.9, page 88
353  *
354  * Enable data whitening, set the maximum payload length and set the
355  * access address size (3 + 1 octets).
356  */
357  NRF_RADIO->PCNF1 =
358  (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
359  (MAX_PAYLOAD_LEN << RADIO_PCNF1_MAXLEN_Pos) |
360  (3UL << RADIO_PCNF1_BALEN_Pos);
361 
362  /* nRF51 Series Reference Manual v2.1, section 16.1.4, page 74
363  * nRF51 Series Reference Manual v2.1, section 16.2.14-15, pages 89-90
364  *
365  * Preset the address to use when receive and transmit packets (logical
366  * address 0, which is assembled by base address BASE0 and prefix byte
367  * PREFIX0.AP0.
368  */
369  NRF_RADIO->RXADDRESSES = 1UL;
370  NRF_RADIO->TXADDRESS = 0UL;
371 
372  /* nRF51 Series Reference Manual v2.1, section 16.1.7, page 76
373  * nRF51 Series Reference Manual v2.1, sections 16.1.16-17, page 90
374  *
375  * Configure the CRC length (3 octets), polynominal and set it to
376  * ignore the access address when calculate the CRC.
377  */
378  NRF_RADIO->CRCCNF =
379  (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |
380  (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos);
381  NRF_RADIO->CRCPOLY = 0x100065B;
382 
383  /* nRF51 Series Reference Manual v2.1, section 16.1.2, page 74
384  * nRF51 Series Reference Manual v2.1, sections 16.1.8, page 87
385  * Link Layer specification section 2.3, Core 4.1, page 2504
386  * Link Layer specification section 2.4, Core 4.1, page 2511
387  *
388  * Configure the header size. The nRF51822 has 3 fields before the
389  * payload field: S0, LENGTH and S1. These fields can be used to store
390  * the PDU header.
391  */
392  NRF_RADIO->PCNF0 = (1UL << RADIO_PCNF0_S0LEN_Pos)
393  | (8UL << RADIO_PCNF0_LFLEN_Pos)
394  | (0UL << RADIO_PCNF0_S1LEN_Pos);
395 
396  /* nRF51 Series Reference Manual v2.1, section 16.1.8, page 76
397  * nRF51 Series Reference Manual v2.1, section 16.1.10-11, pages 78-80
398  * nRF51 Series Reference Manual v2.1, section 16.2.1, page 85
399  *
400  * Enable READY_START short: when the READY event happens, initialize
401  * the START task.
402  *
403  * Enable END_DISABLE short: when the END event happens, initialize the
404  * DISABLE task.
405  */
406  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
407 
408  /* Trigger RADIO interruption when an DISABLE or END event happens */
409  NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk | RADIO_INTENSET_DISABLED_Msk;
410 
411  /* Highest priority interrupt for the radio peripheral */
412  NVIC_SetPriority(RADIO_IRQn, APP_IRQ_PRIORITY_HIGHEST);
413  NVIC_ClearPendingIRQ(RADIO_IRQn);
414  NVIC_EnableIRQ(RADIO_IRQn);
415 }
416 
417 void radio_deinit(void){
418  radio_ctx.state = STOP;
419  NRF_RADIO->TASKS_DISABLE = 1;
420  //NRF_RADIO->POWER = RADIO_POWER_POWER_Disabled;
421 }
422 
423 bool check_set_ch_idx(){
424  radio_ctx.adv_idx++;
425 
426  while(ADV_IDX_CH_MAX != radio_ctx.adv_idx){
427  if(radio_ctx.adv_ch_map[radio_ctx.adv_idx]){
428  return true;
429  } else {
430  radio_ctx.adv_idx++;
431  }
432  }
433 
434  radio_deinit();
435  return false;
436 }
437 
438 void rx_timer_handler(void){
439  //Check if a packet reception has started
440  if(NRF_RADIO->EVENTS_ADDRESS){
441  //Check if the packet received is for a scan request
442  if((SCAN_REQ == (radio_ctx.adv_rxbuf[ADV_HEADER_PDU_OFFSET] & ADV_PDU_MASK))
443  /* && ((2*ADRS_LEN) == radio_ctx.adv_rxbuf[ADV_HEADER_LEN_OFFSET]) */){
444 // add_log(__func__);
445  radio_ctx.is_scan = true;
446  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_TXEN;
447  }
448  } else {
449  NRF_RADIO->TASKS_DISABLE = 1;
450  }
451 }
452 
453 void irq_null_end(void){}
454 void irq_null_dis(void){}
455 
456 void irq_scan_end(void){
457  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
458 }
459 
460 void irq_adv_tx_dis(void){
461  //150 us for IFS and 100 us time to see if the address event has been
462  //generated by receiving a packet
464  TIME_TO_RX_ACCESS_ADRS, rx_timer_handler);
465 
466  NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_rxbuf;
467  NRF_RADIO->EVENTS_ADDRESS = 0;
468 
469  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS;
470  radio_ctx.state = ADV_RX;
471 
472  memset(radio_ctx.adv_rxbuf,0,MAX_RADIO_PDU);
473 
474  radio_ctx.is_scan = false;
475 }
476 
477 void irq_adv_rx_dis(void){
478 
479  if(radio_ctx.is_scan){
480  radio_ctx.state = SCAN;
481  NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.scan_rsp;
482  } else {
483  if(check_set_ch_idx()){
484  adv_set_ch_freq();
485 
486  radio_ctx.state = ADV_TX;
487  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_RXEN;
488 
489  NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_txbuf;
490  NRF_RADIO->TASKS_TXEN = 1UL;
491  }
492  }
493 }
494 
495 void irq_scan_dis(void){
496  if(check_set_ch_idx()){
497  adv_set_ch_freq();
498 
499  radio_ctx.state = ADV_TX;
500  NRF_RADIO->SHORTS = SHORT_READY_START | SHORT_END_DIS | SHORT_DIS_RXEN;
501 
502  NRF_RADIO->PACKETPTR = (uint32_t) radio_ctx.adv_txbuf;
503  NRF_RADIO->TASKS_TXEN = 1UL;
504  }
505 }
506 
507 void irq_adv_nc_dis(void){
508 // add_log(__func__);
509 
510  if(check_set_ch_idx()){
511  adv_set_ch_freq();
512  NRF_RADIO->TASKS_TXEN = 1UL;
513  }
514 }
515 
516 void irq_scan_ready(void){
517 
518 }
519 
520 void irq_adv_tx_ready(void){
521 
522 }
523 
524 #if ISR_MANAGER == 1
525 void ble_adv_radio_Handler ()
526 #else
527 void RADIO_IRQHandler(void)
528 #endif
529 {
530 
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]();
535  }
536 
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]();
541  }
542 }
543 
544 void adv_intvl_handler(void){
545  radio_prepare_adv();
546  radio_send_adv();
547 // add_log(__func__);
548 }
549 
550 void ble_adv_start(void){
551  radio_init();
552  ms_timer_start(MS_TIMER2, MS_REPEATED_CALL, LFCLK_TICKS_625(radio_ctx.adv_intvl), adv_intvl_handler);
553  adv_intvl_handler();
554 }
555 
556 void ble_adv_stop(void){
558 }
559 
void us_timer_start(us_timer_num id, us_timer_mode mode, uint32_t time_us, void(*handler)(void))
Definition: us_timer.c:74
void ble_adv_start(void)
Start advertising based on the parameters set.
Definition: ble_adv.c:550
ble_adv_ch_map_t adv_ch_map
Definition: ble_adv.h:134
void ble_adv_set_tx_power(int8_t pwr)
Set the advertising transmission power in dBm.
Definition: ble_adv.c:229
Microsecond Timer 3.
Definition: us_timer.h:60
uint16_t adv_intvl
Definition: ble_adv.h:126
#define ADRS_LEN
length of MAC address in BLE
Definition: ble_adv.h:65
ble_adv_type_t adv_type
Definition: ble_adv.h:128
Millisecond Timer 2.
Definition: ms_timer.h:71
Repeated call of the timer.
Definition: ms_timer.h:83
void ble_adv_set_adv_param(ble_adv_param_t *adv_param)
Set the advertising parameters to be used.
Definition: ble_adv.c:202
adrs_type_t own_adrs_type
Definition: ble_adv.h:130
One shot call of the timer.
Definition: us_timer.h:72
int8_t ble_adv_get_tx_power(void)
Get the advertising transmission power in dBm.
Definition: ble_adv.c:225
void ble_adv_stop(void)
Stop advertising.
Definition: ble_adv.c:556
void ble_adv_set_scan_rsp_data(uint8_t len, uint8_t *data_ptr)
Set the scan response data.
Definition: ble_adv.c:251
#define LFCLK_TICKS_625(ms)
Definition: nrf_util.h:89
void ms_timer_start(ms_timer_num id, ms_timer_mode mode, uint64_t ticks, void(*handler)(void))
Definition: ms_timer.c:134
void ble_adv_set_random_adrs(uint8_t *rand_adrs)
Set the random address to be used.
Definition: ble_adv.c:242
void printfcomma(uint32_t num)
The structure format for setting the advertisement parameters.
Definition: ble_adv.h:124
void ble_adv_set_adv_data(uint8_t len, uint8_t *data_ptr)
Set the advertising data.
Definition: ble_adv.c:246
void ms_timer_stop(ms_timer_num id)
Definition: ms_timer.c:173
uint32_t read_time_us(void)