Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Device match

uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };

i want to triger a interrupt via PPI when received package from pipe 2 ( 0xC3 0xC2, 0xC2, 0xC2, 0xC2). so how can I config DAB , DAP and DACNF registers ?

my PPI init like below, if it is correct ?

nrf_drv_gpiote_init();

nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
nrf_drv_gpiote_out_init(LED_4, &config);
uint32_t gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(LED_4);


NRF_RADIO->DAB[?] = ?
NRF_RADIO->DAP[?] = ?
NRF_RADIO->DACNF |= ?


NRF_PPI->CH[NRF_ESB_PPI_POS_SYNC].EEP = (uint32_t)&NRF_RADIO->EVENTS_DEVMATCH;
NRF_PPI->CH[NRF_ESB_PPI_POS_SYNC].TEP = (uint32_t)gpiote_task_addr;
NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_POS_SYNC) ;

nrf_drv_gpiote_out_task_enable(LED_4);

Parents
  • Hi,


    You will need to add your own 48 bit device address to the payload to use this for ESB. From the infocenter we have the following:

    The Device Address match unit assumes that the 48 first bits of the payload is the device address and that bit number 6 in S0 is the TxAdd bit.

    From the BLE Spec, we have the following:


    The TxAdd in the advertising channel PDU header indicates whether the advertiser’s address in the AdvA field is public (TxAdd = 0) or random (TxAdd = 1).

    So you can do whatever you want with this field for non-BLE communication, i.e. you can choose if you want to use 0 or 1, just make sure that DACNF register is configured accordingly, based on what you set the bit number 6 in S0 to.

    You can find an example on how to configure these registers in the zephyr github, here is a link.

  • You will need to add your own 48 bit device address to the payload to use this for ESB. From the infocenter we have the following:

    do you mean "48 bit device address' is "base address and prefix address" ? and it is corresponding to the picture of "ADDRESS" ?

Reply Children
  • Hi,

    I'm not understand what's the mean of " and that
    bit number 6 in S0 is the TxAdd bit
     ", could you please give an example ?

  • do you mean "48 bit device address' is "base address and prefix address" ? and it is corresponding to the picture of "ADDRESS" ?

    No. The 48-bit device address is something used by BLE, and it is put into the start of the payload when a device is advertising. In BLE, all peripherals are advertising with the same ADDRESS (0x8e89bed6). This means that a BLE central is able to find all the peripherals that are advertising. But, if the central is looking for a particular device, with a known device address, the BLE central can use the Device Address match unit to filter the signal from these devices. This is usefully if the central and the peripheral have bonded in a previous connection, and the central is only looking for peripherals it have bonded with before. The Device Address match unit is tailored for the whitelisting feature in BLE.

    After the central and the peripheral have connected, the 48-bit device address is no longer directly used, and the Device Address match unit is turned off. The central/master and the peripheral/slave, will then switch to using a different ADDRESS.

    With ESB, you can select and use the ADDRESS you want yourself. Because of that, I don’t think you need to use the Device Address match unit for filtering.

    If the goal is to trigger a interrupt via PPI when you receive a packet, then you can use the NRF_RADIO->EVENTS_ADDRESS.

  • In case you still need to use the Device Address match unit, we will create an example for you.

  • Hi,

    On the transmitter side we need to add a random 48-bit device address to the payload field. I will use pipe 0 in this example code and this random 6 byte device address.

    static nrf_esb_payload_t        tx_payload = NRF_ESB_CREATE_PAYLOAD(0, 0x24, 0x46, 0x67, 0x11, 0x88, 0x43);

    The Device Address Match unit will only work when the RADIO is configured for little endian. By default ESB uses big endian, so we need to change the endian. In the file nrf_esb.c, we need to change the function update_rf_payload_format_esb_dpl() and update_rf_payload_format_esb(). These functions configures the NRF_RADIO->PCNF1 register, and here we need to change RADIO_PCNF1_ENDIAN_Big to RADIO_PCNF1_ENDIAN_Little.

    In the main() while-loop on the transmitter, we should remove the part where we are changing the payload and instead just toggle LED_1, i.e. so that the if else statement looks like this:

     

            if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
    
            {
    
                                                 nrf_gpio_pin_toggle(LED_1);
    
            }
    
            else
    
            {
    
                NRF_LOG("Sending packet failed\r\n");
    
            }

    On the receiver side, we need to configure the Device Address match unit with the Device Address the transmitter have inserted in the payload. Let’s create a function called radio_whitelist_add(), that we can use the configure the registers. This function could look like this:

    void radio_whitelist_add(uint8_t pipe, const uint8_t * addr)
    
    {
    
      NRF_RADIO->DAP[pipe] = ( (((uint16_t)addr[5]) <<  8)
    
                              | (((uint16_t)addr[4]))     );
    
     
    
      NRF_RADIO->DAB[pipe] = ( (((uint32_t)addr[3]) << 24)
    
                              | (((uint32_t)addr[2]) << 16)
    
                              | (((uint32_t)addr[1]) <<  8)
    
                              | (((uint32_t)addr[0]))     );
    
     
    
        NRF_RADIO->DACNF |= (1U << (pipe + RADIO_DACNF_TXADD0_Pos));
    
        NRF_RADIO->DACNF |=  (1U << pipe);
    
    }

    Let’s store the device address we will be using(same as we used in the transmitter).

    static uint8_t const m_adv_addr[]  = {0x24, 0x46, 0x67, 0x11, 0x88, 0x43};

    and let’s call the radio_whitelist_add() function after esb_init(). We could call the function like this:

    radio_whitelist_add(0,m_adv_addr);

     

    I have not configured any interrupts to trigger when we get a EVENTS_DEVMATCH. So for checking if we are actually getting the event, we can configure the PPI to toggle a LED each time we get the EVENTS_DEVMATCH.

    This can be configured with the following function:

    void devmatch_gpiote_toogle( void )
    {
    	uint32_t PPI_CHANNEL = 0;
        uint32_t PIN_GPIO_LED = 20; // LED 4 on the nRF52832-DK
    
        // Configure PIN_GPIO as output
        NRF_GPIO->DIRSET = (1UL << PIN_GPIO_LED);
      
        // Configure GPIOTE->TASKS_OUT[0] to toggle PIN_GPIO_LED
        NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Task       << GPIOTE_CONFIG_MODE_Pos) |
                              (GPIOTE_CONFIG_OUTINIT_Low     << GPIOTE_CONFIG_OUTINIT_Pos) |
                              (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |
                              (PIN_GPIO_LED                  << GPIOTE_CONFIG_PSEL_Pos);
    
        // Configure PPI channel with connection between EVENTS_DEVMATCH and GPIOTE->TASKS_OUT[0]
        NRF_PPI->CH[PPI_CHANNEL].EEP = (uint32_t)&NRF_RADIO->EVENTS_DEVMATCH;
        NRF_PPI->CH[PPI_CHANNEL].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
      
        // Enable PPI channel
        NRF_PPI->CHENSET = (1UL << PPI_CHANNEL);
    }

     

    We could call the devmatch_gpiote_toogle() function after we have called radio_whitelist_add(). We should also remove the toggling in the nrf_esb_event_handler, i.e. comment out the nrf_gpio_pin_write() functions.

    If everthing is working, LED1 should toggle on the transmitter, and LED4 should toggle on the receiver, indicating the we getting the event EVENTS_DEVMATCH.

    Here is the main.c files for the transmitter and the receiver for SDK 11, that I used to test this. Note that if this is a new project, I would generally recommend using the latest SDK instead.

    main_receiver.c

    /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
     *
     * The information contained herein is property of Nordic Semiconductor ASA.
     * Terms and conditions of usage are described in detail in NORDIC
     * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
     *
     * Licensees are granted free, non-transferable use of the information. NO
     * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
     * the file.
     *
     */
    
    #include "nrf_esb.h"
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "sdk_common.h"
    #include "nrf.h"
    #include "nrf_esb_error_codes.h"
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "nrf_error.h"
    #include "nrf_log.h"
    #include "boards.h"
    #include "nrf_log.h"
    
    
    const uint8_t leds_list[LEDS_NUMBER] = LEDS_LIST;
    uint8_t led_nr;
    
    nrf_esb_payload_t rx_payload;
    
    void nrf_esb_error_handler(uint32_t err_code, uint32_t line)
    {
        NRF_LOG_PRINTF("App failed at line %d with error code: 0x%08x\r\n",
                       line, err_code);
    #if DEBUG //lint -e553
        while(true);
    #else
        NVIC_SystemReset();
    #endif
    
    }
    
    #define APP_ERROR_CHECK(err_code) if(err_code) nrf_esb_error_handler(err_code, __LINE__);
    
    /*lint -save -esym(40, BUTTON_1) -esym(40, BUTTON_2) -esym(40, BUTTON_3) -esym(40, BUTTON_4) -esym(40, LED_1) -esym(40, LED_2) -esym(40, LED_3) -esym(40, LED_4) */
    
    void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
    {
        switch (p_event->evt_id)
        {
            case NRF_ESB_EVENT_TX_SUCCESS:
                NRF_LOG("TX SUCCESS EVENT\r\n");
                break;
            case NRF_ESB_EVENT_TX_FAILED:
                NRF_LOG("TX FAILED EVENT\r\n");
                break;
            case NRF_ESB_EVENT_RX_RECEIVED:
                NRF_LOG("RX RECEIVED EVENT\r\n");
                if (nrf_esb_read_rx_payload(&rx_payload) == NRF_SUCCESS)
                {
                    // Set LEDs identical to the ones on the PTX.
                    //nrf_gpio_pin_write(LED_1, !(rx_payload.data[1]%8>0 && rx_payload.data[1]%8<=4));
                    //nrf_gpio_pin_write(LED_2, !(rx_payload.data[1]%8>1 && rx_payload.data[1]%8<=5));
                    //nrf_gpio_pin_write(LED_3, !(rx_payload.data[1]%8>2 && rx_payload.data[1]%8<=6));
                    //nrf_gpio_pin_write(LED_4, !(rx_payload.data[1]%8>3));
    
                    NRF_LOG("Receiving packet: ");
                    NRF_LOG_HEX_CHAR(rx_payload.data[1]);
                    NRF_LOG("\r\n");
                }
                break;
        }
    }
    
    void radio_whitelist_add(uint8_t pipe, const uint8_t * addr)
    {
      NRF_RADIO->DAP[pipe] = ( (((uint16_t)addr[5]) <<  8)
                              | (((uint16_t)addr[4]))     );
    
      NRF_RADIO->DAB[pipe] = ( (((uint32_t)addr[3]) << 24)
                              | (((uint32_t)addr[2]) << 16)
                              | (((uint32_t)addr[1]) <<  8)
                              | (((uint32_t)addr[0]))     );
    
        NRF_RADIO->DACNF |= (1U << (pipe + RADIO_DACNF_TXADD0_Pos));
        NRF_RADIO->DACNF |=  (1U << pipe);
    }
    
    
    
    void clocks_start( void )
    {
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    }
    
    
    void gpio_init( void )
    {
        LEDS_CONFIGURE(LEDS_MASK);
    }
    
    
    uint32_t esb_init( void )
    {
        uint32_t err_code;
        uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
        uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
        uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };
        nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
        nrf_esb_config.payload_length           = 8;
        nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
        nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_2MBPS;
        nrf_esb_config.mode                     = NRF_ESB_MODE_PRX;
        nrf_esb_config.event_handler            = nrf_esb_event_handler;
        nrf_esb_config.selective_auto_ack       = false;
    
        err_code = nrf_esb_init(&nrf_esb_config);
        VERIFY_SUCCESS(err_code);
    
        err_code = nrf_esb_set_base_address_0(base_addr_0);
        VERIFY_SUCCESS(err_code);
    
        err_code = nrf_esb_set_base_address_1(base_addr_1);
        VERIFY_SUCCESS(err_code);
    
        err_code = nrf_esb_set_prefixes(addr_prefix, 8);
        VERIFY_SUCCESS(err_code);
    
        return err_code;
    }
    
    void devmatch_gpiote_toogle( void )
    {
    	uint32_t PPI_CHANNEL = 0;
        uint32_t PIN_GPIO_LED = 20; // LED 4 on the nRF52832-DK
    
        // Configure PIN_GPIO as output
        NRF_GPIO->DIRSET = (1UL << PIN_GPIO_LED);
      
        // Configure GPIOTE->TASKS_OUT[0] to toggle PIN_GPIO_LED
        NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Task       << GPIOTE_CONFIG_MODE_Pos) |
                              (GPIOTE_CONFIG_OUTINIT_Low     << GPIOTE_CONFIG_OUTINIT_Pos) |
                              (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |
                              (PIN_GPIO_LED                  << GPIOTE_CONFIG_PSEL_Pos);
    
        // Configure PPI channel with connection between EVENTS_DEVMATCH and GPIOTE->TASKS_OUT[0]
        NRF_PPI->CH[PPI_CHANNEL].EEP = (uint32_t)&NRF_RADIO->EVENTS_DEVMATCH;
        NRF_PPI->CH[PPI_CHANNEL].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
      
        // Enable PPI channel
        NRF_PPI->CHENSET = (1UL << PPI_CHANNEL);
    }
    
    
    static uint8_t const m_adv_addr[]  = {0x24, 0x46, 0x67, 0x11, 0x88, 0x43};
    
    
    int main(void)
    {
        uint32_t err_code;
    
        gpio_init();
    
        err_code = NRF_LOG_INIT();
        APP_ERROR_CHECK(err_code);
    
        clocks_start();
    
        err_code = esb_init();
        APP_ERROR_CHECK(err_code);
    	radio_whitelist_add(0,m_adv_addr);
    	devmatch_gpiote_toogle();
    
        NRF_LOG("Enhanced ShockBurst Receiver Example running.\r\n");
    
        err_code = nrf_esb_start_rx();
        APP_ERROR_CHECK(err_code);
    
        while (true)
        {
            __WFE();
        }
    }
    /*lint -restore */
    

    main_transmitter.c

    /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
     *
     * The information contained herein is property of Nordic Semiconductor ASA.
     * Terms and conditions of usage are described in detail in NORDIC
     * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
     *
     * Licensees are granted free, non-transferable use of the information. NO
     * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
     * the file.
     *
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "sdk_common.h"
    #include "nrf.h"
    #include "nrf_esb.h"
    #include "nrf_error.h"
    #include "nrf_esb_error_codes.h"
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "nrf_log.h"
    #include "boards.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "app_util.h"
    
    
    
    static nrf_esb_payload_t        tx_payload = NRF_ESB_CREATE_PAYLOAD(0, 0x24, 0x46, 0x67, 0x11, 0x88, 0x43);
    
    
    static nrf_esb_payload_t        rx_payload;
    
    const uint8_t leds_list[LEDS_NUMBER] = LEDS_LIST;
    
    void nrf_esb_error_handler(uint32_t err_code, uint32_t line)
    {
        NRF_LOG_PRINTF("App failed at line %d with error code: 0x%08x\r\n",
                       line, err_code);
    #if DEBUG //lint -e553
        while(true);
    #else
        NVIC_SystemReset();
    #endif
    
    }
    
    #define APP_ERROR_CHECK(err_code) if(err_code) nrf_esb_error_handler(err_code, __LINE__);
    
    /*lint -save -esym(40, BUTTON_1) -esym(40, BUTTON_2) -esym(40, BUTTON_3) -esym(40, BUTTON_4) -esym(40, LED_1) -esym(40, LED_2) -esym(40, LED_3) -esym(40, LED_4) */
    
    void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
    {
        switch (p_event->evt_id)
        {
            case NRF_ESB_EVENT_TX_SUCCESS:
                NRF_LOG("TX SUCCESS EVENT\r\n");
                break;
            case NRF_ESB_EVENT_TX_FAILED:
                NRF_LOG("TX FAILED EVENT\r\n");
                (void) nrf_esb_flush_tx();
                (void) nrf_esb_start_tx();
                break;
            case NRF_ESB_EVENT_RX_RECEIVED:
                NRF_LOG("RX RECEIVED EVENT\r\n");
                while (nrf_esb_read_rx_payload(&rx_payload) == NRF_SUCCESS)
                {
                    if(rx_payload.length > 0)
                    {
                        NRF_LOG("RX RECEIVED PAYLOAD\r\n");
                    }
                }
                break;
        }
        NRF_GPIO->OUTCLR = 0xFUL << 12;
        NRF_GPIO->OUTSET = (p_event->tx_attempts & 0x0F) << 12;
    }
    
    
    void clocks_start( void )
    {
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    }
    
    
    void gpio_init( void )
    {
        nrf_gpio_range_cfg_output(8, 15);
        LEDS_CONFIGURE(LEDS_MASK);
    }
    
    
    uint32_t esb_init( void )
    {
        uint32_t err_code;
        uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
        uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
        uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };
    
        nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;
        nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB_DPL;
        nrf_esb_config.retransmit_delay         = 600;
        nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_2MBPS;
        nrf_esb_config.event_handler            = nrf_esb_event_handler;
        nrf_esb_config.mode                     = NRF_ESB_MODE_PTX;
        nrf_esb_config.selective_auto_ack       = false;
    
        err_code = nrf_esb_init(&nrf_esb_config);
    
        VERIFY_SUCCESS(err_code);
    
        err_code = nrf_esb_set_base_address_0(base_addr_0);
        VERIFY_SUCCESS(err_code);
    
        err_code = nrf_esb_set_base_address_1(base_addr_1);
        VERIFY_SUCCESS(err_code);
    
        err_code = nrf_esb_set_prefixes(addr_prefix, 8);
        VERIFY_SUCCESS(err_code);
    
        return err_code;
    }
    
    
    int main(void)
    {
        ret_code_t err_code;
    
        gpio_init();
    
        err_code = NRF_LOG_INIT();
        APP_ERROR_CHECK(err_code);
    
        clocks_start();
    
        err_code = esb_init();
        APP_ERROR_CHECK(err_code);
    
        LEDS_CONFIGURE(LEDS_MASK);
    
        NRF_LOG("Enhanced ShockBurst Transmitter Example running.\r\n");
    
        while (true)
        {
            NRF_LOG("Transmitting packet ");
            NRF_LOG_HEX_CHAR(tx_payload.data[1]);
            NRF_LOG("\r\n");
    
            tx_payload.noack = false;
            if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
            {
    			 nrf_gpio_pin_toggle(LED_1);
            }
            else
            {
                NRF_LOG("Sending packet failed\r\n");
            }
    
            nrf_delay_us(50000);
        }
    }
    /*lint -restore */
    

  • Hi ,

    thanks for your example, it is works use pipe 0.

    but if change to other pipe ,it is not work.

    •  case 1: ok

    tx_payload1 = NRF_ESB_CREATE_PAYLOAD(0, 0x24,0x46, 0x67, 0x11, 0x88, 0x43);

    radio_whitelist_add(0, addr);

    •  case 2: ok

    tx_payload1 = NRF_ESB_CREATE_PAYLOAD(0, 0x24,0x46, 0x67, 0x11, 0x88, 0x43);

    radio_whitelist_add(1, addr);

    • case 3: not work

    tx_payload1 = NRF_ESB_CREATE_PAYLOAD(1, 0x24,0x46, 0x67, 0x11, 0x88, 0x43); radio_whitelist_add(1, addr);

    could you help me to check why it is not work in other pipe ?

    Abc

Related