BLE_Nano nRF51 Central heart rate
Embed:
(wiki syntax)
Show/hide line numbers
main.c
00001 /* 00002 * Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. 00003 * 00004 * The information contained herein is confidential property of Nordic Semiconductor. The use, 00005 * copying, transfer or disclosure of such information is prohibited except by express written 00006 * agreement with Nordic Semiconductor. 00007 * 00008 */ 00009 00010 /** 00011 * @brief BLE Heart Rate Collector application main file. 00012 * 00013 * This file contains the source code for a sample heart rate collector. 00014 */ 00015 00016 #include <stdint.h> 00017 #include <stdio.h> 00018 #include <string.h> 00019 #include "nordic_common.h" 00020 #include "nrf_sdm.h" 00021 #include "ble.h" 00022 #include "ble_hci.h" 00023 #include "ble_db_discovery.h " 00024 #include "softdevice_handler.h " 00025 #include "app_util.h " 00026 #include "app_error.h " 00027 #include "boards.h" 00028 #include "nrf_gpio.h" 00029 #include "pstorage.h" 00030 #include "device_manager.h" 00031 #include "ble_hrs_c.h" 00032 #include "ble_bas_c.h" 00033 #include "app_util.h " 00034 #include "app_timer.h" 00035 #include "bsp.h" 00036 #include "bsp_btn_ble.h" 00037 #include "nrf_log.h" 00038 00039 #define CENTRAL_LINK_COUNT 1 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/ 00040 #define PERIPHERAL_LINK_COUNT 0 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/ 00041 00042 #define STRING_BUFFER_LEN 50 00043 #define BOND_DELETE_ALL_BUTTON_ID 0 /**< Button used for deleting all bonded centrals during startup. */ 00044 00045 #define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */ 00046 #define APP_TIMER_OP_QUEUE_SIZE 2 /**< Size of timer operation queues. */ 00047 00048 #define APPL_LOG NRF_LOG_PRINTF /**< Logger macro that will be used in this file to do logging over UART or RTT based on nrf_log configuration. */ 00049 #define APPL_LOG_DEBUG NRF_LOG_PRINTF_DEBUG /**< Debug logger macro that will be used in this file to do logging of debug information over UART or RTT based on nrf_log configuration. This will only work if DEBUG is defined*/ 00050 00051 #define SEC_PARAM_BOND 1 /**< Perform bonding. */ 00052 #define SEC_PARAM_MITM 1 /**< Man In The Middle protection not required. */ 00053 #define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ 00054 #define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ 00055 #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ 00056 #define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ 00057 #define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ 00058 #define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ 00059 00060 #define SCAN_INTERVAL 0x00A0 /**< Determines scan interval in units of 0.625 millisecond. */ 00061 #define SCAN_WINDOW 0x0050 /**< Determines scan window in units of 0.625 millisecond. */ 00062 00063 #define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Determines minimum connection interval in millisecond. */ 00064 #define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(30, UNIT_1_25_MS) /**< Determines maximum connection interval in millisecond. */ 00065 #define SLAVE_LATENCY 0 /**< Determines slave latency in counts of connection events. */ 00066 #define SUPERVISION_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Determines supervision time-out in units of 10 millisecond. */ 00067 00068 #define TARGET_UUID 0x180D /**< Target device name that application is looking for. */ 00069 #define UUID16_SIZE 2 /**< Size of 16 bit UUID */ 00070 00071 /**@breif Macro to unpack 16bit unsigned UUID from octet stream. */ 00072 #define UUID16_EXTRACT(DST, SRC) \ 00073 do \ 00074 { \ 00075 (*(DST)) = (SRC)[1]; \ 00076 (*(DST)) <<= 8; \ 00077 (*(DST)) |= (SRC)[0]; \ 00078 } while (0) 00079 00080 /**@brief Variable length data encapsulation in terms of length and pointer to data */ 00081 typedef struct 00082 { 00083 uint8_t * p_data; /**< Pointer to data. */ 00084 uint16_t data_len; /**< Length of data. */ 00085 }data_t; 00086 00087 typedef enum 00088 { 00089 BLE_NO_SCAN, /**< No advertising running. */ 00090 BLE_WHITELIST_SCAN, /**< Advertising with whitelist. */ 00091 BLE_FAST_SCAN, /**< Fast advertising running. */ 00092 } ble_scan_mode_t; 00093 00094 static ble_db_discovery_t m_ble_db_discovery; /**< Structure used to identify the DB Discovery module. */ 00095 static ble_hrs_c_t m_ble_hrs_c; /**< Structure used to identify the heart rate client module. */ 00096 static ble_bas_c_t m_ble_bas_c; /**< Structure used to identify the Battery Service client module. */ 00097 static ble_gap_scan_params_t m_scan_param; /**< Scan parameters requested for scanning and connection. */ 00098 static dm_application_instance_t m_dm_app_id; /**< Application identifier. */ 00099 static dm_handle_t m_dm_device_handle; /**< Device Identifier identifier. */ 00100 static uint8_t m_peer_count = 0; /**< Number of peer's connected. */ 00101 static ble_scan_mode_t m_scan_mode = BLE_FAST_SCAN; /**< Scan mode used by application. */ 00102 static uint16_t m_conn_handle; /**< Current connection handle. */ 00103 static volatile bool m_whitelist_temporarily_disabled = false; /**< True if whitelist has been temporarily disabled. */ 00104 00105 static bool m_memory_access_in_progress = false; /**< Flag to keep track of ongoing operations on persistent memory. */ 00106 00107 /** 00108 * @brief Connection parameters requested for connection. 00109 */ 00110 static const ble_gap_conn_params_t m_connection_param = 00111 { 00112 (uint16_t)MIN_CONNECTION_INTERVAL, // Minimum connection 00113 (uint16_t)MAX_CONNECTION_INTERVAL, // Maximum connection 00114 0, // Slave latency 00115 (uint16_t)SUPERVISION_TIMEOUT // Supervision time-out 00116 }; 00117 00118 static void scan_start(void); 00119 00120 00121 /**@brief Function for asserts in the SoftDevice. 00122 * 00123 * @details This function will be called in case of an assert in the SoftDevice. 00124 * 00125 * @warning This handler is an example only and does not fit a final product. You need to analyze 00126 * how your product is supposed to react in case of Assert. 00127 * @warning On assert from the SoftDevice, the system can only recover on reset. 00128 * 00129 * @param[in] line_num Line number of the failing ASSERT call. 00130 * @param[in] p_file_name File name of the failing ASSERT call. 00131 */ 00132 void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) 00133 { 00134 app_error_handler(0xDEADBEEF, line_num, p_file_name); 00135 } 00136 00137 void uart_error_handle(app_uart_evt_t * p_event) 00138 { 00139 if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR) 00140 { 00141 APP_ERROR_HANDLER(p_event->data.error_communication); 00142 } 00143 else if (p_event->evt_type == APP_UART_FIFO_ERROR) 00144 { 00145 APP_ERROR_HANDLER(p_event->data.error_code); 00146 } 00147 } 00148 00149 00150 /**@brief Function for handling database discovery events. 00151 * 00152 * @details This function is callback function to handle events from the database discovery module. 00153 * Depending on the UUIDs that are discovered, this function should forward the events 00154 * to their respective services. 00155 * 00156 * @param[in] p_event Pointer to the database discovery event. 00157 */ 00158 static void db_disc_handler(ble_db_discovery_evt_t * p_evt) 00159 { 00160 ble_hrs_on_db_disc_evt(&m_ble_hrs_c, p_evt); 00161 ble_bas_on_db_disc_evt(&m_ble_bas_c, p_evt); 00162 } 00163 00164 00165 /**@brief Callback handling device manager events. 00166 * 00167 * @details This function is called to notify the application of device manager events. 00168 * 00169 * @param[in] p_handle Device Manager Handle. For link related events, this parameter 00170 * identifies the peer. 00171 * @param[in] p_event Pointer to the device manager event. 00172 * @param[in] event_status Status of the event. 00173 */ 00174 static ret_code_t device_manager_event_handler(const dm_handle_t * p_handle, 00175 const dm_event_t * p_event, 00176 const ret_code_t event_result) 00177 { 00178 uint32_t err_code; 00179 00180 switch (p_event->event_id) 00181 { 00182 case DM_EVT_CONNECTION: 00183 { 00184 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_CONNECTION\r\n"); 00185 #ifdef ENABLE_DEBUG_LOG_SUPPORT 00186 ble_gap_addr_t * peer_addr; 00187 peer_addr = &p_event->event_param.p_gap_param->params.connected.peer_addr; 00188 APPL_LOG_DEBUG("[APPL]:[%02X %02X %02X %02X %02X %02X]: Connection Established\r\n", 00189 peer_addr->addr[0], peer_addr->addr[1], peer_addr->addr[2], 00190 peer_addr->addr[3], peer_addr->addr[4], peer_addr->addr[5]); 00191 #endif // ENABLE_DEBUG_LOG_SUPPORT 00192 00193 err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); 00194 APP_ERROR_CHECK(err_code); 00195 00196 m_conn_handle = p_event->event_param.p_gap_param->conn_handle; 00197 00198 m_dm_device_handle = (*p_handle); 00199 00200 // Initiate bonding. 00201 err_code = dm_security_setup_req(&m_dm_device_handle); 00202 APP_ERROR_CHECK(err_code); 00203 00204 m_peer_count++; 00205 00206 if (m_peer_count < CENTRAL_LINK_COUNT) 00207 { 00208 scan_start(); 00209 } 00210 APPL_LOG_DEBUG("[APPL]: << DM_EVT_CONNECTION\r\n"); 00211 break; 00212 } 00213 00214 case DM_EVT_DISCONNECTION: 00215 { 00216 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DISCONNECTION\r\n"); 00217 memset(&m_ble_db_discovery, 0 , sizeof (m_ble_db_discovery)); 00218 00219 err_code = bsp_indication_set(BSP_INDICATE_IDLE); 00220 APP_ERROR_CHECK(err_code); 00221 00222 if (m_peer_count == CENTRAL_LINK_COUNT) 00223 { 00224 scan_start(); 00225 } 00226 m_peer_count--; 00227 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DISCONNECTION\r\n"); 00228 break; 00229 } 00230 00231 case DM_EVT_SECURITY_SETUP: 00232 { 00233 APPL_LOG_DEBUG("[APPL]:[0x%02X] >> DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id); 00234 // Slave securtiy request received from peer, if from a non bonded device, 00235 // initiate security setup, else, wait for encryption to complete. 00236 err_code = dm_security_setup_req(&m_dm_device_handle); 00237 APP_ERROR_CHECK(err_code); 00238 APPL_LOG_DEBUG("[APPL]:[0x%02X] << DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id); 00239 break; 00240 } 00241 00242 case DM_EVT_SECURITY_SETUP_COMPLETE: 00243 { 00244 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_SECURITY_SETUP_COMPLETE\r\n"); 00245 APPL_LOG_DEBUG("[APPL]: << DM_EVT_SECURITY_SETUP_COMPLETE\r\n"); 00246 break; 00247 } 00248 00249 case DM_EVT_LINK_SECURED: 00250 APPL_LOG_DEBUG("[APPL]: >> DM_LINK_SECURED_IND\r\n"); 00251 // Discover peer's services. 00252 err_code = ble_db_discovery_start(&m_ble_db_discovery, 00253 p_event->event_param.p_gap_param->conn_handle); 00254 APP_ERROR_CHECK(err_code); 00255 APPL_LOG_DEBUG("[APPL]: << DM_LINK_SECURED_IND\r\n"); 00256 break; 00257 00258 case DM_EVT_DEVICE_CONTEXT_LOADED: 00259 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_LINK_SECURED\r\n"); 00260 APP_ERROR_CHECK(event_result); 00261 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_LOADED\r\n"); 00262 break; 00263 00264 case DM_EVT_DEVICE_CONTEXT_STORED: 00265 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_STORED\r\n"); 00266 APP_ERROR_CHECK(event_result); 00267 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_STORED\r\n"); 00268 break; 00269 00270 case DM_EVT_DEVICE_CONTEXT_DELETED: 00271 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_DELETED\r\n"); 00272 APP_ERROR_CHECK(event_result); 00273 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_DELETED\r\n"); 00274 break; 00275 00276 default: 00277 break; 00278 } 00279 00280 return NRF_SUCCESS; 00281 } 00282 00283 00284 /** 00285 * @brief Parses advertisement data, providing length and location of the field in case 00286 * matching data is found. 00287 * 00288 * @param[in] Type of data to be looked for in advertisement data. 00289 * @param[in] Advertisement report length and pointer to report. 00290 * @param[out] If data type requested is found in the data report, type data length and 00291 * pointer to data will be populated here. 00292 * 00293 * @retval NRF_SUCCESS if the data type is found in the report. 00294 * @retval NRF_ERROR_NOT_FOUND if the data type could not be found. 00295 */ 00296 static uint32_t adv_report_parse(uint8_t type, data_t * p_advdata, data_t * p_typedata) 00297 { 00298 uint32_t index = 0; 00299 uint8_t * p_data; 00300 00301 p_data = p_advdata->p_data; 00302 00303 while (index < p_advdata->data_len) 00304 { 00305 uint8_t field_length = p_data[index]; 00306 uint8_t field_type = p_data[index+1]; 00307 00308 if (field_type == type) 00309 { 00310 p_typedata->p_data = &p_data[index+2]; 00311 p_typedata->data_len = field_length-1; 00312 return NRF_SUCCESS; 00313 } 00314 index += field_length + 1; 00315 } 00316 return NRF_ERROR_NOT_FOUND; 00317 } 00318 00319 00320 /**@brief Function for putting the chip into sleep mode. 00321 * 00322 * @note This function will not return. 00323 */ 00324 static void sleep_mode_enter(void) 00325 { 00326 uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); 00327 APP_ERROR_CHECK(err_code); 00328 00329 // Prepare wakeup buttons. 00330 err_code = bsp_btn_ble_sleep_mode_prepare(); 00331 APP_ERROR_CHECK(err_code); 00332 00333 // Go to system-off mode (this function will not return; wakeup will cause a reset). 00334 err_code = sd_power_system_off(); 00335 APP_ERROR_CHECK(err_code); 00336 } 00337 00338 00339 /**@brief Function for handling the Application's BLE Stack events. 00340 * 00341 * @param[in] p_ble_evt Bluetooth stack event. 00342 */ 00343 static void on_ble_evt(ble_evt_t * p_ble_evt) 00344 { 00345 uint32_t err_code; 00346 const ble_gap_evt_t * p_gap_evt = &p_ble_evt->evt.gap_evt; 00347 00348 switch (p_ble_evt->header.evt_id) 00349 { 00350 case BLE_GAP_EVT_ADV_REPORT: 00351 { 00352 data_t adv_data; 00353 data_t type_data; 00354 00355 // Initialize advertisement report for parsing. 00356 adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data; 00357 adv_data.data_len = p_gap_evt->params.adv_report.dlen; 00358 00359 err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, 00360 &adv_data, 00361 &type_data); 00362 00363 if (err_code != NRF_SUCCESS) 00364 { 00365 // Compare short local name in case complete name does not match. 00366 err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, 00367 &adv_data, 00368 &type_data); 00369 } 00370 00371 // Verify if short or complete name matches target. 00372 if (err_code == NRF_SUCCESS) 00373 { 00374 uint16_t extracted_uuid; 00375 00376 // UUIDs found, look for matching UUID 00377 for (uint32_t u_index = 0; u_index < (type_data.data_len/UUID16_SIZE); u_index++) 00378 { 00379 UUID16_EXTRACT(&extracted_uuid,&type_data.p_data[u_index * UUID16_SIZE]); 00380 00381 APPL_LOG_DEBUG("\t[APPL]: %x\r\n",extracted_uuid); 00382 00383 if(extracted_uuid == TARGET_UUID) 00384 { 00385 // Stop scanning. 00386 err_code = sd_ble_gap_scan_stop(); 00387 00388 if (err_code != NRF_SUCCESS) 00389 { 00390 APPL_LOG_DEBUG("[APPL]: Scan stop failed, reason %d\r\n", err_code); 00391 } 00392 err_code = bsp_indication_set(BSP_INDICATE_IDLE); 00393 APP_ERROR_CHECK(err_code); 00394 00395 m_scan_param.selective = 0; 00396 m_scan_param.p_whitelist = NULL; 00397 00398 // Initiate connection. 00399 err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr, 00400 &m_scan_param, 00401 &m_connection_param); 00402 00403 m_whitelist_temporarily_disabled = false; 00404 00405 if (err_code != NRF_SUCCESS) 00406 { 00407 APPL_LOG_DEBUG("[APPL]: Connection Request Failed, reason %d\r\n", err_code); 00408 } 00409 break; 00410 } 00411 } 00412 } 00413 break; 00414 } 00415 00416 case BLE_GAP_EVT_TIMEOUT: 00417 if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) 00418 { 00419 APPL_LOG_DEBUG("[APPL]: Scan timed out.\r\n"); 00420 scan_start(); 00421 } 00422 else if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) 00423 { 00424 APPL_LOG_DEBUG("[APPL]: Connection Request timed out.\r\n"); 00425 } 00426 break; 00427 case BLE_GAP_EVT_CONNECTED: 00428 { 00429 err_code = ble_hrs_c_handles_assign(&m_ble_hrs_c, p_gap_evt->conn_handle, NULL); 00430 APP_ERROR_CHECK(err_code); 00431 err_code = ble_bas_c_handles_assign(&m_ble_bas_c, p_gap_evt->conn_handle, NULL); 00432 APP_ERROR_CHECK(err_code); 00433 break; 00434 } 00435 case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: 00436 // Accepting parameters requested by peer. 00437 err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, 00438 &p_gap_evt->params.conn_param_update_request.conn_params); 00439 APP_ERROR_CHECK(err_code); 00440 break; 00441 00442 default: 00443 break; 00444 } 00445 } 00446 00447 00448 /**@brief Function for handling the Application's system events. 00449 * 00450 * @param[in] sys_evt system event. 00451 */ 00452 static void on_sys_evt(uint32_t sys_evt) 00453 { 00454 switch (sys_evt) 00455 { 00456 case NRF_EVT_FLASH_OPERATION_SUCCESS: 00457 /* fall through */ 00458 case NRF_EVT_FLASH_OPERATION_ERROR: 00459 00460 if (m_memory_access_in_progress) 00461 { 00462 m_memory_access_in_progress = false; 00463 scan_start(); 00464 } 00465 break; 00466 00467 default: 00468 // No implementation needed. 00469 break; 00470 } 00471 } 00472 00473 00474 /**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler. 00475 * 00476 * @details This function is called from the scheduler in the main loop after a BLE stack event has 00477 * been received. 00478 * 00479 * @param[in] p_ble_evt Bluetooth stack event. 00480 */ 00481 static void ble_evt_dispatch(ble_evt_t * p_ble_evt) 00482 { 00483 dm_ble_evt_handler(p_ble_evt); 00484 ble_db_discovery_on_ble_evt(&m_ble_db_discovery, p_ble_evt); 00485 ble_hrs_c_on_ble_evt(&m_ble_hrs_c, p_ble_evt); 00486 ble_bas_c_on_ble_evt(&m_ble_bas_c, p_ble_evt); 00487 bsp_btn_ble_on_ble_evt(p_ble_evt); 00488 on_ble_evt(p_ble_evt); 00489 } 00490 00491 00492 /**@brief Function for dispatching a system event to interested modules. 00493 * 00494 * @details This function is called from the System event interrupt handler after a system 00495 * event has been received. 00496 * 00497 * @param[in] sys_evt System stack event. 00498 */ 00499 static void sys_evt_dispatch(uint32_t sys_evt) 00500 { 00501 pstorage_sys_event_handler(sys_evt); 00502 on_sys_evt(sys_evt); 00503 } 00504 00505 00506 /**@brief Function for initializing the BLE stack. 00507 * 00508 * @details Initializes the SoftDevice and the BLE event interrupt. 00509 */ 00510 static void ble_stack_init(void) 00511 { 00512 uint32_t err_code; 00513 00514 nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; 00515 00516 // Initialize the SoftDevice handler module. 00517 SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL); 00518 00519 ble_enable_params_t ble_enable_params; 00520 err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, 00521 PERIPHERAL_LINK_COUNT, 00522 &ble_enable_params); 00523 APP_ERROR_CHECK(err_code); 00524 00525 //Check the ram settings against the used number of links 00526 CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT); 00527 00528 // Enable BLE stack. 00529 err_code = softdevice_enable(&ble_enable_params); 00530 APP_ERROR_CHECK(err_code); 00531 00532 // Register with the SoftDevice handler module for BLE events. 00533 err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); 00534 APP_ERROR_CHECK(err_code); 00535 00536 // Register with the SoftDevice handler module for System events. 00537 err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); 00538 APP_ERROR_CHECK(err_code); 00539 } 00540 00541 00542 /**@brief Function for the Device Manager initialization. 00543 * 00544 * @param[in] erase_bonds Indicates whether bonding information should be cleared from 00545 * persistent storage during initialization of the Device Manager. 00546 */ 00547 static void device_manager_init(bool erase_bonds) 00548 { 00549 uint32_t err_code; 00550 dm_init_param_t init_param = {.clear_persistent_data = erase_bonds}; 00551 dm_application_param_t register_param; 00552 00553 err_code = pstorage_init(); 00554 APP_ERROR_CHECK(err_code); 00555 00556 err_code = dm_init(&init_param); 00557 APP_ERROR_CHECK(err_code); 00558 00559 memset(®ister_param.sec_param, 0, sizeof (ble_gap_sec_params_t)); 00560 00561 // Event handler to be registered with the module. 00562 register_param.evt_handler = device_manager_event_handler; 00563 00564 // Service or protocol context for device manager to load, store and apply on behalf of application. 00565 // Here set to client as application is a GATT client. 00566 register_param.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID; 00567 00568 // Secuirty parameters to be used for security procedures. 00569 register_param.sec_param.bond = SEC_PARAM_BOND; 00570 register_param.sec_param.mitm = SEC_PARAM_MITM; 00571 register_param.sec_param.lesc = SEC_PARAM_LESC; 00572 register_param.sec_param.keypress = SEC_PARAM_KEYPRESS; 00573 register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; 00574 register_param.sec_param.oob = SEC_PARAM_OOB; 00575 register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; 00576 register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; 00577 register_param.sec_param.kdist_peer.enc = 1; 00578 register_param.sec_param.kdist_peer.id = 1; 00579 00580 err_code = dm_register(&m_dm_app_id, ®ister_param); 00581 APP_ERROR_CHECK(err_code); 00582 } 00583 00584 00585 /**@brief Function for disabling the use of whitelist for scanning. 00586 */ 00587 static void whitelist_disable(void) 00588 { 00589 uint32_t err_code; 00590 00591 if ((m_scan_mode == BLE_WHITELIST_SCAN) && !m_whitelist_temporarily_disabled) 00592 { 00593 m_whitelist_temporarily_disabled = true; 00594 00595 err_code = sd_ble_gap_scan_stop(); 00596 if (err_code == NRF_SUCCESS) 00597 { 00598 scan_start(); 00599 } 00600 else if (err_code != NRF_ERROR_INVALID_STATE) 00601 { 00602 APP_ERROR_CHECK(err_code); 00603 } 00604 } 00605 m_whitelist_temporarily_disabled = true; 00606 } 00607 00608 00609 /**@brief Function for handling events from the BSP module. 00610 * 00611 * @param[in] event Event generated by button press. 00612 */ 00613 void bsp_event_handler(bsp_event_t event) 00614 { 00615 uint32_t err_code; 00616 switch (event) 00617 { 00618 case BSP_EVENT_SLEEP: 00619 sleep_mode_enter(); 00620 break; 00621 00622 case BSP_EVENT_DISCONNECT: 00623 err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); 00624 if (err_code != NRF_ERROR_INVALID_STATE) 00625 { 00626 APP_ERROR_CHECK(err_code); 00627 } 00628 break; 00629 00630 case BSP_EVENT_WHITELIST_OFF: 00631 whitelist_disable(); 00632 break; 00633 00634 default: 00635 break; 00636 } 00637 } 00638 00639 00640 /**@brief Heart Rate Collector Handler. 00641 */ 00642 static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt) 00643 { 00644 uint32_t err_code; 00645 00646 switch (p_hrs_c_evt->evt_type) 00647 { 00648 case BLE_HRS_C_EVT_DISCOVERY_COMPLETE: 00649 00650 // Heart rate service discovered. Enable notification of Heart Rate Measurement. 00651 err_code = ble_hrs_c_hrm_notif_enable(p_hrs_c); 00652 APP_ERROR_CHECK(err_code); 00653 00654 APPL_LOG_DEBUG("Heart rate service discovered \r\n"); 00655 break; 00656 00657 case BLE_HRS_C_EVT_HRM_NOTIFICATION: 00658 { 00659 APPL_LOG_DEBUG("[APPL]: HR Measurement received %d \r\n", p_hrs_c_evt->params.hrm.hr_value); 00660 00661 APPL_LOG("Heart Rate = %d\r\n", p_hrs_c_evt->params.hrm.hr_value); 00662 break; 00663 } 00664 00665 default: 00666 break; 00667 } 00668 } 00669 00670 00671 /**@brief Battery levelCollector Handler. 00672 */ 00673 static void bas_c_evt_handler(ble_bas_c_t * p_bas_c, ble_bas_c_evt_t * p_bas_c_evt) 00674 { 00675 uint32_t err_code; 00676 00677 switch (p_bas_c_evt->evt_type) 00678 { 00679 case BLE_BAS_C_EVT_DISCOVERY_COMPLETE: 00680 // Batttery service discovered. Enable notification of Battery Level. 00681 APPL_LOG_DEBUG("[APPL]: Battery Service discovered. \r\n"); 00682 00683 APPL_LOG_DEBUG("[APPL]: Reading battery level. \r\n"); 00684 00685 err_code = ble_bas_c_bl_read(p_bas_c); 00686 APP_ERROR_CHECK(err_code); 00687 00688 00689 APPL_LOG_DEBUG("[APPL]: Enabling Battery Level Notification. \r\n"); 00690 err_code = ble_bas_c_bl_notif_enable(p_bas_c); 00691 APP_ERROR_CHECK(err_code); 00692 00693 break; 00694 00695 case BLE_BAS_C_EVT_BATT_NOTIFICATION: 00696 { 00697 APPL_LOG_DEBUG("[APPL]: Battery Level received %d %%\r\n", p_bas_c_evt->params.battery_level); 00698 00699 APPL_LOG_DEBUG("Battery = %d %%\r\n", p_bas_c_evt->params.battery_level); 00700 break; 00701 } 00702 00703 case BLE_BAS_C_EVT_BATT_READ_RESP: 00704 { 00705 APPL_LOG_DEBUG("[APPL]: Battery Level Read as %d %%\r\n", p_bas_c_evt->params.battery_level); 00706 00707 APPL_LOG_DEBUG("Battery = %d %%\r\n", p_bas_c_evt->params.battery_level); 00708 break; 00709 } 00710 00711 default: 00712 break; 00713 } 00714 } 00715 00716 00717 /** 00718 * @brief Heart rate collector initialization. 00719 */ 00720 static void hrs_c_init(void) 00721 { 00722 ble_hrs_c_init_t hrs_c_init_obj; 00723 00724 hrs_c_init_obj.evt_handler = hrs_c_evt_handler; 00725 00726 uint32_t err_code = ble_hrs_c_init(&m_ble_hrs_c, &hrs_c_init_obj); 00727 APP_ERROR_CHECK(err_code); 00728 } 00729 00730 00731 /** 00732 * @brief Battery level collector initialization. 00733 */ 00734 static void bas_c_init(void) 00735 { 00736 ble_bas_c_init_t bas_c_init_obj; 00737 00738 bas_c_init_obj.evt_handler = bas_c_evt_handler; 00739 00740 uint32_t err_code = ble_bas_c_init(&m_ble_bas_c, &bas_c_init_obj); 00741 APP_ERROR_CHECK(err_code); 00742 } 00743 00744 00745 /** 00746 * @brief Database discovery collector initialization. 00747 */ 00748 static void db_discovery_init(void) 00749 { 00750 uint32_t err_code = ble_db_discovery_init(db_disc_handler); 00751 00752 APP_ERROR_CHECK(err_code); 00753 } 00754 00755 00756 /**@brief Function to start scanning. 00757 */ 00758 static void scan_start(void) 00759 { 00760 ble_gap_whitelist_t whitelist; 00761 ble_gap_addr_t * p_whitelist_addr[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; 00762 ble_gap_irk_t * p_whitelist_irk[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; 00763 uint32_t err_code; 00764 uint32_t count; 00765 00766 // Verify if there is any flash access pending, if yes delay starting scanning until 00767 // it's complete. 00768 err_code = pstorage_access_status_get(&count); 00769 APP_ERROR_CHECK(err_code); 00770 00771 if (count != 0) 00772 { 00773 m_memory_access_in_progress = true; 00774 return; 00775 } 00776 00777 // Initialize whitelist parameters. 00778 whitelist.addr_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; 00779 whitelist.irk_count = 0; 00780 whitelist.pp_addrs = p_whitelist_addr; 00781 whitelist.pp_irks = p_whitelist_irk; 00782 00783 // Request creating of whitelist. 00784 err_code = dm_whitelist_create(&m_dm_app_id,&whitelist); 00785 APP_ERROR_CHECK(err_code); 00786 00787 if (((whitelist.addr_count == 0) && (whitelist.irk_count == 0)) || 00788 (m_scan_mode != BLE_WHITELIST_SCAN) || 00789 (m_whitelist_temporarily_disabled)) 00790 { 00791 // No devices in whitelist, hence non selective performed. 00792 m_scan_param.active = 0; // Active scanning set. 00793 m_scan_param.selective = 0; // Selective scanning not set. 00794 m_scan_param.interval = SCAN_INTERVAL;// Scan interval. 00795 m_scan_param.window = SCAN_WINDOW; // Scan window. 00796 m_scan_param.p_whitelist = NULL; // No whitelist provided. 00797 m_scan_param.timeout = 0x0000; // No timeout. 00798 } 00799 else 00800 { 00801 // Selective scanning based on whitelist first. 00802 m_scan_param.active = 0; // Active scanning set. 00803 m_scan_param.selective = 1; // Selective scanning not set. 00804 m_scan_param.interval = SCAN_INTERVAL;// Scan interval. 00805 m_scan_param.window = SCAN_WINDOW; // Scan window. 00806 m_scan_param.p_whitelist = &whitelist; // Provide whitelist. 00807 m_scan_param.timeout = 0x001E; // 30 seconds timeout. 00808 } 00809 00810 err_code = sd_ble_gap_scan_start(&m_scan_param); 00811 APP_ERROR_CHECK(err_code); 00812 00813 err_code = bsp_indication_set(BSP_INDICATE_SCANNING); 00814 APP_ERROR_CHECK(err_code); 00815 } 00816 00817 00818 /**@brief Function for initializing buttons and leds. 00819 * 00820 * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up. 00821 */ 00822 static void buttons_leds_init(bool * p_erase_bonds) 00823 { 00824 bsp_event_t startup_event; 00825 00826 uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, 00827 APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), 00828 bsp_event_handler); 00829 APP_ERROR_CHECK(err_code); 00830 00831 err_code = bsp_btn_ble_init(NULL, &startup_event); 00832 APP_ERROR_CHECK(err_code); 00833 00834 *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); 00835 } 00836 00837 00838 /**@brief Function for initializing the nrf log module. 00839 */ 00840 static void nrf_log_init(void) 00841 { 00842 ret_code_t err_code = NRF_LOG_INIT(); 00843 APP_ERROR_CHECK(err_code); 00844 } 00845 00846 00847 /** @brief Function for the Power manager. 00848 */ 00849 static void power_manage(void) 00850 { 00851 uint32_t err_code = sd_app_evt_wait(); 00852 APP_ERROR_CHECK(err_code); 00853 } 00854 00855 00856 int main(void) 00857 { 00858 bool erase_bonds; 00859 00860 // Initialize. 00861 APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL); 00862 buttons_leds_init(&erase_bonds); 00863 nrf_log_init(); 00864 APPL_LOG("Heart rate collector example\r\n"); 00865 ble_stack_init(); 00866 device_manager_init(erase_bonds); 00867 db_discovery_init(); 00868 hrs_c_init(); 00869 bas_c_init(); 00870 00871 // Start scanning for peripherals and initiate connection 00872 // with devices that advertise Heart Rate UUID. 00873 scan_start(); 00874 00875 for (;; ) 00876 { 00877 power_manage(); 00878 } 00879 } 00880 00881 00882
Generated on Wed Jul 13 2022 07:07:19 by 1.7.2