This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ADC Values passed through BLE Characteristic

Hey All,

I am currently trying to have a Analog Signal come in through P0.05 which then gets converted via the onboard ADC and send out a Service Characteristic. I am using a modified version of the ble-app-lbs but I am stuck with how to get the ADC_IRQHandler to fire(which in another application it was but here I am having trouble) along with pass that through my service into the characteristic.

The board is a nRF51 DK Board

Also not sure why my Notifications for the service is not working.

I apologize for the long code, not sure if you needed to see the other two or not.

Any advice/information would help so much.

Thank you -Nate

Here is the code that I am using

Main.c

> #include <stdint.h>
> #include <string.h>
> #include "nordic_common.h"

> #include "nrf.h"
> #include "nrf_adc.h"
> #include "app_error.h"
> #include "nrf_gpio.h"
> #include "nrf51_bitfields.h"
> #include "app_util_platform.h"
> #include "ble.h"
> #include "ble_hci.h"
> #include "ble_srv_common.h"
> #include "ble_advdata.h"
> #include "ble_dis.h"
> #include "ble_bas.h"
> #include "ble_conn_params.h"
> #include "app_scheduler.h"
> #include "softdevice_handler.h"
> #include "app_timer.h"
> #include "device_manager.h"
> #include "pstorage.h"
> #include "app_gpiote.h"
> #include "bsp.h"
> #include "ble_adcconvert.h"
> #include "ble_advertising.h"
> #include "boards.h"
> #include "bsp.h"
> #include "app_trace.h"
> 
> #define IS_SRVC_CHANGED_CHARACT_PRESENT 1     
> #define WAKEUP_BUTTON_ID                0                                     
> /**< Button used to wake up the
> application. */
> 
> 
> #define DEVICE_NAME                     "EPSensor"                          
> #define APP_ADV_INTERVAL                6000                                  
> #define APP_ADV_TIMEOUT_IN_SECONDS      0                                     
> 
> #define APP_TIMER_PRESCALER             0                                     
> #define APP_TIMER_MAX_TIMERS						6
> #define APP_TIMER_OP_QUEUE_SIZE         4                                     
> 
> #define SAMPLE_RATE_MEAS_INTERVAL				APP_TIMER_TICKS(4,APP_TIMER_PRESCALER)
> 
> #define ADC_REF_VOLTAGE_IN_MILLIVOLTS     1200                                  
> #define ADC_PRE_SCALING_COMPENSATION      3                                     
> #define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
>         ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / 255)
> * ADC_PRE_SCALING_COMPENSATION)
> 
> #define BODY_VOLTAGE_INCREMENT          12000		                               
> 
> #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(30, UNIT_1_25_MS)       
> 	/**< Minimum acceptable connection
> interval (8 msec). */
> #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(30, UNIT_1_25_MS)       
> #define SLAVE_LATENCY                   0                                     
> #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)       
> #define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000,
> APP_TIMER_PRESCALER)  
> #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. */
> 
> 
> 
> #define APP_GPIOTE_MAX_USERS            3                                     
> /**< Maximum number of users of the
> GPIOTE handler. */
> 
> 
> #define DEAD_BEEF                       0xDEADBEEF                            
> /**< Value used as error code on stack
> dump, can be used to identify stack
> location on stack unwind. */
> 
> 
> static ble_adc_t 												m_adc;
> static ble_gap_sec_params_t           
> m_sec_params;                         
> /**< Security requirements for this
> application. */ static uint16_t       
> m_conn_handle =
> BLE_CONN_HANDLE_INVALID;    /**<
> Handle of the current connection. */
> 
> 
> static dm_application_instance_t      
> m_app_handle;                         
> /**< Application identifier allocated
> by device manager */
> 
> static
> app_timer_id_t										m_sampling_timer_id;											 /**< Biopotential sample acquisition
> timer. */
> 
> static
> app_gpiote_user_id_t							m_sampling_gpiote_id; static bool                           
> m_memory_access_in_progress = false;  
> /**< Flag to keep track of ongoing
> operations on persistent memory. */
> 
> static uint8_t adc_sample;
> 
> 
> // YOUR_JOB: Modify these according to
> requirements (e.g. if other event
> types are to pass through //          
> the scheduler).
> #define SCHED_MAX_EVENT_DATA_SIZE       sizeof(app_timer_event_t)             
> /**< Maximum size of scheduler events.
> Note that scheduler BLE stack events
> do not contain any data, as the events
> are being pulled from the stack in the
> event handler. */
> #define SCHED_QUEUE_SIZE                10                                    
> /**< Maximum number of events in the
> scheduler queue. */
> 
> 
> 
> /**@brief Callback function for
> 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]   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(DEAD_BEEF, line_num, p_file_name); }
> 
> /**@brief Function for handling the
> ADC interrupt.  *  * @details  This
> function will fetch the conversion
> result from the ADC, convert the value
> into  *           percentage and send
> it to peer.  */ void
> ADC_IRQHandler(void) {
>       nrf_adc_conversion_event_clean();
> 
>     adc_sample = nrf_adc_result_get();
> 
> 		//ble_adc_convert_add(&m_adc,
> (int16_t)adc_sample);
>     // trigger next ADC conversion
>     nrf_adc_start(); }
> 
> /**@brief Function for configuring ADC
> to do battery level conversion.  */
> static void adc_configure(void) {
>     uint32_t err_code;
>     nrf_adc_config_t adc_config = NRF_ADC_CONFIG_DEFAULT;
> 
>     // Configure ADC
>     adc_config.reference  = NRF_ADC_CONFIG_REF_VBG;
>     adc_config.resolution = NRF_ADC_CONFIG_RES_8BIT;
>     adc_config.scaling    = NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD;
>     nrf_adc_configure(&adc_config);
> 
> 		nrf_adc_input_select(NRF_ADC_CONFIG_INPUT_6);
> 	
>     // Enable ADC interrupt
>     nrf_adc_int_enable(ADC_INTENSET_END_Enabled
> << ADC_INTENSET_END_Pos);
>     err_code = sd_nvic_ClearPendingIRQ(ADC_IRQn);
>     APP_ERROR_CHECK(err_code);
> 
>     err_code = sd_nvic_SetPriority(ADC_IRQn,
> NRF_APP_PRIORITY_HIGH);
>     APP_ERROR_CHECK(err_code);
> 
>     err_code = sd_nvic_EnableIRQ(ADC_IRQn);
>     APP_ERROR_CHECK(err_code); 		 }
> 
> 
> /**@brief Function for handling the
> sample acquisition timer timeout.  * 
> * @details This function will be called each time the sampling timer
> expires.  *  * @param[in]   p_context 
> Pointer used for passing some
> arbitrary information (context) from
> the  *                         
> app_start_timer() call to the timeout
> handler.  */ static void
> sampling_timer_timeout_handler(void *
> p_context) {
>     UNUSED_PARAMETER(p_context); }
> 
> /**@brief Function for the Timer
> initialization.  *  * @details
> Initializes the timer module.  */
> static void timers_init(void) {
> 		uint32_t err_code;
> 	
>     // Initialize timer module, making it use the scheduler
>     APP_TIMER_INIT(APP_TIMER_PRESCALER,
> APP_TIMER_MAX_TIMERS,
> APP_TIMER_OP_QUEUE_SIZE, true);
> 
>     /* YOUR_JOB: Create any timers to be used by the application.
>                  Below is an example of how to create a timer.
>                  For every new timer needed, increase the value of the
> macro APP_TIMER_MAX_TIMERS by
>                  one. 		*/
> 		 		err_code = app_timer_create(&m_sampling_timer_id,
>                                 APP_TIMER_MODE_REPEATED,
>                                 sampling_timer_timeout_handler);
>     APP_ERROR_CHECK(err_code); }
> 
> /**@brief Function for starting
> advertising.  */ static void
> advertising_start(void) {
>     uint32_t             err_code; 		uint32_t						 count;
>     ble_gap_adv_params_t adv_params;
> 
> 	  // Verify if there is any flash
> access pending, if yes delay starting
> advertising until
>     // it's complete.
>     err_code = pstorage_access_status_get(&count);
>     APP_ERROR_CHECK(err_code);
> 
>     if (count != 0)
>     {
>         m_memory_access_in_progress = true;
>         return;
>     }
> 	
>     // Start advertising
>     memset(&adv_params, 0, sizeof(adv_params));
> 
>     adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
>     adv_params.p_peer_addr = NULL;
>     adv_params.fp          = BLE_GAP_ADV_FP_ANY;
>     adv_params.interval    = APP_ADV_INTERVAL;
>     adv_params.timeout     = APP_ADV_TIMEOUT_IN_SECONDS;
> 
>     err_code = sd_ble_gap_adv_start(&adv_params);
>     APP_ERROR_CHECK(err_code);
>     err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
>     APP_ERROR_CHECK(err_code); }
> 
> /**@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));
> 		printf(DEVICE_NAME);
>     APP_ERROR_CHECK(err_code);
> 
> 
>     memset(&gap_conn_params, 0, sizeof(gap_conn_params));
> 
>     gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
>     gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
>     gap_conn_params.slave_latency     = SLAVE_LATENCY;
>     gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
> 
>     err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
>     APP_ERROR_CHECK(err_code); }
> 
> /**@brief Function for putting the
> chip into sleep mode.  *  * @note This
> function will not return.  */
> 
> static void on_adv_evt(ble_adv_evt_t
> ble_adv_evt) {
>     uint32_t err_code;
> 
>     switch (ble_adv_evt)
>     {
>         case BLE_ADV_EVT_FAST:
>             err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
>             APP_ERROR_CHECK(err_code);
>             break;
>         case BLE_ADV_EVT_IDLE:
>             
>             break;
>         default:
>             break;
>     } }
> 
> /**@brief Function for initializing
> the Advertising functionality.  *  *
> @details Encodes the required
> advertising data and passes it to the
> stack.  *          Also builds a
> structure to be passed to the stack
> when starting advertising.  */ static
> void advertising_init(void) {
>     uint32_t      err_code;
>     ble_advdata_t advdata;
>     uint8_t       flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
> 
>     // YOUR_JOB: Use UUIDs for service(s) used in your application.
> 	
>     ble_uuid_t adv_uuids[] =
>     {
>         {BLE_UUID_ADC_CONVERT_SERVICE, BLE_UUID_TYPE_BLE}
>     };
> 
>     // Build and set advertising data
>     memset(&advdata, 0, sizeof(advdata));
> 
>     advdata.name_type               = BLE_ADVDATA_FULL_NAME;
>     advdata.include_appearance      = true;
>     advdata.flags                   = flags;
>     advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) /
> sizeof(adv_uuids[0]);
>     advdata.uuids_complete.p_uuids  = adv_uuids;
> 		 		ble_adv_modes_config_t options = {0}; 		options.ble_adv_fast_enabled =
> BLE_ADV_FAST_ENABLED;
> 		options.ble_adv_fast_interval =
> APP_ADV_INTERVAL;
> 		options.ble_adv_fast_timeout =
> APP_ADV_TIMEOUT_IN_SECONDS;
> 		
>     err_code = ble_advertising_init(&advdata,
> &options, on_adv_evt, NULL);
>     APP_ERROR_CHECK(err_code); }
> 
>    static void advertising_stop(void)
> {
>     uint32_t err_code;
> 
>     err_code = sd_ble_gap_adv_stop();
>     APP_ERROR_CHECK(err_code);
> 
>     err_code = bsp_indication_set(BSP_INDICATE_IDLE);
>     APP_ERROR_CHECK(err_code); }
> 
> 
> /**@brief Function for handling the
> Connection Parameters Module.  *  *
> @details This function will be called
> for all events in the Connection
> Parameters Module which  *         
> are passed to the application.  *     
> @note All this function does is to
> disconnect. This could have been done
> by simply  *                setting
> the disconnect_on_fail config
> parameter, but instead we use the
> event  *                handler
> mechanism to demonstrate its use.  * 
> * @param[in]   p_evt   Event received from the Connection Parameters Module.
> */ static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) {
>     uint32_t err_code;
> 
>     if(p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
>     {
>         err_code = sd_ble_gap_disconnect(m_conn_handle,
> BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
>         APP_ERROR_CHECK(err_code);
>     } }
> 
> 
> /**@brief Function for handling a
> Connection Parameters error.  *  *
> @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 Function for handling the
> Biopotential Measurement Service
> events.  *  * @details This function
> will be called for all Biopotential
> Measurement Service events which  |   
> are passed to the application.  *  *
> @param[in]   p_bms  Biopotential
> Measurement Service structure.  *
> @param[in]   p_evt  Event received
> from the Biopotential Measurement
> Service.  */ static void
> on_adc_evt(ble_adc_t * p_adc,
> ble_adc_evt_t *p_evt) {
>     uint32_t err_code;
> 
>     switch (p_evt->evt_type)
>     {
>         case BLE_ADC_EVT_NOTIFICATION_ENABLED:
>             // Start transmit timer
>             err_code = app_timer_start(m_sampling_timer_id,
> SAMPLE_RATE_MEAS_INTERVAL, NULL);
>             APP_ERROR_CHECK(err_code);
>             break;
> 
>         case BLE_ADC_EVT_NOTIFICATION_DISABLED:
> 						// Stop transmit timer
>             err_code = app_timer_stop(m_sampling_timer_id);
>             APP_ERROR_CHECK(err_code);
>             break;
> 				
> 				case BLE_ADC_EVT_SAMPLE_RATE_CHANGE:
> 								err_code = app_timer_stop(m_sampling_timer_id);
> 								APP_ERROR_CHECK(err_code);
> 								err_code = app_timer_start(m_sampling_timer_id,
> APP_TIMER_TICKS(4,
> APP_TIMER_PRESCALER), NULL);
> 								APP_ERROR_CHECK(err_code);
> 
>     } }
> 
> /**@brief Function for handling the
> Application's BLE Stack events.  *  *
> @param[in]   p_ble_evt   Bluetooth
> stack event.  */ static void
> on_ble_evt(ble_evt_t * p_ble_evt) {
>     uint32_t                         err_code;
>     static ble_gap_evt_auth_status_t m_auth_status;
>     bool                             master_id_matches;
> 		
>     switch (p_ble_evt->header.evt_id)
>     {
>         case BLE_GAP_EVT_CONNECTED:
>             err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
>             APP_ERROR_CHECK(err_code);
>             m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
> 				
> 						// Start sample acquisition timer	
> 						err_code = app_timer_start(m_sampling_timer_id,
> SAMPLE_RATE_MEAS_INTERVAL, NULL);
> 						APP_ERROR_CHECK(err_code);
>             break;
> 
>         case BLE_GAP_EVT_DISCONNECTED:
>             err_code = bsp_indication_set(BSP_INDICATE_IDLE);
>             APP_ERROR_CHECK(err_code);
>             m_conn_handle = BLE_CONN_HANDLE_INVALID;
> 				
> 						// Stop sample acquisition timer
> 						err_code = app_timer_stop(m_sampling_timer_id);
> 						APP_ERROR_CHECK(err_code);
> 
>             advertising_start();
>             break;
> 
> 
>         case BLE_GATTS_EVT_SYS_ATTR_MISSING:
>             err_code = sd_ble_gatts_sys_attr_set(m_conn_handle,
>                                                  NULL,
>                                                  0,
>                                                  BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS |
> BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
>             APP_ERROR_CHECK(err_code);
>             break;
>         default:
>             // No implementation needed.
>             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) {
> 		dm_ble_evt_handler(p_ble_evt);
> 		on_ble_evt(p_ble_evt);
> 		ble_conn_params_on_ble_evt(p_ble_evt);
> 	  ble_adc_on_ble_evt(&m_adc,
> p_ble_evt); }
> 
> /**@brief Function for handling the
> Application's system events.  *  *
> @param[in]   sys_evt   system event. 
> */ static void on_sys_evt(uint32_t sys_evt) {
>     switch(sys_evt)
>     {
>         case NRF_EVT_FLASH_OPERATION_SUCCESS:
>         case NRF_EVT_FLASH_OPERATION_ERROR:
> 
>             if (m_memory_access_in_progress)
>             {
>                 m_memory_access_in_progress = false;
>                 advertising_start();
>             }
>             break;
> 
>         default:
>             // No implementation needed.
>             break;
>     } }
> 
> /**@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) {
>     pstorage_sys_event_handler(sys_evt);
>     on_sys_evt(sys_evt); }
> 
> 
> 
> /**@brief Function for initializing
> services that will be used by the
> application.  */ static void
> services_init(void) { 		uint32_t      
> err_code; 		ble_adc_init_t adc_init;
> 		uint8_t				 sample_rate;
> 		 		//adc_sample = nrf_adc_result_get();
> 	 		memset(&adc_init, 0, sizeof(adc_init));
> 	 		adc_init.p_sample_rate = &adc_sample; 	  adc_init.evt_handler =
> on_adc_evt;
> 		adc_init.support_notification =
> true;
> 		
> 		BLE_GAP_CONN_SEC_MODE_SET_OPEN(&adc_init.adc_sample_rate_attr_md.read_perm);
> 	
> 	
>     err_code = ble_adc_init(&m_adc,&adc_init);
> 	
>     APP_ERROR_CHECK(err_code);
>      }
> 
> /**@brief Function for starting
> timers.
> */ static void timers_start(void) {
>     uint32_t err_code;
> 	 		err_code = app_timer_start(m_sampling_timer_id,
> SAMPLE_RATE_MEAS_INTERVAL, NULL);
>     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   
> = m_adc.sample_rate_handles.cccd_handle;
>     cp_init.disconnect_on_fail             = false;
>     cp_init.evt_handler                    = on_conn_params_evt;
>     cp_init.error_handler                  = conn_params_error_handler;
> 
>     err_code = ble_conn_params_init(&cp_init);
>     APP_ERROR_CHECK(err_code); }
> 
> /**@brief Function for initializing
> the BLE stack.  *  * @details
> Initializes the SoftDevice and the BLE
> event interrupt.  */ static void
> ble_stack_init(void) {
>     uint32_t err_code;
> 
>     // Initialize the SoftDevice handler module.
>     SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_4000MS_CALIBRATION,
> false);
> 
>     // Enable BLE stack 
>     ble_enable_params_t ble_enable_params;
>     memset(&ble_enable_params, 0, sizeof(ble_enable_params));
> 	
>     ble_enable_params.gatts_enable_params.service_changed
> = IS_SRVC_CHANGED_CHARACT_PRESENT;
>     err_code = sd_ble_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 BLE events.
>     err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
>     APP_ERROR_CHECK(err_code); }
> 
> 
> /**@brief Function for the Event
> Scheduler initialization.  */ static
> void scheduler_init(void) {
>     APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); }
> 
> 
> /**@brief Function for initializing
> the GPIOTE handler module.  */ static
> void gpiote_init(void) {	 		uint32_t
> err_code;
> 	
> 		APP_GPIOTE_INIT(APP_GPIOTE_MAX_USERS);	
> }
> 
> /**@brief Function for handling the
> Device Manager events.  *  *
> @param[in] p_evt  Data associated to
> the device manager event.  */ static
> uint32_t
> device_manager_evt_handler(dm_handle_t
> const * p_handle,
>                                            dm_event_t const  * p_event,
>                                            ret_code_t        event_result) {
>     APP_ERROR_CHECK(event_result);
> 
> 
>     return NRF_SUCCESS; }
> 
> 
> /**@brief Function for the Device
> Manager initialization.  */ static
> void device_manager_init(void) {
>     uint32_t               err_code;
>     dm_init_param_t        init_data;
>     dm_application_param_t register_param;
> 
>     // Initialize persistent storage module.
>     err_code = pstorage_init();
>     APP_ERROR_CHECK(err_code);
> 
>     // Clear all bonded centrals if the Bonds Delete button is pushed.
>     //err_code = bsp_button_is_pressed(BOND_DELETE_ALL_BUTTON_ID,&(init_data.clear_persistent_data));
>     //APP_ERROR_CHECK(err_code);
> 
>     err_code = dm_init(&init_data);
>     APP_ERROR_CHECK(err_code);
> 
>     memset(&register_param.sec_param, 0, sizeof(ble_gap_sec_params_t));
> 
> 
>     register_param.evt_handler            = device_manager_evt_handler;
>     register_param.service_type           = DM_PROTOCOL_CNTXT_GATT_SRVR_ID;
> 
>     err_code = dm_register(&m_app_handle,
> &register_param);
>     APP_ERROR_CHECK(err_code); }
> 
> /**@brief Function for the Power
> manager.  */ static void
> power_manage(void) {
>     uint32_t err_code = sd_app_evt_wait();
>     APP_ERROR_CHECK(err_code); }
> 
> 
> /**@brief Function for application
> main entry.  */ int main(void) {	
> 		//uint8_t regs[ADS1291_2_NUM_REGS];
> 		uint32_t err_code;
> 	
>     // Initialize 		ble_stack_init();
>     timers_init();
>     gpiote_init(); 		device_manager_init();
>     scheduler_init();
>     gap_params_init();
>     advertising_init();
>     services_init(); 		adc_configure();
>     conn_params_init(); 	  nrf_adc_start();
> 	
>     // Start execution
>     timers_start();
>     advertising_start();
> 
>     // Enter main loop
>     for (;;)
>     {			
>         app_sched_execute();
>         power_manage();
>     } }
> 
> /**  * @}  */
> 

ble_adcconvert.h

    #ifndef OUR_ADC_SERVICE_H__
> #define OUR_ADC_SERVICE_H__
    > 
    > #include <stdint.h>
    > #include <stdbool.h>
    > #include "ble.h"
    > #include "ble_srv_common.h"
    > 
    > // Base UUID
    > #define BMS_UUID_BASE {0x23, 0xD1, 0x13, 0xEF, 0x5F, 0x78, 0x23, 0x15,
    > 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00,
    > 0x00, 0x00};
    > 
    > // Service UUID
    > #define BLE_UUID_ADC_CONVERT_SERVICE	0x1140
    > 
    > // Characteristic UUIDs
    > #define BLE_UUID_SENSOR_DATA					0x2828
    > 
    > #define BLE_BMS_MAX_BUFFERED_MEASUREMENTS					30
    > 
    > typedef enum {
    >     BLE_ADC_EVT_NOTIFICATION_ENABLED,                   /**< Voltage value notification
    > enabled event. */
    >     BLE_ADC_EVT_NOTIFICATION_DISABLED,                   /**< Voltage value notification
    > disabled event. */
    > 		BLE_ADC_EVT_SAMPLE_RATE_CHANGE }
    > ble_adc_evt_type_t;
    > 
    > /**@brief Biopotential Measurement
    > Service event. */ typedef struct {
    >     ble_adc_evt_type_t evt_type;                        /**< Type of event. */ }
    > ble_adc_evt_t;
    > 
    > typedef struct ble_adc_s ble_adc_t;
    > 
    > 
    > /**@brief Biopotential Measurement
    > Service event handler type. */ typedef
    > void (*ble_adc_evt_handler_t)
    > (ble_adc_t * p_hrs, ble_adc_evt_t *
    > p_evt);
    > 
    > typedef struct {
    >     ble_adc_evt_handler_t        evt_handler;                          
    > /**< Event handler to be called for
    > handling events in the Biopotential
    > Measurement Service. */ 		uint8_t
    > *										 p_sample_rate;																				
    > /**< If not NULL, initial value of the
    > Sample Rate characteristic. */
    > 		ble_srv_security_mode_t			
    > adc_sample_rate_attr_md;
    > 														/**< Initial security level for Sample Rate attribute */ 	 
    > bool                        
    > support_notification; }
    > ble_adc_init_t;
    > 
    > 
    > typedef struct ble_adc_s {  
    >     ble_adc_evt_handler_t        evt_handler;                          
    > /**< Event handler to be called for
    > handling events in the Biopotential
    > Measurement Service. */	
    >     uint16_t                     service_handle;                       
    > /**< Handle of Biopotential
    > Measurement Service (as provided by
    > the BLE stack). */
    > 		ble_gatts_char_handles_t		
    > sample_rate_handles;	 		uint16_t      
    > conn_handle; 		uint8_t											
    > bvm_count;		/**< Handles related to
    > the Sample Rate characteristic. */    
    > /**< Handles related to the Body
    > Sensor Location characteristic. */
    > 		uint8_t                     
    > uuid_type;              		uint8_t
    > 										 sample_rate;
    > 	 		uint16_t										 adc_buffer[BLE_BMS_MAX_BUFFERED_MEASUREMENTS];
    > } ble_adc_t;
    > 
    > /**@brief Initialize the Biopotential
    > Measurement Service.  *  * @param[out]
    > p_adc         * @param[in]  
    > p_adc_init    *  * @return     
    > NRF_SUCCESS on successful
    > initialization of service, otherwise
    > an error code.  */ uint32_t
    > ble_adc_init(ble_adc_t * p_adc, const
    > ble_adc_init_t * p_adc_init);
    > 
    > /**@brief Biopotential Measurement
    > Service BLE stack event handler.  *  *
    > @details Handles all events from the
    > BLE stack of interest to the
    > Biopotential Measurement Service.  * 
    > * @param[in]   p_adc      ADC Sensor Measurement Service structure.  *
    > @param[in]   p_ble_evt  Event received
    > from the BLE stack.  */ void
    > ble_adc_on_ble_evt(ble_adc_t * p_adc,
    > ble_evt_t * p_ble_evt);
    > 
    > /**@brief Function for sending sensor
    > voltage measurement if notification
    > has been enabled.  *  * @details The
    > application calls this function after
    > having performed a voltage
    > measurement.  *          If
    > notification has been enabled, the
    > voltage measurement data is encoded
    > and sent to  *          the client.  *
    > * @param[in]   p_adc                    ADC Sensor Service structure.  *  *
    > @return      NRF_SUCCESS on success,
    > otherwise an error code.  */ uint32_t
    > ble_adc_sensor_measurement_send(ble_adc_t * p_adc);
    > 
    > /**@brief Function for adding a Body
    > Voltage Measurement to the buffer.  * 
    > * @details All buffered voltage measurements will be included in the
    > next biopotential  *         
    > measurement message, up to the maximum
    > number of measurements that will fit
    > into the  *          message. If the
    > buffer is full, the oldest measurement
    > in the buffer will be deleted.  *  *
    > @param[in]   p_bms        Biopotential
    > Measurement Service structure.  *
    > @param[in]   bvm_val 	   New voltage
    > measurement (will be buffered until
    > the next  *                          
    > connection interval).  *  * @return   
    > NRF_SUCCESS on success, otherwise an
    > error code.  */ uint32_t
    > ble_adc_convert_add(ble_adc_t * p_adc,
    > int16_t adc_val);
    > 
    > /**@brief Function for checking if
    > Body Voltage Measurement buffer is
    > full.  *  * @param[in]   p_bms       
    > Biopotential Measurement Service
    > structure.  *  * @return      true if
    > Body Voltage Measurement buffer is
    > full, false otherwise.  */  uint32_t
    > ble_adc_sample_rate_set(ble_adc_t *
    > p_adc, uint8_t sample_rate); bool
    > ble_adc_convert_buffer_is_full(ble_adc_t
    > * p_adc);
    > 
    > 
    > 
    > #endif

ble_adcconvert.c

#include "ble_advdata.h"
#include "ble_advertising.h"
#include "pstorage.h"
#include "nrf_soc.h"
#include "app_trace.h"
#include "nordic_common.h"


#define LOG app_trace_log

static bool m_advertising_start_pending = false; /**< Flag to keep track of ongoing operations on persistent memory. */

static ble_gap_addr_t                  m_peer_address;           /**< Address of the most recently connected peer, used for direct advertising. */
static ble_advdata_t                   m_advdata;                /**< Used by the initialization function to set name, appearance, and UUIDs and advertising flags visible to peer devices. */
static ble_adv_evt_t                   m_adv_evt;                /**< Advertising event propogated to the main application. The event is either a transaction to a new advertising mode, or a request for whitelist or peer address.. */
static ble_advertising_evt_handler_t   m_evt_handler;            /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */
static ble_advertising_error_handler_t m_error_handler;          /**< Handler for the advertising error events. */

static ble_adv_mode_t                m_adv_mode_current;         /**< Variable to keep track of the current advertising mode. */
static uint8_t                       m_direct_adv_cnt;           /**< Counter of direct advertising retries. */
static bool                          m_whitelist_temporarily_disabled = false; /**< Flag to keep track of temporary disabling of the whitelist. */
                                   
static ble_gap_whitelist_t           m_whitelist;                                         /**< Struct that points to whitelisted addresses. */
static ble_gap_addr_t              * mp_whitelist_addr[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; /**< Pointer to a list of addresses. Pointed to by the whitelist */
static ble_gap_irk_t               * mp_whitelist_irk[BLE_GAP_WHITELIST_IRK_MAX_COUNT];   /**< Pointer to a list of Identity Resolving Keys (IRK). Pointed to by the whitelist */
static bool                          m_whitelist_reply_expected = false;                  /**< Flag to verify that whitelist is only set when it is requested. */
static bool                          m_peer_addr_reply_expected = false;                  /**< Flag to verify that. */

static ble_adv_modes_config_t m_adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/

static ble_advdata_manuf_data_t      m_manuf_specific_data;                               /**< Manufacturer specific data structure*/
static uint8_t                       m_manuf_data_array[BLE_GAP_ADV_MAX_SIZE];            /**< Array to store the Manufacturer specific data*/
static ble_advdata_service_data_t    m_service_data;                                      /**< Service data structure. */
static uint8_t                       m_service_data_array[BLE_GAP_ADV_MAX_SIZE];          /**< Array to store the service data. */
static ble_advdata_conn_int_t        m_slave_conn_int;                                    /**< Connection interval range structure.*/
static int8_t                        m_tx_power_level;                                    /**< TX power level*/


/**@brief Function for checking that the whitelist has entries.
 */
static bool whitelist_has_entries(ble_gap_whitelist_t const * whitelist)
{
    if ((whitelist->addr_count != 0) || (whitelist->irk_count != 0))
    {
        return true;
    }
    return false;
}


/**@brief Function for setting the stored peer address back to zero.
 */
static void ble_advertising_peer_address_clear()
{
    memset(&m_peer_address, 0, sizeof(m_peer_address));
}


/**@brief Function for checking if an address is non-zero. Used to determine if 
 */
static bool peer_address_exists(uint8_t const * address)
{
    uint32_t i;

    for (i = 0; i < BLE_GAP_ADDR_LEN; i++)
    {
        if (address[i] != 0)
        {
            return true;
        }
    }
    return false;
}


uint32_t ble_advertising_init(ble_advdata_t const                 * p_advdata,
                              ble_adv_modes_config_t const        * p_config,
                              ble_advertising_evt_handler_t const   evt_handler,
                              ble_advertising_error_handler_t const error_handler)
{
    uint32_t err_code;

    if((p_advdata == NULL) || p_config == NULL)
    {
        return NRF_ERROR_NULL;
    }
    m_adv_mode_current = BLE_ADV_MODE_IDLE;
    m_evt_handler      = evt_handler;
    m_error_handler    = error_handler;
    m_adv_modes_config = *p_config;

    // If interval or timeout is 0, disable the mode.
    if (m_adv_modes_config.ble_adv_fast_interval == 0 || m_adv_modes_config.ble_adv_fast_timeout == 0)
    {
        m_adv_modes_config.ble_adv_fast_enabled = false;
    }
    if (m_adv_modes_config.ble_adv_slow_interval == 0 || m_adv_modes_config.ble_adv_slow_timeout == 0)
    {
        m_adv_modes_config.ble_adv_slow_enabled = false;
    }

    ble_advertising_peer_address_clear();

    // Prepare Whitelist. Address and IRK double pointers point to allocated arrays.
    m_whitelist.pp_addrs = mp_whitelist_addr;
    m_whitelist.pp_irks  = mp_whitelist_irk;

    // Copy and set advertising data.
    memset(&m_advdata, 0, sizeof(m_advdata));

    // Copy advertising data.
    m_advdata.name_type            = p_advdata->name_type;
    m_advdata.include_appearance   = p_advdata->include_appearance;
    m_advdata.flags                = p_advdata->flags;
    m_advdata.short_name_len       = p_advdata->short_name_len;
   /* 
    if(p_advdata->uuids_complete != NULL)
    {
        m_advdata.uuids_complete = p_advdata->uuids_complete;
    }
    */
    m_advdata.uuids_complete = p_advdata->uuids_complete;
    m_advdata.uuids_more_available = p_advdata->uuids_more_available;
    m_advdata.uuids_solicited      = p_advdata->uuids_solicited;
    
    if(p_advdata->p_manuf_specific_data != NULL)
    {
        m_advdata.p_manuf_specific_data   = &m_manuf_specific_data;
        m_manuf_specific_data.data.p_data = m_manuf_data_array;
        m_advdata.p_manuf_specific_data->company_identifier =
        p_advdata->p_manuf_specific_data->company_identifier;
        m_advdata.p_manuf_specific_data->data.size = p_advdata->p_manuf_specific_data->data.size;
        
        for(uint32_t i = 0; i < m_advdata.p_manuf_specific_data->data.size; i++)
        {
            m_manuf_data_array[i] = p_advdata->p_manuf_specific_data->data.p_data[i];
        }
    }
    
    if(p_advdata->p_service_data_array != NULL)
    {
        m_service_data.data.p_data                   = m_service_data_array;
        m_advdata.p_service_data_array               = &m_service_data;
        m_advdata.p_service_data_array->data.p_data  = m_service_data_array;
        m_advdata.p_service_data_array->data.size    = p_advdata->p_service_data_array->data.size;
        m_advdata.p_service_data_array->service_uuid = p_advdata->p_service_data_array->service_uuid;

        for(uint32_t i = 0; i < m_advdata.p_service_data_array->data.size; i++)
        {
            m_service_data_array[i] = p_advdata->p_service_data_array->data.p_data[i];
        }

        m_advdata.service_data_count = p_advdata->service_data_count;
    }


    if(p_advdata->p_slave_conn_int != NULL)
    {
        m_advdata.p_slave_conn_int                    = &m_slave_conn_int;
        m_advdata.p_slave_conn_int->max_conn_interval = p_advdata->p_slave_conn_int->max_conn_interval;
        m_advdata.p_slave_conn_int->min_conn_interval = p_advdata->p_slave_conn_int->min_conn_interval;
    }
    
    if(p_advdata->p_tx_power_level != NULL)
    {
        m_advdata.p_tx_power_level     = &m_tx_power_level;
        m_advdata.p_tx_power_level     = p_advdata->p_tx_power_level;
    }
    err_code = ble_advdata_set(&m_advdata, NULL);
    return err_code;
}


uint32_t ble_advertising_start(ble_adv_mode_t advertising_mode)
{
    uint32_t             err_code;
    ble_gap_adv_params_t adv_params;
    uint32_t             count;

    m_adv_mode_current = advertising_mode;

    // Verify if there is any flash access pending. If there is, delay starting advertising until
    // it is complete.
    err_code = pstorage_access_status_get(&count);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    if (count != 0)
    {
        m_advertising_start_pending = true;
        return NRF_SUCCESS;
    }

    // Fetch the peer address.
    ble_advertising_peer_address_clear();
    if (   (m_adv_modes_config.ble_adv_directed_enabled)
           && m_adv_mode_current == BLE_ADV_MODE_DIRECTED)
    {
        if (m_evt_handler != NULL)
        {
            m_peer_addr_reply_expected = true;
            m_evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST);
        }
        else
        {
            m_peer_addr_reply_expected = false;
        }
    }

    // If a mode is disabled, continue to the next mode. I.e fast instead of direct, slow instead of fast, idle instead of slow.
    if (  (m_adv_mode_current == BLE_ADV_MODE_DIRECTED)
        &&(!m_adv_modes_config.ble_adv_directed_enabled || !peer_address_exists(m_peer_address.addr)))
    {
        m_adv_mode_current = BLE_ADV_MODE_FAST;
    }
    if (!m_adv_modes_config.ble_adv_fast_enabled && m_adv_mode_current == BLE_ADV_MODE_FAST)
    {
        m_adv_mode_current = BLE_ADV_MODE_SLOW;
    }
    if (!m_adv_modes_config.ble_adv_slow_enabled && m_adv_mode_current == BLE_ADV_MODE_SLOW)
    {
        m_adv_mode_current = BLE_ADV_MODE_IDLE;
        m_adv_evt          = BLE_ADV_EVT_IDLE;
    }

    // Fetch the whitelist.
    if (   (m_evt_handler != NULL)
        && (m_adv_mode_current == BLE_ADV_MODE_FAST || m_adv_mode_current == BLE_ADV_MODE_SLOW)
        && (m_adv_modes_config.ble_adv_whitelist_enabled)
        && (!m_whitelist_temporarily_disabled))
    {
        m_whitelist_reply_expected = true;
        m_evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST);
    }
    else
    {
        m_whitelist_reply_expected = false;
    }

    // Initialize advertising parameters with default values.
    memset(&adv_params, 0, sizeof(adv_params));

    adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
    adv_params.p_peer_addr = NULL;
    adv_params.fp          = BLE_GAP_ADV_FP_ANY;
    adv_params.p_whitelist = NULL;

    // Set advertising parameters and events according to selected advertising mode.
    switch (m_adv_mode_current)
    {
        case BLE_ADV_MODE_DIRECTED:
            LOG("[ADV]: Starting direct advertisement.\r\n");
            adv_params.p_peer_addr = &m_peer_address; // Directed advertising.
            adv_params.type        = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
            adv_params.timeout     = 0;               // High dutycycle.
            adv_params.interval    = 0;               // High dutycycle.
            m_adv_evt              = BLE_ADV_EVT_DIRECTED;
            break;

        case BLE_ADV_MODE_FAST:
            adv_params.timeout  = m_adv_modes_config.ble_adv_fast_timeout;
            adv_params.interval = m_adv_modes_config.ble_adv_fast_interval;

            if (   whitelist_has_entries(&m_whitelist)
                && m_adv_modes_config.ble_adv_whitelist_enabled
                && !m_whitelist_temporarily_disabled)
            {
                adv_params.fp          = BLE_GAP_ADV_FP_FILTER_CONNREQ;
                adv_params.p_whitelist = &m_whitelist;
                m_advdata.flags        = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
                err_code               = ble_advdata_set(&m_advdata, NULL);
                if(err_code != NRF_SUCCESS)
                {
                    return err_code;
                }

                m_adv_evt = BLE_ADV_EVT_FAST_WHITELIST;
                LOG("[ADV]: Starting fast advertisement with whitelist.\r\n");
            }
            else
            {
                m_adv_evt = BLE_ADV_EVT_FAST;
                LOG("[ADV]: Starting fast advertisement.\r\n");
            }
            break;

        case BLE_ADV_MODE_SLOW:
            adv_params.interval = m_adv_modes_config.ble_adv_slow_interval;
            adv_params.timeout  = m_adv_modes_config.ble_adv_slow_timeout;

            if (   whitelist_has_entries(&m_whitelist)
                && m_adv_modes_config.ble_adv_whitelist_enabled
                && !m_whitelist_temporarily_disabled)
            {
                adv_params.fp          = BLE_GAP_ADV_FP_FILTER_CONNREQ;
                adv_params.p_whitelist = &m_whitelist;
                m_advdata.flags        = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
                err_code               = ble_advdata_set(&m_advdata, NULL);
                if(err_code != NRF_SUCCESS)
                {
                    return err_code;
                }

                m_adv_evt = BLE_ADV_EVT_SLOW_WHITELIST;
                LOG("[ADV]: Starting slow advertisement with whitelist.\r\n");
            }
            else
            {
                m_adv_evt = BLE_ADV_EVT_SLOW;
                LOG("[ADV]: Starting slow advertisement.\r\n");
            }
            break;

        default:
            break;
    }
    if (m_adv_mode_current != BLE_ADV_MODE_IDLE)
    {
        err_code = sd_ble_gap_adv_start(&adv_params);
        if(err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }
    if (m_evt_handler != NULL)
    {
        m_evt_handler(m_adv_evt);
    }

    return NRF_SUCCESS;
}


void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt)
{
    static uint16_t current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
#ifdef S130
            if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH)
            {
                current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            }
#else
            current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
#endif
            break;

        // Upon disconnection, whitelist will be activated and direct advertising is started.
        case BLE_GAP_EVT_DISCONNECTED:
        {
            uint32_t err_code;
            m_whitelist_temporarily_disabled = false;


            m_direct_adv_cnt = m_adv_modes_config.ble_adv_directed_timeout;

            if (p_ble_evt->evt.gap_evt.conn_handle == current_slave_link_conn_handle)
            {
               err_code = ble_advertising_start(BLE_ADV_MODE_DIRECTED);
               if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
               {
                   m_error_handler(err_code);
               }
            }
            break;
        }
        // Upon time-out, the next advertising mode is started, i.e. go from fast to slow or from slow to idle.
        case BLE_GAP_EVT_TIMEOUT:
            if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
            {
                switch (m_adv_mode_current)
                {
                    case BLE_ADV_MODE_DIRECTED:
                        LOG("[ADV]: Timed out from directed advertising.\r\n");
                        if ((m_direct_adv_cnt > 0) && peer_address_exists(m_peer_address.addr))
                        {
                            uint32_t err_code;

                            m_direct_adv_cnt--;
                            LOG("[ADV]: Remaining direct advertising attempts: %d\r\n",
                                m_direct_adv_cnt);
                            err_code = ble_advertising_start(BLE_ADV_MODE_DIRECTED);
                            if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
                            {
                                m_error_handler(err_code);
                            }
                        }
                        else
                        {
                            uint32_t err_code;
                            err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
                            if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
                            {
                                m_error_handler(err_code);
                            }
                        }
                        break;

                    case BLE_ADV_MODE_FAST:
                    {
                        uint32_t err_code;
                        m_adv_evt = BLE_ADV_EVT_FAST;
                        LOG("[ADV]: Timed out from fast advertising, starting slow advertising.\r\n");
                        err_code = ble_advertising_start(BLE_ADV_MODE_SLOW);
                        if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
                        {
                            m_error_handler(err_code);
                        }
                        break;
                    }
                    case BLE_ADV_MODE_SLOW:
                        m_adv_evt = BLE_ADV_EVT_IDLE;
                        LOG("[ADV]: Timed out from slow advertising, stopping advertising.\r\n");
                        if (m_evt_handler != NULL)
                        {
                            m_evt_handler(m_adv_evt);
                        }
                        break;

                    default:
                        // No implementation needed.
                        break;
                }
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}


void ble_advertising_on_sys_evt(uint32_t sys_evt)
{
    uint32_t err_code = NRF_SUCCESS;
    switch (sys_evt)
    {
        case NRF_EVT_FLASH_OPERATION_SUCCESS:
        // Fall through.

        //When a flash operation finishes, advertising no longer needs to be pending.
        case NRF_EVT_FLASH_OPERATION_ERROR:
            if (m_advertising_start_pending)
            {
                m_advertising_start_pending = false;
                err_code = ble_advertising_start(m_adv_mode_current);
                if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
                {
                    m_error_handler(err_code);
                }
            }
            break;

        default:
            // No implementation needed.
            break;
    }
}

uint32_t ble_advertising_peer_addr_reply(ble_gap_addr_t * p_peer_address)
{
    if(m_peer_addr_reply_expected == false)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    m_peer_address.addr_type = p_peer_address->addr_type;

    for (int i = 0; i < BLE_GAP_ADDR_LEN; i++)
    {
        m_peer_address.addr[i] = p_peer_address->addr[i];
    }

    m_peer_addr_reply_expected = false;
    return NRF_SUCCESS;
}


uint32_t ble_advertising_whitelist_reply(ble_gap_whitelist_t * p_whitelist)
{
    uint32_t i;

    if(m_whitelist_reply_expected == false)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    m_whitelist.addr_count = p_whitelist->addr_count;
    m_whitelist.irk_count  = p_whitelist->irk_count;

    for (i = 0; i < m_whitelist.irk_count; i++)
    {
        mp_whitelist_irk[i] = p_whitelist->pp_irks[i];
    }

    for (i = 0; i < m_whitelist.addr_count; i++)
    {
        mp_whitelist_addr[i] = p_whitelist->pp_addrs[i];
    }

    m_whitelist_reply_expected = false;
    return NRF_SUCCESS;
}


uint32_t ble_advertising_restart_without_whitelist(void)
{
    uint32_t err_code;

    if(     m_adv_modes_config.ble_adv_whitelist_enabled == BLE_ADV_WHITELIST_ENABLED
        && !m_whitelist_temporarily_disabled)
    {
        if (m_adv_mode_current != BLE_ADV_MODE_IDLE)
        {
            err_code = sd_ble_gap_adv_stop();
            if(err_code != NRF_SUCCESS)
            {
                return err_code;
            }
        }
        m_whitelist_temporarily_disabled = true;

        err_code = ble_advertising_start(m_adv_mode_current);
        if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
        {
            m_error_handler(err_code);
        }
    }
    return NRF_SUCCESS;
}
Related