BLE_Nano nRF51 Central heart rate

Committer:
FranKP2138
Date:
Thu May 26 10:12:27 2016 +0000
Revision:
0:2b9b5764efb5
RedBearLab BLE_Nano Central role for heart rate

Who changed what in which revision?

UserRevisionLine numberNew contents of line
FranKP2138 0:2b9b5764efb5 1 /*
FranKP2138 0:2b9b5764efb5 2 * Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
FranKP2138 0:2b9b5764efb5 3 *
FranKP2138 0:2b9b5764efb5 4 * The information contained herein is confidential property of Nordic Semiconductor. The use,
FranKP2138 0:2b9b5764efb5 5 * copying, transfer or disclosure of such information is prohibited except by express written
FranKP2138 0:2b9b5764efb5 6 * agreement with Nordic Semiconductor.
FranKP2138 0:2b9b5764efb5 7 *
FranKP2138 0:2b9b5764efb5 8 */
FranKP2138 0:2b9b5764efb5 9
FranKP2138 0:2b9b5764efb5 10 /**
FranKP2138 0:2b9b5764efb5 11 * @brief BLE Heart Rate Collector application main file.
FranKP2138 0:2b9b5764efb5 12 *
FranKP2138 0:2b9b5764efb5 13 * This file contains the source code for a sample heart rate collector.
FranKP2138 0:2b9b5764efb5 14 */
FranKP2138 0:2b9b5764efb5 15
FranKP2138 0:2b9b5764efb5 16 #include <stdint.h>
FranKP2138 0:2b9b5764efb5 17 #include <stdio.h>
FranKP2138 0:2b9b5764efb5 18 #include <string.h>
FranKP2138 0:2b9b5764efb5 19 #include "nordic_common.h"
FranKP2138 0:2b9b5764efb5 20 #include "nrf_sdm.h"
FranKP2138 0:2b9b5764efb5 21 #include "ble.h"
FranKP2138 0:2b9b5764efb5 22 #include "ble_hci.h"
FranKP2138 0:2b9b5764efb5 23 #include "ble_db_discovery.h"
FranKP2138 0:2b9b5764efb5 24 #include "softdevice_handler.h"
FranKP2138 0:2b9b5764efb5 25 #include "app_util.h"
FranKP2138 0:2b9b5764efb5 26 #include "app_error.h"
FranKP2138 0:2b9b5764efb5 27 #include "boards.h"
FranKP2138 0:2b9b5764efb5 28 #include "nrf_gpio.h"
FranKP2138 0:2b9b5764efb5 29 #include "pstorage.h"
FranKP2138 0:2b9b5764efb5 30 #include "device_manager.h"
FranKP2138 0:2b9b5764efb5 31 #include "ble_hrs_c.h"
FranKP2138 0:2b9b5764efb5 32 #include "ble_bas_c.h"
FranKP2138 0:2b9b5764efb5 33 #include "app_util.h"
FranKP2138 0:2b9b5764efb5 34 #include "app_timer.h"
FranKP2138 0:2b9b5764efb5 35 #include "bsp.h"
FranKP2138 0:2b9b5764efb5 36 #include "bsp_btn_ble.h"
FranKP2138 0:2b9b5764efb5 37 #include "nrf_log.h"
FranKP2138 0:2b9b5764efb5 38
FranKP2138 0:2b9b5764efb5 39 #define CENTRAL_LINK_COUNT 1 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/
FranKP2138 0:2b9b5764efb5 40 #define PERIPHERAL_LINK_COUNT 0 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
FranKP2138 0:2b9b5764efb5 41
FranKP2138 0:2b9b5764efb5 42 #define STRING_BUFFER_LEN 50
FranKP2138 0:2b9b5764efb5 43 #define BOND_DELETE_ALL_BUTTON_ID 0 /**< Button used for deleting all bonded centrals during startup. */
FranKP2138 0:2b9b5764efb5 44
FranKP2138 0:2b9b5764efb5 45 #define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
FranKP2138 0:2b9b5764efb5 46 #define APP_TIMER_OP_QUEUE_SIZE 2 /**< Size of timer operation queues. */
FranKP2138 0:2b9b5764efb5 47
FranKP2138 0:2b9b5764efb5 48 #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. */
FranKP2138 0:2b9b5764efb5 49 #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*/
FranKP2138 0:2b9b5764efb5 50
FranKP2138 0:2b9b5764efb5 51 #define SEC_PARAM_BOND 1 /**< Perform bonding. */
FranKP2138 0:2b9b5764efb5 52 #define SEC_PARAM_MITM 1 /**< Man In The Middle protection not required. */
FranKP2138 0:2b9b5764efb5 53 #define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */
FranKP2138 0:2b9b5764efb5 54 #define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */
FranKP2138 0:2b9b5764efb5 55 #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */
FranKP2138 0:2b9b5764efb5 56 #define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
FranKP2138 0:2b9b5764efb5 57 #define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
FranKP2138 0:2b9b5764efb5 58 #define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */
FranKP2138 0:2b9b5764efb5 59
FranKP2138 0:2b9b5764efb5 60 #define SCAN_INTERVAL 0x00A0 /**< Determines scan interval in units of 0.625 millisecond. */
FranKP2138 0:2b9b5764efb5 61 #define SCAN_WINDOW 0x0050 /**< Determines scan window in units of 0.625 millisecond. */
FranKP2138 0:2b9b5764efb5 62
FranKP2138 0:2b9b5764efb5 63 #define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Determines minimum connection interval in millisecond. */
FranKP2138 0:2b9b5764efb5 64 #define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(30, UNIT_1_25_MS) /**< Determines maximum connection interval in millisecond. */
FranKP2138 0:2b9b5764efb5 65 #define SLAVE_LATENCY 0 /**< Determines slave latency in counts of connection events. */
FranKP2138 0:2b9b5764efb5 66 #define SUPERVISION_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Determines supervision time-out in units of 10 millisecond. */
FranKP2138 0:2b9b5764efb5 67
FranKP2138 0:2b9b5764efb5 68 #define TARGET_UUID 0x180D /**< Target device name that application is looking for. */
FranKP2138 0:2b9b5764efb5 69 #define UUID16_SIZE 2 /**< Size of 16 bit UUID */
FranKP2138 0:2b9b5764efb5 70
FranKP2138 0:2b9b5764efb5 71 /**@breif Macro to unpack 16bit unsigned UUID from octet stream. */
FranKP2138 0:2b9b5764efb5 72 #define UUID16_EXTRACT(DST, SRC) \
FranKP2138 0:2b9b5764efb5 73 do \
FranKP2138 0:2b9b5764efb5 74 { \
FranKP2138 0:2b9b5764efb5 75 (*(DST)) = (SRC)[1]; \
FranKP2138 0:2b9b5764efb5 76 (*(DST)) <<= 8; \
FranKP2138 0:2b9b5764efb5 77 (*(DST)) |= (SRC)[0]; \
FranKP2138 0:2b9b5764efb5 78 } while (0)
FranKP2138 0:2b9b5764efb5 79
FranKP2138 0:2b9b5764efb5 80 /**@brief Variable length data encapsulation in terms of length and pointer to data */
FranKP2138 0:2b9b5764efb5 81 typedef struct
FranKP2138 0:2b9b5764efb5 82 {
FranKP2138 0:2b9b5764efb5 83 uint8_t * p_data; /**< Pointer to data. */
FranKP2138 0:2b9b5764efb5 84 uint16_t data_len; /**< Length of data. */
FranKP2138 0:2b9b5764efb5 85 }data_t;
FranKP2138 0:2b9b5764efb5 86
FranKP2138 0:2b9b5764efb5 87 typedef enum
FranKP2138 0:2b9b5764efb5 88 {
FranKP2138 0:2b9b5764efb5 89 BLE_NO_SCAN, /**< No advertising running. */
FranKP2138 0:2b9b5764efb5 90 BLE_WHITELIST_SCAN, /**< Advertising with whitelist. */
FranKP2138 0:2b9b5764efb5 91 BLE_FAST_SCAN, /**< Fast advertising running. */
FranKP2138 0:2b9b5764efb5 92 } ble_scan_mode_t;
FranKP2138 0:2b9b5764efb5 93
FranKP2138 0:2b9b5764efb5 94 static ble_db_discovery_t m_ble_db_discovery; /**< Structure used to identify the DB Discovery module. */
FranKP2138 0:2b9b5764efb5 95 static ble_hrs_c_t m_ble_hrs_c; /**< Structure used to identify the heart rate client module. */
FranKP2138 0:2b9b5764efb5 96 static ble_bas_c_t m_ble_bas_c; /**< Structure used to identify the Battery Service client module. */
FranKP2138 0:2b9b5764efb5 97 static ble_gap_scan_params_t m_scan_param; /**< Scan parameters requested for scanning and connection. */
FranKP2138 0:2b9b5764efb5 98 static dm_application_instance_t m_dm_app_id; /**< Application identifier. */
FranKP2138 0:2b9b5764efb5 99 static dm_handle_t m_dm_device_handle; /**< Device Identifier identifier. */
FranKP2138 0:2b9b5764efb5 100 static uint8_t m_peer_count = 0; /**< Number of peer's connected. */
FranKP2138 0:2b9b5764efb5 101 static ble_scan_mode_t m_scan_mode = BLE_FAST_SCAN; /**< Scan mode used by application. */
FranKP2138 0:2b9b5764efb5 102 static uint16_t m_conn_handle; /**< Current connection handle. */
FranKP2138 0:2b9b5764efb5 103 static volatile bool m_whitelist_temporarily_disabled = false; /**< True if whitelist has been temporarily disabled. */
FranKP2138 0:2b9b5764efb5 104
FranKP2138 0:2b9b5764efb5 105 static bool m_memory_access_in_progress = false; /**< Flag to keep track of ongoing operations on persistent memory. */
FranKP2138 0:2b9b5764efb5 106
FranKP2138 0:2b9b5764efb5 107 /**
FranKP2138 0:2b9b5764efb5 108 * @brief Connection parameters requested for connection.
FranKP2138 0:2b9b5764efb5 109 */
FranKP2138 0:2b9b5764efb5 110 static const ble_gap_conn_params_t m_connection_param =
FranKP2138 0:2b9b5764efb5 111 {
FranKP2138 0:2b9b5764efb5 112 (uint16_t)MIN_CONNECTION_INTERVAL, // Minimum connection
FranKP2138 0:2b9b5764efb5 113 (uint16_t)MAX_CONNECTION_INTERVAL, // Maximum connection
FranKP2138 0:2b9b5764efb5 114 0, // Slave latency
FranKP2138 0:2b9b5764efb5 115 (uint16_t)SUPERVISION_TIMEOUT // Supervision time-out
FranKP2138 0:2b9b5764efb5 116 };
FranKP2138 0:2b9b5764efb5 117
FranKP2138 0:2b9b5764efb5 118 static void scan_start(void);
FranKP2138 0:2b9b5764efb5 119
FranKP2138 0:2b9b5764efb5 120
FranKP2138 0:2b9b5764efb5 121 /**@brief Function for asserts in the SoftDevice.
FranKP2138 0:2b9b5764efb5 122 *
FranKP2138 0:2b9b5764efb5 123 * @details This function will be called in case of an assert in the SoftDevice.
FranKP2138 0:2b9b5764efb5 124 *
FranKP2138 0:2b9b5764efb5 125 * @warning This handler is an example only and does not fit a final product. You need to analyze
FranKP2138 0:2b9b5764efb5 126 * how your product is supposed to react in case of Assert.
FranKP2138 0:2b9b5764efb5 127 * @warning On assert from the SoftDevice, the system can only recover on reset.
FranKP2138 0:2b9b5764efb5 128 *
FranKP2138 0:2b9b5764efb5 129 * @param[in] line_num Line number of the failing ASSERT call.
FranKP2138 0:2b9b5764efb5 130 * @param[in] p_file_name File name of the failing ASSERT call.
FranKP2138 0:2b9b5764efb5 131 */
FranKP2138 0:2b9b5764efb5 132 void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
FranKP2138 0:2b9b5764efb5 133 {
FranKP2138 0:2b9b5764efb5 134 app_error_handler(0xDEADBEEF, line_num, p_file_name);
FranKP2138 0:2b9b5764efb5 135 }
FranKP2138 0:2b9b5764efb5 136
FranKP2138 0:2b9b5764efb5 137 void uart_error_handle(app_uart_evt_t * p_event)
FranKP2138 0:2b9b5764efb5 138 {
FranKP2138 0:2b9b5764efb5 139 if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR)
FranKP2138 0:2b9b5764efb5 140 {
FranKP2138 0:2b9b5764efb5 141 APP_ERROR_HANDLER(p_event->data.error_communication);
FranKP2138 0:2b9b5764efb5 142 }
FranKP2138 0:2b9b5764efb5 143 else if (p_event->evt_type == APP_UART_FIFO_ERROR)
FranKP2138 0:2b9b5764efb5 144 {
FranKP2138 0:2b9b5764efb5 145 APP_ERROR_HANDLER(p_event->data.error_code);
FranKP2138 0:2b9b5764efb5 146 }
FranKP2138 0:2b9b5764efb5 147 }
FranKP2138 0:2b9b5764efb5 148
FranKP2138 0:2b9b5764efb5 149
FranKP2138 0:2b9b5764efb5 150 /**@brief Function for handling database discovery events.
FranKP2138 0:2b9b5764efb5 151 *
FranKP2138 0:2b9b5764efb5 152 * @details This function is callback function to handle events from the database discovery module.
FranKP2138 0:2b9b5764efb5 153 * Depending on the UUIDs that are discovered, this function should forward the events
FranKP2138 0:2b9b5764efb5 154 * to their respective services.
FranKP2138 0:2b9b5764efb5 155 *
FranKP2138 0:2b9b5764efb5 156 * @param[in] p_event Pointer to the database discovery event.
FranKP2138 0:2b9b5764efb5 157 */
FranKP2138 0:2b9b5764efb5 158 static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
FranKP2138 0:2b9b5764efb5 159 {
FranKP2138 0:2b9b5764efb5 160 ble_hrs_on_db_disc_evt(&m_ble_hrs_c, p_evt);
FranKP2138 0:2b9b5764efb5 161 ble_bas_on_db_disc_evt(&m_ble_bas_c, p_evt);
FranKP2138 0:2b9b5764efb5 162 }
FranKP2138 0:2b9b5764efb5 163
FranKP2138 0:2b9b5764efb5 164
FranKP2138 0:2b9b5764efb5 165 /**@brief Callback handling device manager events.
FranKP2138 0:2b9b5764efb5 166 *
FranKP2138 0:2b9b5764efb5 167 * @details This function is called to notify the application of device manager events.
FranKP2138 0:2b9b5764efb5 168 *
FranKP2138 0:2b9b5764efb5 169 * @param[in] p_handle Device Manager Handle. For link related events, this parameter
FranKP2138 0:2b9b5764efb5 170 * identifies the peer.
FranKP2138 0:2b9b5764efb5 171 * @param[in] p_event Pointer to the device manager event.
FranKP2138 0:2b9b5764efb5 172 * @param[in] event_status Status of the event.
FranKP2138 0:2b9b5764efb5 173 */
FranKP2138 0:2b9b5764efb5 174 static ret_code_t device_manager_event_handler(const dm_handle_t * p_handle,
FranKP2138 0:2b9b5764efb5 175 const dm_event_t * p_event,
FranKP2138 0:2b9b5764efb5 176 const ret_code_t event_result)
FranKP2138 0:2b9b5764efb5 177 {
FranKP2138 0:2b9b5764efb5 178 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 179
FranKP2138 0:2b9b5764efb5 180 switch (p_event->event_id)
FranKP2138 0:2b9b5764efb5 181 {
FranKP2138 0:2b9b5764efb5 182 case DM_EVT_CONNECTION:
FranKP2138 0:2b9b5764efb5 183 {
FranKP2138 0:2b9b5764efb5 184 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_CONNECTION\r\n");
FranKP2138 0:2b9b5764efb5 185 #ifdef ENABLE_DEBUG_LOG_SUPPORT
FranKP2138 0:2b9b5764efb5 186 ble_gap_addr_t * peer_addr;
FranKP2138 0:2b9b5764efb5 187 peer_addr = &p_event->event_param.p_gap_param->params.connected.peer_addr;
FranKP2138 0:2b9b5764efb5 188 APPL_LOG_DEBUG("[APPL]:[%02X %02X %02X %02X %02X %02X]: Connection Established\r\n",
FranKP2138 0:2b9b5764efb5 189 peer_addr->addr[0], peer_addr->addr[1], peer_addr->addr[2],
FranKP2138 0:2b9b5764efb5 190 peer_addr->addr[3], peer_addr->addr[4], peer_addr->addr[5]);
FranKP2138 0:2b9b5764efb5 191 #endif // ENABLE_DEBUG_LOG_SUPPORT
FranKP2138 0:2b9b5764efb5 192
FranKP2138 0:2b9b5764efb5 193 err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
FranKP2138 0:2b9b5764efb5 194 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 195
FranKP2138 0:2b9b5764efb5 196 m_conn_handle = p_event->event_param.p_gap_param->conn_handle;
FranKP2138 0:2b9b5764efb5 197
FranKP2138 0:2b9b5764efb5 198 m_dm_device_handle = (*p_handle);
FranKP2138 0:2b9b5764efb5 199
FranKP2138 0:2b9b5764efb5 200 // Initiate bonding.
FranKP2138 0:2b9b5764efb5 201 err_code = dm_security_setup_req(&m_dm_device_handle);
FranKP2138 0:2b9b5764efb5 202 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 203
FranKP2138 0:2b9b5764efb5 204 m_peer_count++;
FranKP2138 0:2b9b5764efb5 205
FranKP2138 0:2b9b5764efb5 206 if (m_peer_count < CENTRAL_LINK_COUNT)
FranKP2138 0:2b9b5764efb5 207 {
FranKP2138 0:2b9b5764efb5 208 scan_start();
FranKP2138 0:2b9b5764efb5 209 }
FranKP2138 0:2b9b5764efb5 210 APPL_LOG_DEBUG("[APPL]: << DM_EVT_CONNECTION\r\n");
FranKP2138 0:2b9b5764efb5 211 break;
FranKP2138 0:2b9b5764efb5 212 }
FranKP2138 0:2b9b5764efb5 213
FranKP2138 0:2b9b5764efb5 214 case DM_EVT_DISCONNECTION:
FranKP2138 0:2b9b5764efb5 215 {
FranKP2138 0:2b9b5764efb5 216 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DISCONNECTION\r\n");
FranKP2138 0:2b9b5764efb5 217 memset(&m_ble_db_discovery, 0 , sizeof (m_ble_db_discovery));
FranKP2138 0:2b9b5764efb5 218
FranKP2138 0:2b9b5764efb5 219 err_code = bsp_indication_set(BSP_INDICATE_IDLE);
FranKP2138 0:2b9b5764efb5 220 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 221
FranKP2138 0:2b9b5764efb5 222 if (m_peer_count == CENTRAL_LINK_COUNT)
FranKP2138 0:2b9b5764efb5 223 {
FranKP2138 0:2b9b5764efb5 224 scan_start();
FranKP2138 0:2b9b5764efb5 225 }
FranKP2138 0:2b9b5764efb5 226 m_peer_count--;
FranKP2138 0:2b9b5764efb5 227 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DISCONNECTION\r\n");
FranKP2138 0:2b9b5764efb5 228 break;
FranKP2138 0:2b9b5764efb5 229 }
FranKP2138 0:2b9b5764efb5 230
FranKP2138 0:2b9b5764efb5 231 case DM_EVT_SECURITY_SETUP:
FranKP2138 0:2b9b5764efb5 232 {
FranKP2138 0:2b9b5764efb5 233 APPL_LOG_DEBUG("[APPL]:[0x%02X] >> DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id);
FranKP2138 0:2b9b5764efb5 234 // Slave securtiy request received from peer, if from a non bonded device,
FranKP2138 0:2b9b5764efb5 235 // initiate security setup, else, wait for encryption to complete.
FranKP2138 0:2b9b5764efb5 236 err_code = dm_security_setup_req(&m_dm_device_handle);
FranKP2138 0:2b9b5764efb5 237 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 238 APPL_LOG_DEBUG("[APPL]:[0x%02X] << DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id);
FranKP2138 0:2b9b5764efb5 239 break;
FranKP2138 0:2b9b5764efb5 240 }
FranKP2138 0:2b9b5764efb5 241
FranKP2138 0:2b9b5764efb5 242 case DM_EVT_SECURITY_SETUP_COMPLETE:
FranKP2138 0:2b9b5764efb5 243 {
FranKP2138 0:2b9b5764efb5 244 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_SECURITY_SETUP_COMPLETE\r\n");
FranKP2138 0:2b9b5764efb5 245 APPL_LOG_DEBUG("[APPL]: << DM_EVT_SECURITY_SETUP_COMPLETE\r\n");
FranKP2138 0:2b9b5764efb5 246 break;
FranKP2138 0:2b9b5764efb5 247 }
FranKP2138 0:2b9b5764efb5 248
FranKP2138 0:2b9b5764efb5 249 case DM_EVT_LINK_SECURED:
FranKP2138 0:2b9b5764efb5 250 APPL_LOG_DEBUG("[APPL]: >> DM_LINK_SECURED_IND\r\n");
FranKP2138 0:2b9b5764efb5 251 // Discover peer's services.
FranKP2138 0:2b9b5764efb5 252 err_code = ble_db_discovery_start(&m_ble_db_discovery,
FranKP2138 0:2b9b5764efb5 253 p_event->event_param.p_gap_param->conn_handle);
FranKP2138 0:2b9b5764efb5 254 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 255 APPL_LOG_DEBUG("[APPL]: << DM_LINK_SECURED_IND\r\n");
FranKP2138 0:2b9b5764efb5 256 break;
FranKP2138 0:2b9b5764efb5 257
FranKP2138 0:2b9b5764efb5 258 case DM_EVT_DEVICE_CONTEXT_LOADED:
FranKP2138 0:2b9b5764efb5 259 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_LINK_SECURED\r\n");
FranKP2138 0:2b9b5764efb5 260 APP_ERROR_CHECK(event_result);
FranKP2138 0:2b9b5764efb5 261 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_LOADED\r\n");
FranKP2138 0:2b9b5764efb5 262 break;
FranKP2138 0:2b9b5764efb5 263
FranKP2138 0:2b9b5764efb5 264 case DM_EVT_DEVICE_CONTEXT_STORED:
FranKP2138 0:2b9b5764efb5 265 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_STORED\r\n");
FranKP2138 0:2b9b5764efb5 266 APP_ERROR_CHECK(event_result);
FranKP2138 0:2b9b5764efb5 267 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_STORED\r\n");
FranKP2138 0:2b9b5764efb5 268 break;
FranKP2138 0:2b9b5764efb5 269
FranKP2138 0:2b9b5764efb5 270 case DM_EVT_DEVICE_CONTEXT_DELETED:
FranKP2138 0:2b9b5764efb5 271 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_DELETED\r\n");
FranKP2138 0:2b9b5764efb5 272 APP_ERROR_CHECK(event_result);
FranKP2138 0:2b9b5764efb5 273 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_DELETED\r\n");
FranKP2138 0:2b9b5764efb5 274 break;
FranKP2138 0:2b9b5764efb5 275
FranKP2138 0:2b9b5764efb5 276 default:
FranKP2138 0:2b9b5764efb5 277 break;
FranKP2138 0:2b9b5764efb5 278 }
FranKP2138 0:2b9b5764efb5 279
FranKP2138 0:2b9b5764efb5 280 return NRF_SUCCESS;
FranKP2138 0:2b9b5764efb5 281 }
FranKP2138 0:2b9b5764efb5 282
FranKP2138 0:2b9b5764efb5 283
FranKP2138 0:2b9b5764efb5 284 /**
FranKP2138 0:2b9b5764efb5 285 * @brief Parses advertisement data, providing length and location of the field in case
FranKP2138 0:2b9b5764efb5 286 * matching data is found.
FranKP2138 0:2b9b5764efb5 287 *
FranKP2138 0:2b9b5764efb5 288 * @param[in] Type of data to be looked for in advertisement data.
FranKP2138 0:2b9b5764efb5 289 * @param[in] Advertisement report length and pointer to report.
FranKP2138 0:2b9b5764efb5 290 * @param[out] If data type requested is found in the data report, type data length and
FranKP2138 0:2b9b5764efb5 291 * pointer to data will be populated here.
FranKP2138 0:2b9b5764efb5 292 *
FranKP2138 0:2b9b5764efb5 293 * @retval NRF_SUCCESS if the data type is found in the report.
FranKP2138 0:2b9b5764efb5 294 * @retval NRF_ERROR_NOT_FOUND if the data type could not be found.
FranKP2138 0:2b9b5764efb5 295 */
FranKP2138 0:2b9b5764efb5 296 static uint32_t adv_report_parse(uint8_t type, data_t * p_advdata, data_t * p_typedata)
FranKP2138 0:2b9b5764efb5 297 {
FranKP2138 0:2b9b5764efb5 298 uint32_t index = 0;
FranKP2138 0:2b9b5764efb5 299 uint8_t * p_data;
FranKP2138 0:2b9b5764efb5 300
FranKP2138 0:2b9b5764efb5 301 p_data = p_advdata->p_data;
FranKP2138 0:2b9b5764efb5 302
FranKP2138 0:2b9b5764efb5 303 while (index < p_advdata->data_len)
FranKP2138 0:2b9b5764efb5 304 {
FranKP2138 0:2b9b5764efb5 305 uint8_t field_length = p_data[index];
FranKP2138 0:2b9b5764efb5 306 uint8_t field_type = p_data[index+1];
FranKP2138 0:2b9b5764efb5 307
FranKP2138 0:2b9b5764efb5 308 if (field_type == type)
FranKP2138 0:2b9b5764efb5 309 {
FranKP2138 0:2b9b5764efb5 310 p_typedata->p_data = &p_data[index+2];
FranKP2138 0:2b9b5764efb5 311 p_typedata->data_len = field_length-1;
FranKP2138 0:2b9b5764efb5 312 return NRF_SUCCESS;
FranKP2138 0:2b9b5764efb5 313 }
FranKP2138 0:2b9b5764efb5 314 index += field_length + 1;
FranKP2138 0:2b9b5764efb5 315 }
FranKP2138 0:2b9b5764efb5 316 return NRF_ERROR_NOT_FOUND;
FranKP2138 0:2b9b5764efb5 317 }
FranKP2138 0:2b9b5764efb5 318
FranKP2138 0:2b9b5764efb5 319
FranKP2138 0:2b9b5764efb5 320 /**@brief Function for putting the chip into sleep mode.
FranKP2138 0:2b9b5764efb5 321 *
FranKP2138 0:2b9b5764efb5 322 * @note This function will not return.
FranKP2138 0:2b9b5764efb5 323 */
FranKP2138 0:2b9b5764efb5 324 static void sleep_mode_enter(void)
FranKP2138 0:2b9b5764efb5 325 {
FranKP2138 0:2b9b5764efb5 326 uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
FranKP2138 0:2b9b5764efb5 327 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 328
FranKP2138 0:2b9b5764efb5 329 // Prepare wakeup buttons.
FranKP2138 0:2b9b5764efb5 330 err_code = bsp_btn_ble_sleep_mode_prepare();
FranKP2138 0:2b9b5764efb5 331 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 332
FranKP2138 0:2b9b5764efb5 333 // Go to system-off mode (this function will not return; wakeup will cause a reset).
FranKP2138 0:2b9b5764efb5 334 err_code = sd_power_system_off();
FranKP2138 0:2b9b5764efb5 335 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 336 }
FranKP2138 0:2b9b5764efb5 337
FranKP2138 0:2b9b5764efb5 338
FranKP2138 0:2b9b5764efb5 339 /**@brief Function for handling the Application's BLE Stack events.
FranKP2138 0:2b9b5764efb5 340 *
FranKP2138 0:2b9b5764efb5 341 * @param[in] p_ble_evt Bluetooth stack event.
FranKP2138 0:2b9b5764efb5 342 */
FranKP2138 0:2b9b5764efb5 343 static void on_ble_evt(ble_evt_t * p_ble_evt)
FranKP2138 0:2b9b5764efb5 344 {
FranKP2138 0:2b9b5764efb5 345 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 346 const ble_gap_evt_t * p_gap_evt = &p_ble_evt->evt.gap_evt;
FranKP2138 0:2b9b5764efb5 347
FranKP2138 0:2b9b5764efb5 348 switch (p_ble_evt->header.evt_id)
FranKP2138 0:2b9b5764efb5 349 {
FranKP2138 0:2b9b5764efb5 350 case BLE_GAP_EVT_ADV_REPORT:
FranKP2138 0:2b9b5764efb5 351 {
FranKP2138 0:2b9b5764efb5 352 data_t adv_data;
FranKP2138 0:2b9b5764efb5 353 data_t type_data;
FranKP2138 0:2b9b5764efb5 354
FranKP2138 0:2b9b5764efb5 355 // Initialize advertisement report for parsing.
FranKP2138 0:2b9b5764efb5 356 adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data;
FranKP2138 0:2b9b5764efb5 357 adv_data.data_len = p_gap_evt->params.adv_report.dlen;
FranKP2138 0:2b9b5764efb5 358
FranKP2138 0:2b9b5764efb5 359 err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
FranKP2138 0:2b9b5764efb5 360 &adv_data,
FranKP2138 0:2b9b5764efb5 361 &type_data);
FranKP2138 0:2b9b5764efb5 362
FranKP2138 0:2b9b5764efb5 363 if (err_code != NRF_SUCCESS)
FranKP2138 0:2b9b5764efb5 364 {
FranKP2138 0:2b9b5764efb5 365 // Compare short local name in case complete name does not match.
FranKP2138 0:2b9b5764efb5 366 err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
FranKP2138 0:2b9b5764efb5 367 &adv_data,
FranKP2138 0:2b9b5764efb5 368 &type_data);
FranKP2138 0:2b9b5764efb5 369 }
FranKP2138 0:2b9b5764efb5 370
FranKP2138 0:2b9b5764efb5 371 // Verify if short or complete name matches target.
FranKP2138 0:2b9b5764efb5 372 if (err_code == NRF_SUCCESS)
FranKP2138 0:2b9b5764efb5 373 {
FranKP2138 0:2b9b5764efb5 374 uint16_t extracted_uuid;
FranKP2138 0:2b9b5764efb5 375
FranKP2138 0:2b9b5764efb5 376 // UUIDs found, look for matching UUID
FranKP2138 0:2b9b5764efb5 377 for (uint32_t u_index = 0; u_index < (type_data.data_len/UUID16_SIZE); u_index++)
FranKP2138 0:2b9b5764efb5 378 {
FranKP2138 0:2b9b5764efb5 379 UUID16_EXTRACT(&extracted_uuid,&type_data.p_data[u_index * UUID16_SIZE]);
FranKP2138 0:2b9b5764efb5 380
FranKP2138 0:2b9b5764efb5 381 APPL_LOG_DEBUG("\t[APPL]: %x\r\n",extracted_uuid);
FranKP2138 0:2b9b5764efb5 382
FranKP2138 0:2b9b5764efb5 383 if(extracted_uuid == TARGET_UUID)
FranKP2138 0:2b9b5764efb5 384 {
FranKP2138 0:2b9b5764efb5 385 // Stop scanning.
FranKP2138 0:2b9b5764efb5 386 err_code = sd_ble_gap_scan_stop();
FranKP2138 0:2b9b5764efb5 387
FranKP2138 0:2b9b5764efb5 388 if (err_code != NRF_SUCCESS)
FranKP2138 0:2b9b5764efb5 389 {
FranKP2138 0:2b9b5764efb5 390 APPL_LOG_DEBUG("[APPL]: Scan stop failed, reason %d\r\n", err_code);
FranKP2138 0:2b9b5764efb5 391 }
FranKP2138 0:2b9b5764efb5 392 err_code = bsp_indication_set(BSP_INDICATE_IDLE);
FranKP2138 0:2b9b5764efb5 393 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 394
FranKP2138 0:2b9b5764efb5 395 m_scan_param.selective = 0;
FranKP2138 0:2b9b5764efb5 396 m_scan_param.p_whitelist = NULL;
FranKP2138 0:2b9b5764efb5 397
FranKP2138 0:2b9b5764efb5 398 // Initiate connection.
FranKP2138 0:2b9b5764efb5 399 err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr,
FranKP2138 0:2b9b5764efb5 400 &m_scan_param,
FranKP2138 0:2b9b5764efb5 401 &m_connection_param);
FranKP2138 0:2b9b5764efb5 402
FranKP2138 0:2b9b5764efb5 403 m_whitelist_temporarily_disabled = false;
FranKP2138 0:2b9b5764efb5 404
FranKP2138 0:2b9b5764efb5 405 if (err_code != NRF_SUCCESS)
FranKP2138 0:2b9b5764efb5 406 {
FranKP2138 0:2b9b5764efb5 407 APPL_LOG_DEBUG("[APPL]: Connection Request Failed, reason %d\r\n", err_code);
FranKP2138 0:2b9b5764efb5 408 }
FranKP2138 0:2b9b5764efb5 409 break;
FranKP2138 0:2b9b5764efb5 410 }
FranKP2138 0:2b9b5764efb5 411 }
FranKP2138 0:2b9b5764efb5 412 }
FranKP2138 0:2b9b5764efb5 413 break;
FranKP2138 0:2b9b5764efb5 414 }
FranKP2138 0:2b9b5764efb5 415
FranKP2138 0:2b9b5764efb5 416 case BLE_GAP_EVT_TIMEOUT:
FranKP2138 0:2b9b5764efb5 417 if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN)
FranKP2138 0:2b9b5764efb5 418 {
FranKP2138 0:2b9b5764efb5 419 APPL_LOG_DEBUG("[APPL]: Scan timed out.\r\n");
FranKP2138 0:2b9b5764efb5 420 scan_start();
FranKP2138 0:2b9b5764efb5 421 }
FranKP2138 0:2b9b5764efb5 422 else if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
FranKP2138 0:2b9b5764efb5 423 {
FranKP2138 0:2b9b5764efb5 424 APPL_LOG_DEBUG("[APPL]: Connection Request timed out.\r\n");
FranKP2138 0:2b9b5764efb5 425 }
FranKP2138 0:2b9b5764efb5 426 break;
FranKP2138 0:2b9b5764efb5 427 case BLE_GAP_EVT_CONNECTED:
FranKP2138 0:2b9b5764efb5 428 {
FranKP2138 0:2b9b5764efb5 429 err_code = ble_hrs_c_handles_assign(&m_ble_hrs_c, p_gap_evt->conn_handle, NULL);
FranKP2138 0:2b9b5764efb5 430 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 431 err_code = ble_bas_c_handles_assign(&m_ble_bas_c, p_gap_evt->conn_handle, NULL);
FranKP2138 0:2b9b5764efb5 432 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 433 break;
FranKP2138 0:2b9b5764efb5 434 }
FranKP2138 0:2b9b5764efb5 435 case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
FranKP2138 0:2b9b5764efb5 436 // Accepting parameters requested by peer.
FranKP2138 0:2b9b5764efb5 437 err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
FranKP2138 0:2b9b5764efb5 438 &p_gap_evt->params.conn_param_update_request.conn_params);
FranKP2138 0:2b9b5764efb5 439 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 440 break;
FranKP2138 0:2b9b5764efb5 441
FranKP2138 0:2b9b5764efb5 442 default:
FranKP2138 0:2b9b5764efb5 443 break;
FranKP2138 0:2b9b5764efb5 444 }
FranKP2138 0:2b9b5764efb5 445 }
FranKP2138 0:2b9b5764efb5 446
FranKP2138 0:2b9b5764efb5 447
FranKP2138 0:2b9b5764efb5 448 /**@brief Function for handling the Application's system events.
FranKP2138 0:2b9b5764efb5 449 *
FranKP2138 0:2b9b5764efb5 450 * @param[in] sys_evt system event.
FranKP2138 0:2b9b5764efb5 451 */
FranKP2138 0:2b9b5764efb5 452 static void on_sys_evt(uint32_t sys_evt)
FranKP2138 0:2b9b5764efb5 453 {
FranKP2138 0:2b9b5764efb5 454 switch (sys_evt)
FranKP2138 0:2b9b5764efb5 455 {
FranKP2138 0:2b9b5764efb5 456 case NRF_EVT_FLASH_OPERATION_SUCCESS:
FranKP2138 0:2b9b5764efb5 457 /* fall through */
FranKP2138 0:2b9b5764efb5 458 case NRF_EVT_FLASH_OPERATION_ERROR:
FranKP2138 0:2b9b5764efb5 459
FranKP2138 0:2b9b5764efb5 460 if (m_memory_access_in_progress)
FranKP2138 0:2b9b5764efb5 461 {
FranKP2138 0:2b9b5764efb5 462 m_memory_access_in_progress = false;
FranKP2138 0:2b9b5764efb5 463 scan_start();
FranKP2138 0:2b9b5764efb5 464 }
FranKP2138 0:2b9b5764efb5 465 break;
FranKP2138 0:2b9b5764efb5 466
FranKP2138 0:2b9b5764efb5 467 default:
FranKP2138 0:2b9b5764efb5 468 // No implementation needed.
FranKP2138 0:2b9b5764efb5 469 break;
FranKP2138 0:2b9b5764efb5 470 }
FranKP2138 0:2b9b5764efb5 471 }
FranKP2138 0:2b9b5764efb5 472
FranKP2138 0:2b9b5764efb5 473
FranKP2138 0:2b9b5764efb5 474 /**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
FranKP2138 0:2b9b5764efb5 475 *
FranKP2138 0:2b9b5764efb5 476 * @details This function is called from the scheduler in the main loop after a BLE stack event has
FranKP2138 0:2b9b5764efb5 477 * been received.
FranKP2138 0:2b9b5764efb5 478 *
FranKP2138 0:2b9b5764efb5 479 * @param[in] p_ble_evt Bluetooth stack event.
FranKP2138 0:2b9b5764efb5 480 */
FranKP2138 0:2b9b5764efb5 481 static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
FranKP2138 0:2b9b5764efb5 482 {
FranKP2138 0:2b9b5764efb5 483 dm_ble_evt_handler(p_ble_evt);
FranKP2138 0:2b9b5764efb5 484 ble_db_discovery_on_ble_evt(&m_ble_db_discovery, p_ble_evt);
FranKP2138 0:2b9b5764efb5 485 ble_hrs_c_on_ble_evt(&m_ble_hrs_c, p_ble_evt);
FranKP2138 0:2b9b5764efb5 486 ble_bas_c_on_ble_evt(&m_ble_bas_c, p_ble_evt);
FranKP2138 0:2b9b5764efb5 487 bsp_btn_ble_on_ble_evt(p_ble_evt);
FranKP2138 0:2b9b5764efb5 488 on_ble_evt(p_ble_evt);
FranKP2138 0:2b9b5764efb5 489 }
FranKP2138 0:2b9b5764efb5 490
FranKP2138 0:2b9b5764efb5 491
FranKP2138 0:2b9b5764efb5 492 /**@brief Function for dispatching a system event to interested modules.
FranKP2138 0:2b9b5764efb5 493 *
FranKP2138 0:2b9b5764efb5 494 * @details This function is called from the System event interrupt handler after a system
FranKP2138 0:2b9b5764efb5 495 * event has been received.
FranKP2138 0:2b9b5764efb5 496 *
FranKP2138 0:2b9b5764efb5 497 * @param[in] sys_evt System stack event.
FranKP2138 0:2b9b5764efb5 498 */
FranKP2138 0:2b9b5764efb5 499 static void sys_evt_dispatch(uint32_t sys_evt)
FranKP2138 0:2b9b5764efb5 500 {
FranKP2138 0:2b9b5764efb5 501 pstorage_sys_event_handler(sys_evt);
FranKP2138 0:2b9b5764efb5 502 on_sys_evt(sys_evt);
FranKP2138 0:2b9b5764efb5 503 }
FranKP2138 0:2b9b5764efb5 504
FranKP2138 0:2b9b5764efb5 505
FranKP2138 0:2b9b5764efb5 506 /**@brief Function for initializing the BLE stack.
FranKP2138 0:2b9b5764efb5 507 *
FranKP2138 0:2b9b5764efb5 508 * @details Initializes the SoftDevice and the BLE event interrupt.
FranKP2138 0:2b9b5764efb5 509 */
FranKP2138 0:2b9b5764efb5 510 static void ble_stack_init(void)
FranKP2138 0:2b9b5764efb5 511 {
FranKP2138 0:2b9b5764efb5 512 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 513
FranKP2138 0:2b9b5764efb5 514 nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;
FranKP2138 0:2b9b5764efb5 515
FranKP2138 0:2b9b5764efb5 516 // Initialize the SoftDevice handler module.
FranKP2138 0:2b9b5764efb5 517 SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);
FranKP2138 0:2b9b5764efb5 518
FranKP2138 0:2b9b5764efb5 519 ble_enable_params_t ble_enable_params;
FranKP2138 0:2b9b5764efb5 520 err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
FranKP2138 0:2b9b5764efb5 521 PERIPHERAL_LINK_COUNT,
FranKP2138 0:2b9b5764efb5 522 &ble_enable_params);
FranKP2138 0:2b9b5764efb5 523 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 524
FranKP2138 0:2b9b5764efb5 525 //Check the ram settings against the used number of links
FranKP2138 0:2b9b5764efb5 526 CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT);
FranKP2138 0:2b9b5764efb5 527
FranKP2138 0:2b9b5764efb5 528 // Enable BLE stack.
FranKP2138 0:2b9b5764efb5 529 err_code = softdevice_enable(&ble_enable_params);
FranKP2138 0:2b9b5764efb5 530 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 531
FranKP2138 0:2b9b5764efb5 532 // Register with the SoftDevice handler module for BLE events.
FranKP2138 0:2b9b5764efb5 533 err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
FranKP2138 0:2b9b5764efb5 534 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 535
FranKP2138 0:2b9b5764efb5 536 // Register with the SoftDevice handler module for System events.
FranKP2138 0:2b9b5764efb5 537 err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
FranKP2138 0:2b9b5764efb5 538 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 539 }
FranKP2138 0:2b9b5764efb5 540
FranKP2138 0:2b9b5764efb5 541
FranKP2138 0:2b9b5764efb5 542 /**@brief Function for the Device Manager initialization.
FranKP2138 0:2b9b5764efb5 543 *
FranKP2138 0:2b9b5764efb5 544 * @param[in] erase_bonds Indicates whether bonding information should be cleared from
FranKP2138 0:2b9b5764efb5 545 * persistent storage during initialization of the Device Manager.
FranKP2138 0:2b9b5764efb5 546 */
FranKP2138 0:2b9b5764efb5 547 static void device_manager_init(bool erase_bonds)
FranKP2138 0:2b9b5764efb5 548 {
FranKP2138 0:2b9b5764efb5 549 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 550 dm_init_param_t init_param = {.clear_persistent_data = erase_bonds};
FranKP2138 0:2b9b5764efb5 551 dm_application_param_t register_param;
FranKP2138 0:2b9b5764efb5 552
FranKP2138 0:2b9b5764efb5 553 err_code = pstorage_init();
FranKP2138 0:2b9b5764efb5 554 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 555
FranKP2138 0:2b9b5764efb5 556 err_code = dm_init(&init_param);
FranKP2138 0:2b9b5764efb5 557 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 558
FranKP2138 0:2b9b5764efb5 559 memset(&register_param.sec_param, 0, sizeof (ble_gap_sec_params_t));
FranKP2138 0:2b9b5764efb5 560
FranKP2138 0:2b9b5764efb5 561 // Event handler to be registered with the module.
FranKP2138 0:2b9b5764efb5 562 register_param.evt_handler = device_manager_event_handler;
FranKP2138 0:2b9b5764efb5 563
FranKP2138 0:2b9b5764efb5 564 // Service or protocol context for device manager to load, store and apply on behalf of application.
FranKP2138 0:2b9b5764efb5 565 // Here set to client as application is a GATT client.
FranKP2138 0:2b9b5764efb5 566 register_param.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID;
FranKP2138 0:2b9b5764efb5 567
FranKP2138 0:2b9b5764efb5 568 // Secuirty parameters to be used for security procedures.
FranKP2138 0:2b9b5764efb5 569 register_param.sec_param.bond = SEC_PARAM_BOND;
FranKP2138 0:2b9b5764efb5 570 register_param.sec_param.mitm = SEC_PARAM_MITM;
FranKP2138 0:2b9b5764efb5 571 register_param.sec_param.lesc = SEC_PARAM_LESC;
FranKP2138 0:2b9b5764efb5 572 register_param.sec_param.keypress = SEC_PARAM_KEYPRESS;
FranKP2138 0:2b9b5764efb5 573 register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
FranKP2138 0:2b9b5764efb5 574 register_param.sec_param.oob = SEC_PARAM_OOB;
FranKP2138 0:2b9b5764efb5 575 register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
FranKP2138 0:2b9b5764efb5 576 register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
FranKP2138 0:2b9b5764efb5 577 register_param.sec_param.kdist_peer.enc = 1;
FranKP2138 0:2b9b5764efb5 578 register_param.sec_param.kdist_peer.id = 1;
FranKP2138 0:2b9b5764efb5 579
FranKP2138 0:2b9b5764efb5 580 err_code = dm_register(&m_dm_app_id, &register_param);
FranKP2138 0:2b9b5764efb5 581 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 582 }
FranKP2138 0:2b9b5764efb5 583
FranKP2138 0:2b9b5764efb5 584
FranKP2138 0:2b9b5764efb5 585 /**@brief Function for disabling the use of whitelist for scanning.
FranKP2138 0:2b9b5764efb5 586 */
FranKP2138 0:2b9b5764efb5 587 static void whitelist_disable(void)
FranKP2138 0:2b9b5764efb5 588 {
FranKP2138 0:2b9b5764efb5 589 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 590
FranKP2138 0:2b9b5764efb5 591 if ((m_scan_mode == BLE_WHITELIST_SCAN) && !m_whitelist_temporarily_disabled)
FranKP2138 0:2b9b5764efb5 592 {
FranKP2138 0:2b9b5764efb5 593 m_whitelist_temporarily_disabled = true;
FranKP2138 0:2b9b5764efb5 594
FranKP2138 0:2b9b5764efb5 595 err_code = sd_ble_gap_scan_stop();
FranKP2138 0:2b9b5764efb5 596 if (err_code == NRF_SUCCESS)
FranKP2138 0:2b9b5764efb5 597 {
FranKP2138 0:2b9b5764efb5 598 scan_start();
FranKP2138 0:2b9b5764efb5 599 }
FranKP2138 0:2b9b5764efb5 600 else if (err_code != NRF_ERROR_INVALID_STATE)
FranKP2138 0:2b9b5764efb5 601 {
FranKP2138 0:2b9b5764efb5 602 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 603 }
FranKP2138 0:2b9b5764efb5 604 }
FranKP2138 0:2b9b5764efb5 605 m_whitelist_temporarily_disabled = true;
FranKP2138 0:2b9b5764efb5 606 }
FranKP2138 0:2b9b5764efb5 607
FranKP2138 0:2b9b5764efb5 608
FranKP2138 0:2b9b5764efb5 609 /**@brief Function for handling events from the BSP module.
FranKP2138 0:2b9b5764efb5 610 *
FranKP2138 0:2b9b5764efb5 611 * @param[in] event Event generated by button press.
FranKP2138 0:2b9b5764efb5 612 */
FranKP2138 0:2b9b5764efb5 613 void bsp_event_handler(bsp_event_t event)
FranKP2138 0:2b9b5764efb5 614 {
FranKP2138 0:2b9b5764efb5 615 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 616 switch (event)
FranKP2138 0:2b9b5764efb5 617 {
FranKP2138 0:2b9b5764efb5 618 case BSP_EVENT_SLEEP:
FranKP2138 0:2b9b5764efb5 619 sleep_mode_enter();
FranKP2138 0:2b9b5764efb5 620 break;
FranKP2138 0:2b9b5764efb5 621
FranKP2138 0:2b9b5764efb5 622 case BSP_EVENT_DISCONNECT:
FranKP2138 0:2b9b5764efb5 623 err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
FranKP2138 0:2b9b5764efb5 624 if (err_code != NRF_ERROR_INVALID_STATE)
FranKP2138 0:2b9b5764efb5 625 {
FranKP2138 0:2b9b5764efb5 626 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 627 }
FranKP2138 0:2b9b5764efb5 628 break;
FranKP2138 0:2b9b5764efb5 629
FranKP2138 0:2b9b5764efb5 630 case BSP_EVENT_WHITELIST_OFF:
FranKP2138 0:2b9b5764efb5 631 whitelist_disable();
FranKP2138 0:2b9b5764efb5 632 break;
FranKP2138 0:2b9b5764efb5 633
FranKP2138 0:2b9b5764efb5 634 default:
FranKP2138 0:2b9b5764efb5 635 break;
FranKP2138 0:2b9b5764efb5 636 }
FranKP2138 0:2b9b5764efb5 637 }
FranKP2138 0:2b9b5764efb5 638
FranKP2138 0:2b9b5764efb5 639
FranKP2138 0:2b9b5764efb5 640 /**@brief Heart Rate Collector Handler.
FranKP2138 0:2b9b5764efb5 641 */
FranKP2138 0:2b9b5764efb5 642 static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt)
FranKP2138 0:2b9b5764efb5 643 {
FranKP2138 0:2b9b5764efb5 644 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 645
FranKP2138 0:2b9b5764efb5 646 switch (p_hrs_c_evt->evt_type)
FranKP2138 0:2b9b5764efb5 647 {
FranKP2138 0:2b9b5764efb5 648 case BLE_HRS_C_EVT_DISCOVERY_COMPLETE:
FranKP2138 0:2b9b5764efb5 649
FranKP2138 0:2b9b5764efb5 650 // Heart rate service discovered. Enable notification of Heart Rate Measurement.
FranKP2138 0:2b9b5764efb5 651 err_code = ble_hrs_c_hrm_notif_enable(p_hrs_c);
FranKP2138 0:2b9b5764efb5 652 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 653
FranKP2138 0:2b9b5764efb5 654 APPL_LOG_DEBUG("Heart rate service discovered \r\n");
FranKP2138 0:2b9b5764efb5 655 break;
FranKP2138 0:2b9b5764efb5 656
FranKP2138 0:2b9b5764efb5 657 case BLE_HRS_C_EVT_HRM_NOTIFICATION:
FranKP2138 0:2b9b5764efb5 658 {
FranKP2138 0:2b9b5764efb5 659 APPL_LOG_DEBUG("[APPL]: HR Measurement received %d \r\n", p_hrs_c_evt->params.hrm.hr_value);
FranKP2138 0:2b9b5764efb5 660
FranKP2138 0:2b9b5764efb5 661 APPL_LOG("Heart Rate = %d\r\n", p_hrs_c_evt->params.hrm.hr_value);
FranKP2138 0:2b9b5764efb5 662 break;
FranKP2138 0:2b9b5764efb5 663 }
FranKP2138 0:2b9b5764efb5 664
FranKP2138 0:2b9b5764efb5 665 default:
FranKP2138 0:2b9b5764efb5 666 break;
FranKP2138 0:2b9b5764efb5 667 }
FranKP2138 0:2b9b5764efb5 668 }
FranKP2138 0:2b9b5764efb5 669
FranKP2138 0:2b9b5764efb5 670
FranKP2138 0:2b9b5764efb5 671 /**@brief Battery levelCollector Handler.
FranKP2138 0:2b9b5764efb5 672 */
FranKP2138 0:2b9b5764efb5 673 static void bas_c_evt_handler(ble_bas_c_t * p_bas_c, ble_bas_c_evt_t * p_bas_c_evt)
FranKP2138 0:2b9b5764efb5 674 {
FranKP2138 0:2b9b5764efb5 675 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 676
FranKP2138 0:2b9b5764efb5 677 switch (p_bas_c_evt->evt_type)
FranKP2138 0:2b9b5764efb5 678 {
FranKP2138 0:2b9b5764efb5 679 case BLE_BAS_C_EVT_DISCOVERY_COMPLETE:
FranKP2138 0:2b9b5764efb5 680 // Batttery service discovered. Enable notification of Battery Level.
FranKP2138 0:2b9b5764efb5 681 APPL_LOG_DEBUG("[APPL]: Battery Service discovered. \r\n");
FranKP2138 0:2b9b5764efb5 682
FranKP2138 0:2b9b5764efb5 683 APPL_LOG_DEBUG("[APPL]: Reading battery level. \r\n");
FranKP2138 0:2b9b5764efb5 684
FranKP2138 0:2b9b5764efb5 685 err_code = ble_bas_c_bl_read(p_bas_c);
FranKP2138 0:2b9b5764efb5 686 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 687
FranKP2138 0:2b9b5764efb5 688
FranKP2138 0:2b9b5764efb5 689 APPL_LOG_DEBUG("[APPL]: Enabling Battery Level Notification. \r\n");
FranKP2138 0:2b9b5764efb5 690 err_code = ble_bas_c_bl_notif_enable(p_bas_c);
FranKP2138 0:2b9b5764efb5 691 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 692
FranKP2138 0:2b9b5764efb5 693 break;
FranKP2138 0:2b9b5764efb5 694
FranKP2138 0:2b9b5764efb5 695 case BLE_BAS_C_EVT_BATT_NOTIFICATION:
FranKP2138 0:2b9b5764efb5 696 {
FranKP2138 0:2b9b5764efb5 697 APPL_LOG_DEBUG("[APPL]: Battery Level received %d %%\r\n", p_bas_c_evt->params.battery_level);
FranKP2138 0:2b9b5764efb5 698
FranKP2138 0:2b9b5764efb5 699 APPL_LOG_DEBUG("Battery = %d %%\r\n", p_bas_c_evt->params.battery_level);
FranKP2138 0:2b9b5764efb5 700 break;
FranKP2138 0:2b9b5764efb5 701 }
FranKP2138 0:2b9b5764efb5 702
FranKP2138 0:2b9b5764efb5 703 case BLE_BAS_C_EVT_BATT_READ_RESP:
FranKP2138 0:2b9b5764efb5 704 {
FranKP2138 0:2b9b5764efb5 705 APPL_LOG_DEBUG("[APPL]: Battery Level Read as %d %%\r\n", p_bas_c_evt->params.battery_level);
FranKP2138 0:2b9b5764efb5 706
FranKP2138 0:2b9b5764efb5 707 APPL_LOG_DEBUG("Battery = %d %%\r\n", p_bas_c_evt->params.battery_level);
FranKP2138 0:2b9b5764efb5 708 break;
FranKP2138 0:2b9b5764efb5 709 }
FranKP2138 0:2b9b5764efb5 710
FranKP2138 0:2b9b5764efb5 711 default:
FranKP2138 0:2b9b5764efb5 712 break;
FranKP2138 0:2b9b5764efb5 713 }
FranKP2138 0:2b9b5764efb5 714 }
FranKP2138 0:2b9b5764efb5 715
FranKP2138 0:2b9b5764efb5 716
FranKP2138 0:2b9b5764efb5 717 /**
FranKP2138 0:2b9b5764efb5 718 * @brief Heart rate collector initialization.
FranKP2138 0:2b9b5764efb5 719 */
FranKP2138 0:2b9b5764efb5 720 static void hrs_c_init(void)
FranKP2138 0:2b9b5764efb5 721 {
FranKP2138 0:2b9b5764efb5 722 ble_hrs_c_init_t hrs_c_init_obj;
FranKP2138 0:2b9b5764efb5 723
FranKP2138 0:2b9b5764efb5 724 hrs_c_init_obj.evt_handler = hrs_c_evt_handler;
FranKP2138 0:2b9b5764efb5 725
FranKP2138 0:2b9b5764efb5 726 uint32_t err_code = ble_hrs_c_init(&m_ble_hrs_c, &hrs_c_init_obj);
FranKP2138 0:2b9b5764efb5 727 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 728 }
FranKP2138 0:2b9b5764efb5 729
FranKP2138 0:2b9b5764efb5 730
FranKP2138 0:2b9b5764efb5 731 /**
FranKP2138 0:2b9b5764efb5 732 * @brief Battery level collector initialization.
FranKP2138 0:2b9b5764efb5 733 */
FranKP2138 0:2b9b5764efb5 734 static void bas_c_init(void)
FranKP2138 0:2b9b5764efb5 735 {
FranKP2138 0:2b9b5764efb5 736 ble_bas_c_init_t bas_c_init_obj;
FranKP2138 0:2b9b5764efb5 737
FranKP2138 0:2b9b5764efb5 738 bas_c_init_obj.evt_handler = bas_c_evt_handler;
FranKP2138 0:2b9b5764efb5 739
FranKP2138 0:2b9b5764efb5 740 uint32_t err_code = ble_bas_c_init(&m_ble_bas_c, &bas_c_init_obj);
FranKP2138 0:2b9b5764efb5 741 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 742 }
FranKP2138 0:2b9b5764efb5 743
FranKP2138 0:2b9b5764efb5 744
FranKP2138 0:2b9b5764efb5 745 /**
FranKP2138 0:2b9b5764efb5 746 * @brief Database discovery collector initialization.
FranKP2138 0:2b9b5764efb5 747 */
FranKP2138 0:2b9b5764efb5 748 static void db_discovery_init(void)
FranKP2138 0:2b9b5764efb5 749 {
FranKP2138 0:2b9b5764efb5 750 uint32_t err_code = ble_db_discovery_init(db_disc_handler);
FranKP2138 0:2b9b5764efb5 751
FranKP2138 0:2b9b5764efb5 752 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 753 }
FranKP2138 0:2b9b5764efb5 754
FranKP2138 0:2b9b5764efb5 755
FranKP2138 0:2b9b5764efb5 756 /**@brief Function to start scanning.
FranKP2138 0:2b9b5764efb5 757 */
FranKP2138 0:2b9b5764efb5 758 static void scan_start(void)
FranKP2138 0:2b9b5764efb5 759 {
FranKP2138 0:2b9b5764efb5 760 ble_gap_whitelist_t whitelist;
FranKP2138 0:2b9b5764efb5 761 ble_gap_addr_t * p_whitelist_addr[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
FranKP2138 0:2b9b5764efb5 762 ble_gap_irk_t * p_whitelist_irk[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
FranKP2138 0:2b9b5764efb5 763 uint32_t err_code;
FranKP2138 0:2b9b5764efb5 764 uint32_t count;
FranKP2138 0:2b9b5764efb5 765
FranKP2138 0:2b9b5764efb5 766 // Verify if there is any flash access pending, if yes delay starting scanning until
FranKP2138 0:2b9b5764efb5 767 // it's complete.
FranKP2138 0:2b9b5764efb5 768 err_code = pstorage_access_status_get(&count);
FranKP2138 0:2b9b5764efb5 769 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 770
FranKP2138 0:2b9b5764efb5 771 if (count != 0)
FranKP2138 0:2b9b5764efb5 772 {
FranKP2138 0:2b9b5764efb5 773 m_memory_access_in_progress = true;
FranKP2138 0:2b9b5764efb5 774 return;
FranKP2138 0:2b9b5764efb5 775 }
FranKP2138 0:2b9b5764efb5 776
FranKP2138 0:2b9b5764efb5 777 // Initialize whitelist parameters.
FranKP2138 0:2b9b5764efb5 778 whitelist.addr_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT;
FranKP2138 0:2b9b5764efb5 779 whitelist.irk_count = 0;
FranKP2138 0:2b9b5764efb5 780 whitelist.pp_addrs = p_whitelist_addr;
FranKP2138 0:2b9b5764efb5 781 whitelist.pp_irks = p_whitelist_irk;
FranKP2138 0:2b9b5764efb5 782
FranKP2138 0:2b9b5764efb5 783 // Request creating of whitelist.
FranKP2138 0:2b9b5764efb5 784 err_code = dm_whitelist_create(&m_dm_app_id,&whitelist);
FranKP2138 0:2b9b5764efb5 785 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 786
FranKP2138 0:2b9b5764efb5 787 if (((whitelist.addr_count == 0) && (whitelist.irk_count == 0)) ||
FranKP2138 0:2b9b5764efb5 788 (m_scan_mode != BLE_WHITELIST_SCAN) ||
FranKP2138 0:2b9b5764efb5 789 (m_whitelist_temporarily_disabled))
FranKP2138 0:2b9b5764efb5 790 {
FranKP2138 0:2b9b5764efb5 791 // No devices in whitelist, hence non selective performed.
FranKP2138 0:2b9b5764efb5 792 m_scan_param.active = 0; // Active scanning set.
FranKP2138 0:2b9b5764efb5 793 m_scan_param.selective = 0; // Selective scanning not set.
FranKP2138 0:2b9b5764efb5 794 m_scan_param.interval = SCAN_INTERVAL;// Scan interval.
FranKP2138 0:2b9b5764efb5 795 m_scan_param.window = SCAN_WINDOW; // Scan window.
FranKP2138 0:2b9b5764efb5 796 m_scan_param.p_whitelist = NULL; // No whitelist provided.
FranKP2138 0:2b9b5764efb5 797 m_scan_param.timeout = 0x0000; // No timeout.
FranKP2138 0:2b9b5764efb5 798 }
FranKP2138 0:2b9b5764efb5 799 else
FranKP2138 0:2b9b5764efb5 800 {
FranKP2138 0:2b9b5764efb5 801 // Selective scanning based on whitelist first.
FranKP2138 0:2b9b5764efb5 802 m_scan_param.active = 0; // Active scanning set.
FranKP2138 0:2b9b5764efb5 803 m_scan_param.selective = 1; // Selective scanning not set.
FranKP2138 0:2b9b5764efb5 804 m_scan_param.interval = SCAN_INTERVAL;// Scan interval.
FranKP2138 0:2b9b5764efb5 805 m_scan_param.window = SCAN_WINDOW; // Scan window.
FranKP2138 0:2b9b5764efb5 806 m_scan_param.p_whitelist = &whitelist; // Provide whitelist.
FranKP2138 0:2b9b5764efb5 807 m_scan_param.timeout = 0x001E; // 30 seconds timeout.
FranKP2138 0:2b9b5764efb5 808 }
FranKP2138 0:2b9b5764efb5 809
FranKP2138 0:2b9b5764efb5 810 err_code = sd_ble_gap_scan_start(&m_scan_param);
FranKP2138 0:2b9b5764efb5 811 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 812
FranKP2138 0:2b9b5764efb5 813 err_code = bsp_indication_set(BSP_INDICATE_SCANNING);
FranKP2138 0:2b9b5764efb5 814 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 815 }
FranKP2138 0:2b9b5764efb5 816
FranKP2138 0:2b9b5764efb5 817
FranKP2138 0:2b9b5764efb5 818 /**@brief Function for initializing buttons and leds.
FranKP2138 0:2b9b5764efb5 819 *
FranKP2138 0:2b9b5764efb5 820 * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up.
FranKP2138 0:2b9b5764efb5 821 */
FranKP2138 0:2b9b5764efb5 822 static void buttons_leds_init(bool * p_erase_bonds)
FranKP2138 0:2b9b5764efb5 823 {
FranKP2138 0:2b9b5764efb5 824 bsp_event_t startup_event;
FranKP2138 0:2b9b5764efb5 825
FranKP2138 0:2b9b5764efb5 826 uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS,
FranKP2138 0:2b9b5764efb5 827 APP_TIMER_TICKS(100, APP_TIMER_PRESCALER),
FranKP2138 0:2b9b5764efb5 828 bsp_event_handler);
FranKP2138 0:2b9b5764efb5 829 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 830
FranKP2138 0:2b9b5764efb5 831 err_code = bsp_btn_ble_init(NULL, &startup_event);
FranKP2138 0:2b9b5764efb5 832 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 833
FranKP2138 0:2b9b5764efb5 834 *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
FranKP2138 0:2b9b5764efb5 835 }
FranKP2138 0:2b9b5764efb5 836
FranKP2138 0:2b9b5764efb5 837
FranKP2138 0:2b9b5764efb5 838 /**@brief Function for initializing the nrf log module.
FranKP2138 0:2b9b5764efb5 839 */
FranKP2138 0:2b9b5764efb5 840 static void nrf_log_init(void)
FranKP2138 0:2b9b5764efb5 841 {
FranKP2138 0:2b9b5764efb5 842 ret_code_t err_code = NRF_LOG_INIT();
FranKP2138 0:2b9b5764efb5 843 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 844 }
FranKP2138 0:2b9b5764efb5 845
FranKP2138 0:2b9b5764efb5 846
FranKP2138 0:2b9b5764efb5 847 /** @brief Function for the Power manager.
FranKP2138 0:2b9b5764efb5 848 */
FranKP2138 0:2b9b5764efb5 849 static void power_manage(void)
FranKP2138 0:2b9b5764efb5 850 {
FranKP2138 0:2b9b5764efb5 851 uint32_t err_code = sd_app_evt_wait();
FranKP2138 0:2b9b5764efb5 852 APP_ERROR_CHECK(err_code);
FranKP2138 0:2b9b5764efb5 853 }
FranKP2138 0:2b9b5764efb5 854
FranKP2138 0:2b9b5764efb5 855
FranKP2138 0:2b9b5764efb5 856 int main(void)
FranKP2138 0:2b9b5764efb5 857 {
FranKP2138 0:2b9b5764efb5 858 bool erase_bonds;
FranKP2138 0:2b9b5764efb5 859
FranKP2138 0:2b9b5764efb5 860 // Initialize.
FranKP2138 0:2b9b5764efb5 861 APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
FranKP2138 0:2b9b5764efb5 862 buttons_leds_init(&erase_bonds);
FranKP2138 0:2b9b5764efb5 863 nrf_log_init();
FranKP2138 0:2b9b5764efb5 864 APPL_LOG("Heart rate collector example\r\n");
FranKP2138 0:2b9b5764efb5 865 ble_stack_init();
FranKP2138 0:2b9b5764efb5 866 device_manager_init(erase_bonds);
FranKP2138 0:2b9b5764efb5 867 db_discovery_init();
FranKP2138 0:2b9b5764efb5 868 hrs_c_init();
FranKP2138 0:2b9b5764efb5 869 bas_c_init();
FranKP2138 0:2b9b5764efb5 870
FranKP2138 0:2b9b5764efb5 871 // Start scanning for peripherals and initiate connection
FranKP2138 0:2b9b5764efb5 872 // with devices that advertise Heart Rate UUID.
FranKP2138 0:2b9b5764efb5 873 scan_start();
FranKP2138 0:2b9b5764efb5 874
FranKP2138 0:2b9b5764efb5 875 for (;; )
FranKP2138 0:2b9b5764efb5 876 {
FranKP2138 0:2b9b5764efb5 877 power_manage();
FranKP2138 0:2b9b5764efb5 878 }
FranKP2138 0:2b9b5764efb5 879 }
FranKP2138 0:2b9b5764efb5 880
FranKP2138 0:2b9b5764efb5 881
FranKP2138 0:2b9b5764efb5 882