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

tested UART_C and Beacon for NRF52833

HI All team Members !

Hope you all doing well ! . Yesterday , i have tested the two SDK's "ble_app_uart_c" as a BLE Beacons Scanner and "ble_app_beacon" as a BLE Beacon transmitter . I followed the following link .

https://devzone.nordicsemi.com/f/nordic-q-a/40365/how-to-use-ble_gap_phy_coded-in-ble_app_beacon-example/157628#157628

As "ble_app_beacon" example was written for NRF52840 so for porting to NRF52833 i used the following link . Which worked perfectly !

https://devzone.nordicsemi.com/f/nordic-q-a/57816/ble_app_beacon-not-available-for-pca10100/234466#234466

Now issue is that after doing the above steps ,when i have seen the data on serial Monitor @115200 baud rate .i was continoulsy getting "BLEBLEBLEBLE"  on Beacons Scanner / "ble_app_uart_c" output .

And Beacon Transmitter Window nothing displayed after "Beacon example started.."  startup message .

Can you please help me in this regard ?

Thanks in Advance ,

Best Regards

Muhammad Usman

Parents
  • Hi Muhammad,

    Can you upload your two projects so that I can have a look?

  • Hi Einar Thorsrud !

    Thank you for the reply ! Let me share you all my findings.

    I have few observations with screen shots . I also attached the original project files as well .

    SDK version is 17.0.2

    And IDE I am using is Segger Embedded studio

    I have made changes according to following link.

    https://devzone.nordicsemi.com/f/nordic-q-a/40365/how-to-use-ble_gap_phy_coded-in-ble_app_beacon-example/157628#157628

    Here is the BLE_APP_BEACON_PCA10100_S140 ,after the changes made according to the above mentioned link .

     

    Output on the Docklight is : system resets again and again

    ________________________________________________________________________________________

    Here is the ble_app_uart_c_pca10100_s122,after the changes made according to the above mentioned link .

    Output on the Docklight is : Sending BLE continuously  

    ---------------------------------------------------------------------------------------------------------------------------------------

                                             In Second Step 

    -----------------------------------------------------------------------------------------------------------------------------------------

    after making 2nd changes in “ BLE_APP_BEACON_PCA10100_S140”

    Output on the Docklight is:

    _____________________________________________________________________________________

     

    Here is the ble_app_uart_c_pca10100_s122, after 2nd Change

    Output on the Docklight is

    ____________________________________________________________________________________

    I have attached the "main.c" for the BLE_APP_BEACON_PCA10100_S140

    &

    "nrf_ble_scan.c" for the  ble_app_uart_c_pca10100_s122

    i made changes to the above mentioned files only according the the link mentioned at the top 

    
     // BLE_APP_BEACON 
    
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "nordic_common.h"
    #include "bsp.h"
    #include "nrf_soc.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "ble_advdata.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    
    #define APP_BLE_CONN_CFG_TAG            1                                  /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(100, UNIT_0_625_MS)  /**< The advertising interval for non-connectable advertisement (100 ms). This value can vary between 100ms to 10.24s). */
    
    #define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */
    #define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */
    #define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
    #define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
    #define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
    #define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
    #define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
    #define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                            0x45, 0x56, 0x67, 0x78, \
                                            0x89, 0x9a, 0xab, 0xbc, \
                                            0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */
    
    #define DEAD_BEEF                       0xDEADBEEF                         /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    #define MAJ_VAL_OFFSET_IN_BEACON_INFO   18                                 /**< Position of the MSB of the Major Value in m_beacon_info array. */
    #define UICR_ADDRESS                    0x10001080                         /**< Address of the UICR register used by this example. The major and minor versions to be encoded into the advertising data will be picked up from this location. */
    #endif
    
    static ble_gap_adv_params_t m_adv_params;                                  /**< Parameters to be passed to the stack when starting advertising. */
    static uint8_t              m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
    static uint8_t              m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];  /**< Buffer for storing an encoded advertising set. */
    
    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = NULL,
            .len    = 0
    
        }
    };
    
    
    static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
    {
        APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                             // implementation.
        APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                             // manufacturer specific data in this implementation.
        APP_BEACON_UUID,     // 128 bit UUID value.
        APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
        APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
        APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                             // this implementation.
    };
    
    
    /**@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 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_FLAG_BR_EDR_NOT_SUPPORTED;
    
        ble_advdata_manuf_data_t manuf_specific_data;
    
        manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;
    
    #if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
        // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
        // UICR instead of using the default values. The major and minor values obtained from the UICR
        // are encoded into advertising data in big endian order (MSB First).
        // To set the UICR used by this example to a desired value, write to the address 0x10001080
        // using the nrfjprog tool. The command to be used is as follows.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
        // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
        // the following command should be used.
        // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
        uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
        uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);
    
        uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;
    
        m_beacon_info[index++] = MSB_16(major_value);
        m_beacon_info[index++] = LSB_16(major_value);
    
        m_beacon_info[index++] = MSB_16(minor_value);
        m_beacon_info[index++] = LSB_16(minor_value);
    #endif
    
        manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
        manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type             = BLE_ADVDATA_NO_NAME;
        advdata.flags                 = flags;
        advdata.p_manuf_specific_data = &manuf_specific_data;
    
        // Initialize advertising parameters (used when starting advertising).
        memset(&m_adv_params, 0, sizeof(m_adv_params));
    
        m_adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;//BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
       /* m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
        m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
        m_adv_params.duration        = 0;       // Never time out. */
        m_adv_params.primary_phy     = BLE_GAP_PHY_CODED;
        m_adv_params.secondary_phy   = BLE_GAP_PHY_CODED;
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for starting advertising.
     */
    static void advertising_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
        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)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing logging. */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    /**@brief Function for initializing LEDs. */
    static void leds_init(void)
    {
        ret_code_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing timers. */
    static void timers_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        // Initialize.
        log_init();
        timers_init();
        leds_init();
        power_management_init();
        ble_stack_init();
        advertising_init();
    
        // Start execution.
        NRF_LOG_INFO("Beacon example started CODED PHY...");
        advertising_start();
    
        // Enter main loop.
        for (;; )
        {
            idle_state_handle();
        }
    }
    

    // BLE_UART_C ---> nrf_ble_scan.c
    
    
    include "sdk_common.h"
    #if NRF_MODULE_ENABLED(NRF_BLE_SCAN)
    
    #include "sdk_config.h"
    #include <stdlib.h>
    
    #include "nrf_ble_scan.h"
    
    #include <string.h>
    #include "app_error.h"
    #include "nrf_assert.h"
    #include "sdk_macros.h"
    #include "ble_advdata.h"
    
    #define NRF_LOG_MODULE_NAME ble_scan
    #include "nrf_log.h"
    NRF_LOG_MODULE_REGISTER();
    
    
    /**@brief Function for establishing the connection with a device.
     *
     * @details Connection is established if @ref NRF_BLE_SCAN_EVT_FILTER_MATCH
     *          or @ref NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT occurs and the module was
     *          initialized in the automatic connection mode. This function can generate an event
     *          to the main application when @ref sd_ble_gap_connect is used inside the function and it returns value
     *          that is different than @ref NRF_SUCCESS.
     *
     * @param[in] p_scan_ctx   Pointer to the Scanning Module instance.
     * @param[in] p_adv_report Advertising data.
     */
    static void nrf_ble_scan_connect_with_target(nrf_ble_scan_t           const * const p_scan_ctx,
                                                 ble_gap_evt_adv_report_t const * const p_adv_report)
    {
        ret_code_t err_code;
        scan_evt_t scan_evt;
    
        // For readability.
        ble_gap_addr_t const        * p_addr        = &p_adv_report->peer_addr;
        ble_gap_scan_params_t const * p_scan_params = &p_scan_ctx->scan_params;
        ble_gap_conn_params_t const * p_conn_params = &p_scan_ctx->conn_params;
        uint8_t                       con_cfg_tag   = p_scan_ctx->conn_cfg_tag;
    
        // Return if the automatic connection is disabled.
        if (!p_scan_ctx->connect_if_match)
        {
            return;
        }
    
        // Stop scanning.
        nrf_ble_scan_stop();
    
        memset(&scan_evt, 0, sizeof(scan_evt));
    
        // Establish connection.
        err_code = sd_ble_gap_connect(p_addr,
                                      p_scan_params,
                                      p_conn_params,
                                      con_cfg_tag);
    
        NRF_LOG_DEBUG("Connecting");
    
        scan_evt.scan_evt_id                    = NRF_BLE_SCAN_EVT_CONNECTING_ERROR;
        scan_evt.params.connecting_err.err_code = err_code;
    
        NRF_LOG_DEBUG("Connection status: %d", err_code);
    
        // If an error occurred, send an event to the event handler.
        if ((err_code != NRF_SUCCESS) && (p_scan_ctx->evt_handler != NULL))
        {
            p_scan_ctx->evt_handler(&scan_evt);
        }
    
    }
    
    
    /**@brief Function for decoding the BLE address type.
     *
     * @param[in] p_addr 	The BLE address.
     *
     * @return    			Address type, or an error if the address type is incorrect, that is it does not match @ref BLE_GAP_ADDR_TYPES.
     *
     */
    static uint16_t nrf_ble_scan_address_type_decode(uint8_t const * p_addr)
    {
        uint8_t addr_type = p_addr[0];
    
        // See Bluetooth Core Specification Vol 6, Part B, section 1.3.
        addr_type  = addr_type >> 6;
        addr_type &= 0x03;
    
        // Check address type.
        switch (addr_type)
        {
            case 0:
            {
                return BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE;
            }
    
            case 1:
            {
                return BLE_GAP_ADDR_TYPE_PUBLIC;
            }
    
            case 2:
            {
                return BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
            }
    
            case 3:
            {
                return BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
            }
    
            default:
            {
                return BLE_ERROR_GAP_INVALID_BLE_ADDR;
            }
        }
    }
    
    
    #if (NRF_BLE_SCAN_FILTER_ENABLE == 1)
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
    
    /**@brief Function for searching for the provided address in the advertisement packets.
     *
     * @details Use this function to parse the received advertising data for the provided address.
     *        
     *
     * @param[in]   p_adv_report   Advertising data to parse.
     * @param[in]   p_addr         Address to search for. The address length must correspond to @ref BLE_GAP_ADDR_LEN.
     *
     * @return   True if the provided address was found, false otherwise.
     */
    static bool find_peer_addr(ble_gap_evt_adv_report_t const * const p_adv_report,
                               ble_gap_addr_t const                 * p_addr)
    {
        if (p_addr->addr_type == p_adv_report->peer_addr.addr_type)
        {
            // Compare addresses.
            if (memcmp(p_addr->addr,
                       p_adv_report->peer_addr.addr,
                       sizeof(p_adv_report->peer_addr.addr)) == 0)
            {
                return true;
            }
        }
        return false;
    }
    
    
    /** @brief Function for comparing the provided address with the addresses of the advertising devices.
     *
     * @param[in] p_adv_report    Advertising data to parse.
     * @param[in] p_scan_ctx      Pointer to the Scanning Module instance.
     *
     * @retval True when the address matches with the addresses of the advertising devices. False otherwise.
     */
    static bool adv_addr_compare(ble_gap_evt_adv_report_t const * const p_adv_report,
                                 nrf_ble_scan_t const * const           p_scan_ctx)
    {
        ble_gap_addr_t const * p_addr  = p_scan_ctx->scan_filters.addr_filter.target_addr;
        uint8_t                counter = p_scan_ctx->scan_filters.addr_filter.addr_cnt;
    
        for (uint8_t index = 0; index < counter; index++)
        {
            // Search for address.
            if (find_peer_addr(p_adv_report, &p_addr[index]))
            {
                return true;
            }
        }
    
        return false;
    }
    
    
    /**@brief Function for adding target address to the scanning filter.
     *
     * @param[in]     p_addr            Target address in the format required by the SoftDevice. If you need to convert the address, use @ref nrf_ble_scan_copy_addr_to_sd_gap_addr. The address length must correspond to @ref BLE_GAP_ADDR_LEN.
     * @param[in,out] p_scan_ctx        Pointer to the Scanning Module instance.
     *
     * @retval NRF_SUCCESS                    If the filter is added successfully or if you try to add a filter that was already added before.
     * @retval NRF_ERROR_NO_MEMORY            If the number of available filters is exceeded.
     * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address type is invalid.
     */
    static ret_code_t nrf_ble_scan_addr_filter_add(nrf_ble_scan_t * const p_scan_ctx,
                                                   uint8_t        const * p_addr)
    {
        ble_gap_addr_t * p_addr_filter = p_scan_ctx->scan_filters.addr_filter.target_addr;
        uint8_t        * p_counter     = &p_scan_ctx->scan_filters.addr_filter.addr_cnt;
        uint8_t          index;
        uint16_t         addr_type;
        uint8_t          temp_addr[BLE_GAP_ADDR_LEN];
    
        // If no memory for filter.
        if (*p_counter >= NRF_BLE_SCAN_ADDRESS_CNT)
        {
            return NRF_ERROR_NO_MEM;
        }
    
        // Check for duplicated filter.
        for (index = 0; index < NRF_BLE_SCAN_ADDRESS_CNT; index++)
        {
            if (!memcmp(p_addr_filter[index].addr, p_addr, BLE_GAP_ADDR_LEN))
            {
                return NRF_SUCCESS;
            }
        }
    
        // Inverting the address.
        for (uint8_t i = 0; i < BLE_GAP_ADDR_LEN; i++)
        {
            temp_addr[i] = p_addr[(BLE_GAP_ADDR_LEN - 1) - i];
        }
    
        // Decode address type.
        addr_type = nrf_ble_scan_address_type_decode(temp_addr);
    
        if (addr_type == BLE_ERROR_GAP_INVALID_BLE_ADDR)
        {
            return BLE_ERROR_GAP_INVALID_BLE_ADDR;
        }
    
        // Add target address to filter.
        p_addr_filter[*p_counter].addr_type = (uint8_t)addr_type;
    
        for (uint8_t i = 0; i < BLE_GAP_ADDR_LEN; i++)
        {
            p_addr_filter[*p_counter].addr[i] = p_addr[i];
        }
    
        NRF_LOG_DEBUG("Filter set on address type %i, address 0x",
                      p_addr_filter[*p_counter].addr_type);
    
        for (index = 0; index < BLE_GAP_ADDR_LEN; index++)
        {
            NRF_LOG_DEBUG("%x", p_addr_filter[*p_counter].addr[index]);
        }
    
        NRF_LOG_DEBUG("\n\r");
    
        // Increase the address filter counter.
        *p_counter += 1;
    
        return NRF_SUCCESS;
    }
    
    
    #endif // NRF_BLE_SCAN_ADDRESS_CNT
    
    
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
    /** @brief Function for comparing the provided name with the advertised name.
     *
     * @param[in] p_adv_report    Advertising data to parse.
     * @param[in] p_scan_ctx      Pointer to the Scanning Module instance.
     *
     * @retval True when the names match. False otherwise.
     */
    static bool adv_name_compare(ble_gap_evt_adv_report_t const * p_adv_report,
                                 nrf_ble_scan_t     const * const p_scan_ctx)
    {
        nrf_ble_scan_name_filter_t const * p_name_filter = &p_scan_ctx->scan_filters.name_filter;
        uint8_t                            counter       =
            p_scan_ctx->scan_filters.name_filter.name_cnt;
        uint8_t  index;
        uint16_t data_len;
    
        data_len = p_adv_report->data.len;
    
        // Compare the name found with the name filter.
        for (index = 0; index < counter; index++)
        {
            if (ble_advdata_name_find(p_adv_report->data.p_data,
                                      data_len,
                                      p_name_filter->target_name[index]))
            {
                return true;
            }
        }
    
        return false;
    }
    
    
    /**@brief Function for adding name of the peripheral to the scanning filter.
     *
     * @param[in]     p_name            Peripheral name.
     * @param[in,out] p_scan_ctx        Pointer to the Scanning Module instance.
     *
     * @retval NRF_SUCCESS              If the filter is added successfully or if you try to add a filter that was already added before.
     * @retval NRF_ERROR_NULL           If a NULL pointer is passed as input.
     * @retval NRF_ERROR_DATA_SIZE      If the name filter length is too long. The maximum filter name length corresponds to @ref NRF_BLE_SCAN_NAME_MAX_LEN.
     * @retval NRF_ERROR_NO_MEMORY      If the number of available filters is exceeded.
     */
    static ret_code_t nrf_ble_scan_name_filter_add(nrf_ble_scan_t * const p_scan_ctx,
                                                   char           const * p_name)
    {
        uint8_t   index;
        uint8_t * counter  = &p_scan_ctx->scan_filters.name_filter.name_cnt;
        uint8_t   name_len = strlen(p_name);
    
        // Check the name length.
        if ((name_len == 0) || (name_len > NRF_BLE_SCAN_NAME_MAX_LEN))
        {
            return NRF_ERROR_DATA_SIZE;
        }
    
        // If no memory for filter.
        if (*counter >= NRF_BLE_SCAN_NAME_CNT)
        {
            return NRF_ERROR_NO_MEM;
        }
    
        // Check for duplicated filter.
        for (index = 0; index < NRF_BLE_SCAN_NAME_CNT; index++)
        {
            if (!strcmp(p_scan_ctx->scan_filters.name_filter.target_name[index], p_name))
            {
                return NRF_SUCCESS;
            }
        }
    
        // Add name to filter.
        memcpy(p_scan_ctx->scan_filters.name_filter.target_name[(*counter)++],
               p_name,
               strlen(p_name));
    
        NRF_LOG_DEBUG("Adding filter on %s name", p_name);
    
        return NRF_SUCCESS;
    }
    
    
    #endif // NRF_BLE_SCAN_NAME_CNT
    
    
    #if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
    /** @brief Function for comparing the provided short name with the advertised short name.
     *
     * @param[in] p_adv_report    Advertising data to parse.
     * @param[in] p_scan_ctx      Pointer to the Scanning Module instance.
     *
     * @retval True when the names match. False otherwise.
     */
    static bool adv_short_name_compare(ble_gap_evt_adv_report_t const * const p_adv_report,
                                       nrf_ble_scan_t           const * const p_scan_ctx)
    {
        nrf_ble_scan_short_name_filter_t const * p_name_filter =
            &p_scan_ctx->scan_filters.short_name_filter;
        uint8_t  counter = p_scan_ctx->scan_filters.short_name_filter.name_cnt;
        uint8_t  index;
        uint16_t data_len;
    
        data_len = p_adv_report->data.len;
    
        // Compare the name found with the name filters.
        for (index = 0; index < counter; index++)
        {
            if (ble_advdata_short_name_find(p_adv_report->data.p_data,
                                            data_len,
                                            p_name_filter->short_name[index].short_target_name,
                                            p_name_filter->short_name[index].short_name_min_len))
            {
                return true;
            }
        }
    
        return false;
    }
    
    
    /**@brief Function for adding the short name of the peripheral to the scanning filter.
     *
     * @param[in]     p_short_name      Short name of the peripheral.
     * @param[in,out] p_scan_ctx        Pointer to the Scanning Module instance.
     *
     * @retval NRF_SUCCESS              If the filter is added successfully or if you try to add a filter that was already added before.
     * @retval NRF_ERROR_NULL           If a NULL pointer is passed as input.
     * @retval NRF_ERROR_DATA_SIZE      If the name filter length is too long. The maximum filter name length corresponds to @ref NRF_BLE_SCAN_SHORT_NAME_MAX_LEN.
     * @retval NRF_ERROR_NO_MEMORY      If the number of available filters is exceeded.
     */
    static ret_code_t nrf_ble_scan_short_name_filter_add(nrf_ble_scan_t            * const p_scan_ctx,
                                                         nrf_ble_scan_short_name_t const * p_short_name)
    {
        uint8_t   index;
        uint8_t * p_counter =
            &p_scan_ctx->scan_filters.short_name_filter.name_cnt;
        nrf_ble_scan_short_name_filter_t * p_short_name_filter =
            &p_scan_ctx->scan_filters.short_name_filter;
        uint8_t name_len = strlen(p_short_name->p_short_name);
    
        // Check the name length.
        if ((name_len == 0) || (name_len > NRF_BLE_SCAN_SHORT_NAME_MAX_LEN))
        {
            return NRF_ERROR_DATA_SIZE;
        }
    
        // If no memory for filter.
        if (*p_counter >= NRF_BLE_SCAN_SHORT_NAME_CNT)
        {
            return NRF_ERROR_NO_MEM;
        }
    
        // Check for duplicated filter.
        for (index = 0; index < NRF_BLE_SCAN_SHORT_NAME_CNT; index++)
        {
            if (!strcmp(p_short_name_filter->short_name[index].short_target_name,
                        p_short_name->p_short_name))
            {
                return NRF_SUCCESS;
            }
        }
    
        // Add name to the filter.
        p_short_name_filter->short_name[(*p_counter)].short_name_min_len =
            p_short_name->short_name_min_len;
        memcpy(p_short_name_filter->short_name[(*p_counter)++].short_target_name,
               p_short_name->p_short_name,
               strlen(p_short_name->p_short_name));
    
        NRF_LOG_DEBUG("Adding filter on %s name", p_short_name->p_short_name);
    
        return NRF_SUCCESS;
    }
    
    
    #endif
    
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
    /**@brief Function for comparing the provided UUID with the UUID in the advertisement packets.
     *
     * @param[in]   p_adv_report   Advertising data to parse.
     * @param[in]   p_scan_ctx     Pointer to the Scanning Module instance.
     *
     * @return      True if the UUIDs match. False otherwise.
     */
    static bool adv_uuid_compare(ble_gap_evt_adv_report_t const * const p_adv_report,
                                 nrf_ble_scan_t           const * const p_scan_ctx)
    {
        nrf_ble_scan_uuid_filter_t const * p_uuid_filter    = &p_scan_ctx->scan_filters.uuid_filter;
        bool const                         all_filters_mode = p_scan_ctx->scan_filters.all_filters_mode;
        uint8_t const                      counter          =
            p_scan_ctx->scan_filters.uuid_filter.uuid_cnt;
        uint8_t  index;
        uint16_t data_len;
        uint8_t  uuid_match_cnt = 0;
    
        data_len = p_adv_report->data.len;
    
        for (index = 0; index < counter; index++)
        {
    
            if (ble_advdata_uuid_find(p_adv_report->data.p_data,
                                      data_len,
                                      &p_uuid_filter->uuid[index]))
            {
                uuid_match_cnt++;
    
                // In the normal filter mode, only one UUID is needed to match.
                if (!all_filters_mode)
                {
                    break;
                }
            }
            else if (all_filters_mode)
            {
                break;
            }
            else
            {
                // Do nothing.
            }
        }
    
        // In the multifilter mode, all UUIDs must be found in the advertisement packets.
        if ((all_filters_mode && (uuid_match_cnt == counter)) ||
            ((!all_filters_mode) && (uuid_match_cnt > 0)))
        {
            return true;
        }
    
        return false;
    }
    
    
    /**@brief Function for adding UUID to the scanning filter.
     *
     * @param[in]     uuid       UUID, 16-bit size.
     * @param[in,out] p_scan_ctx Pointer to the Scanning Module instance.
     *
     * @retval NRF_SUCCESS              If the scanning started. Otherwise, an error code is returned, also if you tried to add a filter that was already added before.
     * @retval NRF_ERROR_NO_MEMORY      If the number of available filters is exceeded.
     */
    static ret_code_t nrf_ble_scan_uuid_filter_add(nrf_ble_scan_t * const p_scan_ctx,
                                                   ble_uuid_t     const * p_uuid)
    {
        ble_uuid_t * p_uuid_filter = p_scan_ctx->scan_filters.uuid_filter.uuid;
        uint8_t    * p_counter     = &p_scan_ctx->scan_filters.uuid_filter.uuid_cnt;
        uint8_t      index;
    
        // If no memory.
        if (*p_counter >= NRF_BLE_SCAN_UUID_CNT)
        {
            return NRF_ERROR_NO_MEM;
        }
    
        // Check for duplicated filter.
        for (index = 0; index < NRF_BLE_SCAN_UUID_CNT; index++)
        {
            if (p_uuid_filter[index].uuid == p_uuid->uuid)
            {
                return NRF_SUCCESS;
            }
        }
    
        // Add UUID to the filter.
        p_uuid_filter[(*p_counter)++] = *p_uuid;
        NRF_LOG_DEBUG("Added filter on UUID %x", p_uuid->uuid);
    
        return NRF_SUCCESS;
    }
    
    
    #endif // NRF_BLE_SCAN_UUID_CNT
    
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT)
    /**@brief Function for comparing the provided appearance with the appearance in the advertisement packets.
     *
     * @param[in]     p_adv_report Advertising data to parse.
     * @param[in,out] p_scan_ctx   Pointer to the Scanning Module instance.
     *
     * @return      True if the appearances match. False otherwise.
     */
    static bool adv_appearance_compare(ble_gap_evt_adv_report_t const * const p_adv_report,
                                       nrf_ble_scan_t           const * const p_scan_ctx)
    {
        nrf_ble_scan_appearance_filter_t const * p_appearance_filter =
            &p_scan_ctx->scan_filters.appearance_filter;
        uint8_t const counter =
            p_scan_ctx->scan_filters.appearance_filter.appearance_cnt;
        uint8_t  index;
        uint16_t data_len;
    
        data_len = p_adv_report->data.len;
    
        // Verify if the advertised appearance matches the provided appearance.
        for (index = 0; index < counter; index++)
        {
            if (ble_advdata_appearance_find(p_adv_report->data.p_data,
                                            data_len,
                                            &p_appearance_filter->appearance[index]))
            {
                return true;
            }
        }
        return false;
    }
    
    
    /**@brief Function for adding appearance to the scanning filter.
     *
     * @param[in]     appearance       Appearance to be added.
     * @param[in,out] p_scan_ctx       Pointer to the Scanning Module instance.
     *
     * @retval NRF_SUCCESS             If the filter is added successfully or if you try to add a filter that was already added before.
     * @retval NRF_ERROR_NULL          If a NULL pointer is passed as input.
     * @retval NRF_ERROR_NO_MEMORY     If the number of available filters is exceeded.
     */
    static ret_code_t nrf_ble_scan_appearance_filter_add(nrf_ble_scan_t * const p_scan_ctx,
                                                         uint16_t               appearance)
    {
        uint16_t * p_appearance_filter = p_scan_ctx->scan_filters.appearance_filter.appearance;
        uint8_t  * p_counter           = &p_scan_ctx->scan_filters.appearance_filter.appearance_cnt;
        uint8_t    index;
    
        // If no memory.
        if (*p_counter >= NRF_BLE_SCAN_APPEARANCE_CNT)
        {
            return NRF_ERROR_NO_MEM;
        }
    
        // Check for duplicated filter.
        for ( index = 0; index < NRF_BLE_SCAN_APPEARANCE_CNT; index++)
        {
            if (p_appearance_filter[index] == appearance)
            {
                return NRF_SUCCESS;
            }
        }
    
        // Add appearance to the filter.
        p_appearance_filter[(*p_counter)++] = appearance;
        NRF_LOG_DEBUG("Added filter on appearance %x", appearance);
        return NRF_SUCCESS;
    }
    
    
    #endif // NRF_BLE_SCAN_APPEARANCE_CNT
    
    
    ret_code_t nrf_ble_scan_filter_set(nrf_ble_scan_t     * const p_scan_ctx,
                                       nrf_ble_scan_filter_type_t type,
                                       void const               * p_data)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
        VERIFY_PARAM_NOT_NULL(p_data);
    
        switch (type)
        {
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
            case SCAN_NAME_FILTER:
            {
                char * p_name = (char *)p_data;
                return nrf_ble_scan_name_filter_add(p_scan_ctx, p_name);
            }
    #endif
    
    #if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
            case SCAN_SHORT_NAME_FILTER:
            {
                nrf_ble_scan_short_name_t * p_short_name = (nrf_ble_scan_short_name_t *)p_data;
                return nrf_ble_scan_short_name_filter_add(p_scan_ctx, p_short_name);
            }
    #endif
    
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
            case SCAN_ADDR_FILTER:
            {
                uint8_t * p_addr = (uint8_t *)p_data;
                return nrf_ble_scan_addr_filter_add(p_scan_ctx, p_addr);
            }
    #endif
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
            case SCAN_UUID_FILTER:
            {
                ble_uuid_t * p_uuid = (ble_uuid_t *)p_data;
                return nrf_ble_scan_uuid_filter_add(p_scan_ctx, p_uuid);
            }
    #endif
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
            case SCAN_APPEARANCE_FILTER:
            {
                uint16_t appearance = *((uint16_t *)p_data);
                return nrf_ble_scan_appearance_filter_add(p_scan_ctx, appearance);
            }
    #endif
    
            default:
                return NRF_ERROR_INVALID_PARAM;
        }
    }
    
    
    ret_code_t nrf_ble_scan_all_filter_remove(nrf_ble_scan_t * const p_scan_ctx)
    {
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
        nrf_ble_scan_name_filter_t * p_name_filter = &p_scan_ctx->scan_filters.name_filter;
        memset(p_name_filter->target_name, 0, sizeof(p_name_filter->target_name));
        p_name_filter->name_cnt = 0;
    #endif
    
    #if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
        nrf_ble_scan_short_name_filter_t * p_short_name_filter =
            &p_scan_ctx->scan_filters.short_name_filter;
        memset(p_short_name_filter->short_name, 0, sizeof(p_short_name_filter->short_name));
        p_short_name_filter->name_cnt = 0;
    #endif
    
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
        nrf_ble_scan_addr_filter_t * p_addr_filter = &p_scan_ctx->scan_filters.addr_filter;
        memset(p_addr_filter->target_addr, 0, sizeof(p_addr_filter->target_addr));
        p_addr_filter->addr_cnt = 0;
    #endif
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
        nrf_ble_scan_uuid_filter_t * p_uuid_filter = &p_scan_ctx->scan_filters.uuid_filter;
        memset(p_uuid_filter->uuid, 0, sizeof(p_uuid_filter->uuid));
        p_uuid_filter->uuid_cnt = 0;
    #endif
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
        nrf_ble_scan_appearance_filter_t * p_appearance_filter =
            &p_scan_ctx->scan_filters.appearance_filter;
        memset(p_appearance_filter->appearance, 0, sizeof(p_appearance_filter->appearance));
        p_appearance_filter->appearance_cnt = 0;
    #endif
    
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_scan_filters_enable(nrf_ble_scan_t * const p_scan_ctx,
                                           uint8_t                mode,
                                           bool                   match_all)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
    
        // Check if the mode is correct.
        if ((!(mode & NRF_BLE_SCAN_ADDR_FILTER)) &&
            (!(mode & NRF_BLE_SCAN_NAME_FILTER)) &&
            (!(mode & NRF_BLE_SCAN_UUID_FILTER)) &&
            (!(mode & NRF_BLE_SCAN_SHORT_NAME_FILTER)) &&
            (!(mode & NRF_BLE_SCAN_APPEARANCE_FILTER)))
        {
            return NRF_ERROR_INVALID_PARAM;
        }
    
        ret_code_t err_code;
    
        // Disable filters.
        err_code = nrf_ble_scan_filters_disable(p_scan_ctx);
        ASSERT(err_code == NRF_SUCCESS);
    
        nrf_ble_scan_filters_t * p_filters = &p_scan_ctx->scan_filters;
    
        // Turn on the filters of your choice.
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
        if (mode & NRF_BLE_SCAN_ADDR_FILTER)
        {
            p_filters->addr_filter.addr_filter_enabled = true;
        }
    #endif
    
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
        if (mode & NRF_BLE_SCAN_NAME_FILTER)
        {
            p_filters->name_filter.name_filter_enabled = true;
        }
    #endif
    
    #if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
        if (mode & NRF_BLE_SCAN_SHORT_NAME_FILTER)
        {
            p_filters->short_name_filter.short_name_filter_enabled = true;
        }
    #endif
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
        if (mode & NRF_BLE_SCAN_UUID_FILTER)
        {
            p_filters->uuid_filter.uuid_filter_enabled = true;
        }
    #endif
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
        if (mode & NRF_BLE_SCAN_APPEARANCE_FILTER)
        {
            p_filters->appearance_filter.appearance_filter_enabled = true;
        }
    #endif
    
        // Select the filter mode.
        p_filters->all_filters_mode = match_all;
    
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_scan_filters_disable(nrf_ble_scan_t * const p_scan_ctx)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
    
        // Disable all filters.
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
        bool * p_name_filter_enabled = &p_scan_ctx->scan_filters.name_filter.name_filter_enabled;
        *p_name_filter_enabled = false;
    #endif
    
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
        bool * p_addr_filter_enabled = &p_scan_ctx->scan_filters.addr_filter.addr_filter_enabled;
        *p_addr_filter_enabled = false;
    #endif
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
        bool * p_uuid_filter_enabled = &p_scan_ctx->scan_filters.uuid_filter.uuid_filter_enabled;
        *p_uuid_filter_enabled = false;
    #endif
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
        bool * p_appearance_filter_enabled =
            &p_scan_ctx->scan_filters.appearance_filter.appearance_filter_enabled;
        *p_appearance_filter_enabled = false;
    #endif
    
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_scan_filter_get(nrf_ble_scan_t * const   p_scan_ctx,
                                       nrf_ble_scan_filters_t * p_status)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
        VERIFY_PARAM_NOT_NULL(p_status);
    
        *p_status = p_scan_ctx->scan_filters;
    
        return NRF_SUCCESS;
    }
    
    
    #endif // NRF_BLE_SCAN_FILTER_ENABLE
    
    /**@brief Function for calling the BLE_GAP_EVT_ADV_REPORT event to check whether the received
     *        scanning data matches the scan configuration.
     *
     * @param[in] p_scan_ctx    Pointer to the Scanning Module instance.
     * @param[in] p_adv_report  Advertising report.
     */
    static void nrf_ble_scan_on_adv_report(nrf_ble_scan_t           const * const p_scan_ctx,
                                           ble_gap_evt_adv_report_t const * const p_adv_report)
    {
        scan_evt_t scan_evt;
    
    #if (NRF_BLE_SCAN_FILTER_ENABLE == 1)
        uint8_t filter_cnt       = 0;
        uint8_t filter_match_cnt = 0;
    #endif
    
        memset(&scan_evt, 0, sizeof(scan_evt));
    
        scan_evt.p_scan_params = &p_scan_ctx->scan_params;
    
        // If the whitelist is used, do not check the filters and return.
        if (is_whitelist_used(p_scan_ctx))
        {
            scan_evt.scan_evt_id        = NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT;
            scan_evt.params.p_not_found = p_adv_report;
            p_scan_ctx->evt_handler(&scan_evt);
    
            UNUSED_RETURN_VALUE(sd_ble_gap_scan_start(NULL, &p_scan_ctx->scan_buffer));
            nrf_ble_scan_connect_with_target(p_scan_ctx, p_adv_report);
    
            return;
        }
    
    #if (NRF_BLE_SCAN_FILTER_ENABLE == 1)
        bool const all_filter_mode   = p_scan_ctx->scan_filters.all_filters_mode;
        bool       is_filter_matched = false;
    
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
        bool const addr_filter_enabled = p_scan_ctx->scan_filters.addr_filter.addr_filter_enabled;
    #endif
    
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
        bool const name_filter_enabled = p_scan_ctx->scan_filters.name_filter.name_filter_enabled;
    #endif
    
    #if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
        bool const short_name_filter_enabled =
            p_scan_ctx->scan_filters.short_name_filter.short_name_filter_enabled;
    #endif
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
        bool const uuid_filter_enabled = p_scan_ctx->scan_filters.uuid_filter.uuid_filter_enabled;
    #endif
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
        bool const appearance_filter_enabled =
            p_scan_ctx->scan_filters.appearance_filter.appearance_filter_enabled;
    #endif
    
    
    #if (NRF_BLE_SCAN_ADDRESS_CNT > 0)
        // Check the address filter.
        if (addr_filter_enabled)
        {
            // Number of active filters.
            filter_cnt++;
            if (adv_addr_compare(p_adv_report, p_scan_ctx))
            {
                // Number of filters matched.
                filter_match_cnt++;
                // Information about the filters matched.
                scan_evt.params.filter_match.filter_match.address_filter_match = true;
                is_filter_matched = true;
            }
        }
    #endif
    
    #if (NRF_BLE_SCAN_NAME_CNT > 0)
        // Check the name filter.
        if (name_filter_enabled)
        {
            filter_cnt++;
            if (adv_name_compare(p_adv_report, p_scan_ctx))
            {
                filter_match_cnt++;
    
                // Information about the filters matched.
                scan_evt.params.filter_match.filter_match.name_filter_match = true;
                is_filter_matched = true;
            }
        }
    #endif
    
    #if (NRF_BLE_SCAN_SHORT_NAME_CNT > 0)
        if (short_name_filter_enabled)
        {
            filter_cnt++;
            if (adv_short_name_compare(p_adv_report, p_scan_ctx))
            {
                filter_match_cnt++;
    
                // Information about the filters matched.
                scan_evt.params.filter_match.filter_match.short_name_filter_match = true;
                is_filter_matched = true;
            }
        }
    #endif
    
    #if (NRF_BLE_SCAN_UUID_CNT > 0)
        // Check the UUID filter.
        if (uuid_filter_enabled)
        {
            filter_cnt++;
            if (adv_uuid_compare(p_adv_report, p_scan_ctx))
            {
                filter_match_cnt++;
                // Information about the filters matched.
                scan_evt.params.filter_match.filter_match.uuid_filter_match = true;
                is_filter_matched = true;
            }
        }
    #endif
    
    #if (NRF_BLE_SCAN_APPEARANCE_CNT > 0)
        // Check the appearance filter.
        if (appearance_filter_enabled)
        {
            filter_cnt++;
            if (adv_appearance_compare(p_adv_report, p_scan_ctx))
            {
                filter_match_cnt++;
                // Information about the filters matched.
                scan_evt.params.filter_match.filter_match.appearance_filter_match = true;
                is_filter_matched = true;
            }
        }
    
        scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_NOT_FOUND;
    #endif
    
        scan_evt.params.filter_match.p_adv_report = p_adv_report;
    
        // In the multifilter mode, the number of the active filters must equal the number of the filters matched to generate the notification.
        if (all_filter_mode && (filter_match_cnt == filter_cnt))
        {
            scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_FILTER_MATCH;
            nrf_ble_scan_connect_with_target(p_scan_ctx, p_adv_report);
        }
        // In the normal filter mode, only one filter match is needed to generate the notification to the main application.
        else if ((!all_filter_mode) && is_filter_matched)
        {
            scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_FILTER_MATCH;
            nrf_ble_scan_connect_with_target(p_scan_ctx, p_adv_report);
        }
        else
        {
            scan_evt.scan_evt_id        = NRF_BLE_SCAN_EVT_NOT_FOUND;
            scan_evt.params.p_not_found = p_adv_report;
    
        }
    
        // If the event handler is not NULL, notify the main application.
        if (p_scan_ctx->evt_handler != NULL)
        {
            p_scan_ctx->evt_handler(&scan_evt);
        }
    
    #endif // NRF_BLE_SCAN_FILTER_ENABLE
    
        // Resume the scanning.
        UNUSED_RETURN_VALUE(sd_ble_gap_scan_start(NULL, &p_scan_ctx->scan_buffer));
    }
    
    
    /**@brief Function for checking whether the whitelist is used.
     *
     * @param[in] p_scan_ctx   Scanning Module instance.
     */
    bool is_whitelist_used(nrf_ble_scan_t const * const p_scan_ctx)
    {
        if (p_scan_ctx->scan_params.filter_policy == BLE_GAP_SCAN_FP_WHITELIST ||
            p_scan_ctx->scan_params.filter_policy == BLE_GAP_SCAN_FP_WHITELIST_NOT_RESOLVED_DIRECTED)
        {
            return true;
        }
    
        return false;
    }
    
    
    /**@brief Function for restoring the default scanning parameters.
     *
     * @param[out] p_scan_ctx    Pointer to the Scanning Module instance.
     */
    static void nrf_ble_scan_default_param_set(nrf_ble_scan_t * const p_scan_ctx)
    {
        // Set the default parameters.
        p_scan_ctx->scan_params.active        = 1;
    #if (NRF_SD_BLE_API_VERSION > 7)
        p_scan_ctx->scan_params.interval_us   = NRF_BLE_SCAN_SCAN_INTERVAL * UNIT_0_625_MS;
        p_scan_ctx->scan_params.window_us     = NRF_BLE_SCAN_SCAN_WINDOW * UNIT_0_625_MS;
    #else
        p_scan_ctx->scan_params.interval      = NRF_BLE_SCAN_SCAN_INTERVAL;
        p_scan_ctx->scan_params.window        = NRF_BLE_SCAN_SCAN_WINDOW;
    #endif // #if (NRF_SD_BLE_API_VERSION > 7)
        p_scan_ctx->scan_params.timeout       = NRF_BLE_SCAN_SCAN_DURATION;
        p_scan_ctx->scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;   //BLE_GAP_SCAN_FP_WHITELIST;
        p_scan_ctx->scan_params.scan_phys     = BLE_GAP_PHY_CODED;   //BLE_GAP_PHY_1MBPS;
    }
    
    
    /**@brief Function for setting the default connection parameters.
     *
     * @param[out] p_scan_ctx    Pointer to the Scanning Module instance.
     */
    static void nrf_ble_scan_default_conn_param_set(nrf_ble_scan_t * const p_scan_ctx)
    {
        p_scan_ctx->conn_params.conn_sup_timeout =
            (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS);
        p_scan_ctx->conn_params.min_conn_interval =
            (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS);
        p_scan_ctx->conn_params.max_conn_interval =
            (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS);
        p_scan_ctx->conn_params.slave_latency =
            (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY;
    }
    
    
    /**@brief Function for calling the BLE_GAP_EVT_TIMEOUT event.
     *
     * @param[in] p_scan_ctx  Pointer to the Scanning Module instance.
     * @param[in] p_gap       GAP event structure.
     */
    static void nrf_ble_scan_on_timeout(nrf_ble_scan_t const * const p_scan_ctx,
                                        ble_gap_evt_t  const * const p_gap)
    {
        ble_gap_evt_timeout_t const * p_timeout = &p_gap->params.timeout;
        scan_evt_t                    scan_evt;
    
        memset(&scan_evt, 0, sizeof(scan_evt));
    
        if (p_timeout->src == BLE_GAP_TIMEOUT_SRC_SCAN)
        {
            NRF_LOG_DEBUG("BLE_GAP_SCAN_TIMEOUT");
            if (p_scan_ctx->evt_handler != NULL)
            {
                scan_evt.scan_evt_id        = NRF_BLE_SCAN_EVT_SCAN_TIMEOUT;
                scan_evt.p_scan_params      = &p_scan_ctx->scan_params;
                scan_evt.params.timeout.src = p_timeout->src;
    
                p_scan_ctx->evt_handler(&scan_evt);
            }
        }
    }
    
    
    /**@brief Function for stopping the scanning.
     */
    void nrf_ble_scan_stop(void)
    {
        // It is ok to ignore the function return value here, because this function can return NRF_SUCCESS or
        // NRF_ERROR_INVALID_STATE, when app is not in the scanning state.
        UNUSED_RETURN_VALUE(sd_ble_gap_scan_stop());
    }
    
    
    ret_code_t nrf_ble_scan_init(nrf_ble_scan_t            * const p_scan_ctx,
                                 nrf_ble_scan_init_t const * const p_init,
                                 nrf_ble_scan_evt_handler_t        evt_handler)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
    
        p_scan_ctx->evt_handler = evt_handler;
    
    #if (NRF_BLE_SCAN_FILTER_ENABLE == 1)
        // Disable all scanning filters.
        memset(&p_scan_ctx->scan_filters, 0, sizeof(p_scan_ctx->scan_filters));
    #endif
    
        // If the pointer to the initialization structure exist, use it to scan the configuration.
        if (p_init != NULL)
        {
            p_scan_ctx->connect_if_match = p_init->connect_if_match;
            p_scan_ctx->conn_cfg_tag     = p_init->conn_cfg_tag;
    
            if (p_init->p_scan_param != NULL)
            {
                p_scan_ctx->scan_params = *p_init->p_scan_param;
            }
            else
            {
                // Use the default static configuration.
                nrf_ble_scan_default_param_set(p_scan_ctx);
            }
    
            if (p_init->p_conn_param != NULL)
            {
                p_scan_ctx->conn_params = *p_init->p_conn_param;
            }
            else
            {
                // Use the default static configuration.
                nrf_ble_scan_default_conn_param_set(p_scan_ctx);
            }
        }
        // If pointer is NULL, use the static default configuration.
        else
        {
            nrf_ble_scan_default_param_set(p_scan_ctx);
            nrf_ble_scan_default_conn_param_set(p_scan_ctx);
    
            p_scan_ctx->connect_if_match = false;
        }
    
        // Assign a buffer where the advertising reports are to be stored by the SoftDevice.
        p_scan_ctx->scan_buffer.p_data = p_scan_ctx->scan_buffer_data;
        p_scan_ctx->scan_buffer.len    = NRF_BLE_SCAN_BUFFER;
    
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_scan_start(nrf_ble_scan_t const * const p_scan_ctx)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
    
        ret_code_t err_code;
        scan_evt_t scan_evt;
    
        memset(&scan_evt, 0, sizeof(scan_evt));
    
        nrf_ble_scan_stop();
    
        // If the whitelist is used and the event handler is not NULL, send the whitelist request to the main application.
        if (is_whitelist_used(p_scan_ctx))
        {
            if (p_scan_ctx->evt_handler != NULL)
            {
                scan_evt.scan_evt_id = NRF_BLE_SCAN_EVT_WHITELIST_REQUEST;
                p_scan_ctx->evt_handler(&scan_evt);
            }
        }
    
        // Start the scanning.
        err_code = sd_ble_gap_scan_start(&p_scan_ctx->scan_params, &p_scan_ctx->scan_buffer);
    
        // It is okay to ignore this error, because the scan stopped earlier.
        if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_SUCCESS))
        {
            NRF_LOG_ERROR("sd_ble_gap_scan_start returned 0x%x", err_code);
            return (err_code);
        }
        NRF_LOG_DEBUG("Scanning");
    
        return NRF_SUCCESS;
    }
    
    
    ret_code_t nrf_ble_scan_params_set(nrf_ble_scan_t              * const p_scan_ctx,
                                       ble_gap_scan_params_t const * const p_scan_param)
    {
        VERIFY_PARAM_NOT_NULL(p_scan_ctx);
    
        nrf_ble_scan_stop();
    
        if (p_scan_param != NULL)
        {
            // Assign new scanning parameters.
            p_scan_ctx->scan_params = *p_scan_param;
        }
        else
        {
            // If NULL, use the default static configuration.
            nrf_ble_scan_default_param_set(p_scan_ctx);
        }
    
        NRF_LOG_DEBUG("Scanning parameters have been changed successfully");
    
        return NRF_SUCCESS;
    }
    
    
    /**@brief Function for calling the BLE_GAP_EVT_CONNECTED event.
     *
     * @param[in] p_scan_ctx  Pointer to the Scanning Module instance.
     * @param[in] p_gap_evt   GAP event structure.
     */
    static void nrf_ble_scan_on_connected_evt(nrf_ble_scan_t const * const p_scan_ctx,
                                              ble_gap_evt_t  const * const p_gap_evt)
    {
        scan_evt_t scan_evt;
    
        memset(&scan_evt, 0, sizeof(scan_evt));
        scan_evt.scan_evt_id                  = NRF_BLE_SCAN_EVT_CONNECTED;
        scan_evt.params.connected.p_connected = &p_gap_evt->params.connected;
        scan_evt.params.connected.conn_handle = p_gap_evt->conn_handle;
        scan_evt.p_scan_params                = &p_scan_ctx->scan_params;
    
        if (p_scan_ctx->evt_handler != NULL)
        {
            p_scan_ctx->evt_handler(&scan_evt);
        }
    }
    
    
    ret_code_t nrf_ble_scan_copy_addr_to_sd_gap_addr(ble_gap_addr_t * p_gap_addr,
                                                     const uint8_t    addr[BLE_GAP_ADDR_LEN])
    {
        uint16_t addr_type;
    
        addr_type = nrf_ble_scan_address_type_decode(addr);
    
        if (addr_type == BLE_ERROR_GAP_INVALID_BLE_ADDR)
        {
            return BLE_ERROR_GAP_INVALID_BLE_ADDR;
        }
    
        p_gap_addr->addr_type = addr_type;
    
        for (uint8_t i = 0; i < BLE_GAP_ADDR_LEN; ++i)
        {
            p_gap_addr->addr[i] = addr[BLE_GAP_ADDR_LEN - (i + 1)];
        }
    
        return NRF_SUCCESS;
    }
    
    
    void nrf_ble_scan_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_contex)
    {
        nrf_ble_scan_t                 * p_scan_data  = (nrf_ble_scan_t *)p_contex;
        ble_gap_evt_adv_report_t const * p_adv_report = &p_ble_evt->evt.gap_evt.params.adv_report;
        ble_gap_evt_t const            * p_gap_evt    = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_ADV_REPORT:
                nrf_ble_scan_on_adv_report(p_scan_data, p_adv_report);
                break;
    
            case BLE_GAP_EVT_TIMEOUT:
                nrf_ble_scan_on_timeout(p_scan_data, p_gap_evt);
                break;
    
            case BLE_GAP_EVT_CONNECTED:
                nrf_ble_scan_on_connected_evt(p_scan_data, p_gap_evt);
                break;
    
            default:
                break;
        }
    }
    
    
    #endif // NRF_BLE_SCAN_ENABLED

    Thank you so much in advance for your response !

    Your help and expert opinion will be very helpful for me .

    Thanks & Regards,

    Muhammad Usman

  • Hi Einar Thorsrud !

    Thank ! i will send in few hours . RIght now i don't have hardware access .Can you please tell me where is the option for debug build target ?

    Thanks & regards

  • Hi Einar Thorsrud !

     Thank You !

     i run the debugger . My findings are the following .

     When Program counter goes to  NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED");

      PC(r15) = 0x00028d88

      pc= 0x0015074

     i  attached the image of above results as well .

    After that program stuck at the following 

    NRF_BREAKPOINT_COND;

      PC(r15) = 0x00028e5c

      pc= 0x0015074

     i  attached the image of above results as well .

    Thanks again for your prompt response !

    Best Regards

    Muhammad Usman

  • Hi Einar Thorsurd !

    Thank for your help ! i believe problem is solved !

    followed the following link 

    https://devzone.nordicsemi.com/f/nordic-q-a/51708/softdevice-assertion-failed

    and replaced the soft device files S140 SDK 17.2.0 to the components folder as directed by the above link.

    After that i got the beacon messages as shown in the image .

    Again Thank you so much for the nice support!

    Thanks & Best Regards

    Muhammad Usman 

Reply Children
No Data
Related