Appiko
rf_rx_ble.c
1 /*
2  * rf_rx_ble.c : BLE Support file for RF Receiver application
3  * Copyright (C) 2019 Appiko
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #include "rf_rx_ble.h"
20 
21 #include "nrf_nvic.h"
22 #include "ble.h"
23 #include "nrf_sdm.h"
24 #include "app_error.h"
25 #include "boards.h"
26 #include "stddef.h"
27 #include "common_util.h"
28 #include "nrf_util.h"
29 #include "log.h"
30 #include "evt_sd_handler.h"
31 #include "string.h"
32 #include "hal_nop_delay.h"
33 
36 #define DEVICE_NAME_CHAR 'B','T'
37 const uint8_t device_name[] = { DEVICE_NAME_CHAR };
38 
39 
42 #define BTDONGLE_UUID_COMPLETE 0x0a, 0xde, 0xfb, 0x07, 0x74, 0x83, 0x66, 0xb0, 0x0d, 0x48, 0xf5, 0x07, 0x70, 0xdc, 0x73, 0x3c
43 
45 #define BTDONGLE_UUID_SERVICE 0xdc70
46 
48 #define BTDONGLE_UUID_SYSINFO 0xdc71
49 
50 #define BTDONGLE_UUID_CONFIG 0xdc72
51 
53 #define ADVERTISING_INTERVAL MSEC_TO_UNITS(500, UNIT_0_625_MS)
54 
55 #define MIN_CONN_INTERVAL MSEC_TO_UNITS(200, UNIT_1_25_MS)
56 
57 #define MAX_CONN_INTERVAL MSEC_TO_UNITS(500, UNIT_1_25_MS)
58 
59 #define SLAVE_LATENCY 0
60 
61 #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)
62 
63 
64 #define APP_ADV_DATA { \
65  0x02, BLE_GAP_AD_TYPE_FLAGS, BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE, \
66  sizeof(device_name) + 1, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, DEVICE_NAME_CHAR, \
67  0x11, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, BTDONGLE_UUID_COMPLETE \
68  }
69 
70 #define APP_SCAN_RSP_DATA { \
71  0x02, BLE_GAP_AD_TYPE_TX_POWER_LEVEL, 0 , \
72  0x0A, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, \
73  'B', 'T', ' ', 'D', 'o', 'n' , 'g', 'l', 'e', \
74  0x04, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, 0 , 0 , 0 \
75  }
76 
77 
78 uint8_t adv_data[] = APP_ADV_DATA ;
80 uint8_t h_adv;
81 
83 uint16_t h_conn;
84 
86 uint16_t h_rf_rx_service;
87 
90 ble_gatts_char_handles_t h_status_byte;
91 
94 //ble_gatts_char_handles_t h_config_char;
95 
98 
99 volatile bool bluetooth_status = false;
100 void SWI1_IRQHandler(void)
101 {
102 // log_printf("radio going down\n");
103 }
104 
105 void (* connected_callback) (void);
106 
114 static void ble_evt_handler(ble_evt_t * evt)
115 {
116  uint32_t err_code;
117  log_printf("BLE Event : %d\n", evt->header.evt_id);
118  switch(evt->header.evt_id)
119  {
120  case BLE_GAP_EVT_ADV_SET_TERMINATED:
121  break;
122  case BLE_GAP_EVT_CONN_PARAM_UPDATE:
123  break;
124 
125  case BLE_GAP_EVT_CONNECTED:
126  h_conn = evt->evt.gap_evt.conn_handle;
127  connected_callback ();
128  break;
129  case BLE_GAP_EVT_DISCONNECTED:
130  h_conn = BLE_CONN_HANDLE_INVALID;
131  bluetooth_status = false;
132  rf_rx_ble_adv_start(connected_callback);
133 
134 // sd_softdevice_disable ();
135  break;
136  case BLE_GATTS_EVT_WRITE:
137  break;
138  case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
139  {
140  uint16_t mtu_val = BLE_GATT_ATT_MTU_DEFAULT;
141  err_code = sd_ble_gatts_exchange_mtu_reply(h_conn, mtu_val);
142  APP_ERROR_CHECK(err_code);
143  break;
144  }
145  case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
146  {
147  ble_gap_phys_t const phys = {
148  .rx_phys = BLE_GAP_PHY_AUTO,
149  .tx_phys = BLE_GAP_PHY_AUTO,
150  };
151 
152  err_code = sd_ble_gap_phy_update(h_conn, &phys);
153  APP_ERROR_CHECK(err_code);
154  break;
155  }
156  case BLE_GAP_EVT_PHY_UPDATE:
157  {
158  log_printf("Tx_get : %x Rx_get : %x Status : %x\n",
159  evt->evt.gap_evt.params.phy_update.tx_phy,
160  evt->evt.gap_evt.params.phy_update.rx_phy,
161  evt->evt.gap_evt.params.phy_update.status);
162  break;
163  }
164  }
165 
166 }
167 
173 static void soc_evt_handler(uint32_t evt_id)
174 {
175  log_printf("soc evt %x\n", evt_id);
176 }
177 
178 void rf_rx_ble_disconn(void)
179 {
180  if(h_conn != BLE_CONN_HANDLE_INVALID)
181  {
182  uint32_t err_code;
183  err_code = sd_ble_gap_disconnect(h_conn,
184  BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
185  APP_ERROR_CHECK(err_code);
186  }
187 }
188 
189 void rf_rx_ble_stack_init()
190 {
191  uint32_t err_code;
192  const nrf_clock_lf_cfg_t cfg = BOARD_LFCLKSRC_STRUCT;
193 
194 
195  err_code = sd_softdevice_enable(&cfg, app_error_fault_handler);
196  APP_ERROR_CHECK(err_code);
197 
198  uint32_t app_ram_start = 0x20001c00;
199  log_printf("Init %x", app_ram_start);
200  err_code = sd_ble_enable(&app_ram_start);
201  log_printf(" RAM needed %x\n", app_ram_start);
202  APP_ERROR_CHECK(err_code);
203 
204  evt_sd_handler_init(ble_evt_handler, soc_evt_handler);
205 
206  //So that the application wakes up after every radio activity
207  err_code = sd_radio_notification_cfg_set(
208  NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE,
209  NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
210  APP_ERROR_CHECK(err_code);
211 
212  // Initialize Radio Notification software interrupt
213  err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
214  APP_ERROR_CHECK(err_code);
215 
216  err_code = sd_nvic_SetPriority(SWI1_IRQn, APP_IRQ_PRIORITY_LOWEST);
217  APP_ERROR_CHECK(err_code);
218 
219  err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
220  APP_ERROR_CHECK(err_code);
221 
222  h_conn = BLE_CONN_HANDLE_INVALID;
223 }
224 
225 void rf_rx_ble_service_init(void)
226 {
227  uint32_t err_code;
228  ble_uuid_t ble_uuid;
229  uint8_t uuid_type;
230 
231  /**** Create the BT Dongle service *****/
232  ble_uuid128_t base_uuid = {{BTDONGLE_UUID_COMPLETE}};
233  err_code = sd_ble_uuid_vs_add(&base_uuid, &uuid_type);
234  APP_ERROR_CHECK(err_code);
235 
236  ble_uuid.type = uuid_type;
237  ble_uuid.uuid = BTDONGLE_UUID_SERVICE;
238 
239  err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
240  &ble_uuid, &h_rf_rx_service);
241  APP_ERROR_CHECK(err_code);
242 
243  /**** Create the read-only characteristic *****/
244  ble_gatts_char_md_t char_md;
245  ble_gatts_attr_t attr_char_value;
246  ble_gatts_attr_md_t attr_md;
247 // ble_gatts_attr_md_t cccd_md;
248 
249  memset(&char_md, 0, sizeof(char_md));
250 // memset(&cccd_md, 0, sizeof(cccd_md));
251 
252 // BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
253 // BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
254 // cccd_md.vloc = BLE_GATTS_VLOC_STACK;
255 
256  char_md.char_props.read = 1;
257  char_md.char_props.write = 0;
258 // char_md.char_props.notify = 1;
259  char_md.p_char_user_desc = NULL;
260  char_md.p_char_pf = NULL;
261  char_md.p_user_desc_md = NULL;
262 // char_md.p_cccd_md = &cccd_md;
263  char_md.p_cccd_md = NULL;
264  char_md.p_sccd_md = NULL;
265 
266  ble_uuid.type = uuid_type;
267  ble_uuid.uuid = (BTDONGLE_UUID_SYSINFO);
268 
269  memset(&attr_md, 0, sizeof(attr_md));
270 
271  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
272  BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
273  attr_md.vloc = BLE_GATTS_VLOC_STACK;
274  attr_md.rd_auth = 0;
275  attr_md.wr_auth = 0;
276  attr_md.vlen = 0;
277 
278  memset(&attr_char_value, 0, sizeof(attr_char_value));
279 
280  attr_char_value.p_uuid = &ble_uuid;
281  attr_char_value.p_attr_md = &attr_md;
282  attr_char_value.init_len = sizeof(mod_ble_data_t);
283  attr_char_value.init_offs = 0;
284  attr_char_value.max_len = sizeof(mod_ble_data_t);
285  attr_char_value.p_value = NULL;
286 
287  err_code = sd_ble_gatts_characteristic_add(
288  h_rf_rx_service, &char_md, &attr_char_value, &h_status_byte);
289  APP_ERROR_CHECK(err_code);
290 
291 }
292 
293 void rf_rx_ble_gap_params_init(void)
294 {
295  uint32_t err_code;
296  ble_gap_conn_params_t gap_conn_params;
297  ble_gap_conn_sec_mode_t sec_mode;
298 
299  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
300 
301  err_code = sd_ble_gap_device_name_set(
302  &sec_mode, (const uint8_t *)device_name, sizeof(device_name));
303  APP_ERROR_CHECK(err_code);
304 
305  memset(&gap_conn_params, 0, sizeof(gap_conn_params));
306 
307  gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
308  gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
309  gap_conn_params.slave_latency = SLAVE_LATENCY;
310  gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
311 
312  err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
313  APP_ERROR_CHECK(err_code);
314 }
315 
316 void rf_rx_ble_adv_init()
317 {
318  h_adv = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
319  uint8_t scn_rsp_data[] = APP_SCAN_RSP_DATA;
320  uint32_t err_code;
321  ble_gap_adv_data_t adv_payload;
322 
323 
324  adv_payload.adv_data.p_data = adv_data;
325  adv_payload.adv_data.len = sizeof(adv_data);
326 
327  adv_payload.scan_rsp_data.p_data = scn_rsp_data;
328  adv_payload.scan_rsp_data.len = sizeof(scn_rsp_data);
329 
330  ble_gap_adv_params_t adv_params;
331 
332  memset(&adv_params, 0, sizeof(adv_params));
333 
334  //Set channel 37, 38 and 39 as advertising channels
335  memset(adv_params.channel_mask, 0, 5);
336 
337  //Set the advertising to timeout in 180s
338  adv_params.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
339 
340  //Any device can scan request and connect
341  adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
342 
343  //Period between sending advertising packets
344  adv_params.interval = ADVERTISING_INTERVAL;
345 
346  //Use 1Mbps physical layer to be backward compatible
347  adv_params.primary_phy = BLE_GAP_PHY_1MBPS;
348 
349  //The advertisement would be unidirected connectable and scannable
350  adv_params.properties.type =
351  BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
352 
353  adv_params.p_peer_addr = NULL;
354  adv_params.scan_req_notification = 0;
355 
356  err_code = sd_ble_gap_adv_set_configure(&h_adv,
357  (ble_gap_adv_data_t const *)&adv_payload,
358  (ble_gap_adv_params_t const *) &adv_params);
359  APP_ERROR_CHECK(err_code);
360 }
361 
362 void rf_rx_ble_adv_start(void (*conn_func) (void))
363 {
364  connected_callback = conn_func;
365  bluetooth_status = true;
366  uint32_t err_code;
367  err_code = sd_ble_gap_adv_start(h_adv, BLE_CONN_CFG_TAG_DEFAULT);
368  APP_ERROR_CHECK(err_code);
369 }
370 
371 bool rf_rx_is_bt_on ()
372 {
373  return bluetooth_status;
374 }
375 
376 void rf_rx_ble_update_status_byte (mod_ble_data_t * status_byte)
377 {
378  uint32_t err_code;
379 // uint16_t len = sizeof(mod_ble_data_t);
380  ble_gatts_value_t val =
381  {
382  .len = sizeof(mod_ble_data_t),
383  .offset = 0,
384  .p_value =(uint8_t *) status_byte
385  };
386  err_code = sd_ble_gatts_value_set(h_conn,
387  h_status_byte.value_handle, &val);
388  APP_ERROR_CHECK(err_code);
389 
390 // ble_gatts_hvx_params_t params =
391 // {
392 // .p_len = &len,
393 // .p_data = (uint8_t *) status_byte,
394 // .type = BLE_GATT_HVX_NOTIFICATION,
395 // .handle = h_status_byte.value_handle,
396 // };
397 //
398 // err_code = sd_ble_gatts_hvx (h_conn, &params);
399 // APP_ERROR_CHECK(err_code);
400 }
#define APP_SCAN_RSP_DATA
Definition: main.c:85
void evt_sd_handler_init(void(*ble_evt_handler)(ble_evt_t *ble_evt), void(*soc_evt_handler)(uint32_t soc_evt_id))
Initializes the SWI2 interrupt routine and stores the handlers for the BLE and SoC events.
#define BOARD_LFCLKSRC_STRUCT
Definition: bluey_1v1.h:122
#define APP_ERROR_CHECK(ERR_CODE)
Macro calls error handler if the provided error code is not NRF_SUCCESS. The behavior of this call de...
Definition: app_error.h:55
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
Callback to be invoked in case of fault i.e. unrecoverable errors occurring within the application or...
Definition: app_error.c:55
#define APP_ADV_DATA
Definition: main.c:77