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;
}
Parents
  • If I understand correctly, you trigger ADC in main() and then on each ADC_IRQ. I'm not sure if it would be a good idea because the conversions would not take long and you would end up getting interrupted too often! I've seen in past that if I try to pump out characteristic data too fast, things get messed up on device

    You already seem to be having a sampling timer. Probably you should move triggering off the ADC in that

    Here's an example from Nordic related to sampling ADC inputs, it's not tuned to what you are trying but will give you idea on usage

Reply
  • If I understand correctly, you trigger ADC in main() and then on each ADC_IRQ. I'm not sure if it would be a good idea because the conversions would not take long and you would end up getting interrupted too often! I've seen in past that if I try to pump out characteristic data too fast, things get messed up on device

    You already seem to be having a sampling timer. Probably you should move triggering off the ADC in that

    Here's an example from Nordic related to sampling ADC inputs, it's not tuned to what you are trying but will give you idea on usage

Children
No Data
Related