Radio Notification

Radio Notification

In this tutorial we will set up a beacon example and modify it to use radio notification. Then we will use radio notification to light a LED when the radio is transmitting.

While this is a relatively simple example, radio notification has some very powerful uses. You can for example use radio notification to finish those last second calculations before the SoftDevice takes control of the processor core.

Tools

Installing the command line tools

Start off by downloading and installing the command line tools executable.

Open the command line and type:

  • nrfjprog --help

This will list the different input parameters and other help documentation. If the command line reports that it cannot find the program follow the instructions below in Adding PATH Variables.

Adding PATH Variables

Sometimes nrfjprog.exe will not be added to PATH by default, this is how to do it manually. If you are looking for more information on what the PATH variable is, please consult this answer at Superuser.

In windows 7 navigate to environment variables by (for other systems consult the link above):

  • Pressing: Win+Break
  1. Then click on Advanced system settings

  2. Click on Environment Variables...

Add the variable to path by clicking the Edit... button

image description

Then add nrfjprog by adding ´;C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin´ to the end of the variable value for PATH. Make sure that you add a ; between entries in PATH values, i.e. path1;path2.

Then press OK. Now you will be able to see the help dialog when you type nrfjprog --help in a new command line.

Setting up the example

This tutorial assumes you have read and completed the tutorials on Setting up an example project on the nRF51 DK and BLE Advertising, a beginner's tutorial. For this tutorial we will use the ble_app_beacon example for SoftDevice S130/S132. Download and extract the SDK, the project can be found in:

  • nRF 51 DK..\examples\ble_peripheral\ble_app_beacon\pca10028\s130\arm5_no_packs
  • nRF 52 DK..\examples\ble_peripheral\ble_app_beacon\pca10040\s132\arm5_no_packs

The SoftDevice hex file can be found in

  • nRF 51 ...[YOUR_SDK11_LOCATION]\nRF5_SDK_11.0.0_89a8197\components\softdevice\s130\hex
  • nRF 52 ...[YOUR_SDK11_LOCATION]\nRF5_SDK_11.0.0_89a8197\components\softdevice\s132\hex

Program the hex file by first erasing and the programming the chip with:

nRF51

nrfjprog --family nRF51 --eraseall
nrfjprog --family nRF51 --program [SOFTDEVICE_LOCATION]\s130_nrf51_2.0.0_softdevice.hex

nRF52

nrfjprog --family nRF51 --eraseall
nrfjprog --family nRF51 --program [SOFTDEVICE_LOCATION]\s132_nrf52_2.0.0_softdevice.hex

Next, compile the code in Keil and flash to your device. Verify that everything is working correctly by checking that LED1 is blinking to indicate advertising, further/alternate verification is possible by checking Master Control Panel for relevant beacons.

The radio notification function

In this tutorial we will describe how to set up radio notifications using the SoftDevice API, the documentation can be found here. If you want to use the SDK 11 functions be aware of this bug.

First we will have to add nrf_nvic.h to our project in order to be able to use sd_nvic functions. Include it by adding

#include nrf_nvic.h

to the includes at the top of main.c.

Next we will create a function and include it in our code, above main. The different parameters will be discussed in the next section.

/**@brief Function for initializing Radio Notification Software Interrupts.
 */
uint32_t radio_notification_init(uint32_t irq_priority, uint8_t notification_type, uint8_t notification_distance)
{
    uint32_t err_code;

    err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Configure the event
    return sd_radio_notification_cfg_set(notification_type, notification_distance);
}

Radio notification uses software interrupt 1 for its returns, for this tutorial we will use the event handler to toggle the status of a LED. Add the following handler above main.

/**@brief Software interrupt 1 IRQ Handler, handles radio notification interrupts.
 */
void SWI1_IRQHandler(bool radio_evt)
{
    if (radio_evt)
    {
        nrf_gpio_pin_toggle(BSP_LED_2); //Toggle the status of the LED on each radio notification event
    }
}

Note that a BSP binding is used to ensure code compatibility between nRF51 DK and nRF52 DK.

Configuring radio notifications

To initialize radio notification using our function we will utilize some predefined enumerators and structs.

nRF51: The interrupt priority is a value from 0 to 3, where 0 corresponds to highest priority. 0 and 2 are reserved values, i.e. we have a choice between:

  • Application High priority - 1
  • Application Low priority - 3

nRF52: The interrupt priority is a value from 0 to 7, where 0 corresponds to the highest priority. 0, 1, 4 and 5 are reserved values and we have a choice between priority levels 2, 3, 6 and 7.

image description

The distance is the time window before/after the radio goes active. The radio events are radio_on and radio_off, e.g. a notification distance of 800µs corresponds to a radio notification event 800µs before the radio goes active, and another event right after the radio has gone inactive. The different distances are shown below.

/**@brief Possible values of notification_distances */
enum NRF_RADIO_NOTIFICATION_DISTANCES
{
  NRF_RADIO_NOTIFICATION_DISTANCE_NONE = 0, /** The event does not have a notification. */
  NRF_RADIO_NOTIFICATION_DISTANCE_800US,    /** The distance from the active notification to start of radio activity. */
  NRF_RADIO_NOTIFICATION_DISTANCE_1740US,   /** The distance from the active notification to start of radio activity. */
  NRF_RADIO_NOTIFICATION_DISTANCE_2680US,   /** The distance from the active notification to start of radio activity. */
  NRF_RADIO_NOTIFICATION_DISTANCE_3620US,   /** The distance from the active notification to start of radio activity. */
  NRF_RADIO_NOTIFICATION_DISTANCE_4560US,   /** The distance from the active notification to start of radio activity. */
  NRF_RADIO_NOTIFICATION_DISTANCE_5500US    /** The distance from the active notification to start of radio activity. */
};

The TYPE enumeration allows you select between

  • NRF_RADIO_NOTIFICATION_TYPE_NONE - Triggers no interrupts
  • NRF_RADIO_NOTIFICATION_TYPE_INT_ON_ACTIVE - Triggers interrupt before a radio event
  • NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INAVTIVE - Triggers interrupt after a radio event
  • NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH - Triggers interrupt before and after radio event

In the SoftDevice Specification different examples of signals can be seen.

Running the example

Radio notifications should always be initialized/deinitialized when the SoftDevice is guaranteed to be inactive, for example right after it is initialized. Lets set up a radio signal with low priority that is active 800 µs before the radio event occurs. In main, after ble_stack_init(); we add

err_code = radio_notification_init(3, NRF_RADIO_NOTIFICATION_TYPE_INT_ON_ACTIVE, NRF_RADIO_NOTIFICATION_DISTANCE_800US);
APP_ERROR_CHECK(err_code=);

Compile and flash the project. The blinking frequency of the LED will change proportionally to the advertising interval.

Final notes and further reading

Radio notification is a powerful tool that can be essential in making your application. Some useful information can be found below.

Anonymous
  • I want to be notified when radio becomes active and inactive. How?

    If I use NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH when calling radio_notification_init(), how would I know which event happens in SWI1_IRQHandler()? The input parameter radio_evt is just a bool value.

  • void SWI1_IRQHandler(bool radio_evt)
    

    When would this ever be an argument of 0? When if ever does the softdevice call SWI1_IRQ but not as a radio_evt?

  • To disable radio notifications you have a few options, some fit certain solutions better than others. To ensure proper operation we need to heed the following sentence from the SoftDevice specification.

    To ensure that the Radio Notification signals behave in a consistent way, the Radio Notification 
    shall always be configured when the SoftDevice is in an idle state with no protocol stack or 
    other SoftDevice activity in progress. Therefore, it is recommended to configure the Radio 
    Notification signals directly after the SoftDevice has been enabled.
    

    Start off by making sure that the first time it is initialized is in a section where the SoftDevice is not active, for example right after initialization.

    In the right context, radio notification can be disabled by calling:

    // Deinitialize Radio Notification software interrupt
    uint32_t ble_radio_notification_uninit(void)
    {
        err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        err_code = sd_nvic_DisableIRQ(SWI1_IRQn);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_NONE, NRF_RADIO_NOTIFICATION_DISTANCE_NONE);
    }
    

    This context limitations is the same as for the first initialization of the radio notifications, as described above. We need to find some context where there will not be any SoftDevice activity. Since we already have radio notifications set up it is simplest to call ble_radio_notification_uninit() inside itself. However if we want to restart it we will be faced with the problem of when/how to restart it.

    One of the tools available is a radio timeslot where radio activity is guaranteed to not occur. When using timeslots be aware that you cannot call SoftDevice functions in the signal handler as it executes at priority 0.

  • Hi,

    Once radio notification is enabled how to disable it? Could you please let me know.

  • I understand and followed this article, but not works

    1. environment. nRF51 DK board, SDK 10 example, Softdevice S110 v8.0.0
    2. Just beacon example: It works, LED1 blink
    3. Added radio notification: compile ok, but no LED blinks

    I got answer. I should radio notification init after SoftDevice Init.