Tx/Rx Options#

RAIL provides some useful options when transmitting and receiving packets. In this document, we're going to cover those. Also, the Listen Before Talk as well as the Address Filtering features will be discussed in this article.

Tx Options#

The main Tx options should be passed to RAIL using the RAIL_TxOptions_t parameter of the RAIL_StartTx APIs. The available options are practically implemented as a bitmask type:

  • RAIL_TX_OPTION_WAIT_FOR_ACK: Waits for ACK after transmitting a packet. I.e., the radio will automatically switch to Rx mode after Tx (disregarding auto state transitions) with a given timeout.

  • RAIL_TX_OPTION_REMOVE_CRC: Ignores the config's CRC setting and does not transmit CRC.

  • RAIL_TX_OPTION_SYNC_WORD_ID: If set, Tx will use the second configured sync word. If unset, it will use the first one.

  • RAIL_TX_OPTION_ANTENNA0: Uses antenna 0 (usually used when 2 antennas are available for antenna diversity).

  • RAIL_TX_OPTION_ANTENNA1: Uses antenna 1 (usually used when 2 antennas are available for antenna diversity).

  • RAIL_TX_OPTION_ALT_PREAMBLE_LEN: Uses an alternative preamble length configured by the RAIL_SetTxAltPreambleLength() API.

  • RAIL_TX_OPTION_CCA_PEAK_RSSI: Uses peak RSSI measurement in CCA instead of averaging (detailed later).

  • RAIL_TX_OPTION_CCA_ONLY: With this option the transmit after the CCA should be started manually (detailed later).

  • RAIL_TX_OPTION_RESEND: If the Tx FIFO has a single, complete packet in it, this option can be used the send it over on over without reloading the FIFO.

  • RAIL_TX_OPTION_CONCURRENT_PHY_ID: Selects the Tx PHY when concurrent mode is used in the Wi-SUN stack.

If both RAIL_TX_OPTION_ANTENNA0/1 option is not set, the active antenna will be the one, which was selected by the last Tx/Rx operation.

RAIL_TX_OPTION_CCA_PEAK_RSSI isn't supported on EFR32xG1 platforms.

The usual groups are also defined: RAIL_TX_OPTIONS_ALL, RAIL_TX_OPTIONS_NONE and RAIL_TX_OPTIONS_DEFAULT (which is the same as RAIL_TX_OPTIONS_NONE).

Rx Options#

Rx options can be configured using RAIL_ConfigRxOptions(), which takes two RAIL_RxOptions_t parameter, mask and options. This way, it's easy to change the options individually, without tweaking the rest. The available options are:

  • RAIL_RX_OPTION_STORE_CRC: By default, RAIL does not store the CRC, only checks it. By enabling this, it will store it as well. It can be used for example for sniffer applications.

  • RAIL_RX_OPTION_IGNORE_CRC_ERRORS: Frames will be received even if it failed CRC check. When enabled, the result of the CRC check will be stored in the RAIL_RxPacketDetails_t.crcPassed field.

  • RAIL_RX_OPTION_ENABLE_DUALSYNC: Enables the detection of both sync word.

  • RAIL_RX_OPTION_TRACK_ABORTED_FRAMES: RAIL aborts frame reception when it filters it using the address filter. With this option enabled, it will receive the full frame (but still generates the correct error event) so the network analyzer can display it (through PTI).

  • RAIL_RX_OPTION_REMOVE_APPENDED_INFO: Disables the storage of the appended info. Appended info is used to store the base of RAIL_RxPacketDetails_t, like timestamp and RSSI. If not needed, it can be disabled, saving some buffer space.

  • RAIL_RX_OPTION_ANTENNA0: Uses antenna 0 (usually used when 2 antennas are available for antenna diversity).

  • RAIL_RX_OPTION_ANTENNA1: Uses antenna 1 (usually used when 2 antennas are available for antenna diversity).

  • RAIL_RX_OPTION_ANTENNA_AUTO: Uses both antennas, with antenna diversity (must be configured before using it).

  • RAIL_RX_OPTION_DISABLE_FRAME_DETECTION: Disables the frame detection system. Useful, if you only want to check the energy of a channel, and do not want to receive frames, because it would break the application's state machines.

  • RAIL_RX_OPTION_CHANNEL_SWITCHING: Enables concurrent listening on two IEEE 802.15.4 channels, with duty cycling. It requires a specially tuned radio config and only available on a few platforms.

  • RAIL_RX_OPTION_FAST_RX2RX: Speeds up returning to receive mode after finished (or aborted) receiving a packet. However, it will generate an Rx error event if packet reception is completed while the previous packet is still processing.

  • RAIL_RX_OPTION_ENABLE_COLLISION_DETECTION: Enables collision detection required by the Wi-SUN stack.

RAIL_RX_OPTION_IGNORE_CRC_ERRORS affects also on ACK packets and Auto State transition: packets with CRC error will be handled as successfully received packets.

*RAIL_RX_OPTION_ENABLE_DUALSYNC is not available for certain combinations of chips, PHYs, and protocols. Also, it is not possible to listen only for SYNC2.

RAIL_RX_OPTION_ANTENNA_AUTO is not a unique value, it's actually RAIL_RX_OPTION_ANTENNA0|RAIL_RX_OPTION_ANTENNA1

The usual groups are also defined: RAIL_RX_OPTIONS_ALL, RAIL_RX_OPTIONS_NONE and RAIL_RX_OPTIONS_DEFAULT (which is the same as RAIL_RX_OPTIONS_NONE).

Some options, like the antenna selections will restart receive mode (if changed in receive mode).

Listen Before Talk Options#

Listen before talk setups are often required in protocols, and a good idea to implement in some proprietary protocols as well. It solves most collisions between transmissions.

Listen before talk operations are built up from 3 tasks:

  • CCA (Clear Channel Assessment): the "listen" itself, where the radio is in Rx, measuring RSSI, and decides for or against transmission

  • Backoffs: randomized delays between CCA operations

  • Transmission: this is the 'talk' part, in which the radio sends the preconfigured packet

Measuring RSSI means averaging during a predefined period in most cases. However, setting the RAIL_TX_OPTION_CCA_PEAK_RSSI option makes it available to use the peak instead of the mean RSSI value.

Generally, the radio starts with CCA: If the RSSI is below threshold, it starts transmitting. If not, it waits a random backoff period and tries CCA again. The radio should repeat this with increasing backoff periods, until successful transmission or timeout.

CCA period on EFR32 is derived from symbol time, so the minimum and maximum configurable values can differ from radio config to radio config.

The backoffs are implemented on the same timer that handles the scheduling, so it could cause problems if you start a listen before start operation from a scheduled Rx. Also, scheduled listen before talk Tx operations are not supported.

CSMA/CA#

The most common listen before talk protocol is CSMA/CA (Carrier-sense Multiple Access with Collision Avoidance), which is fully supported by the EFR32 hardware. CSMA/CA defines backoffs as a random number with even distribution between 0 and unit * (2^BE - 1), where BE is the backoff exponent, which increments with each retries.

To trigger a CSMA/CA transmission, you can start transmitting with RAIL_StartCcaCsmaTx() instead of RAIL_StartTx(). The API has an extra argument, with the type of RAIL_CsmaConfig_t, that configures the CSMA/CA parameters:

  • csmaMinBoExp and csmaMaxBoExp are setting the minimum and maximum backoff exponent (i.e., the first value of BE will be csmaMinBoExp, and BE increments up to csmaMaxBoExp).

  • csmaTries sets the number of tries (i.e., how many CCA should be performed before reporting back a busy channel).

  • ccaThreshold sets a threshold for comparing against the measured RSSI during the CCA; if the measured RSSI exceeds the threshold the channel will be judged busy.

  • ccaBackoff is the backoff unit in μs.

  • ccaDuration sets the duration the CCA should take in μs (i.e., how long it should measure the RSSI).

  • csmaTimeout sets the timeout in μs: if the CSMA/CA operation exceeds this timeout it will stop. This is useful, since due to the random backoffs, the CSMA/CA duration can vary. Set it to 0 to disable the timeout.

ccaBackoff will be truncated if it is higher than 511. Setting csmaTries to 0 will disable CSMA/CA: calling RAIL_StartCcaCsmaTx() or RAIL_StartTx() has the same result.

There's also a special setup: if csmaMinBoExp and csmaMaxBoExp are both set to 0, that means a fixed backoff configuration. In this case, the backoff will always take the time set in ccaBackoff. With fixed backoff the ccaBackoff won't be truncated.

LBT#

Another common listen before talk protocol is the obviously named LBT. It is defined in ETSI EN 300 220-1, under the Polite Spectrum Access chapter.

LBT defines backoffs as a unit * BO, where BO is a random number with even distribution between a minimum and maximum.

LBT is not supported by the EFR32 hardware, it is converted to a CSMA/CA configuration in RAIL. Because of this, if you can choose between the two, you should choose CSMA/CA.

Note that LBT can be configured with a minimum backoff limit, while CSMA/CA's minimum backoff period is always 0. This is not supported by the hardware, so LBT is implemented with a bit of cheating. The CCA period is set to the configured period + unit * minBO. It doesn't really matter if the CCA period is longer, and this guarantees that the minimum backoff is fulfilled.

Another limitation is that the maximum backoff must be power of 2, so the configured backoff will be rounded to the closest power of 2.

Much like CSMA/CA, LBT has its own StartTx API, RAIL_StartCcaLbtTx(), which has a familiar config struct, RAIL_LbtConfig_t to configure the LBT parameters:

  • lbtMinBoRand and lbtMaxBoRand are setting the limits of the random backoff, just like with CSMA/CA

  • lbtTries sets the number of tries, similarly to CSMA/CA

  • lbtBackoff is the backoff unit in μs

  • lbtThreshold is a similar threshold what we've seen in CSMA/CA

  • lbtDuration sets the duration the CCA should take in μs

  • lbtTimeout sets the same timeout as CSMA/CA

Setting lbtTries to 0 will disable LBT, just like with CSMA/CA.

Custom Listen Before Talk#

A single CCA operation can be started using RAIL_TX_OPTION_CCA_ONLY and with csmaTries set to 1. With this and software timers, a custom listen before talk protocol can be implemented. Additionally, the RSSI API (RAIL_GetRssi() and RAIL_StartAverageRSSI()) can be also used for similar purposes.

Address Filtering#

EFR32 supports hardware based address filtering, as long as the address is stored in the same location in all the frames (unlike 802.15.4, which is only supported through the protocol specific API). EFR32 supports 2 address fields (e.g., for group and device address), both can be up to 8 Bytes long. Both fields can be configured for up to 4 addresses (e.g., for broadcast, unicast and 2 multicast address). Any combination can be allowed on these two fields, e.g., enable address1 for field0 only if field1 has address1, or if field0 has address2, anything is allowed on field1.

Enabling the address filter starts with configuring it, using:

RAIL_AddrConfig_t addrConfig = {
    .offsets = {2, 0},
    .sizes = {4, 0},
    .matchTable = ADDRCONFIG_MATCH_TABLE_SINGLE_FIELD,
};
RAIL_ConfigAddressFilter(rail_handle, &addrConfig);

Its only parameter (apart from the usual rail_handle) is RAIL_AddrConfig_t. RAIL_AddrConfig_t configures:

  • offsets[(2)], which sets the offset of the addresses in the frame. For the first field, from the end of sync word; for the second field, from the end of the first field. Note that this means that the fields cannot overlap.

  • sizes[(2)], which sets the size of the fields in byte. Setting it to 0 disables the field.

  • matchTable, which configures the enabled combinations of the fields.

If you only use a single field, you can safely use ADDRCONFIG_MATCH_TABLE_SINGLE_FIELD. If you need both address fields, you should understand how the match table works. That is out of the scope of this article, but you can rely on the API documentation.

Next, you load the addresses, using:

uint8_t address[4] = {0xAA, 0xBB, 0xCC, 0xDD};
RAIL_SetAddressFilterAddress(railHandle, 0, 1, address, true);

Which will enable the address 0xAABBCCDD on field 0, index 1, in enabled state. Make sure your address length matches what you configured for the field. You can later disable (and re-enable) it with:

RAIL_EnableAddressFilterAddress(railHandle, false, 0, 1);

Note that this API is referencing the address by its field and index. If you want to enable/disable addresses based on the value, i.e., the address itself, you should track which index is used for each address.

Finally, to enable (or disable) the whole address filter, use:

RAIL_EnableAddressFilter(railHandle, true);

Once address filter is enabled, you can get notifications on filtered frames using the RAIL_EVENT_RX_ADDRESS_FILTERED event.

API Introduced in this Article#

Functions#

Types and Enums#