RedBearLab, BLE_Nano, nRF51, Central

Dependencies:   mbed

Committer:
FranKP2138
Date:
Sun May 22 17:01:39 2016 +0000
Revision:
0:79288901821e
Example Central - not run - there are some error

Who changed what in which revision?

UserRevisionLine numberNew contents of line
FranKP2138 0:79288901821e 1 /*
FranKP2138 0:79288901821e 2 * Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
FranKP2138 0:79288901821e 3 *
FranKP2138 0:79288901821e 4 * The information contained herein is confidential property of Nordic Semiconductor. The use,
FranKP2138 0:79288901821e 5 * copying, transfer or disclosure of such information is prohibited except by express written
FranKP2138 0:79288901821e 6 * agreement with Nordic Semiconductor.
FranKP2138 0:79288901821e 7 *
FranKP2138 0:79288901821e 8 */
FranKP2138 0:79288901821e 9
FranKP2138 0:79288901821e 10 /**
FranKP2138 0:79288901821e 11 * @brief BLE LED Button Service central and client application main file.
FranKP2138 0:79288901821e 12 *
FranKP2138 0:79288901821e 13 * This example can be a central for up to 8 peripherals.
FranKP2138 0:79288901821e 14 * The peripheral is called ble_app_blinky and can be found in the ble_peripheral
FranKP2138 0:79288901821e 15 * folder.
FranKP2138 0:79288901821e 16 */
FranKP2138 0:79288901821e 17
FranKP2138 0:79288901821e 18 #include <stdint.h>
FranKP2138 0:79288901821e 19 #include <stdio.h>
FranKP2138 0:79288901821e 20 #include <string.h>
FranKP2138 0:79288901821e 21 #include "nordic_common.h"//ok
FranKP2138 0:79288901821e 22 #include "softdevice_handler.h"
FranKP2138 0:79288901821e 23 #include "app_timer.h"
FranKP2138 0:79288901821e 24 #include "app_trace.h"
FranKP2138 0:79288901821e 25 #include "boards.h"
FranKP2138 0:79288901821e 26 #include "bsp.h"
FranKP2138 0:79288901821e 27 #include "bsp_btn_ble.h"
FranKP2138 0:79288901821e 28 #include "ble.h"
FranKP2138 0:79288901821e 29 #include "app_uart.h"
FranKP2138 0:79288901821e 30 #include "ble_advdata.h"
FranKP2138 0:79288901821e 31 #include "ble_advertising.h"
FranKP2138 0:79288901821e 32 #include "ble_conn_params.h"
FranKP2138 0:79288901821e 33 #include "ble_db_discovery.h"
FranKP2138 0:79288901821e 34 #include "ble_lbs_c.h"
FranKP2138 0:79288901821e 35 #include "ble_conn_state.h"
FranKP2138 0:79288901821e 36 #include "nrf_log.h"
FranKP2138 0:79288901821e 37
FranKP2138 0:79288901821e 38 #define CENTRAL_LINK_COUNT 8 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/
FranKP2138 0:79288901821e 39 #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:79288901821e 40 #define TOTAL_LINK_COUNT CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT /**< Total number of links used by the application. */
FranKP2138 0:79288901821e 41 #define APPL_LOG app_trace_log /**< Macro used to log debug information over UART. */
FranKP2138 0:79288901821e 42
FranKP2138 0:79288901821e 43 #define CENTRAL_SCANNING_LED BSP_LED_0_MASK
FranKP2138 0:79288901821e 44 #define CENTRAL_CONNECTED_LED BSP_LED_1_MASK
FranKP2138 0:79288901821e 45
FranKP2138 0:79288901821e 46 #define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
FranKP2138 0:79288901821e 47 #define APP_TIMER_MAX_TIMERS (2+BSP_APP_TIMERS_NUMBER) /**< Maximum number of timers used by the application. */
FranKP2138 0:79288901821e 48 #define APP_TIMER_OP_QUEUE_SIZE 2 /**< Size of timer operation queues. */
FranKP2138 0:79288901821e 49
FranKP2138 0:79288901821e 50 #define SCAN_INTERVAL 0x00A0 /**< Determines scan interval in units of 0.625 millisecond. */
FranKP2138 0:79288901821e 51 #define SCAN_WINDOW 0x0050 /**< Determines scan window in units of 0.625 millisecond. */
FranKP2138 0:79288901821e 52 #define SCAN_TIMEOUT 0x0000 /**< Timout when scanning. 0x0000 disables timeout. */
FranKP2138 0:79288901821e 53 #define SCAN_REQUEST 0 /**< Active scannin is not set. */
FranKP2138 0:79288901821e 54 #define SCAN_WHITELIST_ONLY 0 /**< We will not ignore unknown devices. */
FranKP2138 0:79288901821e 55
FranKP2138 0:79288901821e 56 #define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Determines minimum connection interval in milliseconds. */
FranKP2138 0:79288901821e 57 #define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(30, UNIT_1_25_MS) /**< Determines maximum connection interval in milliseconds. */
FranKP2138 0:79288901821e 58 #define SLAVE_LATENCY 0 /**< Determines slave latency in terms of connection events. */
FranKP2138 0:79288901821e 59 #define SUPERVISION_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Determines supervision time-out in units of 10 milliseconds. */
FranKP2138 0:79288901821e 60
FranKP2138 0:79288901821e 61 #define UUID16_SIZE 2 /**< Size of a UUID, in bytes. */
FranKP2138 0:79288901821e 62
FranKP2138 0:79288901821e 63 #define LEDBUTTON_LED BSP_LED_2_MASK /**< LED to indicate a change of state of the the Button characteristic on the peer. */
FranKP2138 0:79288901821e 64
FranKP2138 0:79288901821e 65 #define LEDBUTTON_BUTTON_PIN BSP_BUTTON_0 /**< Button that will write to the LED characteristic of the peer */
FranKP2138 0:79288901821e 66 #define BUTTON_DETECTION_DELAY APP_TIMER_TICKS(50, APP_TIMER_PRESCALER) /**< Delay from a GPIOTE event until a button is reported as pushed (in number of timer ticks). */
FranKP2138 0:79288901821e 67
FranKP2138 0:79288901821e 68 static const char m_target_periph_name[] = "Nordic_Blinky"; /**< Name of the device we try to connect to. This name is searched for in the scan report data*/
FranKP2138 0:79288901821e 69
FranKP2138 0:79288901821e 70
FranKP2138 0:79288901821e 71 /** @brief Scan parameters requested for scanning and connection. */
FranKP2138 0:79288901821e 72 static const ble_gap_scan_params_t m_scan_param =
FranKP2138 0:79288901821e 73 {
FranKP2138 0:79288901821e 74 SCAN_REQUEST,
FranKP2138 0:79288901821e 75 SCAN_WHITELIST_ONLY,
FranKP2138 0:79288901821e 76 NULL,
FranKP2138 0:79288901821e 77 (uint16_t)SCAN_INTERVAL,
FranKP2138 0:79288901821e 78 (uint16_t)SCAN_WINDOW,
FranKP2138 0:79288901821e 79 SCAN_TIMEOUT
FranKP2138 0:79288901821e 80 };
FranKP2138 0:79288901821e 81
FranKP2138 0:79288901821e 82 /**@brief Connection parameters requested for connection. */
FranKP2138 0:79288901821e 83 static const ble_gap_conn_params_t m_connection_param =
FranKP2138 0:79288901821e 84 {
FranKP2138 0:79288901821e 85 (uint16_t)MIN_CONNECTION_INTERVAL,
FranKP2138 0:79288901821e 86 (uint16_t)MAX_CONNECTION_INTERVAL,
FranKP2138 0:79288901821e 87 (uint16_t)SLAVE_LATENCY,
FranKP2138 0:79288901821e 88 (uint16_t)SUPERVISION_TIMEOUT
FranKP2138 0:79288901821e 89 };
FranKP2138 0:79288901821e 90
FranKP2138 0:79288901821e 91 static ble_lbs_c_t m_ble_lbs_c[TOTAL_LINK_COUNT]; /**< Main structures used by the LED Button client module. */
FranKP2138 0:79288901821e 92 static uint8_t m_ble_lbs_c_count; /**< Keeps track of how many instances of LED Button client module have been initialized. >*/
FranKP2138 0:79288901821e 93 static ble_db_discovery_t m_ble_db_discovery[TOTAL_LINK_COUNT]; /**< list of DB structures used by the database discovery module. */
FranKP2138 0:79288901821e 94
FranKP2138 0:79288901821e 95 /**@brief Function to handle asserts in the SoftDevice.
FranKP2138 0:79288901821e 96 *
FranKP2138 0:79288901821e 97 * @details This function will be called in case of an assert in the SoftDevice.
FranKP2138 0:79288901821e 98 *
FranKP2138 0:79288901821e 99 * @warning This handler is an example only and does not fit a final product. You need to analyze
FranKP2138 0:79288901821e 100 * how your product is supposed to react in case of Assert.
FranKP2138 0:79288901821e 101 * @warning On assert from the SoftDevice, the system can only recover on reset.
FranKP2138 0:79288901821e 102 *
FranKP2138 0:79288901821e 103 * @param[in] line_num Line number of the failing ASSERT call.
FranKP2138 0:79288901821e 104 * @param[in] p_file_name File name of the failing ASSERT call.
FranKP2138 0:79288901821e 105 */
FranKP2138 0:79288901821e 106 void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
FranKP2138 0:79288901821e 107 {
FranKP2138 0:79288901821e 108 app_error_handler(0xDEADBEEF, line_num, p_file_name);
FranKP2138 0:79288901821e 109 }
FranKP2138 0:79288901821e 110
FranKP2138 0:79288901821e 111
FranKP2138 0:79288901821e 112 /**@brief Function for the LEDs initialization.
FranKP2138 0:79288901821e 113 *
FranKP2138 0:79288901821e 114 * @details Initializes all LEDs used by the application.
FranKP2138 0:79288901821e 115 */
FranKP2138 0:79288901821e 116 static void leds_init(void)
FranKP2138 0:79288901821e 117 {
FranKP2138 0:79288901821e 118 LEDS_CONFIGURE(CENTRAL_SCANNING_LED | CENTRAL_CONNECTED_LED | LEDBUTTON_LED);
FranKP2138 0:79288901821e 119 LEDS_OFF(CENTRAL_SCANNING_LED | CENTRAL_CONNECTED_LED | LEDBUTTON_LED);
FranKP2138 0:79288901821e 120 }
FranKP2138 0:79288901821e 121
FranKP2138 0:79288901821e 122
FranKP2138 0:79288901821e 123 /**
FranKP2138 0:79288901821e 124 * @brief Parses advertisement data, providing length and location of the field in case
FranKP2138 0:79288901821e 125 * matching data is found.
FranKP2138 0:79288901821e 126 *
FranKP2138 0:79288901821e 127 * @param[in] type Type of data to be looked for in advertisement data.
FranKP2138 0:79288901821e 128 * @param[in] p_advdata Advertisement report length and pointer to report.
FranKP2138 0:79288901821e 129 * @param[out] p_typedata If data type requested is found in the data report, type data length and
FranKP2138 0:79288901821e 130 * pointer to data will be populated here.
FranKP2138 0:79288901821e 131 *
FranKP2138 0:79288901821e 132 * @retval NRF_SUCCESS if the data type is found in the report.
FranKP2138 0:79288901821e 133 * @retval NRF_ERROR_NOT_FOUND if the data type could not be found.
FranKP2138 0:79288901821e 134 */
FranKP2138 0:79288901821e 135 static uint32_t adv_report_parse(uint8_t type, uint8_array_t * p_advdata, uint8_array_t * p_typedata)
FranKP2138 0:79288901821e 136 {
FranKP2138 0:79288901821e 137 uint32_t index = 0;
FranKP2138 0:79288901821e 138 uint8_t * p_data;
FranKP2138 0:79288901821e 139
FranKP2138 0:79288901821e 140 p_data = p_advdata->p_data;
FranKP2138 0:79288901821e 141
FranKP2138 0:79288901821e 142 while (index < p_advdata->size)
FranKP2138 0:79288901821e 143 {
FranKP2138 0:79288901821e 144 uint8_t field_length = p_data[index];
FranKP2138 0:79288901821e 145 uint8_t field_type = p_data[index + 1];
FranKP2138 0:79288901821e 146
FranKP2138 0:79288901821e 147 if (field_type == type)
FranKP2138 0:79288901821e 148 {
FranKP2138 0:79288901821e 149 p_typedata->p_data = &p_data[index + 2];
FranKP2138 0:79288901821e 150 p_typedata->size = field_length - 1;
FranKP2138 0:79288901821e 151 return NRF_SUCCESS;
FranKP2138 0:79288901821e 152 }
FranKP2138 0:79288901821e 153 index += field_length + 1;
FranKP2138 0:79288901821e 154 }
FranKP2138 0:79288901821e 155 return NRF_ERROR_NOT_FOUND;
FranKP2138 0:79288901821e 156 }
FranKP2138 0:79288901821e 157
FranKP2138 0:79288901821e 158
FranKP2138 0:79288901821e 159 /**@brief Function to start scanning.
FranKP2138 0:79288901821e 160 */
FranKP2138 0:79288901821e 161 static void scan_start(void)
FranKP2138 0:79288901821e 162 {
FranKP2138 0:79288901821e 163 ret_code_t err_code;
FranKP2138 0:79288901821e 164
FranKP2138 0:79288901821e 165 err_code = sd_ble_gap_scan_stop();
FranKP2138 0:79288901821e 166 // It is okay to ignore this error since we are stopping the scan anyway.
FranKP2138 0:79288901821e 167 if (err_code != NRF_ERROR_INVALID_STATE)
FranKP2138 0:79288901821e 168 {
FranKP2138 0:79288901821e 169 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 170 }
FranKP2138 0:79288901821e 171
FranKP2138 0:79288901821e 172 NRF_LOG_PRINTF("[APP]: start scanning for device name %s\r\n", m_target_periph_name);
FranKP2138 0:79288901821e 173 err_code = sd_ble_gap_scan_start(&m_scan_param);
FranKP2138 0:79288901821e 174 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 175
FranKP2138 0:79288901821e 176 }
FranKP2138 0:79288901821e 177
FranKP2138 0:79288901821e 178
FranKP2138 0:79288901821e 179 /**@brief Handles events coming from the LED Button central module.
FranKP2138 0:79288901821e 180 *
FranKP2138 0:79288901821e 181 * @param[in] p_lbs_c The instance of LBS_C that triggered the event.
FranKP2138 0:79288901821e 182 * @param[in] p_lbs_c_evt The LBS_C event.
FranKP2138 0:79288901821e 183 */
FranKP2138 0:79288901821e 184 static void lbs_c_evt_handler(ble_lbs_c_t * p_lbs_c, ble_lbs_c_evt_t * p_lbs_c_evt)
FranKP2138 0:79288901821e 185 {
FranKP2138 0:79288901821e 186 const uint16_t conn_handle = p_lbs_c_evt->conn_handle;
FranKP2138 0:79288901821e 187 switch (p_lbs_c_evt->evt_type)
FranKP2138 0:79288901821e 188 {
FranKP2138 0:79288901821e 189 case BLE_LBS_C_EVT_DISCOVERY_COMPLETE:
FranKP2138 0:79288901821e 190 {
FranKP2138 0:79288901821e 191 ret_code_t err_code;
FranKP2138 0:79288901821e 192
FranKP2138 0:79288901821e 193 NRF_LOG_PRINTF("[APP]: LED Button service discovered on conn_handle 0x%x\r\n",
FranKP2138 0:79288901821e 194 conn_handle);
FranKP2138 0:79288901821e 195
FranKP2138 0:79288901821e 196 err_code = app_button_enable();
FranKP2138 0:79288901821e 197 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 198
FranKP2138 0:79288901821e 199 // LED Button service discovered. Enable notification of Button.
FranKP2138 0:79288901821e 200 err_code = ble_lbs_c_button_notif_enable(p_lbs_c);
FranKP2138 0:79288901821e 201 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 202 } break; // BLE_LBS_C_EVT_DISCOVERY_COMPLETE
FranKP2138 0:79288901821e 203
FranKP2138 0:79288901821e 204 case BLE_LBS_C_EVT_BUTTON_NOTIFICATION:
FranKP2138 0:79288901821e 205 {
FranKP2138 0:79288901821e 206 NRF_LOG_PRINTF("[APP]: Link 0x%x, Button state changed on peer to 0x%x\r\n",
FranKP2138 0:79288901821e 207 conn_handle,
FranKP2138 0:79288901821e 208 p_lbs_c_evt->params.button.button_state);
FranKP2138 0:79288901821e 209 if (p_lbs_c_evt->params.button.button_state)
FranKP2138 0:79288901821e 210 {
FranKP2138 0:79288901821e 211 LEDS_ON(LEDBUTTON_LED);
FranKP2138 0:79288901821e 212 }
FranKP2138 0:79288901821e 213 else
FranKP2138 0:79288901821e 214 {
FranKP2138 0:79288901821e 215 LEDS_OFF(LEDBUTTON_LED);
FranKP2138 0:79288901821e 216 }
FranKP2138 0:79288901821e 217 } break; // BLE_LBS_C_EVT_BUTTON_NOTIFICATION
FranKP2138 0:79288901821e 218
FranKP2138 0:79288901821e 219 default:
FranKP2138 0:79288901821e 220 // No implementation needed.
FranKP2138 0:79288901821e 221 break;
FranKP2138 0:79288901821e 222 }
FranKP2138 0:79288901821e 223 }
FranKP2138 0:79288901821e 224
FranKP2138 0:79288901821e 225 /**@brief Function for handling the advertising report BLE event.
FranKP2138 0:79288901821e 226 *
FranKP2138 0:79288901821e 227 * @param[in] p_ble_evt Bluetooth stack event.
FranKP2138 0:79288901821e 228 */
FranKP2138 0:79288901821e 229 static void on_adv_report(const ble_evt_t * const p_ble_evt)
FranKP2138 0:79288901821e 230 {
FranKP2138 0:79288901821e 231 uint32_t err_code;
FranKP2138 0:79288901821e 232 uint8_array_t adv_data;
FranKP2138 0:79288901821e 233 uint8_array_t dev_name;
FranKP2138 0:79288901821e 234 bool do_connect = false;
FranKP2138 0:79288901821e 235
FranKP2138 0:79288901821e 236 // For readibility.
FranKP2138 0:79288901821e 237 const ble_gap_evt_t * const p_gap_evt = &p_ble_evt->evt.gap_evt;
FranKP2138 0:79288901821e 238 const ble_gap_addr_t * const peer_addr = &p_gap_evt->params.adv_report.peer_addr;
FranKP2138 0:79288901821e 239
FranKP2138 0:79288901821e 240 // Initialize advertisement report for parsing
FranKP2138 0:79288901821e 241 adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data;
FranKP2138 0:79288901821e 242 adv_data.size = p_gap_evt->params.adv_report.dlen;
FranKP2138 0:79288901821e 243
FranKP2138 0:79288901821e 244
FranKP2138 0:79288901821e 245 //search for advertising names
FranKP2138 0:79288901821e 246 bool found_name = false;
FranKP2138 0:79288901821e 247 err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
FranKP2138 0:79288901821e 248 &adv_data,
FranKP2138 0:79288901821e 249 &dev_name);
FranKP2138 0:79288901821e 250 if (err_code != NRF_SUCCESS)
FranKP2138 0:79288901821e 251 {
FranKP2138 0:79288901821e 252 // Look for the short local name if it was not found as complete
FranKP2138 0:79288901821e 253 err_code = adv_report_parse(BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, &adv_data, &dev_name);
FranKP2138 0:79288901821e 254 if (err_code != NRF_SUCCESS)
FranKP2138 0:79288901821e 255 {
FranKP2138 0:79288901821e 256 // If we can't parse the data, then exit
FranKP2138 0:79288901821e 257 return;
FranKP2138 0:79288901821e 258 }
FranKP2138 0:79288901821e 259 else
FranKP2138 0:79288901821e 260 {
FranKP2138 0:79288901821e 261 found_name = true;
FranKP2138 0:79288901821e 262 }
FranKP2138 0:79288901821e 263 }
FranKP2138 0:79288901821e 264 else
FranKP2138 0:79288901821e 265 {
FranKP2138 0:79288901821e 266 found_name = true;
FranKP2138 0:79288901821e 267 }
FranKP2138 0:79288901821e 268 if (found_name)
FranKP2138 0:79288901821e 269 {
FranKP2138 0:79288901821e 270 if (strlen(m_target_periph_name) != 0)
FranKP2138 0:79288901821e 271 {
FranKP2138 0:79288901821e 272 if(memcmp(m_target_periph_name, dev_name.p_data, dev_name.size) == 0)
FranKP2138 0:79288901821e 273 {
FranKP2138 0:79288901821e 274 do_connect = true;
FranKP2138 0:79288901821e 275 }
FranKP2138 0:79288901821e 276 }
FranKP2138 0:79288901821e 277 }
FranKP2138 0:79288901821e 278
FranKP2138 0:79288901821e 279 if (do_connect)
FranKP2138 0:79288901821e 280 {
FranKP2138 0:79288901821e 281 // Initiate connection.
FranKP2138 0:79288901821e 282 err_code = sd_ble_gap_connect(peer_addr, &m_scan_param, &m_connection_param);
FranKP2138 0:79288901821e 283 if (err_code != NRF_SUCCESS)
FranKP2138 0:79288901821e 284 {
FranKP2138 0:79288901821e 285 APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code);
FranKP2138 0:79288901821e 286 }
FranKP2138 0:79288901821e 287 }
FranKP2138 0:79288901821e 288 }
FranKP2138 0:79288901821e 289
FranKP2138 0:79288901821e 290 /**@brief Function for handling BLE Stack events concerning central applications.
FranKP2138 0:79288901821e 291 *
FranKP2138 0:79288901821e 292 * @details This function keeps the connection handles of central applications up-to-date. It
FranKP2138 0:79288901821e 293 * parses scanning reports, initiating a connection attempt to peripherals when a
FranKP2138 0:79288901821e 294 * target UUID is found, and manages connection parameter update requests. Additionally,
FranKP2138 0:79288901821e 295 * it updates the status of LEDs used to report central applications activity.
FranKP2138 0:79288901821e 296 *
FranKP2138 0:79288901821e 297 * @note Since this function updates connection handles, @ref BLE_GAP_EVT_DISCONNECTED events
FranKP2138 0:79288901821e 298 * should be dispatched to the target application before invoking this function.
FranKP2138 0:79288901821e 299 *
FranKP2138 0:79288901821e 300 * @param[in] p_ble_evt Bluetooth stack event.
FranKP2138 0:79288901821e 301 */
FranKP2138 0:79288901821e 302 static void on_ble_evt(const ble_evt_t * const p_ble_evt)
FranKP2138 0:79288901821e 303 {
FranKP2138 0:79288901821e 304 // For readability.
FranKP2138 0:79288901821e 305 const ble_gap_evt_t * const p_gap_evt = &p_ble_evt->evt.gap_evt;
FranKP2138 0:79288901821e 306
FranKP2138 0:79288901821e 307 switch (p_ble_evt->header.evt_id)
FranKP2138 0:79288901821e 308 {
FranKP2138 0:79288901821e 309 // Upon connection, check which peripheral has connected, initiate DB
FranKP2138 0:79288901821e 310 // discovery, update LEDs status and resume scanning if necessary.
FranKP2138 0:79288901821e 311 case BLE_GAP_EVT_CONNECTED:
FranKP2138 0:79288901821e 312 {
FranKP2138 0:79288901821e 313 uint32_t err_code;
FranKP2138 0:79288901821e 314
FranKP2138 0:79288901821e 315 NRF_LOG_PRINTF("[APP]: link 0x%x established, start discovery on it\r\n",
FranKP2138 0:79288901821e 316 p_gap_evt->conn_handle);
FranKP2138 0:79288901821e 317 APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < TOTAL_LINK_COUNT);
FranKP2138 0:79288901821e 318
FranKP2138 0:79288901821e 319 err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c[p_gap_evt->conn_handle],
FranKP2138 0:79288901821e 320 p_gap_evt->conn_handle,
FranKP2138 0:79288901821e 321 NULL);
FranKP2138 0:79288901821e 322 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 323
FranKP2138 0:79288901821e 324 err_code = ble_db_discovery_start(&m_ble_db_discovery[p_gap_evt->conn_handle],
FranKP2138 0:79288901821e 325 p_gap_evt->conn_handle);
FranKP2138 0:79288901821e 326 if (err_code != NRF_ERROR_BUSY)
FranKP2138 0:79288901821e 327 {
FranKP2138 0:79288901821e 328 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 329 }
FranKP2138 0:79288901821e 330
FranKP2138 0:79288901821e 331 // Update LEDs status, and check if we should be looking for more
FranKP2138 0:79288901821e 332 // peripherals to connect to.
FranKP2138 0:79288901821e 333 LEDS_ON(CENTRAL_CONNECTED_LED);
FranKP2138 0:79288901821e 334 if (ble_conn_state_n_centrals() == CENTRAL_LINK_COUNT)
FranKP2138 0:79288901821e 335 {
FranKP2138 0:79288901821e 336 LEDS_OFF(CENTRAL_SCANNING_LED);
FranKP2138 0:79288901821e 337 }
FranKP2138 0:79288901821e 338 else
FranKP2138 0:79288901821e 339 {
FranKP2138 0:79288901821e 340 // Resume scanning.
FranKP2138 0:79288901821e 341 LEDS_ON(CENTRAL_SCANNING_LED);
FranKP2138 0:79288901821e 342 scan_start();
FranKP2138 0:79288901821e 343 }
FranKP2138 0:79288901821e 344 } break; // BLE_GAP_EVT_CONNECTED
FranKP2138 0:79288901821e 345
FranKP2138 0:79288901821e 346 // Upon disconnection, reset the connection handle of the peer which disconnected, update
FranKP2138 0:79288901821e 347 // the LEDs status and start scanning again.
FranKP2138 0:79288901821e 348 case BLE_GAP_EVT_DISCONNECTED:
FranKP2138 0:79288901821e 349 {
FranKP2138 0:79288901821e 350 uint32_t central_link_cnt; // Number of central links.
FranKP2138 0:79288901821e 351
FranKP2138 0:79288901821e 352 NRF_LOG_PRINTF("LBS central link 0x%x disconnected (reason: %d)\r\n",
FranKP2138 0:79288901821e 353 p_gap_evt->conn_handle,
FranKP2138 0:79288901821e 354 p_gap_evt->params.disconnected.reason);
FranKP2138 0:79288901821e 355
FranKP2138 0:79288901821e 356 uint32_t err_code = app_button_disable();
FranKP2138 0:79288901821e 357 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 358
FranKP2138 0:79288901821e 359 // Start scanning
FranKP2138 0:79288901821e 360 scan_start();
FranKP2138 0:79288901821e 361
FranKP2138 0:79288901821e 362 // Update LEDs status.
FranKP2138 0:79288901821e 363 LEDS_ON(CENTRAL_SCANNING_LED);
FranKP2138 0:79288901821e 364 central_link_cnt = ble_conn_state_n_centrals();
FranKP2138 0:79288901821e 365 if (central_link_cnt == 0)
FranKP2138 0:79288901821e 366 {
FranKP2138 0:79288901821e 367 LEDS_OFF(CENTRAL_CONNECTED_LED);
FranKP2138 0:79288901821e 368 }
FranKP2138 0:79288901821e 369 } break; // BLE_GAP_EVT_DISCONNECTED
FranKP2138 0:79288901821e 370
FranKP2138 0:79288901821e 371 case BLE_GAP_EVT_ADV_REPORT:
FranKP2138 0:79288901821e 372 on_adv_report(p_ble_evt);
FranKP2138 0:79288901821e 373 break; // BLE_GAP_ADV_REPORT
FranKP2138 0:79288901821e 374
FranKP2138 0:79288901821e 375 case BLE_GAP_EVT_TIMEOUT:
FranKP2138 0:79288901821e 376 {
FranKP2138 0:79288901821e 377 // We have not specified a timeout for scanning, so only connection attemps can timeout.
FranKP2138 0:79288901821e 378 if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
FranKP2138 0:79288901821e 379 {
FranKP2138 0:79288901821e 380 APPL_LOG("[APPL]: Connection Request timed out.\r\n");
FranKP2138 0:79288901821e 381 }
FranKP2138 0:79288901821e 382 } break; // BLE_GAP_EVT_TIMEOUT
FranKP2138 0:79288901821e 383
FranKP2138 0:79288901821e 384 case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
FranKP2138 0:79288901821e 385 {
FranKP2138 0:79288901821e 386 // Accept parameters requested by peer.
FranKP2138 0:79288901821e 387 ret_code_t err_code;
FranKP2138 0:79288901821e 388 err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
FranKP2138 0:79288901821e 389 &p_gap_evt->params.conn_param_update_request.conn_params);
FranKP2138 0:79288901821e 390 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 391 } break; // BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST
FranKP2138 0:79288901821e 392
FranKP2138 0:79288901821e 393 default:
FranKP2138 0:79288901821e 394 // No implementation needed.
FranKP2138 0:79288901821e 395 break;
FranKP2138 0:79288901821e 396 }
FranKP2138 0:79288901821e 397 }
FranKP2138 0:79288901821e 398
FranKP2138 0:79288901821e 399
FranKP2138 0:79288901821e 400 /**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
FranKP2138 0:79288901821e 401 *
FranKP2138 0:79288901821e 402 * @details This function is called from the scheduler in the main loop after a BLE stack event has
FranKP2138 0:79288901821e 403 * been received.
FranKP2138 0:79288901821e 404 *
FranKP2138 0:79288901821e 405 * @param[in] p_ble_evt Bluetooth stack event.
FranKP2138 0:79288901821e 406 */
FranKP2138 0:79288901821e 407 static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
FranKP2138 0:79288901821e 408 {
FranKP2138 0:79288901821e 409 uint16_t conn_handle;
FranKP2138 0:79288901821e 410 conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
FranKP2138 0:79288901821e 411
FranKP2138 0:79288901821e 412 ble_conn_state_on_ble_evt(p_ble_evt);
FranKP2138 0:79288901821e 413 on_ble_evt(p_ble_evt);
FranKP2138 0:79288901821e 414
FranKP2138 0:79288901821e 415 // Make sure taht an invalid connection handle are not passed since
FranKP2138 0:79288901821e 416 // our array of modules is bound to TOTAL_LINK_COUNT.
FranKP2138 0:79288901821e 417 if (conn_handle < TOTAL_LINK_COUNT)
FranKP2138 0:79288901821e 418 {
FranKP2138 0:79288901821e 419 ble_db_discovery_on_ble_evt(&m_ble_db_discovery[conn_handle], p_ble_evt);
FranKP2138 0:79288901821e 420 ble_lbs_c_on_ble_evt(&m_ble_lbs_c[conn_handle], p_ble_evt);
FranKP2138 0:79288901821e 421 }
FranKP2138 0:79288901821e 422 }
FranKP2138 0:79288901821e 423
FranKP2138 0:79288901821e 424
FranKP2138 0:79288901821e 425 /**@brief LED Button collector initialization.
FranKP2138 0:79288901821e 426 */
FranKP2138 0:79288901821e 427 static void lbs_c_init(void)
FranKP2138 0:79288901821e 428 {
FranKP2138 0:79288901821e 429 uint32_t err_code;
FranKP2138 0:79288901821e 430 ble_lbs_c_init_t lbs_c_init_obj;
FranKP2138 0:79288901821e 431
FranKP2138 0:79288901821e 432 lbs_c_init_obj.evt_handler = lbs_c_evt_handler;
FranKP2138 0:79288901821e 433
FranKP2138 0:79288901821e 434 for(m_ble_lbs_c_count = 0; m_ble_lbs_c_count < TOTAL_LINK_COUNT; m_ble_lbs_c_count++)
FranKP2138 0:79288901821e 435 {
FranKP2138 0:79288901821e 436 err_code = ble_lbs_c_init(&m_ble_lbs_c[m_ble_lbs_c_count], &lbs_c_init_obj);
FranKP2138 0:79288901821e 437 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 438 }
FranKP2138 0:79288901821e 439 m_ble_lbs_c_count = 0;
FranKP2138 0:79288901821e 440 }
FranKP2138 0:79288901821e 441
FranKP2138 0:79288901821e 442
FranKP2138 0:79288901821e 443 /**@brief Function for initializing the BLE stack.
FranKP2138 0:79288901821e 444 *
FranKP2138 0:79288901821e 445 * @details Initializes the SoftDevice and the BLE event interrupts.
FranKP2138 0:79288901821e 446 */
FranKP2138 0:79288901821e 447 static void ble_stack_init(void)
FranKP2138 0:79288901821e 448 {
FranKP2138 0:79288901821e 449 ret_code_t err_code;
FranKP2138 0:79288901821e 450
FranKP2138 0:79288901821e 451 nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;
FranKP2138 0:79288901821e 452
FranKP2138 0:79288901821e 453 // Initialize the SoftDevice handler module.
FranKP2138 0:79288901821e 454 SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);
FranKP2138 0:79288901821e 455
FranKP2138 0:79288901821e 456 ble_enable_params_t ble_enable_params;
FranKP2138 0:79288901821e 457 err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
FranKP2138 0:79288901821e 458 PERIPHERAL_LINK_COUNT,
FranKP2138 0:79288901821e 459 &ble_enable_params);
FranKP2138 0:79288901821e 460 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 461
FranKP2138 0:79288901821e 462 // Stack checks first if there are still entries in the table before checking if a vendor
FranKP2138 0:79288901821e 463 // specific UUID is already in the table thus to be able to call sd_ble_uuid_vs_add several
FranKP2138 0:79288901821e 464 // times with the same entry, vs_uuid_count has to be 1 bigger than what is actually needed.
FranKP2138 0:79288901821e 465 ble_enable_params.common_enable_params.vs_uuid_count = 2;
FranKP2138 0:79288901821e 466
FranKP2138 0:79288901821e 467 // Check the ram settings against the used number of links
FranKP2138 0:79288901821e 468 CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT);
FranKP2138 0:79288901821e 469
FranKP2138 0:79288901821e 470 // Enable BLE stack.
FranKP2138 0:79288901821e 471 err_code = softdevice_enable(&ble_enable_params);
FranKP2138 0:79288901821e 472 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 473
FranKP2138 0:79288901821e 474 // Register with the SoftDevice handler module for BLE events.
FranKP2138 0:79288901821e 475 err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
FranKP2138 0:79288901821e 476 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 477 }
FranKP2138 0:79288901821e 478
FranKP2138 0:79288901821e 479
FranKP2138 0:79288901821e 480 /**@brief Function to write to the LED characterestic of all connected clients.
FranKP2138 0:79288901821e 481 *
FranKP2138 0:79288901821e 482 * @details Based on if the button is pressed or released, we write a high or low LED status to
FranKP2138 0:79288901821e 483 * the server.
FranKP2138 0:79288901821e 484 *
FranKP2138 0:79288901821e 485 * @param[in] button_action The button action (press/release).
FranKP2138 0:79288901821e 486 * Determines if the LEDs of the servers will be ON or OFF.
FranKP2138 0:79288901821e 487 *
FranKP2138 0:79288901821e 488 * @return NRF_SUCCESS on success, else the error code from ble_lbs_led_status_send.
FranKP2138 0:79288901821e 489 */
FranKP2138 0:79288901821e 490 static uint32_t led_status_send_to_all(uint8_t button_action)
FranKP2138 0:79288901821e 491 {
FranKP2138 0:79288901821e 492 uint32_t err_code;
FranKP2138 0:79288901821e 493
FranKP2138 0:79288901821e 494 for (uint32_t i = 0; i< CENTRAL_LINK_COUNT; i++)
FranKP2138 0:79288901821e 495 {
FranKP2138 0:79288901821e 496 err_code = ble_lbs_led_status_send(&m_ble_lbs_c[i], button_action);
FranKP2138 0:79288901821e 497 if (err_code != NRF_SUCCESS &&
FranKP2138 0:79288901821e 498 err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
FranKP2138 0:79288901821e 499 err_code != NRF_ERROR_INVALID_STATE)
FranKP2138 0:79288901821e 500 {
FranKP2138 0:79288901821e 501 return err_code;
FranKP2138 0:79288901821e 502 }
FranKP2138 0:79288901821e 503 }
FranKP2138 0:79288901821e 504 return NRF_SUCCESS;
FranKP2138 0:79288901821e 505 }
FranKP2138 0:79288901821e 506
FranKP2138 0:79288901821e 507
FranKP2138 0:79288901821e 508 /**@brief Function for handling events from the button handler module.
FranKP2138 0:79288901821e 509 *
FranKP2138 0:79288901821e 510 * @param[in] pin_no The pin that the event applies to.
FranKP2138 0:79288901821e 511 * @param[in] button_action The button action (press/release).
FranKP2138 0:79288901821e 512 */
FranKP2138 0:79288901821e 513 static void button_event_handler(uint8_t pin_no, uint8_t button_action)
FranKP2138 0:79288901821e 514 {
FranKP2138 0:79288901821e 515 uint32_t err_code;
FranKP2138 0:79288901821e 516
FranKP2138 0:79288901821e 517 switch (pin_no)
FranKP2138 0:79288901821e 518 {
FranKP2138 0:79288901821e 519 case LEDBUTTON_BUTTON_PIN:
FranKP2138 0:79288901821e 520 err_code = led_status_send_to_all(button_action);
FranKP2138 0:79288901821e 521 if (err_code == NRF_SUCCESS)
FranKP2138 0:79288901821e 522 {
FranKP2138 0:79288901821e 523 NRF_LOG_PRINTF("LBS write LED state %d\r\n", button_action);
FranKP2138 0:79288901821e 524 }
FranKP2138 0:79288901821e 525 break;
FranKP2138 0:79288901821e 526
FranKP2138 0:79288901821e 527 default:
FranKP2138 0:79288901821e 528 APP_ERROR_HANDLER(pin_no);
FranKP2138 0:79288901821e 529 break;
FranKP2138 0:79288901821e 530 }
FranKP2138 0:79288901821e 531 }
FranKP2138 0:79288901821e 532
FranKP2138 0:79288901821e 533
FranKP2138 0:79288901821e 534 /**@brief Function for initializing the button handler module.
FranKP2138 0:79288901821e 535 */
FranKP2138 0:79288901821e 536 static void buttons_init(void)
FranKP2138 0:79288901821e 537 {
FranKP2138 0:79288901821e 538 uint32_t err_code;
FranKP2138 0:79288901821e 539
FranKP2138 0:79288901821e 540 //The array must be static because a pointer to it will be saved in the button handler module.
FranKP2138 0:79288901821e 541 static app_button_cfg_t buttons[] =
FranKP2138 0:79288901821e 542 {
FranKP2138 0:79288901821e 543 {LEDBUTTON_BUTTON_PIN, false, BUTTON_PULL, button_event_handler}
FranKP2138 0:79288901821e 544 };
FranKP2138 0:79288901821e 545
FranKP2138 0:79288901821e 546 err_code = app_button_init(buttons, sizeof(buttons) / sizeof(buttons[0]),
FranKP2138 0:79288901821e 547 BUTTON_DETECTION_DELAY);
FranKP2138 0:79288901821e 548 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 549 }
FranKP2138 0:79288901821e 550
FranKP2138 0:79288901821e 551
FranKP2138 0:79288901821e 552 /**@brief Function for handling database discovery events.
FranKP2138 0:79288901821e 553 *
FranKP2138 0:79288901821e 554 * @details This function is callback function to handle events from the database discovery module.
FranKP2138 0:79288901821e 555 * Depending on the UUIDs that are discovered, this function should forward the events
FranKP2138 0:79288901821e 556 * to their respective services.
FranKP2138 0:79288901821e 557 *
FranKP2138 0:79288901821e 558 * @param[in] p_event Pointer to the database discovery event.
FranKP2138 0:79288901821e 559 */
FranKP2138 0:79288901821e 560 static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
FranKP2138 0:79288901821e 561 {
FranKP2138 0:79288901821e 562 NRF_LOG_PRINTF("[APP]: call to ble_lbs_on_db_disc_evt for instance %d and link 0x%x!\r\n",
FranKP2138 0:79288901821e 563 p_evt->conn_handle,
FranKP2138 0:79288901821e 564 p_evt->conn_handle);
FranKP2138 0:79288901821e 565 ble_lbs_on_db_disc_evt(&m_ble_lbs_c[p_evt->conn_handle], p_evt);
FranKP2138 0:79288901821e 566 }
FranKP2138 0:79288901821e 567
FranKP2138 0:79288901821e 568
FranKP2138 0:79288901821e 569 /** @brief Database discovery initialization.
FranKP2138 0:79288901821e 570 */
FranKP2138 0:79288901821e 571 static void db_discovery_init(void)
FranKP2138 0:79288901821e 572 {
FranKP2138 0:79288901821e 573 ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
FranKP2138 0:79288901821e 574 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 575 }
FranKP2138 0:79288901821e 576
FranKP2138 0:79288901821e 577
FranKP2138 0:79288901821e 578
FranKP2138 0:79288901821e 579 /** @brief Function to sleep until a BLE event is received by the application.
FranKP2138 0:79288901821e 580 */
FranKP2138 0:79288901821e 581 static void power_manage(void)
FranKP2138 0:79288901821e 582 {
FranKP2138 0:79288901821e 583 ret_code_t err_code = sd_app_evt_wait();
FranKP2138 0:79288901821e 584 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 585 }
FranKP2138 0:79288901821e 586
FranKP2138 0:79288901821e 587
FranKP2138 0:79288901821e 588 int main(void)
FranKP2138 0:79288901821e 589 {
FranKP2138 0:79288901821e 590 ret_code_t err_code;
FranKP2138 0:79288901821e 591
FranKP2138 0:79288901821e 592 err_code = NRF_LOG_INIT();
FranKP2138 0:79288901821e 593 APP_ERROR_CHECK(err_code);
FranKP2138 0:79288901821e 594 NRF_LOG_PRINTF("[APP]: Multilink Example\r\n");
FranKP2138 0:79288901821e 595 leds_init();
FranKP2138 0:79288901821e 596 APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
FranKP2138 0:79288901821e 597 buttons_init();
FranKP2138 0:79288901821e 598 ble_stack_init();
FranKP2138 0:79288901821e 599
FranKP2138 0:79288901821e 600 db_discovery_init();
FranKP2138 0:79288901821e 601 lbs_c_init();
FranKP2138 0:79288901821e 602
FranKP2138 0:79288901821e 603 // Start scanning for peripherals and initiate connection to devices which
FranKP2138 0:79288901821e 604 // advertise.
FranKP2138 0:79288901821e 605 scan_start();
FranKP2138 0:79288901821e 606
FranKP2138 0:79288901821e 607 // Turn on the LED to signal scanning.
FranKP2138 0:79288901821e 608 LEDS_ON(CENTRAL_SCANNING_LED);
FranKP2138 0:79288901821e 609
FranKP2138 0:79288901821e 610 for (;;)
FranKP2138 0:79288901821e 611 {
FranKP2138 0:79288901821e 612 // Wait for BLE events.
FranKP2138 0:79288901821e 613 power_manage();
FranKP2138 0:79288901821e 614 }
FranKP2138 0:79288901821e 615 }
FranKP2138 0:79288901821e 616