-
-
Save anonymous/41be2f1584a462dd2c2971764595305f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include "nordic_common.h" | |
#include "softdevice_handler.h" | |
#include "peer_manager.h" | |
#include "app_timer.h" | |
#include "app_util.h" | |
#include "boards.h" | |
#include "app_button.h" | |
#include "bsp.h" | |
#include "bsp_btn_ble.h" | |
#include "ble.h" | |
#include "ble_advdata.h" | |
#include "ble_advertising.h" | |
#include "ble_conn_params.h" | |
#include "ble_db_discovery.h" | |
#include "ble_gap.h" | |
#include "ble_hci.h" | |
#include "ble_conn_state.h" | |
#include "fstorage.h" | |
#include "fds.h" | |
#include "ble_nus_c.h" | |
#include "app_uart.h" | |
#define NRF_LOG_MODULE_NAME "APP" | |
#include "nrf_log.h" | |
#include "nrf_log_ctrl.h" | |
#if (NRF_SD_BLE_API_VERSION == 3) | |
#define NRF_BLE_MAX_MTU_SIZE GATT_MTU_SIZE_DEFAULT /**< MTU size used in the softdevice enabling and to reply to a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. */ | |
#endif | |
#define APP_FEATURE_NOT_SUPPORTED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 /**< Reply when unsupported features are requested. */ | |
#define CENTRAL_LINK_COUNT 2 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/ | |
#define PERIPHERAL_LINK_COUNT 1 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/ | |
#define UART_TX_BUF_SIZE 256 /**< Size of the UART TX buffer, in bytes. Must be a power of two. */ | |
#define UART_RX_BUF_SIZE 256 // Changed from 1 /**< Size of the UART RX buffer, in bytes. Must be a power of two. */ | |
#define CENTRAL_SCANNING_LED BSP_LED_0_MASK | |
#define CENTRAL_CONNECTED_LED BSP_LED_1_MASK | |
#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */ | |
#define APP_TIMER_MAX_TIMERS (2 + BSP_APP_TIMERS_NUMBER) /**< Maximum number of timers used by the application. */ | |
#define APP_TIMER_OP_QUEUE_SIZE 2 /**< Size of timer operation queues. */ | |
#define SEC_PARAM_BOND 1 /**< Perform bonding. */ | |
#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ | |
#define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ | |
#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ | |
#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ | |
#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ | |
#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size in octets. */ | |
#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size in octets. */ | |
#define SCAN_INTERVAL 0x00A0 | |
#define SCAN_ACTIVE 1 | |
#define SCAN_WINDOW 0x0050 /**< Determines scan window in units of 0.625 millisecond. */ | |
#define SCAN_TIMEOUT 0 | |
#define MIN_CONNECTION_INTERVAL (uint16_t) MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Determines minimum connection interval in milliseconds. */ | |
#define MAX_CONNECTION_INTERVAL (uint16_t) MSEC_TO_UNITS(30, UNIT_1_25_MS) /**< Determines maximum connection interval in milliseconds. */ | |
#define SLAVE_LATENCY 0 /**< Determines slave latency in terms of connection events. */ | |
#define SUPERVISION_TIMEOUT (uint16_t) MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Determines supervision time-out in units of 10 milliseconds. */ | |
#define UUID16_SIZE 4 /**< Size of a UUID, in bytes. */ | |
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN | |
/**@brief Macro to unpack 16bit unsigned UUID from an octet stream. */ | |
#define UUID16_EXTRACT(DST, SRC) \ | |
do \ | |
{ \ | |
(*(DST)) = (SRC)[1]; \ | |
(*(DST)) <<= 8; \ | |
(*(DST)) |= (SRC)[0]; \ | |
} while (0) | |
/**@brief Variable length data encapsulation in terms of length and pointer to data. */ | |
typedef struct | |
{ | |
uint8_t * p_data; /**< Pointer to data. */ | |
uint16_t data_len; /**< Length of data. */ | |
} data_t; | |
/** | |
* @brief Parameters used when scanning. | |
*/ | |
static const ble_gap_scan_params_t m_scan_params = | |
{ | |
.active = 1, | |
.interval = SCAN_INTERVAL, | |
.window = SCAN_WINDOW, | |
.timeout = SCAN_TIMEOUT, | |
#if (NRF_SD_BLE_API_VERSION == 2) | |
.selective = 0, | |
.p_whitelist = NULL, | |
#endif | |
#if (NRF_SD_BLE_API_VERSION == 3) | |
.use_whitelist = 0, | |
#endif | |
}; | |
/**@brief Connection parameters requested for connection. */ | |
static const ble_gap_conn_params_t m_connection_param = | |
{ | |
(uint16_t)MIN_CONNECTION_INTERVAL, | |
(uint16_t)MAX_CONNECTION_INTERVAL, | |
0, | |
(uint16_t)SUPERVISION_TIMEOUT | |
}; | |
static uint16_t m_conn_handle_nus_c = BLE_CONN_HANDLE_INVALID; | |
static ble_nus_c_t m_ble_nus_c; //Implement the Nordic UART Service | |
static ble_db_discovery_t m_ble_db_discovery[CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT]; /**< list of DB structures used by the database discovery module. */ | |
#define PERIPHERAL_ADVERTISING_LED BSP_LED_2_MASK | |
#define PERIPHERAL_CONNECTED_LED BSP_LED_3_MASK | |
#define DEVICE_NAME "MultiConnect" /**< Name of device used for advertising. */ | |
#define MANUFACTURER_NAME "Nordic" /**< Manufacturer. Will be passed to Device Information Service. */ | |
#define APP_ADV_INTERVAL 300 /**< The advertising interval (in units of 0.625 ms). This value corresponds to 187.5 ms. */ | |
#define APP_ADV_TIMEOUT_IN_SECONDS 180 /**< The advertising timeout in units of seconds. */ | |
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ | |
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000, APP_TIMER_PRESCALER) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ | |
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ | |
static const char m_target_periph_name[] = "DELTA-01DMX79E, GoPro 9088"; // Any peripherals can be added | |
static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_NUS_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}}; | |
/* | |
static const ble_uuid_t m_nus_uuid = | |
{ | |
.uuid = BLE_UUID_NUS_SERVICE, | |
.type = 0x02 | |
}; | |
*/ | |
/**@brief Function to handle asserts in the SoftDevice. | |
* | |
* @details This function will be called in case of an assert in the SoftDevice. | |
* | |
* @warning This handler is an example only and does not fit a final product. You need to analyze | |
* how your product is supposed to react in case of Assert. | |
* @warning On assert from the SoftDevice, the system can only recover on reset. | |
* | |
* @param[in] line_num Line number of the failing ASSERT call. | |
* @param[in] p_file_name File name of the failing ASSERT call. | |
*/ | |
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) | |
{ | |
app_error_handler(0xDEADBEEF, line_num, p_file_name); | |
} | |
/**@brief Function for handling errors from the Connection Parameters module. | |
* | |
* @param[in] nrf_error Error code containing information about what went wrong. | |
*/ | |
static void conn_params_error_handler(uint32_t nrf_error) | |
{ | |
APP_ERROR_HANDLER(nrf_error); | |
} | |
/** | |
* @brief Parses advertisement data, providing length and location of the field in case | |
* matching data is found. | |
* | |
* @param[in] Type of data to be looked for in advertisement data. | |
* @param[in] Advertisement report length and pointer to report. | |
* @param[out] If data type requested is found in the data report, type data length and | |
* pointer to data will be populated here. | |
* | |
* @retval NRF_SUCCESS if the data type is found in the report. | |
* @retval NRF_ERROR_NOT_FOUND if the data type could not be found. | |
*/ | |
static uint32_t adv_report_parse(uint8_t type, data_t * p_advdata, data_t * p_typedata) | |
{ | |
uint32_t index = 0; | |
uint8_t * p_data; | |
p_data = p_advdata->p_data; | |
while (index < p_advdata->data_len) | |
{ | |
uint8_t field_length = p_data[index]; | |
uint8_t field_type = p_data[index + 1]; | |
if (field_type == type) | |
{ | |
p_typedata->p_data = &p_data[index + 2]; | |
p_typedata->data_len = field_length - 1; | |
return NRF_SUCCESS; | |
} | |
index += field_length + 1; | |
} | |
return NRF_ERROR_NOT_FOUND; | |
} | |
/**@brief Function for initiating scanning. | |
*/ | |
static void scan_start(void) | |
{ | |
ret_code_t err_code; | |
(void) sd_ble_gap_scan_stop(); | |
err_code = sd_ble_gap_scan_start(&m_scan_params); | |
if (err_code != NRF_ERROR_INVALID_STATE) | |
{ | |
APP_ERROR_CHECK(err_code); | |
} | |
} | |
/**@brief Function for initiating advertising and scanning. | |
*/ | |
static void adv_scan_start(void) | |
{ | |
ret_code_t err_code; | |
uint32_t count; | |
//check if there are no flash operations in progress | |
err_code = fs_queued_op_count_get(&count); | |
APP_ERROR_CHECK(err_code); | |
if (count == 0) | |
{ | |
scan_start(); | |
// Turn on the LED to signal scanning. | |
LEDS_ON(CENTRAL_SCANNING_LED); | |
// Start advertising. | |
err_code = ble_advertising_start(BLE_ADV_MODE_FAST); | |
APP_ERROR_CHECK(err_code); | |
} | |
} | |
/**@brief Function for handling Peer Manager events. | |
* | |
* @param[in] p_evt Peer Manager event. | |
*/ | |
static void pm_evt_handler(pm_evt_t const * p_evt) | |
{ | |
ret_code_t err_code; | |
switch (p_evt->evt_id) | |
{ | |
case PM_EVT_BONDED_PEER_CONNECTED: | |
{ | |
err_code = pm_peer_rank_highest(p_evt->peer_id); | |
if (err_code != NRF_ERROR_BUSY) | |
{ | |
APP_ERROR_CHECK(err_code); | |
} | |
} | |
break;//PM_EVT_BONDED_PEER_CONNECTED | |
case PM_EVT_CONN_SEC_START: | |
break;//PM_EVT_CONN_SEC_START | |
case PM_EVT_CONN_SEC_SUCCEEDED: | |
{ | |
NRF_LOG_INFO("Link secured. Role: %d. conn_handle: %d, Procedure: %d\r\n", | |
ble_conn_state_role(p_evt->conn_handle), | |
p_evt->conn_handle, | |
p_evt->params.conn_sec_succeeded.procedure); | |
err_code = pm_peer_rank_highest(p_evt->peer_id); | |
if (err_code != NRF_ERROR_BUSY) | |
{ | |
APP_ERROR_CHECK(err_code); | |
} | |
} | |
break;//PM_EVT_CONN_SEC_SUCCEEDED | |
case PM_EVT_CONN_SEC_FAILED: | |
{ | |
switch (p_evt->params.conn_sec_failed.error) | |
{ | |
case PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING: | |
err_code = pm_conn_secure(p_evt->conn_handle, true); | |
if (err_code != NRF_ERROR_INVALID_STATE) | |
{ | |
APP_ERROR_CHECK(err_code); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
break;//PM_EVT_CONN_SEC_FAILED | |
case PM_EVT_CONN_SEC_CONFIG_REQ: | |
{ | |
// Reject pairing request from an already bonded peer. | |
pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false}; | |
pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); | |
} | |
break;//PM_EVT_CONN_SEC_CONFIG_REQ | |
case PM_EVT_STORAGE_FULL: | |
{ | |
err_code = fds_gc(); | |
if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) | |
{ | |
// Retry. | |
} | |
else | |
{ | |
APP_ERROR_CHECK(err_code); | |
} | |
} | |
break;//PM_EVT_STORAGE_FULL | |
case PM_EVT_ERROR_UNEXPECTED: | |
// Assert. | |
APP_ERROR_CHECK(p_evt->params.error_unexpected.error); | |
break;//PM_EVT_ERROR_UNEXPECTED | |
case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: | |
break;//PM_EVT_PEER_DATA_UPDATE_SUCCEEDED | |
case PM_EVT_PEER_DATA_UPDATE_FAILED: | |
// Assert. | |
APP_ERROR_CHECK_BOOL(false); | |
break;//PM_EVT_PEER_DATA_UPDATE_FAILED | |
case PM_EVT_PEER_DELETE_SUCCEEDED: | |
break;//PM_EVT_PEER_DELETE_SUCCEEDED | |
case PM_EVT_PEER_DELETE_FAILED: | |
// Assert. | |
APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error); | |
break;//PM_EVT_PEER_DELETE_FAILED | |
case PM_EVT_PEERS_DELETE_SUCCEEDED: | |
adv_scan_start(); | |
break;//PM_EVT_PEERS_DELETE_SUCCEEDED | |
case PM_EVT_PEERS_DELETE_FAILED: | |
// Assert. | |
APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error); | |
break;//PM_EVT_PEERS_DELETE_FAILED | |
case PM_EVT_LOCAL_DB_CACHE_APPLIED: | |
break;//PM_EVT_LOCAL_DB_CACHE_APPLIED | |
case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED: | |
// The local database has likely changed, send service changed indications. | |
pm_local_database_has_changed(); | |
break;//PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED | |
case PM_EVT_SERVICE_CHANGED_IND_SENT: | |
break;//PM_EVT_SERVICE_CHANGED_IND_SENT | |
case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED: | |
break;//PM_EVT_SERVICE_CHANGED_IND_CONFIRMED | |
default: | |
// No implementation needed. | |
break; | |
} | |
} | |
//static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt) | |
//{ | |
// | |
// switch (p_hrs_c_evt->evt_type) | |
// { | |
// case BLE_HRS_C_EVT_DISCOVERY_COMPLETE: | |
// { | |
// | |
// if (m_conn_handle_nus_c == BLE_CONN_HANDLE_INVALID) | |
// { | |
// ret_code_t err_code; | |
// m_conn_handle_nus_c = p_hrs_c_evt->conn_handle; | |
// NRF_LOG_INFO("Discovered on conn_handle 0x%x\r\n", | |
// m_conn_handle_nus_c); | |
// err_code = ble_hrs_c_handles_assign(p_hrs_c, | |
// m_conn_handle_nus_c, | |
// &p_hrs_c_evt->params.peer_db); | |
// APP_ERROR_CHECK(err_code); | |
// | |
// // Initiate bonding. | |
// err_code = pm_conn_secure(m_conn_handle_nus_c, false); | |
// | |
// | |
// if (err_code != NRF_ERROR_INVALID_STATE) | |
// { | |
// APP_ERROR_CHECK(err_code); | |
// } | |
// | |
// err_code = ble_hrs_c_hrm_notif_enable(p_hrs_c); | |
// APP_ERROR_CHECK(err_code); | |
// } | |
// } | |
// break; // BLE_HRS_C_EVT_DISCOVERY_COMPLETE | |
// case BLE_HRS_C_EVT_HRM_NOTIFICATION: | |
// { | |
// ret_code_t err_code; | |
// NRF_LOG_INFO("Service = %d\r\n", p_hrs_c_evt->params.hrm.hr_value); | |
//// err_code = ble_hrs_heart_rate_measurement_send(&m_hrs, p_hrs_c_evt->params.hrm.hr_value); | |
// if ((err_code != NRF_SUCCESS) && | |
// (err_code != NRF_ERROR_INVALID_STATE) && | |
// (err_code != BLE_ERROR_NO_TX_PACKETS) && | |
// (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING) | |
// ) | |
// { | |
// APP_ERROR_HANDLER(err_code); | |
// } | |
// } break; // BLE_HRS_C_EVT_HRM_NOTIFICATION | |
// default: | |
// // No implementation needed. | |
// break; | |
// } | |
//} | |
/**< Adding to make sure that there is UART Service */ | |
void uart_event_handle(app_uart_evt_t * p_event) | |
{ | |
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN]; | |
static uint8_t index=0; | |
switch (p_event->evt_type) | |
{ | |
case APP_UART_DATA_READY: | |
UNUSED_VARIABLE(app_uart_get(&data_array[index])); | |
index++; | |
if((data_array[index-1] == '\n') || (index >= (BLE_NUS_MAX_DATA_LEN))) | |
{ | |
while(ble_nus_c_string_send(&m_ble_nus_c, data_array, index) != NRF_SUCCESS) | |
{ | |
} | |
index=0; | |
} | |
break; | |
case APP_UART_COMMUNICATION_ERROR: | |
APP_ERROR_HANDLER(p_event-> data.error_communication); | |
break; | |
case APP_UART_FIFO_ERROR: | |
APP_ERROR_HANDLER(p_event -> data.error_code); | |
break; | |
default: | |
break; | |
} | |
} | |
/**@brief Function for searching a given name in the advertisement packets. | |
* | |
* @details Use this function to parse received advertising data and to find a given | |
* name in them either as 'complete_local_name' or as 'short_local_name'. | |
* | |
* @param[in] p_adv_report advertising data to parse. | |
* @param[in] name_to_find name to search. | |
* @return true if the given name was found, false otherwise. | |
*/ | |
static bool find_adv_name(const ble_gap_evt_adv_report_t *p_adv_report, const char * name_to_find) | |
{ | |
uint32_t err_code; | |
data_t adv_data; | |
data_t dev_name; | |
// Initialize advertisement report for parsing | |
adv_data.p_data = (uint8_t *)p_adv_report->data; | |
adv_data.data_len = p_adv_report->dlen; | |
//search for advertising names | |
err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, | |
&adv_data, | |
&dev_name); | |
if (err_code == NRF_SUCCESS) | |
{ | |
if (memcmp(name_to_find, dev_name.p_data, dev_name.data_len )== 0) | |
{ | |
return true; | |
} | |
} | |
else | |
{ | |
// Look for the short local name if it was not found as complete | |
err_code = adv_report_parse(BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, | |
&adv_data, | |
&dev_name); | |
if (err_code != NRF_SUCCESS) | |
{ | |
return false; | |
} | |
if (memcmp(m_target_periph_name, dev_name.p_data, dev_name.data_len )== 0) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
/**@brief Function for searching a UUID in the advertisement packets. | |
* | |
* @details Use this function to parse received advertising data and to find a given | |
* UUID in them. | |
* | |
* @param[in] p_adv_report advertising data to parse. | |
* @param[in] uuid_to_find UUIID to search. | |
* @return true if the given UUID was found, false otherwise. | |
*/ | |
static bool find_adv_uuid(const ble_gap_evt_adv_report_t *p_adv_report, const uint16_t uuid_to_find) | |
{ | |
uint32_t err_code; | |
data_t adv_data; | |
data_t type_data; | |
// Initialize advertisement report for parsing. | |
adv_data.p_data = (uint8_t *)p_adv_report->data; | |
adv_data.data_len = p_adv_report->dlen; | |
err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, | |
&adv_data, | |
&type_data); | |
if (err_code != NRF_SUCCESS) | |
{ | |
// Look for the services in 'complete' if it was not found in 'more available'. | |
err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, | |
&adv_data, | |
&type_data); | |
if (err_code != NRF_SUCCESS) | |
{ | |
// If we can't parse the data, then exit. | |
return false; | |
} | |
} | |
// Verify if any UUID match the given UUID. | |
for (uint32_t u_index = 0; u_index < (type_data.data_len / UUID16_SIZE); u_index++) | |
{ | |
uint16_t extracted_uuid; | |
UUID16_EXTRACT(&extracted_uuid, &type_data.p_data[u_index * UUID16_SIZE]); | |
if (extracted_uuid == uuid_to_find) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
/**@brief Function for handling BLE Stack events concerning central applications. | |
* | |
* @details This function keeps the connection handles of central applications up-to-date. It | |
* parses scanning reports, initiating a connection attempt to peripherals when a target UUID | |
* is found, and manages connection parameter update requests. Additionally, it updates the status | |
* of LEDs used to report central applications activity. | |
* | |
* @note Since this function updates connection handles, @ref BLE_GAP_EVT_DISCONNECTED events | |
* should be dispatched to the target application before invoking this function. | |
* | |
* @param[in] p_ble_evt Bluetooth stack event. | |
*/ | |
static void on_ble_central_evt(const ble_evt_t * const p_ble_evt) | |
{ | |
const ble_gap_evt_t * const p_gap_evt = &p_ble_evt->evt.gap_evt; | |
ret_code_t err_code; | |
switch (p_ble_evt->header.evt_id) | |
{ | |
case BLE_GAP_EVT_CONNECTED: | |
{ | |
NRF_LOG_INFO("Central Connected \r\n"); | |
if (m_conn_handle_nus_c == BLE_CONN_HANDLE_INVALID) | |
{ | |
NRF_LOG_INFO("Find out about: 0x%x\r\n", p_gap_evt->conn_handle); | |
APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT); | |
err_code = ble_db_discovery_start(&m_ble_db_discovery[p_gap_evt->conn_handle], p_gap_evt->conn_handle); | |
APP_ERROR_CHECK(err_code); | |
} | |
LEDS_ON(CENTRAL_CONNECTED_LED); | |
if (ble_conn_state_n_centrals() == CENTRAL_LINK_COUNT) | |
{ | |
LEDS_OFF(CENTRAL_SCANNING_LED); | |
} | |
else | |
{ | |
// Resume scanning. | |
LEDS_ON(CENTRAL_SCANNING_LED); | |
scan_start(); | |
} | |
} break; // BLE_GAP_EVT_CONNECTED | |
/** Upon disconnection, reset the connection handle of the peer which disconnected, update | |
* the LEDs status and start scanning again. */ | |
case BLE_GAP_EVT_DISCONNECTED: | |
{ | |
uint8_t n_centrals; | |
if (p_gap_evt->conn_handle == m_conn_handle_nus_c) | |
{ | |
NRF_LOG_INFO("Central disconnected (reason: %d)\r\n", | |
p_gap_evt->params.disconnected.reason); | |
m_conn_handle_nus_c = BLE_CONN_HANDLE_INVALID; | |
} | |
if | |
(m_conn_handle_nus_c == BLE_CONN_HANDLE_INVALID) | |
{ | |
// Start scanning | |
scan_start(); | |
// Update LEDs status. | |
LEDS_ON(CENTRAL_SCANNING_LED); | |
} | |
n_centrals = ble_conn_state_n_centrals(); | |
if (n_centrals == 0) | |
{ | |
LEDS_OFF(CENTRAL_CONNECTED_LED); | |
} | |
} | |
break; // BLE_GAP_EVT_DISCONNECTED | |
case BLE_GAP_EVT_ADV_REPORT: | |
{ | |
if (strlen(m_target_periph_name) != 0) | |
{ | |
if (find_adv_name(&p_gap_evt->params.adv_report, m_target_periph_name)) | |
{ | |
// Initiate connection. | |
err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr, | |
&m_scan_params, | |
&m_connection_param); | |
if (err_code != NRF_SUCCESS) | |
{ | |
NRF_LOG_INFO("Connection Request Failed, reason %d\r\n", err_code); | |
} | |
} | |
} | |
else | |
{ | |
/** We do not want to connect to two peripherals offering the same service, so when | |
* a UUID is matched, we check that we are not already connected to a peer which | |
* offers the same service. */ | |
if ((find_adv_uuid(&p_gap_evt->params.adv_report, BLE_UUID_UNIVERSAL_SERVICE)&& | |
(m_conn_handle_nus_c == BLE_CONN_HANDLE_INVALID))) | |
{ | |
// Initiate connection. | |
err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr, | |
&m_scan_params, | |
&m_connection_param); | |
if (err_code != NRF_SUCCESS) | |
{ | |
NRF_LOG_INFO("Connection Request Failed, reason %d\r\n", err_code); | |
} | |
} | |
} | |
} | |
break; // BLE_GAP_ADV_REPORT | |
case BLE_GAP_EVT_TIMEOUT: | |
{ | |
// We have not specified a timeout for scanning, so only connection attemps can timeout. | |
if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) | |
{ | |
NRF_LOG_INFO("Connection Request timed out.\r\n"); | |
} | |
} | |
break; // BLE_GAP_EVT_TIMEOUT | |
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: | |
{ | |
// Accept parameters requested by peer. | |
err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, | |
&p_gap_evt->params.conn_param_update_request.conn_params); | |
APP_ERROR_CHECK(err_code); | |
} | |
break; // BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST | |
case BLE_GATTC_EVT_TIMEOUT: | |
// Disconnect on GATT Client timeout event. | |
NRF_LOG_DEBUG("GATT Client Timeout.\r\n"); | |
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, | |
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); | |
APP_ERROR_CHECK(err_code); | |
break; // BLE_GATTC_EVT_TIMEOUT | |
case BLE_GATTS_EVT_TIMEOUT: | |
// Disconnect on GATT Server timeout event. | |
NRF_LOG_DEBUG("GATT Server Timeout.\r\n"); | |
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, | |
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); | |
APP_ERROR_CHECK(err_code); | |
break; // BLE_GATTS_EVT_TIMEOUT | |
#if (NRF_SD_BLE_API_VERSION == 3) | |
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: | |
err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, | |
NRF_BLE_MAX_MTU_SIZE); | |
APP_ERROR_CHECK(err_code); | |
break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST | |
#endif | |
default: | |
// No implementation needed. | |
break; | |
} | |
} | |
/**@brief Function for handling BLE Stack events involving peripheral applications. Manages the | |
* LEDs used to report the status of the peripheral applications. | |
* | |
* @param[in] p_ble_evt Bluetooth stack event. | |
*/ | |
static void on_ble_peripheral_evt(ble_evt_t * p_ble_evt) | |
{ | |
ret_code_t err_code; | |
switch (p_ble_evt->header.evt_id) | |
{ | |
case BLE_GAP_EVT_CONNECTED: | |
NRF_LOG_INFO("Peripheral connected\r\n"); | |
LEDS_OFF(PERIPHERAL_ADVERTISING_LED); | |
LEDS_ON(PERIPHERAL_CONNECTED_LED); | |
break; //BLE_GAP_EVT_CONNECTED | |
case BLE_GAP_EVT_DISCONNECTED: | |
NRF_LOG_INFO("Peripheral disconnected\r\n"); | |
LEDS_OFF(PERIPHERAL_CONNECTED_LED); | |
break;//BLE_GAP_EVT_DISCONNECTED | |
case BLE_GATTC_EVT_TIMEOUT: | |
// Disconnect on GATT Client timeout event. | |
NRF_LOG_DEBUG("GATT Client Timeout.\r\n"); | |
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, | |
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); | |
APP_ERROR_CHECK(err_code); | |
break; // BLE_GATTC_EVT_TIMEOUT | |
case BLE_GATTS_EVT_TIMEOUT: | |
// Disconnect on GATT Server timeout event. | |
NRF_LOG_DEBUG("GATT Server Timeout.\r\n"); | |
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, | |
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); | |
APP_ERROR_CHECK(err_code); | |
break; // BLE_GATTS_EVT_TIMEOUT | |
case BLE_EVT_USER_MEM_REQUEST: | |
err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gap_evt.conn_handle, NULL); | |
APP_ERROR_CHECK(err_code); | |
break;//BLE_EVT_USER_MEM_REQUEST | |
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: | |
{ | |
ble_gatts_evt_rw_authorize_request_t req; | |
ble_gatts_rw_authorize_reply_params_t auth_reply; | |
req = p_ble_evt->evt.gatts_evt.params.authorize_request; | |
if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) | |
{ | |
if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || | |
(req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || | |
(req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) | |
{ | |
if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) | |
{ | |
auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; | |
} | |
else | |
{ | |
auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; | |
} | |
auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; | |
err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, | |
&auth_reply); | |
APP_ERROR_CHECK(err_code); | |
} | |
} | |
} | |
break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST | |
#if (NRF_SD_BLE_API_VERSION == 3) | |
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: | |
err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, | |
NRF_BLE_MAX_MTU_SIZE); | |
APP_ERROR_CHECK(err_code); | |
break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST | |
#endif | |
default: | |
// No implementation needed. | |
break; | |
} | |
} | |
/**@brief Function for handling advertising events. | |
* | |
* @param[in] ble_adv_evt Advertising event. | |
*/ | |
static void on_adv_evt(ble_adv_evt_t ble_adv_evt) | |
{ | |
switch (ble_adv_evt) | |
{ | |
case BLE_ADV_EVT_FAST: | |
NRF_LOG_INFO("Advertising: \r\n"); | |
LEDS_ON(PERIPHERAL_ADVERTISING_LED); | |
break;//BLE_ADV_EVT_FAST | |
case BLE_ADV_EVT_IDLE: | |
{ | |
ret_code_t err_code; | |
err_code = ble_advertising_start(BLE_ADV_MODE_FAST); | |
APP_ERROR_CHECK(err_code); | |
} | |
break;//BLE_ADV_EVT_IDLE | |
default: | |
// No implementation needed. | |
break; | |
} | |
} | |
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, const ble_nus_c_evt_t * p_ble_nus_evt) | |
{ | |
uint32_t err_code; | |
switch (p_ble_nus_evt->evt_type) | |
{ | |
case BLE_NUS_C_EVT_DISCOVERY_COMPLETE: | |
err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles); | |
APP_ERROR_CHECK(err_code); | |
err_code = ble_nus_c_rx_notif_enable(p_ble_nus_c); | |
APP_ERROR_CHECK(err_code); | |
NRF_LOG_INFO("The device has the Nordic UART Service\r\n"); | |
break; | |
case BLE_NUS_C_EVT_NUS_RX_EVT: | |
for (uint32_t i = 0; i < p_ble_nus_evt->data_len; i++) | |
{ | |
while (app_uart_put( p_ble_nus_evt->p_data[i]) != NRF_SUCCESS); | |
} | |
break; | |
case BLE_NUS_C_EVT_DISCONNECTED: | |
NRF_LOG_INFO("Disconnected\r\n"); | |
scan_start(); | |
break; | |
} | |
} | |
/**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler. | |
* | |
* @details This function is called from the scheduler in the main loop after a BLE stack event has | |
* been received. | |
* | |
* @param[in] p_ble_evt Bluetooth stack event. | |
*/ | |
static void ble_evt_dispatch(ble_evt_t * p_ble_evt) | |
{ | |
uint16_t conn_handle; | |
uint16_t role; | |
ble_conn_state_on_ble_evt(p_ble_evt); | |
//bsp_btn_ble_on_ble_evt(p_ble_evt); | |
pm_on_ble_evt(p_ble_evt); | |
// The connection handle should really be retrievable for any event type. | |
conn_handle = p_ble_evt->evt.gap_evt.conn_handle; | |
role = ble_conn_state_role(conn_handle); | |
// Based on the role this device plays in the connection, dispatch to the right applications. | |
if (role == BLE_GAP_ROLE_PERIPH) | |
{ | |
// Manages peripheral LEDs. | |
on_ble_peripheral_evt(p_ble_evt); | |
ble_advertising_on_ble_evt(p_ble_evt); | |
ble_conn_params_on_ble_evt(p_ble_evt); | |
} | |
else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT)) | |
{ | |
/** on_ble_central_evt will update the connection handles, so we want to execute it | |
* after dispatching to the central applications upon disconnection. */ | |
if (p_ble_evt->header.evt_id != BLE_GAP_EVT_DISCONNECTED) | |
{ | |
on_ble_central_evt(p_ble_evt); | |
} | |
if (conn_handle < CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT) | |
{ | |
ble_db_discovery_on_ble_evt(&m_ble_db_discovery[conn_handle], p_ble_evt); | |
} | |
// Dispatch to peripheral applications. | |
ble_nus_c_on_ble_evt(&m_ble_nus_c,p_ble_evt); | |
// If the peer disconnected, we update the connection handles last. | |
if (p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED) | |
{ | |
on_ble_central_evt(p_ble_evt); | |
} | |
} | |
} | |
/**@brief Function for dispatching a system event to interested modules. | |
* | |
* @details This function is called from the System event interrupt handler after a system | |
* event has been received. | |
* | |
* @param[in] sys_evt System stack event. | |
*/ | |
static void sys_evt_dispatch(uint32_t sys_evt) | |
{ | |
fs_sys_event_handler(sys_evt); | |
ble_advertising_on_sys_evt(sys_evt); | |
} | |
//static void hrs_c_init(void) | |
//{ | |
// uint32_t err_code; | |
// ble_hrs_c_init_t hrs_c_init_obj; | |
// | |
// hrs_c_init_obj.evt_handler = hrs_c_evt_handler; | |
// err_code = ble_hrs_c_init(&m_ble_hrs_c, &hrs_c_init_obj); | |
// APP_ERROR_CHECK(err_code); | |
// | |
//} | |
/**@brief Function for initializing the BLE stack. | |
* | |
* @details Initializes the SoftDevice and the BLE event interrupts. | |
*/ | |
static void ble_stack_init(void) | |
{ | |
ret_code_t err_code; | |
// Initialize the SoftDevice handler module. | |
nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; | |
SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL); | |
ble_enable_params_t ble_enable_params; | |
err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, | |
PERIPHERAL_LINK_COUNT, | |
&ble_enable_params); | |
APP_ERROR_CHECK(err_code); | |
//Check the ram settings against the used number of links | |
CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT); | |
// Enable BLE stack. | |
#if (NRF_SD_BLE_API_VERSION == 3) | |
ble_enable_params.gatt_enable_params.att_mtu = NRF_BLE_MAX_MTU_SIZE; | |
#endif | |
err_code = softdevice_enable(&ble_enable_params); | |
APP_ERROR_CHECK(err_code); | |
// Register with the SoftDevice handler module for BLE events. | |
err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); | |
APP_ERROR_CHECK(err_code); | |
// Register with the SoftDevice handler module for System events. | |
err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); | |
APP_ERROR_CHECK(err_code); | |
} | |
/**@brief Function for the Peer Manager initialization. | |
* | |
* @param[in] erase_bonds Indicates whether bonding information should be cleared from | |
* persistent storage during initialization of the Peer Manager. | |
*/ | |
static void peer_manager_init(bool erase_bonds) | |
{ | |
ble_gap_sec_params_t sec_param; | |
ret_code_t err_code; | |
err_code = pm_init(); | |
APP_ERROR_CHECK(err_code); | |
if (erase_bonds) | |
{ | |
err_code = pm_peers_delete(); | |
APP_ERROR_CHECK(err_code); | |
} | |
memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); | |
// Security parameters to be used for all security procedures. | |
sec_param.bond = SEC_PARAM_BOND; | |
sec_param.mitm = SEC_PARAM_MITM; | |
sec_param.lesc = SEC_PARAM_LESC; | |
sec_param.keypress = SEC_PARAM_KEYPRESS; | |
sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; | |
sec_param.oob = SEC_PARAM_OOB; | |
sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; | |
sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; | |
sec_param.kdist_own.enc = 1; | |
sec_param.kdist_own.id = 1; | |
sec_param.kdist_peer.enc = 1; | |
sec_param.kdist_peer.id = 1; | |
err_code = pm_sec_params_set(&sec_param); | |
APP_ERROR_CHECK(err_code); | |
err_code = pm_register(pm_evt_handler); | |
APP_ERROR_CHECK(err_code); | |
} | |
/**@brief Function for initializing buttons and leds. | |
* | |
* @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to | |
* wake the application up. | |
*/ | |
static void buttons_leds_init(bool * p_erase_bonds) | |
{ | |
bsp_event_t startup_event; | |
ret_code_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, | |
APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), | |
NULL); | |
APP_ERROR_CHECK(err_code); | |
err_code = bsp_btn_ble_init(NULL, &startup_event); | |
APP_ERROR_CHECK(err_code); | |
*p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); | |
} | |
/**@brief Function for the GAP initialization. | |
* | |
* @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the | |
* device including the device name, appearance, and the preferred connection parameters. | |
*/ | |
static void gap_params_init(void) | |
{ | |
uint32_t err_code; | |
ble_gap_conn_params_t gap_conn_params; | |
ble_gap_conn_sec_mode_t sec_mode; | |
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); | |
err_code = sd_ble_gap_device_name_set(&sec_mode, | |
(const uint8_t *)DEVICE_NAME, | |
strlen(DEVICE_NAME)); | |
APP_ERROR_CHECK(err_code); | |
memset(&gap_conn_params, 0, sizeof(gap_conn_params)); | |
gap_conn_params.min_conn_interval = MIN_CONNECTION_INTERVAL; | |
gap_conn_params.max_conn_interval = MAX_CONNECTION_INTERVAL; | |
gap_conn_params.slave_latency = SLAVE_LATENCY; | |
gap_conn_params.conn_sup_timeout = SUPERVISION_TIMEOUT; | |
err_code = sd_ble_gap_ppcp_set(&gap_conn_params); | |
APP_ERROR_CHECK(err_code); | |
} | |
/**@brief Function for initializing the Connection Parameters module. | |
*/ | |
static void conn_params_init(void) | |
{ | |
uint32_t err_code; | |
ble_conn_params_init_t cp_init; | |
memset(&cp_init, 0, sizeof(cp_init)); | |
cp_init.p_conn_params = NULL; | |
cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; | |
cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; | |
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; | |
cp_init.start_on_notify_cccd_handle = BLE_CONN_HANDLE_INVALID; | |
cp_init.disconnect_on_fail = true; | |
cp_init.evt_handler = NULL; | |
cp_init.error_handler = conn_params_error_handler; | |
err_code = ble_conn_params_init(&cp_init); | |
APP_ERROR_CHECK(err_code); | |
} | |
/**@brief Function for handling database discovery events. | |
* | |
* @details This function is callback function to handle events from the database discovery module. | |
* Depending on the UUIDs that are discovered, this function should forward the events | |
* to their respective services. | |
* | |
* @param[in] p_event Pointer to the database discovery event. | |
*/ | |
static void db_disc_handler(ble_db_discovery_evt_t * p_evt) | |
{ | |
ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt); | |
} | |
/**@brief Function for initializing the Advertising functionality. | |
*/ | |
static void advertising_init(void) | |
{ | |
uint32_t err_code; | |
ble_advdata_t advdata; | |
ble_adv_modes_config_t options; | |
// Build advertising data struct to pass into @ref ble_advertising_init. | |
memset(&advdata, 0, sizeof(advdata)); | |
advdata.name_type = BLE_ADVDATA_FULL_NAME; | |
advdata.include_appearance = true; | |
advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; | |
advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); | |
advdata.uuids_complete.p_uuids = m_adv_uuids; | |
memset(&options, 0, sizeof(options)); | |
options.ble_adv_fast_enabled = true; | |
options.ble_adv_fast_interval = APP_ADV_INTERVAL; | |
options.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS; | |
err_code = ble_advertising_init(&advdata, NULL, &options, on_adv_evt, NULL); | |
APP_ERROR_CHECK(err_code); | |
} | |
#define BUTTON_PRESS 1 /**< Passed to button handler */ | |
#define BUTTON_RELEASE 0 /**< Passed to button handler */ | |
#define BUTTON0_PIN 13 | |
#define BUTTON1_PIN 14 | |
#define BUTTON_COUNT 4 | |
#define BUTTON_ACTIVE_STATE 0 | |
#define BUTTON_PULL NRF_GPIO_PIN_PULLUP | |
#define BUTTON_CFG(num) BUTTON##num##_PIN, BUTTON_ACTIVE_STATE, \ | |
BUTTON_PULL, button_handler | |
enum OP_MODE {INIT, CENTRAL, PERIPHERAL}; | |
enum OP_MODE mode = INIT; | |
void button_handler(uint8_t pin_no, uint8_t button_action) | |
{ | |
if (button_action == BUTTON_PRESS) | |
{ | |
switch(pin_no) | |
{ | |
case BUTTON0_PIN: | |
if(mode== PERIPHERAL) //switch from peripheral to central | |
{ | |
sd_ble_gap_scan_stop(); | |
} | |
scan_start(); | |
mode= CENTRAL; | |
break; | |
case BUTTON1_PIN: | |
if(mode== CENTRAL)// switch from central to peripheral | |
{ | |
sd_ble_gap_scan_stop(); | |
} | |
ble_advertising_start(BLE_ADV_MODE_FAST); | |
mode= PERIPHERAL; | |
break; | |
default: | |
break; | |
} | |
} | |
} /* app_button_handler */ | |
/**< Button configuration list to pass to app_button_init */ | |
app_button_cfg_t button_cfg[] = | |
{ | |
{ BUTTON_CFG(0) }, | |
{ BUTTON_CFG(1) } | |
}; | |
/** | |
* @brief Database discovery initialization. | |
*/ | |
static void db_discovery_init(void) | |
{ | |
uint32_t err_code = ble_db_discovery_init(db_disc_handler); | |
APP_ERROR_CHECK(err_code); | |
} | |
/* | |
static void db_discovery_init1(void) | |
{ | |
uint32_t err_code = ble_db_discovery_init(db_disc_handler1); | |
APP_ERROR_CHECK(err_code); | |
} | |
*/ | |
// Might use this function | |
static void uart_init(void) | |
{ | |
uint32_t err_code; | |
const app_uart_comm_params_t comm_params = | |
{ | |
.rx_pin_no = RX_PIN_NUMBER, | |
.tx_pin_no = TX_PIN_NUMBER, | |
.rts_pin_no = RTS_PIN_NUMBER, | |
.cts_pin_no = CTS_PIN_NUMBER, | |
.flow_control = APP_UART_FLOW_CONTROL_ENABLED, | |
.use_parity = false, | |
.baud_rate = UART_BAUDRATE_BAUDRATE_Baud115200 | |
}; | |
APP_UART_FIFO_INIT(&comm_params, | |
UART_RX_BUF_SIZE, | |
UART_TX_BUF_SIZE, | |
uart_event_handle, | |
APP_IRQ_PRIORITY_LOW, | |
err_code); | |
APP_ERROR_CHECK(err_code); | |
} | |
/**@brief Function for initializing the NUS Client. | |
*/ | |
static void nus_c_init(void) | |
{ | |
uint32_t err_code; | |
ble_nus_c_init_t nus_c_init_t; | |
nus_c_init_t.evt_handler = ble_nus_c_evt_handler; | |
err_code = ble_nus_c_init(&m_ble_nus_c, &nus_c_init_t); | |
APP_ERROR_CHECK(err_code); | |
} | |
/** @brief Function to sleep until a BLE event is received by the application. | |
*/ | |
static void power_manage(void) | |
{ | |
ret_code_t err_code = sd_app_evt_wait(); | |
APP_ERROR_CHECK(err_code); | |
} | |
int main(void) | |
{ | |
bool erase_bonds; | |
APP_ERROR_CHECK( NRF_LOG_INIT(NULL)); | |
//NRF_LOG_INFO("Universal Multi Connection \r\n"); | |
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL); | |
//uart_init(); | |
buttons_leds_init(&erase_bonds); | |
if (erase_bonds) | |
{ | |
NRF_LOG_INFO("Bonds erased!\r\n"); | |
} | |
// app_button_init(button_cfg, BUTTON_COUNT, | |
// APP_TIMER_TICKS(50, APP_TIMER_PRESCALER)); | |
app_button_enable(); | |
peer_manager_init(erase_bonds); | |
db_discovery_init(); | |
ble_stack_init(); | |
nus_c_init(); | |
gap_params_init(); | |
conn_params_init(); | |
// services_init(); | |
advertising_init(); | |
//NRF_LOG_INFO("Scan started\r\n"); | |
adv_scan_start(); | |
for (;;) | |
{ | |
if (NRF_LOG_PROCESS() == false) | |
{ | |
// Wait for BLE events. | |
power_manage(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment