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 Thorsud !

    Thank You ! for your help . I have tested your project files . I have attached the project folder converted from the nrf52840(pca10056) to nrf52833(pca10100) as followed by the link mentioned in the post startup.

    Transmitter side i started the "BLE_Beacon_coded_phy"  SDK and Receiver side started the scanner_coded_phy in debug mode . I got the following errors as mentioned in the screen shot .

    Project Code is:

    scanner_coded_phy (2).zip

    Thanks and Regards,

  • Hi Muhammad,

    I do not have a nRF52833 DK to test with right now, so I was not able to reproduce the issue. The project works well on the nRF52840 DK. It would be interesting to see the error message though, but it is too small in the screenshot. Can you try uploading again using Insert -> Image/Video/File so that it gets full resolution? Alternatively/even better, copy paste the error text instead of a screenshot. With that I might be able to understand a bit more of what is going on.

  • Hi Einar Thorsud !

    Thank you so much for the response ! Yes , let me share again the image and also type .

    Thank you Again,

    Message is :

    <info> app: code phy beacon scanner started ....

    <error> app: SoftDevice :ASSERTION FAILED .

  • Hi,

    I see. Can you test running the debug build target? That way you should see where the SoftDevice asserted (program counter value). Then I can check in the SoftDevice to see what could cause that specific assert.

  • 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

Reply Children
No Data
Related