Appiko
lsm_testing_ble.c
1 /*
2  * lsm_testing_ble.c : BLE Support file for LSM6D 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 "lsm_testing_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 'A','C','C','E'
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  0x0B, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, \
73  'A', 'c','c', 'e', ' ', 'S' , 'm', 'o', 'k','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_lsm_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  lsm_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 lsm_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 lsm_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 lsm_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_lsm_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 
248  memset(&char_md, 0, sizeof(char_md));
249 
250  char_md.char_props.read = 1;
251  char_md.char_props.write = 0;
252  char_md.p_char_user_desc = NULL;
253  char_md.p_char_pf = NULL;
254  char_md.p_user_desc_md = NULL;
255  char_md.p_cccd_md = NULL;
256  char_md.p_sccd_md = NULL;
257 
258  ble_uuid.type = uuid_type;
259  ble_uuid.uuid = (BTDONGLE_UUID_SYSINFO);
260 
261  memset(&attr_md, 0, sizeof(attr_md));
262 
263  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
264  BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
265  attr_md.vloc = BLE_GATTS_VLOC_STACK;
266  attr_md.rd_auth = 0;
267  attr_md.wr_auth = 0;
268  attr_md.vlen = 0;
269 
270  memset(&attr_char_value, 0, sizeof(attr_char_value));
271 
272  attr_char_value.p_uuid = &ble_uuid;
273  attr_char_value.p_attr_md = &attr_md;
274  attr_char_value.init_len = sizeof(mod_ble_data_t);
275  attr_char_value.init_offs = 0;
276  attr_char_value.max_len = sizeof(mod_ble_data_t);
277  attr_char_value.p_value = NULL;
278 
279  err_code = sd_ble_gatts_characteristic_add(
280  h_lsm_service, &char_md, &attr_char_value, &h_status_byte);
281  APP_ERROR_CHECK(err_code);
282 
283 }
284 
285 void lsm_ble_gap_params_init(void)
286 {
287  uint32_t err_code;
288  ble_gap_conn_params_t gap_conn_params;
289  ble_gap_conn_sec_mode_t sec_mode;
290 
291  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
292 
293  err_code = sd_ble_gap_device_name_set(
294  &sec_mode, (const uint8_t *)device_name, sizeof(device_name));
295  APP_ERROR_CHECK(err_code);
296 
297  memset(&gap_conn_params, 0, sizeof(gap_conn_params));
298 
299  gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
300  gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
301  gap_conn_params.slave_latency = SLAVE_LATENCY;
302  gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
303 
304  err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
305  APP_ERROR_CHECK(err_code);
306 }
307 
308 void lsm_ble_adv_init()
309 {
310  h_adv = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
311  uint8_t scn_rsp_data[] = APP_SCAN_RSP_DATA;
312  uint32_t err_code;
313  ble_gap_adv_data_t adv_payload;
314 
315 
316  adv_payload.adv_data.p_data = adv_data;
317  adv_payload.adv_data.len = sizeof(adv_data);
318 
319  adv_payload.scan_rsp_data.p_data = scn_rsp_data;
320  adv_payload.scan_rsp_data.len = sizeof(scn_rsp_data);
321 
322  ble_gap_adv_params_t adv_params;
323 
324  memset(&adv_params, 0, sizeof(adv_params));
325 
326  //Set channel 37, 38 and 39 as advertising channels
327  memset(adv_params.channel_mask, 0, 5);
328 
329  //Set the advertising to timeout in 180s
330  adv_params.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
331 
332  //Any device can scan request and connect
333  adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
334 
335  //Period between sending advertising packets
336  adv_params.interval = ADVERTISING_INTERVAL;
337 
338  //Use 1Mbps physical layer to be backward compatible
339  adv_params.primary_phy = BLE_GAP_PHY_1MBPS;
340 
341  //The advertisement would be unidirected connectable and scannable
342  adv_params.properties.type =
343  BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
344 
345  adv_params.p_peer_addr = NULL;
346  adv_params.scan_req_notification = 0;
347 
348  err_code = sd_ble_gap_adv_set_configure(&h_adv,
349  (ble_gap_adv_data_t const *)&adv_payload,
350  (ble_gap_adv_params_t const *) &adv_params);
351  APP_ERROR_CHECK(err_code);
352 }
353 
354 void lsm_ble_adv_start(void (*conn_func) (void))
355 {
356  connected_callback = conn_func;
357  bluetooth_status = true;
358  uint32_t err_code;
359  err_code = sd_ble_gap_adv_start(h_adv, BLE_CONN_CFG_TAG_DEFAULT);
360  APP_ERROR_CHECK(err_code);
361 }
362 
363 bool lsm_is_bt_on ()
364 {
365  return bluetooth_status;
366 }
367 
368 void lsm_ble_update_status_byte(mod_ble_data_t * status_byte)
369 {
370  uint32_t err_code;
371  ble_gatts_value_t val =
372  {
373  .len = sizeof(mod_ble_data_t),
374  .offset = 0,
375  .p_value =(uint8_t *) status_byte
376  };
377  err_code = sd_ble_gatts_value_set(h_conn,
378  h_status_byte.value_handle, &val);
379  APP_ERROR_CHECK(err_code);
380 
381 }
#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