The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Dependents:   hello SerialTestv11 SerialTestv12 Sierpinski ... more

mbed 2

This is the mbed 2 library. If you'd like to learn about Mbed OS please see the mbed-os docs.

Revision:
171:3a7713b1edbc
Parent:
167:84c0a372a020
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TARGET_TB_SENSE_1/TOOLCHAIN_ARM_MICRO/rail.h	Thu Nov 08 11:45:42 2018 +0000
@@ -0,0 +1,2985 @@
+/**************************************************************************//**
+ * @file rail.h
+ * @brief The main header file for the RAIL library. It describes the external
+ *        APIs available to a RAIL user
+ * @copyright Copyright 2015 Silicon Laboratories, Inc. www.silabs.com
+ *****************************************************************************/
+
+#ifndef __RAIL_H__
+#define __RAIL_H__
+
+// Get the standard include types
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h> // For memcpy()
+
+// Get the RAIL-specific structures and types
+#include "rail_chip_specific.h"
+#include "rail_types.h"
+#include "rail_assert_error_codes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup RAIL_API RAIL API
+ * @brief This is the primary API layer for the Radio Abstraction Interface
+ *   Layer (RAIL)
+ * @{
+ */
+
+/**
+ * @defgroup Protocol_Specific Protocol Specific
+ * @brief Protocol specific RAIL APIs
+ */
+
+/******************************************************************************
+ * General Radio Operation
+ *****************************************************************************/
+/**
+ * @addtogroup General
+ * @brief Basic APIs to set up and interact with the RAIL library
+ * @{
+ */
+
+/**
+ * Gets the version information for the compiled RAIL library.
+ *
+ * @param[out] version A pointer to \ref RAIL_Version_t structure to
+ *   populate with version information.
+ * @param[in] verbose Populate \ref RAIL_Version_t struct with verbose
+ *   information.
+ * @return void.
+ *
+ * The version information contains a major version number, a minor version
+ * number, and a rev (revision) number.
+ */
+void RAIL_GetVersion(RAIL_Version_t *version, bool verbose);
+
+/**
+ * Initializes RAIL.
+ *
+ * @param[in,out] railCfg The configuration and state structure for setting up
+ *   the library, which contains memory and other options needed by RAIL.
+ *   This structure must be allocated in application global read-write
+ *   memory. RAIL may modify fields within or referenced by this structure
+ *   during its operation.
+ * @param[in] cb A callback that notifies the application when the radio is
+ *   finished initializing and is ready for further configuration. This
+ *   callback is useful for potential transceiver products that require a
+ *   power up sequence before further configuration is available. After the
+ *   callback fires, the radio is ready for additional configuration before
+ *   transmit and receive operations.
+ * @return Handle for initialized rail instance or NULL if an
+ *   invalid value was passed in the railCfg.
+ */
+RAIL_Handle_t RAIL_Init(RAIL_Config_t *railCfg,
+                        RAIL_InitCompleteCallbackPtr_t cb);
+
+/**
+ * Collects entropy from the radio if available.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[out] buffer The buffer to write the collected entropy.
+ * @param[in] bytes The number of bytes to fill in in the input buffer.
+ * @return Returns the number of bytes of entropy collected. For
+ *   chips that don't support entropy collection, the function returns 0.
+ *   Values less than the requested amount may also be returned on platforms
+ *   that use entropy pools to collect random data periodically.
+ *
+ * Attempts to fill the provided buffer with the requested number of bytes of
+ * entropy. If the requested number of bytes can't be provided, as many
+ * bytes as possible will be filled and returned. For chips
+ * that do not support this function, 0 bytes will always be returned. For
+ * information about the specific mechanism for gathering entropy, see
+ * documentation for the chip family.
+ */
+uint16_t RAIL_GetRadioEntropy(RAIL_Handle_t railHandle,
+                              uint8_t *buffer,
+                              uint16_t bytes);
+
+/** @} */ // end of group General
+
+/******************************************************************************
+ * PTI
+ *****************************************************************************/
+/**
+ * @addtogroup PTI Packet Trace (PTI)
+ * @brief Basic APIs to set up and interact with PTI settings
+ * @{
+ */
+
+/**
+ * Configures PTI pin locations, serial protocols, and baud rates.
+ *
+ * @param[in] railHandle A RAIL instance handle (currently not used).
+ * @param[in] ptiConfig A configuration structure applied to the
+ *   relevant PTI registers.
+ * @return Status code indicating success of the function call.
+ *
+ * This method must be called before RAIL_EnablePti() is called.
+ * Although we do take a RAIL handle for potential future
+ * expansion of this function, it is currently not used. That is,
+ * there is only one PTI configuration that can be active on a
+ * chip, regardless of the number of protocols (unless the application
+ * takes responsibility to update the configuration upon a protocol switch),
+ * and the configuration is not saved in your RAIL instance. For optimal
+ * future compatibility, pass in a chip specific handle, such as
+ * \ref RAIL_EFR32_HANDLE for now.
+ */
+RAIL_Status_t RAIL_ConfigPti(RAIL_Handle_t railHandle,
+                             const RAIL_PtiConfig_t *ptiConfig);
+
+/**
+ * Gets the currently active PTI configuration.
+ *
+ * @param[in] railHandle A RAIL instance handle (currently not used).
+ * @param[out] ptiConfig A configuration structure filled with the active
+ *   PTI configuration.
+ * @return RAIL status indicating success of the function call.
+ *
+ * Although most combinations of configurations can be set, it is safest
+ * to call this method after configuration to confirm which values were
+ * actually set. As in RAIL_ConfigPti, railHandle is not used. This function
+ * will always return the single active PTI configuration regardless of the
+ * active protocol. For optimal future compatibility, pass in a chip
+ * specific handle, such as \ref RAIL_EFR32_HANDLE for now.
+ */
+RAIL_Status_t RAIL_GetPtiConfig(RAIL_Handle_t railHandle,
+                                RAIL_PtiConfig_t *ptiConfig);
+
+/**
+ * Enables the PTI output of the packet data.
+ *
+ * @param[in] railHandle A RAIL instance handle (currently not used).
+ * @param[in] enable PTI is enabled if true; disable if false.
+ * @return RAIL status indicating success of the function call.
+ *
+ * Similarly to how there is only one PTI configuration per chip,
+ * PTI can only be enabled or disabled for all protocols. It cannot
+ * be individually set to enabled and disabled per protocol
+ * (unless the application takes the responsibility of switching it when
+ * the protocol switches), and enable/disable is not saved as part of your
+ * RAIL instance. For optimal future compatibility, pass in a chip
+ * specific handle, such as \ref RAIL_EFR32_HANDLE for now.
+ */
+RAIL_Status_t RAIL_EnablePti(RAIL_Handle_t railHandle,
+                             bool enable);
+
+/**
+ * Sets a protocol that RAIL outputs on PTI.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] protocol The enum representing which protocol the node is using.
+ * @return Status code indicating success of the function call.
+ *
+ * The protocol is output via the Packet Trace Interface (PTI) for each packet.
+ * Before any protocol is set, the default value is \ref
+ * RAIL_PTI_PROTOCOL_CUSTOM. One of the enum values should be used so that
+ * the Network Analyzer can decode the packet.
+ */
+RAIL_Status_t RAIL_SetPtiProtocol(RAIL_Handle_t railHandle,
+                                  RAIL_PtiProtocol_t protocol);
+
+/** @} */ // end of group PTI
+
+/******************************************************************************
+ * Antenna Control
+ *****************************************************************************/
+/**
+ * @addtogroup Antenna_Control
+ * @brief Basic APIs to control the Antenna functionality
+ * @{
+ */
+
+/**
+ * Configures Antenna pin locations
+ * @param[in] railHandle a RAIL instance handle.
+ * @param[in] config A configuration structure applied to the relevant Antenna
+ *   Configuration registers.
+ * @return Status code indicating success of the function call.
+ *
+ * Although we do take a RAIL handle for potential future expansion, it is
+ * currently not used.
+ *
+ */
+RAIL_Status_t RAIL_ConfigAntenna(RAIL_Handle_t railHandle,
+                                 const RAIL_AntennaConfig_t *config);
+
+/** @} */ // end of group Antenna_Control
+
+/******************************************************************************
+ * Radio Configuration
+ *****************************************************************************/
+/// @addtogroup Radio_Configuration Radio Configuration
+/// @brief Routines for setting up and querying radio configuration information.
+///
+/// These routines allow for runtime flexibility in the radio
+/// configuration. Some of the parameters, however, are meant to be generated
+/// from the radio calculator in Simplicity Studio. The basic code to configure
+/// the radio from this calculator output looks like the example below.
+///
+/// @code{.c}
+/// // Associate a specific channel config with a particular RAIL instance, and
+/// // load the settings that correspond to the first usable channel.
+/// RAIL_ConfigChannels(railHandle, channelConfigs[0]);
+/// @endcode
+///
+/// For more information about the types of parameters that can be changed in
+/// the other functions and how to use them, see their individual documentation.
+///
+/// @{
+
+/**
+ * Loads a static radio configuration.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] config A pointer to a radio configuration.
+ * @return Status code indicating success of the function call.
+ *
+ * The configuration passed into this function should be generated for you
+ * and not manually created or edited. By default this function should not be
+ * called in RAIL 2.x and later unless a non-default radio configuration needs
+ * to be applied. In RAIL 2.x and later, the RAIL_ConfigChannels function
+ * applies the default radio configuration automatically.
+ */
+RAIL_Status_t RAIL_ConfigRadio(RAIL_Handle_t railHandle,
+                               RAIL_RadioConfig_t config);
+
+/**
+ * Modifies the currently configured fixed frame length in bytes.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] length The expected fixed frame length. A value of 0 is infinite.
+ *   A value of RAIL_SETFIXEDLENGTH_INVALID restores the frame's length back to
+ *   that length specified by the default frame type configuration.
+ * @return Length configured; The new frame length configured into the hardware
+ *   for use. 0 if in infinite mode, or RAIL_SETFIXEDLENGTH_INVALID if the frame
+ *   length has not yet been overridden by a valid value.
+ *
+ * Sets the fixed-length configuration for transmit and receive.
+ * Be careful when using this function in receive and transmit as this
+ * function changes the default frame configuration and remains in force until
+ * it is called again with an input value of RAIL_SETFIXEDLENGTH_INVALID. This
+ * function will override any fixed or variable length settings from a radio
+ * configuration.
+ */
+uint16_t RAIL_SetFixedLength(RAIL_Handle_t railHandle, uint16_t length);
+
+/**
+ * Configures the channels supported by this device.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] config A pointer to the channel configuration for your device.
+ *   This pointer will be cached in the library so it must be something that
+ *   will exist for the runtime of the application. Typically, this should be
+ *   what is stored in Flash by the configuration tool.
+ * @param[in] cb Function called whenever a radio configuration change occurs.
+ * @return Returns the first available channel in the configuration.
+ *
+ * When configuring channels on the EFR32, the radio tuner is reconfigured
+ * based on the frequency and channel spacing in the channel configuration.
+ */
+uint16_t RAIL_ConfigChannels(RAIL_Handle_t railHandle,
+                             const RAIL_ChannelConfig_t *config,
+                             RAIL_RadioConfigChangedCallback_t cb);
+
+/**
+ * Checks to see if the channel exists in RAIL.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel A channel number to check.
+ * @return Returns RAIL_STATUS_NO_ERROR if channel exists
+ *
+ * Returns RAIL_STATUS_INVALID_PARAMETER if the given channel does not exist
+ * in the channel configuration currently used, and RAIL_STATUS_NO_ERROR if the
+ * channel is valid.
+ */
+RAIL_Status_t RAIL_IsValidChannel(RAIL_Handle_t railHandle,
+                                  uint16_t channel);
+
+/**
+ * Returns the symbol rate for the current PHY.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return The symbol rate in symbols per second or 0.
+ *
+ * The symbol rate is the rate of symbol changes over the air. For non-DSSS
+ * PHYs, this is the same as the baudrate. For DSSS PHYs, it is the baudrate
+ * divided by the length of a chipping sequence. For more information,
+ * see the modem calculator documentation. If the rate is unable to be
+ * calculated, this function will return 0.
+ */
+uint32_t RAIL_GetSymbolRate(RAIL_Handle_t railHandle);
+
+/**
+ * Returns the bit rate for the current PHY.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return The bit rate in bits per second or 0.
+ *
+ * The bit rate is the effective over-the-air data rate. It does not account
+ * for extra spreading for forward error correction, and so on, but
+ * accounts for modulation schemes, DSSS, and other configurations. For more
+ * information, see the modem calculator documentation. If the rate is unable
+ * to be calculated, this function will return 0.
+ */
+uint32_t RAIL_GetBitRate(RAIL_Handle_t railHandle);
+
+/**
+ * Sets the PA capacitor tune value for transmit and receive.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] txPaCtuneValue PA Ctune value for TX mode.
+ * @param[in] rxPaCtuneValue PA Ctune value for RX mode.
+ * @return Status code indicating success of the function call.
+ *
+ * Provides the ability to tune the impedance of the transmit
+ * and receive modes by changing the amount of capacitance at
+ * the PA output.
+ */
+RAIL_Status_t RAIL_SetPaCTune(RAIL_Handle_t railHandle,
+                              uint8_t txPaCtuneValue,
+                              uint8_t rxPaCtuneValue);
+
+/** @} */ // end of group Radio_Configuration
+
+/******************************************************************************
+ * Timing Information
+ *****************************************************************************/
+/**
+ * @addtogroup System_Timing System Timing
+ * @brief Functionality related to the RAIL timer and general system time.
+ *
+ * These functions can be used to get information about the current system time
+ * or to manipulate the RAIL timer.
+ *
+ * The system time returned by RAIL_GetTime() is in the same timebase that is
+ * used throughout RAIL. Any callbacks that return a timestamp, such as
+ * rxPacketReceived() callback, will use this same timebase as will any APIs
+ * that accept an absolute time for scheduling their action. Throughout this
+ * documentation the timebase used for this will be referred to as the RAIL
+ * timebase. This is currently a value in microseconds from chip boot time.
+ * This means that it will wrap every 1.19 hours.
+ * (`(2^32 - 1) / (3600 sec/hr * 1000000 us/sec)`).
+ *
+ * The provided timer is hardware backed and interrupt driven. It can be used
+ * for timing any event in your system, but will be especially helpful for
+ * timing protocol based state machines and other systems that interact with
+ * the radio. If you do not want to process the expiration in interrupt
+ * context, leave the timerExpired() callback empty and poll for expiration
+ * with the RAIL_IsTimerExpired() function.
+ *
+ * @{
+ */
+
+/**
+ * Configure the RAIL timer plugin.
+ *
+ * @param[in] enable Enables/Disables the RAIL multitimer.
+ * @return True if the multitimer was successfully enabled/disabled, false
+ *   otherwise.
+ *
+ * @note This function must be called before calling \ref RAIL_SetMultiTimer.
+ *       This function must be called to use the timer driver plugin
+ *       with the RAIL single protocol library.
+ *       This function should not be called while the RAIL timer is running.
+ *       Call \ref RAIL_IsTimerRunning before enabling/disabling the multitimer.
+ *       If the multitimer is not needed, do not call this function.
+ *       This will allow the multitimer code to be dead stripped.
+ */
+bool RAIL_ConfigMultiTimer(bool enable);
+
+/**
+ * Gets the current RAIL time.
+ *
+ * @return Returns the RAIL timebase in microseconds. Note that this wraps
+ *   after around 1.19 hours since it's stored in a 32bit value.
+ *
+ * Returns the current time in the RAIL timebase (microseconds). It can be
+ * used to compare with packet timestamps or to schedule transmits.
+ */
+RAIL_Time_t RAIL_GetTime(void);
+
+/**
+ * Sets the current RAIL time.
+ *
+ * @param[in] time Set the RAIL timebase to this value in microseconds.
+ * @return Status code indicating success of the function call.
+ *
+ * Sets the current time in the RAIL timebase in microseconds.
+ */
+RAIL_Status_t RAIL_SetTime(RAIL_Time_t time);
+
+/**
+ * Schedules a timer to expire using the RAIL timebase.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] time The timer's expiration time in the RAIL timebase.
+ * @param[in] mode Indicates whether the time argument is an absolute
+ *   RAIL time or relative to the current RAIL time. Specifying mode
+ *   \ref RAIL_TIME_DISABLED is the same as calling RAIL_CancelTimer().
+ * @param[in] cb The callback for RAIL to call when the timer expires.
+ * @return RAIL_STATUS_NO_ERROR on success and
+ *   RAIL_STATUS_INVALID_PARAMETER if the timer could not be scheduled.
+ *
+ * Configures a timer to expire after some period in the RAIL timebase.
+ * This timer can be used to implement low level protocol features.
+ *
+ * @warning It is an error to attempt to schedule the timer when it is
+ *   still running from a previous request -- unless the cb callback is
+ *   identical to that used in the previous request, in which case the
+ *   timer is rescheduled to the new time. Note that in this case if
+ *   the original timer expires as it is being rescheduled, the callback
+ *   may or may not occur. It is generally good practice to cancel a
+ *   running timer before rescheduling it to minimize such ambiguity.
+ */
+RAIL_Status_t RAIL_SetTimer(RAIL_Handle_t railHandle,
+                            RAIL_Time_t time,
+                            RAIL_TimeMode_t mode,
+                            RAIL_TimerCallback_t cb);
+
+/**
+ * Returns the absolute time that the RAIL timer was configured to expire.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return The absolute time that this timer was set to expire.
+ *
+ * It will give the absolute time regardless of the \ref RAIL_TimeMode_t that
+ * was passed into \ref RAIL_SetTimer. Note that this time might be in the
+ * past if the timer already expired. The return value is undefined if the
+ * timer was never set.
+ */
+RAIL_Time_t RAIL_GetTimer(RAIL_Handle_t railHandle);
+
+/**
+ * Stops the currently scheduled RAIL timer.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return void.
+ *
+ * Cancels the timer. If this function is called before the timer expires,
+ * the cb callback specified in the earlier RAIL_SetTimer() call will never
+ * be called.
+ */
+void RAIL_CancelTimer(RAIL_Handle_t railHandle);
+
+/**
+ * Checks whether the RAIL timer has expired.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return True if the previously scheduled timer has expired and false
+ *   otherwise.
+ *
+ * Polling via this function can be used as an alternative to the callback.
+ */
+bool RAIL_IsTimerExpired(RAIL_Handle_t railHandle);
+
+/**
+ * Checks whether the RAIL timer is currently running.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Returns true if the timer is running and false if
+ *   the timer has expired or was never set.
+ */
+bool RAIL_IsTimerRunning(RAIL_Handle_t railHandle);
+
+/**
+ * Starts a multitimer instance.
+ *
+ * @note
+ *    It is legal to start an already running timer. If this is done, the timer
+ *    will first be stopped before the new configurations are applied.
+ *    If expirationTime is 0, the callback will be called
+ *    immediately.
+ *
+ * @param[in,out] tmr A pointer to the timer instance to start.
+ * @param[in] expirationTime When the timer is to expire.
+ * @param[in] expirationMode Select mode of expirationTime. See \ref
+ *            RAIL_TimeMode_t.
+ * @param[in] callback Function to call on timer expiry. See \ref
+ *            RAIL_MultiTimerCallback_t. NULL is a legal value.
+ * @param[in] cbArg Extra callback function parameter for user application.
+ *
+ * @return
+ *    \ref RAIL_STATUS_NO_ERROR on success.@n
+ *    \ref RAIL_STATUS_INVALID_PARAMETER if tmr has an illegal value or if
+ *         timeout is in the past.
+ */
+RAIL_Status_t RAIL_SetMultiTimer(RAIL_MultiTimer_t *tmr,
+                                 RAIL_Time_t expirationTime,
+                                 RAIL_TimeMode_t expirationMode,
+                                 RAIL_MultiTimerCallback_t callback,
+                                 void *cbArg);
+
+/**
+ * Stops the currently scheduled RAIL multi timer.
+ *
+ * @param[in,out] tmr A RAIL timer instance handle.
+ *
+ * @return
+ *    true if timer was successfully cancelled.
+ *    false if timer was not running.
+ *
+ * Cancels the timer. If this function is called before the timer expires,
+ * the cb callback specified in the earlier RAIL_SetTimer() call will never
+ * be called.
+ */
+bool RAIL_CancelMultiTimer(RAIL_MultiTimer_t *tmr);
+
+/**
+ * Check if a given timer is running.
+ *
+ * @param[in] tmr A pointer to the timer structure to query.
+ *
+ * @return
+ *    true if timer is running.
+ *    false if timer is not running.
+ */
+bool RAIL_IsMultiTimerRunning(RAIL_MultiTimer_t *tmr);
+
+/**
+ * Check if a given timer has expired.
+ *
+ * @param[in] tmr A pointer to the timer structure to query.
+ *
+ * @return
+ *    true if timer is expired.
+ *    false if timer is running.
+ */
+bool RAIL_IsMultiTimerExpired(RAIL_MultiTimer_t *tmr);
+
+/**
+ * Get time left before a given timer instance expires.
+ *
+ * @param[in] tmr A pointer to the timer structure to query.
+ * @param[in] timeMode An indication as to how the function provides the time
+ *            remaining. By choosing \ref
+ *            RAIL_TimeMode_t::RAIL_TIME_ABSOLUTE, the function returns the
+ *            absolute expiration time, and by choosing \ref
+ *            RAIL_TimeMode_t::RAIL_TIME_DELAY, the function returns the
+ *            amount of time remaining before the timer's expiration.
+ *
+ * @return
+ *    Time left expressed in RAIL's time units.
+ *    0 if the soft timer is not running or has already expired.
+ */
+RAIL_Time_t RAIL_GetMultiTimer(RAIL_MultiTimer_t *tmr,
+                               RAIL_TimeMode_t timeMode);
+
+/**
+ * Initialize RAIL timer synchronization.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] sleepConfig A sleep configuration.
+ *
+ * @return Status code indicating success of the function call.
+ */
+RAIL_Status_t RAIL_ConfigSleep(RAIL_Handle_t railHandle,
+                               RAIL_SleepConfig_t sleepConfig);
+
+/**
+ * Stop the RAIL timer and prepare RAIL for sleep.
+ *
+ * @param[in] wakeupProcessTime Time in microseconds that the application and
+ *                              hardware need to recover from sleep state.
+ * @param[out] deepSleepAllowed
+ *   true - system can go to deep sleep.
+ *   false - system should not go to deep sleep. Deep sleep should be blocked
+ *           in this case.
+ *
+ * @return Status code indicating success of the function call.
+ *
+ * @warning The active RAIL configuration must be idle for enabling sleep.
+ */
+RAIL_Status_t RAIL_Sleep(uint16_t wakeupProcessTime, bool *deepSleepAllowed);
+
+/**
+ * Wake RAIL from sleep and restart the RAIL timer.
+ *
+ * @param[in] elapsedTime Add the sleep duration to the RAIL timer
+ *   before restarting the RAIL timer.
+ *
+ * @return Status code indicating success of the function call.
+ *
+ * If timer sync was enabled by \ref RAIL_ConfigSleep, synchronize the RAIL
+ * timer using an alternate timer. Otherwise, add elapsedTime to the RAIL
+ * timer.
+ */
+RAIL_Status_t RAIL_Wake(RAIL_Time_t elapsedTime);
+
+/** @} */ // end of group System_Timing
+
+/******************************************************************************
+ * Events
+ *****************************************************************************/
+/**
+ * @addtogroup Events
+ * @brief APIs related to events
+ * @{
+ */
+
+/**
+ * Configures radio events.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] mask Bitmask containing which events should be modified.
+ * @param[in] events Define which events should trigger \ref RAIL_Config_t::eventsCallback
+ *   The full list of available callbacks can be found by looking at the
+ *   RAIL_EVENT_* set of defines.
+ * @return Status code indicating success of the function call.
+ *
+ * Sets up which radio interrupts generate a RAIL event. The full list of
+ * options is in \ref RAIL_Events_t.
+ */
+RAIL_Status_t RAIL_ConfigEvents(RAIL_Handle_t railHandle,
+                                RAIL_Events_t mask,
+                                RAIL_Events_t events);
+
+/** @} */ // end of group Events
+
+/******************************************************************************
+ * Data Management
+ *****************************************************************************/
+/// @addtogroup Data_Management Data Management
+/// @brief Data management functions
+///
+/// These functions allow the application to choose how data is presented to the
+/// application. RAIL provides data in a packet-based method or in a FIFO-based
+/// method which gives the application more granularity and responsibility in
+/// managing transmit and receive data, and allows packet sizes larger than
+/// the RX or TX FIFO buffers.
+///
+/// The application can configure RAIL data management through
+/// RAIL_ConfigData().
+/// This function allows the application to specify the type of radio data
+/// (\ref RAIL_TxDataSource_t and \ref RAIL_RxDataSource_t) and the method of
+/// interacting with data (\ref RAIL_DataMethod_t). By default, RAIL
+/// configures TX and RX both with packet data source and packet mode.
+///
+/// In packet based data management:
+///   - Packet lengths are determined from the Radio Configurator configuration
+///     or after receive packet completion using RAIL_GetRxPacketInfo().
+///   - Load transmit data with RAIL_WriteTxFifo().
+///   - Received packet data is made available on successful packet completion
+///     via \ref RAIL_Config_t::eventsCallback with \ref RAIL_EVENT_RX_PACKET_RECEIVED
+///     which can then use RAIL_GetRxPacketInfo() and RAIL_GetRxPacketDetails() to
+///     access packet information, and RAIL_PeekRxPacket() to access packet
+///     data.
+///   - Filtered, Aborted, or FrameError received packet data is automatically
+///     dropped without the application needing to worry about consuming it.
+///     The application can choose to not even be bothered with the events
+///     related to such packets: \ref RAIL_EVENT_RX_ADDRESS_FILTERED,
+///     \ref RAIL_EVENT_RX_PACKET_ABORTED, or \ref RAIL_EVENT_RX_FRAME_ERROR.
+///
+/// In FIFO based data management:
+///   - Packet Lengths are determined from the Radio Configurator configuration
+///     or by application knowledge of packet payload structure.
+///   - Load transmit data with RAIL_WriteTxFifo() with reset set to false.
+///   - Received data can be retrieved prior to packet completion through
+///     RAIL_ReadRxFifo(), and is never dropped on Filtered, Aborted, or
+///     FrameError packets. The application should enable and handle these
+///     events so it can flush any packet data it's already retrieved.
+///   - After packet completion, remaining packet data for Filtered, Aborted,
+///     or FrameError packets can be either flushed automatically by RAIL
+///     or consumed by the application just like a successfully received packet,
+///     as determined from RAIL_GetRxPacketInfo(). RAIL_GetRxPacketDetails()
+///     provides packet detailed information only for successfully received
+///     packets.
+///   - Set the TX FIFO threshold through RAIL_SetTxFifoThreshold(). The
+///     \ref RAIL_Config_t::eventsCallback with \ref RAIL_EVENT_TX_FIFO_ALMOST_EMPTY
+///     will occur telling the application to load more TX packet data, if needed
+///     lest a \ref RAIL_EVENT_TX_UNDERFLOW event occurs.
+///   - Set the RX FIFO threshold through RAIL_SetRxFifoThreshold(). The
+///     \ref RAIL_Config_t::eventsCallback with \ref RAIL_EVENT_RX_FIFO_ALMOST_FULL
+///     will occur telling the application to consume some RX packet data lest a
+///     \ref RAIL_EVENT_RX_FIFO_OVERFLOW event occurs.
+///   - Get RX FIFO count information through
+///     RAIL_GetRxPacketInfo(\ref RAIL_RX_PACKET_HANDLE_NEWEST)
+///     (or RAIL_GetRxFifoBytesAvailable()).
+///   - Get TX FIFO count information through RAIL_GetTxFifoSpaceAvailable().
+///   - Reset RX and/or TX FIFOs with RAIL_ResetFifo().
+///
+/// When trying to determine an appropriate threshold, the application needs
+/// to know each FIFO's size. The receive FIFO is internal to RAIL and its
+/// size is 512 bytes. The receive FIFO is level-based in that the \ref
+/// RAIL_EVENT_RX_FIFO_ALMOST_FULL event will constantly pend if the threshold
+/// is exceeded. This normally means that inside this event's callback, the
+/// application should
+/// empty enough of the FIFO to go under the threshold. To defer reading the
+/// FIFO to main context, the application can disable or re-enable the receive
+/// FIFO threshold event using RAIL_ConfigEvents() with the mask
+/// \ref RAIL_EVENT_RX_FIFO_ALMOST_FULL.
+///
+/// The transmit FIFO is specified by the application and its actual size is
+/// the value returned from the most recent call to RAIL_SetTxFifo(),
+/// The transmit FIFO is edge-based in that it only provides the \ref
+/// RAIL_EVENT_TX_FIFO_ALMOST_EMPTY event once when the threshold is crossed
+/// in the emptying direction.
+///
+/// In FIFO mode, the FIFOs can store multiple packets. Depending on the
+/// traffic, RAIL can receive multiple packets into the receive FIFO before the
+/// application gets around to reading out the received data from the FIFO.
+/// RAIL_ReadRxFifo() won't allow reading beyond a packet boundary so
+/// process packet completion events promptly. Keep in mind that in FIFO mode,
+/// packet data already read from packets that are subsequently aborted,
+/// frameerror, or filtered should be flushed.
+///
+/// While RAIL defaults to packet mode, the application can explicitly
+/// initialize RAIL for packet mode in the following manner:
+/// @code{.c}
+/// static const RAIL_DataConfig_t railDataConfig = {
+///   .txSource = TX_PACKET_DATA,
+///   .rxSource = RX_PACKET_DATA,
+///   .txMethod = PACKET_MODE,
+///   .rxMethod = PACKET_MODE,
+/// };
+///
+/// status = RAIL_ConfigData(&railDataConfig);
+///
+/// // Events that can occur in Packet Mode:
+///    RAIL_EVENT_TX_PACKET_SENT
+///    RAIL_EVENT_RX_PACKET_RECEIVED
+/// and optionally (packet data automatically dropped):
+///    RAIL_EVENT_RX_ADDRESS_FILTERED
+///    RAIL_EVENT_RX_PACKET_ABORTED
+///    RAIL_EVENT_RX_FRAME_ERROR
+/// @endcode
+///
+/// Initializing RAIL for FIFO Mode requires a few more function calls:
+/// @code{.c}
+/// static const RAIL_DataConfig_t railDataConfig = {
+///   .txSource = TX_PACKET_DATA,
+///   .rxSource = RX_PACKET_DATA,
+///   .txMethod = FIFO_MODE,
+///   .rxMethod = FIFO_MODE,
+/// };
+///
+/// status = RAIL_ConfigData(&railDataConfig);
+///
+/// // Gets the size of the FIFOs.
+/// // The transmit and receive FIFOs are the same size
+/// uint16_t fifoSize = RAIL_GetTxFifoSpaceAvailable();
+///
+/// // Sets the transmit and receive FIFO thresholds.
+/// // For this example, set the threshold in the middle of each FIFO
+/// RAIL_SetRxFifoThreshold(fifoSize / 2);
+/// RAIL_SetTxFifoThreshold(fifoSize / 2);
+///
+/// // Events that can occur in FIFO mode:
+///    RAIL_EVENT_TX_FIFO_ALMOST_EMPTY
+///    RAIL_EVENT_TX_UNDERFLOW
+///    RAIL_EVENT_TXACK_UNDERFLOW
+///    RAIL_EVENT_TX_PACKET_SENT
+///    RAIL_EVENT_RX_FIFO_ALMOST_FULL
+///    RAIL_EVENT_RX_FIFO_OVERFLOW
+///    RAIL_EVENT_RX_ADDRESS_FILTERED
+///    RAIL_EVENT_RX_PACKET_ABORTED
+///    RAIL_EVENT_RX_FRAME_ERROR
+///    RAIL_EVENT_RX_PACKET_RECEIVED
+/// @endcode
+///
+/// On receive, an application can use multiple data sources that
+/// are only compatible with the FIFO method of data delivery. All that differs
+/// from the FIFO mode example above is the RAIL_DataConfig_t::rxSource setting.
+/// IQ data samples are taken at the hardware's oversample rate and the amount
+/// of data can easily overwhelm the CPU processing time. The sample rate
+/// depends on the chosen PHY, as determined by the data rate and the decimation
+/// chain. It is <b>not</b> recommended to use the IQ data source with sample
+/// rates above 300 k samples/second as the CPU might not be able to keep up
+/// with the data. Depending on the application and needed CPU bandwidth, slower
+/// data rates may be required.
+/// @code{.c}
+/// // IQ data is provided into the receive FIFO
+/// static const RAIL_DataConfig_t railDataConfig = {
+///   .txSource = TX_PACKET_DATA,
+///   .rxSource = RX_IQDATA_FILTLSB,
+///   .txMethod = FIFO_MODE,
+///   .rxMethod = FIFO_MODE,
+/// };
+///
+/// // When reading IQ data out of the FIFO, it comes in the following format:
+/// //------------------------------------
+/// // I[LSB] | I[MSB] | Q[LSB] | Q[MSB] |
+/// //------------------------------------
+/// @endcode
+///
+/// @note \ref RAIL_DataConfig_t.txMethod and \ref RAIL_DataConfig_t.rxMethod
+///   must have the same \ref RAIL_DataMethod_t configuration.
+///
+/// @warning Do not call RAIL_ReadRxFifo() function while in
+/// \ref RAIL_DataMethod_t::PACKET_MODE.
+/// @{
+
+/**
+ * RAIL data management configuration
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] dataConfig RAIL data configuration structure.
+ * @return Status code indicating success of the function call.
+ *
+ * This function configures how RAIL manages data. The application can
+ * configure RAIL to receive data in a packet-based or FIFO-based format.
+ * FIFO mode is necessary to support packets larger than the radio's
+ * FIFO buffers.
+ *
+ * With FIFO mode, the application sets appropriate FIFO thresholds via
+ * RAIL_SetTxFifoThreshold() and RAIL_SetRxFifoThreshold(), and then
+ * enables and handles the \ref RAIL_EVENT_TX_FIFO_ALMOST_EMPTY event
+ * callback (to feed more packet data via RAIL_WriteTxFifo() before the
+ * FIFO underflows), and the \ref RAIL_EVENT_RX_FIFO_ALMOST_FULL event
+ * callback (to consume packet data via RAIL_ReadRxFifo() before the
+ * RX FIFO overflows).
+ *
+ * When configuring TX or RX for FIFO mode, this function resets the configured
+ * FIFOs. When configuring TX or RX for Packet mode, this function will reset
+ * the corresponding FIFO thresholds such that they won't trigger the
+ * \ref RAIL_EVENT_RX_FIFO_ALMOST_FULL or \ref RAIL_EVENT_TX_FIFO_ALMOST_EMPTY
+ * events.
+ *
+ * When \ref RAIL_DataConfig_t.rxMethod is set to \ref
+ * RAIL_DataMethod_t.FIFO_MODE, the radio won't drop packet data of
+ * aborted or CRC error packets, but will present it to the application
+ * to deal with accordingly. On completion of such erroneous packets, the
+ * \ref RAIL_Config_t::eventsCallback with \ref RAIL_EVENT_RX_PACKET_ABORTED,
+ * \ref RAIL_EVENT_RX_FRAME_ERROR, or \ref RAIL_EVENT_RX_ADDRESS_FILTERED will
+ * tell the application it can drop any data it read via RAIL_ReadRxFifo() during reception.
+ * For CRC error packets when the \ref RAIL_RX_OPTION_IGNORE_CRC_ERRORS
+ * RX option is in effect, the application would check for that from the
+ * \ref RAIL_RxPacketStatus_t obtained by calling RAIL_GetRxPacketInfo().
+ * RAIL will automatically flush any remaining packet data after reporting
+ * one of these packet completion events, or the application can explicitly
+ * flush it by calling RAIL_ReleaseRxPacket().
+ *
+ * When \ref RAIL_DataConfig_t.rxMethod is set to \ref
+ * RAIL_DataMethod_t.PACKET_MODE, the radio will drop all packet data
+ * associated with aborted packets including those with CRC errors (unless
+ * configured to ignore CRC errors via the
+ * \ref RAIL_RX_OPTION_IGNORE_CRC_ERRORS RX option). The application will
+ * never be bothered to deal with packet data from such packets.
+ *
+ * In either mode, the application can set RX options as needed, and
+ * packet details are not available for aborted packets.
+ */
+RAIL_Status_t RAIL_ConfigData(RAIL_Handle_t railHandle,
+                              const RAIL_DataConfig_t *dataConfig);
+
+/**
+ * Writes data to the transmit FIFO.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] dataPtr Application provided pointer to transmit data
+ * @param[in] writeLength Number of bytes to write to the transmit FIFO
+ * @param[in] reset If true resets TX FIFO before writing the data.
+ * @return The number of bytes written to the transmit FIFO.
+ *
+ * This function reads data from the provided dataPtr and writes it to the TX
+ * FIFO. If the requested writeLength exceeds the current number of bytes open
+ * in the transmit FIFO, the function only writes until the transmit FIFO
+ * is full. The function returns the number of bytes written to the transmit
+ * FIFO, and returns zero if railHandle is NULL or if the TX FIFO is full.
+ *
+ * @note It is the protocol's packet configuration, as set up by the radio
+ *   configurator or via RAIL_SetFixedLength(), that determines how many
+ *   bytes of data are consumed from the TX FIFO for a successful transmit
+ *   operation, not the writeLength value passed in. If not enough data has
+ *   been put into the TX FIFO, a \ref RAIL_EVENT_TX_UNDERFLOW event will
+ *   occur. If too much data, the extra data will either become the first bytes
+ *   sent in a subsequent packet, or will be thrown away if the FIFO gets
+ *   reset prior to the next transmit. In general, the proper number of
+ *   packet bytes to put into the TX FIFO are all payload bytes except for
+ *   any CRC bytes which the packet configuration would cause to be sent
+ *   automatically.
+ *
+ * @note This function does not create a critical section but, depending on the
+ *   application, a critical section could be appropriate.
+ */
+uint16_t RAIL_WriteTxFifo(RAIL_Handle_t railHandle,
+                          const uint8_t *dataPtr,
+                          uint16_t writeLength,
+                          bool reset);
+
+/**
+ * Set the address of the TX FIFO, a circular buffer used for TX data
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in,out] addr Pointer to a read-write memory location in RAM
+ *   used as the TX FIFO. This memory must persist until the next call to
+ *   this function.
+ * @param[in] initLength Number of initial bytes already in the TX FIFO.
+ * @param[in] size Desired size of the TX FIFO in bytes.
+ * @return Returns the FIFO size in bytes that has been set.
+ *
+ * This function is used to set the memory location for the TX FIFO. This
+ * function must be called at least once before any transmit operations occur.
+ *
+ * The FIFO size can be determined by the return value of this function. The
+ * chosen size is determined based on the available FIFO sizes supported by
+ * the hardware. For more on supported FIFO sizes see chip-specific
+ * documentation, such as \ref efr32_main. The returned FIFO size will be the
+ * closest allowed size less than or equal to the passed in size parameter,
+ * unless the size parameter is smaller than the minimum FIFO size. If the
+ * initLength parameter is larger than the returned size, than the FIFO will be
+ * full up to its size.
+ *
+ * User may write to the custom memory location directly before calling this
+ * function, or use \ref RAIL_WriteTxFifo to write to the memory location after
+ * calling this function. For previously-written memory to be set in the TX
+ * FIFO, user must specify its initLength.
+ *
+ * This function reserves the block of RAM starting at txBufPtr with a length
+ * of the returned FIFO size. That RAM block is used internally as a circular
+ * buffer for the transmit FIFO. The FIFO must be able to hold the entire FIFO
+ * size. The caller must guarantee the custom FIFO remains intact and unchanged
+ * (except via calls to \ref RAIL_WriteTxFifo) until the next call to this
+ * function.
+ *
+ * @note It is the protocol's packet configuration, as set up by the radio
+ *   configurator or via RAIL_SetFixedLength(), that determines how many
+ *   bytes of data are consumed from the TX FIFO for a successful transmit
+ *   operation, not the initLength value passed in. If not enough data has
+ *   been put into the TX FIFO, a \ref RAIL_EVENT_TX_UNDERFLOW event will
+ *   occur. If too much data, the extra data will either become the first bytes
+ *   sent in a subsequent packet, or will be thrown away if the FIFO gets
+ *   reset prior to the next transmit. In general, the proper number of
+ *   packet bytes to put into the TX FIFO are all payload bytes except for
+ *   any CRC bytes which the packet configuration would cause to be sent
+ *   automatically.
+ */
+uint16_t RAIL_SetTxFifo(RAIL_Handle_t railHandle,
+                        uint8_t *addr,
+                        uint16_t initLength,
+                        uint16_t size);
+
+/**
+ * Reads packet data from RAIL's internal receive FIFO buffer.
+ * This function can be used in any RX mode, though in Packet
+ * mode it can only be used on the oldest unreleased packet whose
+ * RAIL_RxPacketStatus_t is among the RAIL_RX_PACKET_READY_ set.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[out] dataPtr An application-provided pointer to store data.
+ *   If NULL, the data is thrown away rather than copied out.
+ * @param[in] readLength A number of packet bytes to read from the FIFO.
+ * @return The number of packet bytes read from the receive FIFO.
+ *
+ * This function reads packet data from the head of receive FIFO and
+ * writes it to the provided dataPtr. It does not permit reading more
+ * data than is available in the FIFO, nor does it permit reading more
+ * data than remains in the oldest unreleased packet.
+ *
+ * Because this function does not have a critical section, either use it
+ * only in one context or make sure function calls are protected to prevent
+ * buffer corruption.
+ *
+ * @note When reading data from an arriving packet that is not yet complete
+ *   keep in mind its data is highly suspect because it has not yet passed
+ *   any CRC integrity checking. Also note the packet could be aborted,
+ *   cancelled, or fail momentarily, invalidating its data in Packet mode.
+ *   Furthermore, there is a small chance towards the end of packet reception
+ *   that the RX FIFO could include not only packet data received so far,
+ *   but also some raw radio-appended info detail bytes that RAIL's
+ *   packet-completion processing will subsequently deal with. It's up to the
+ *   application to know its packet format well enough to avoid reading this
+ *   info as it will corrupt the packet's details and possibly corrupt the
+ *   RX FIFO buffer.
+ */
+uint16_t RAIL_ReadRxFifo(RAIL_Handle_t railHandle,
+                         uint8_t *dataPtr,
+                         uint16_t readLength);
+
+/**
+ * Configures the RAIL transmit FIFO almost empty threshold.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] txThreshold The threshold once fallen under will fire \ref RAIL_Config_t::eventsCallback
+ *   with \ref RAIL_EVENT_TX_FIFO_ALMOST_EMPTY set.
+ * @return Configured transmit FIFO threshold value.
+ *
+ * This function configures the threshold for the transmit FIFO. When the count
+ * of the transmit FIFO is less than the configured threshold, \ref RAIL_Config_t::eventsCallback
+ * will fire with \ref RAIL_EVENT_TX_FIFO_ALMOST_EMPTY set. A value of
+ * 0 is invalid and will not change the current configuration.
+ */
+uint16_t RAIL_SetTxFifoThreshold(RAIL_Handle_t railHandle,
+                                 uint16_t txThreshold);
+
+/**
+ * Configures the RAIL receive FIFO almost full threshold.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] rxThreshold The threshold once exceeded will fire \ref RAIL_Config_t::eventsCallback
+ *   with \ref RAIL_EVENT_RX_FIFO_ALMOST_FULL set.
+ * @return Configured receive FIFO threshold value.
+ *
+ * This function configures the threshold for the receive FIFO. When the count
+ * of the receive FIFO is greater than the configured threshold,
+ * \ref RAIL_Config_t::eventsCallback will fire with
+ * \ref RAIL_EVENT_RX_FIFO_ALMOST_FULL set. A value of 0xFFFF is invalid and
+ * will not change the current configuration. Depending on the size of the
+ * receive FIFO hardware, the maximum value can vary. If the rxThreshold value
+ * exceeds the capability of the hardware, the RX threshold will be configured
+ * so that it fires only when the FIFO is one byte away from being full.
+ */
+uint16_t RAIL_SetRxFifoThreshold(RAIL_Handle_t railHandle,
+                                 uint16_t rxThreshold);
+
+/**
+ * Gets the RAIL transmit FIFO almost empty threshold value.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Configured TX Threshold value.
+ *
+ * Retrieves the configured TX threshold value.
+ */
+uint16_t RAIL_GetTxFifoThreshold(RAIL_Handle_t railHandle);
+
+/**
+ * Gets the RAIL receive FIFO almost full threshold value.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Configured RX Threshold value.
+ *
+ * Retrieves the configured RX threshold value.
+ */
+uint16_t RAIL_GetRxFifoThreshold(RAIL_Handle_t railHandle);
+
+/**
+ * Resets the RAIL FIFOs.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] txFifo If true, reset the transmit FIFO.
+ * @param[in] rxFifo If true, reset the receive FIFO.
+ * @return void.
+ *
+ * This function can reset each FIFO. The application should not reset the RX
+ * FIFO while receiving a frame.
+ */
+void RAIL_ResetFifo(RAIL_Handle_t railHandle, bool txFifo, bool rxFifo);
+
+/**
+ * Get the number of bytes available in the receive FIFO.
+ * This function should only be used in RX FIFO mode; apps should
+ * probably be using RAIL_GetRxPacketInfo() instead.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Number of raw bytes in the receive FIFO.
+ *
+ * @note The number of bytes returned may not just reflect the current
+ *   packet's data but could also include raw appended info bytes added
+ *   after successful packet reception and bytes from subsequently received
+ *   packets. It is up to the app to never try to consume more than the
+ *   packet's actual data when using the value returned here in a subsequent
+ *   call to RAIL_ReadRxFifo(), otherwise the Rx buffer will be corrupted.
+ */
+uint16_t RAIL_GetRxFifoBytesAvailable(RAIL_Handle_t railHandle);
+
+/**
+ * Gets the number of bytes open in the transmit FIFO.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Number of bytes open in the transmit FIFO.
+ *
+ * Gets the number of bytes open in the transmit FIFO.
+ */
+uint16_t RAIL_GetTxFifoSpaceAvailable(RAIL_Handle_t railHandle);
+
+/** @} */ // end of group Data_Management
+
+/******************************************************************************
+ * State Transitions
+ *****************************************************************************/
+/**
+ * @addtogroup State_Transitions State Transitions
+ * @{
+ */
+
+/**
+ * Configures RAIL automatic state transitions after RX.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] transitions The state transitions to apply after reception.
+ * @return Status code indicating success of the function call.
+ *
+ * This function fails if unsupported transitions are passed in or if the
+ * radio is currently in the RX state. Success can transition to TX, RX, or
+ * IDLE, while error can transition to RX or IDLE.
+ */
+RAIL_Status_t RAIL_SetRxTransitions(RAIL_Handle_t railHandle,
+                                    const RAIL_StateTransitions_t *transitions);
+
+/**
+ * Configures RAIL automatic state transitions after TX.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] transitions The state transitions to apply after transmission.
+ * @return Status code indicating a success of the function call.
+ *
+ * This function fails if unsupported transitions are passed in or if the
+ * radio is currently in the TX state. Success and error can each transition
+ * to RX or IDLE.
+ */
+RAIL_Status_t RAIL_SetTxTransitions(RAIL_Handle_t railHandle,
+                                    const RAIL_StateTransitions_t *transitions);
+
+/**
+ * Configures RAIL automatic state transition timing.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in,out] timings The timings used to configure the RAIL state
+ *   machine. This structure is overwritten with the actual times that were
+ *   set, if an input timing is invalid.
+ * @return Status code indicating a success of the function call.
+ *
+ * The timings given are close to the actual transition time. However,
+ * a still uncharacterized software overhead occurs. Also, timings are not
+ * always adhered to when using an automatic transition after an error, due to
+ * the cleanup required to recover from the error.
+ */
+RAIL_Status_t RAIL_SetStateTiming(RAIL_Handle_t railHandle,
+                                  RAIL_StateTiming_t *timings);
+
+/**
+ * Places the radio into an idle state.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] mode The method for shutting down the radio.
+ * @param[in] wait Whether this function should wait for the radio to reach
+ *   idle before returning.
+ * @return void.
+ *
+ * This function is used to remove the radio from TX and RX states. How these
+ * states are left is defined by the mode parameter.
+ *
+ * In multiprotocol, this API will also cause the radio to be yielded so that
+ * other tasks can be run. See \ref rail_radio_scheduler_yield for more details.
+ */
+void RAIL_Idle(RAIL_Handle_t railHandle,
+               RAIL_IdleMode_t mode,
+               bool wait);
+
+/**
+ * Gets the current radio state.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return An enumeration for the current radio state.
+ *
+ * Returns the state of the radio as a bitmask containing:
+ * \ref RAIL_RF_STATE_IDLE, \ref RAIL_RF_STATE_RX, \ref RAIL_RF_STATE_TX,
+ * and \ref RAIL_RF_STATE_ACTIVE. \ref RAIL_RF_STATE_IDLE, \ref
+ * RAIL_RF_STATE_RX, and \ref RAIL_RF_STATE_TX bits are mutually exclusive.
+ * The radio can transition through intermediate states,
+ * which are not reported but are instead bucketed into the state
+ * being transitioned into. For example, when the transmitter is in the
+ * process of shutting down, this function will return TX, as if the
+ * shutdown process hadn't started yet.
+ */
+RAIL_RadioState_t RAIL_GetRadioState(RAIL_Handle_t railHandle);
+
+/** @} */ // end of group State_Transitions
+
+/******************************************************************************
+ * Transmit
+ *****************************************************************************/
+/**
+ * @addtogroup Transmit
+ * @brief APIs related to transmitting data packets
+ * @{
+ */
+
+/// @addtogroup PA Power Amplifier (PA)
+/// @brief APIs for interacting with one of the on chip PAs.
+///
+/// These APIs let you configure the on chip PA to get the appropriate output
+/// power.
+///
+/// There a few types of functions that are found here
+///   1) Configuration functions: These functions set and get configuration
+///      for the PA. In this case, "configuration" refers to a) indicating
+///      which PA to use, b) the voltage supplied by your board to the PA,
+///      and c) the ramp time over which to ramp the PA up to its full
+///      power.
+///   2) Power-setting functions: These functions consume the actual
+///      values written to the PA registers, and write them appropriately.
+///      These values are referred to as "(raw) power levels". The range of
+///      acceptable values for these functions depends on which PA is
+///      currently active. The higher the power level set, the higher
+///      the dBm power actually output by the chip. However, the mapping
+///      between dBm and these power levels can vary greatly between
+///      modules/boards.
+///   3) Conversion functions: These functions do the work of converting
+///      between the "power levels" discussed previously and the actual
+///      dBm values output by the chip. Continue reading for more details
+///      on how to handle unit conversion.
+///
+/// The accuracy of the chip output power in dBm will vary from application to
+/// to application. For some protocols or channels the protocol itself or
+/// legal limitations will require applications to know exactly what power
+/// they're transmitting at, in dBm. Other applications will not have
+/// these restrictions, and users will simply find some power level(s)
+/// that fit their criteria for the trade-off between radio range and
+/// power savings, regardless of what dBm power that maps to.
+///
+/// In order to provide a solution that fits all these applications,
+/// Silicon Labs has provided a great deal of flexibility in
+/// \ref RAIL_ConvertRawToDbm and \ref RAIL_ConvertDbmToRaw, the two functions
+/// that do the conversion between the dBm power and the raw power levels.
+/// Those levels of customizability are outlined below
+///  1) No customizability needed: for a given dBm value, the result
+///     of RAIL_ConvertDbmToRaw provides an appropriate
+///     raw power level that, when written to the registers via
+///     RAIL_SetPowerLevel, causes the chip to actually output at that
+///     dBm power. In this case, no action is needed by the user,
+///     the WEAK versions of the conversion functions can be used,
+///     and the default include paths in pa_conversions_efr32.h can
+///     be used.
+///  2) The mapping of power level to dBm is not good, but the
+///     level of precision is sufficient: In pa_conversions_efr32.c
+///     the WEAK versions of the conversion functions work by using
+///     8-segment piecewise linear curves to convert between dBm
+///     and power levels for PA's with hundreds of power levels
+///     and simple mapping tables for use with PA's with only a few
+///     levels. If this method is sufficiently precise, but the mapping
+///     between power levels and dBm is wrong, Silicon Labs recommends
+///     copying pa_curves_efr32.h into a new file, updating the segments
+///     to form a better fit (_DCDC_CURVES or _VBAT_CURVES defines), and
+///     then adding the RAIL_PA_CURVES define to your build with the path
+///     to the new file.
+///  3) A different level of precision is needed and the fit is bad:
+///     If the piecewise-linear line segment fit is not appropriate for
+///     your solution, the functions in pa_conversions_efr32.c can be
+///     totally rewritten, as long as RAIL_ConvertDbmToRaw and
+///     RAIL_ConvertRawToDbm have the same signatures. It is completely
+///     acceptable to re-write these in a way that makes the
+///     pa_curves_efr32.h and pa_curve_types_efr32.h files referenced in
+///     pa_conversions_efr32.h unnecessary. Those files are needed solely
+///     for the conversion methods that Silicon Labs provides.
+///  4) dBm values are not necessary: If your application does not require
+///     dBm values at all, Silicon Labs recommends overwriting
+///     RAIL_ConvertDbmToRaw and RAIL_ConvertRawToDbm with smaller functions
+///     (i.e. return 0 or whatever was input). These functions are called
+///     from within the RAIL library, so they can never be deadstripped,
+///     but making them as small as possible is the best way to reduce code
+///     size. From there, you can simply call RAIL_SetTxPower, without
+///     converting from a dBm value. If you never want the library to coerce the
+///     power based on channels, RAIL_ConvertRawToDbm should be overwritten
+///     to always return 0 and RAIL_ConvertDbmToRaw should be overwritten to
+///     always return 255.
+///
+/// The following is example code on how to initialize your PA
+/// @code{.c}
+///
+/// #include "pa_conversions_efr32.h"
+///
+/// // Helper macro to declare all the curve structures used by the Silicon Labs-provided
+/// // conversion functions
+/// RAIL_DECLARE_TX_POWER_VBAT_CURVES(piecewiseSegments, curvesSg, curves24Hp, curves24Lp);
+///
+/// // Put the variables declared above into the appropriate structure
+/// RAIL_TxPowerCurvesConfig_t txPowerCurvesConfig = { curves24Hp, curvesSg, curves24Lp, piecewiseSegments };
+///
+/// // In the Silicon Labs implementation, the user is required to save those curves into
+/// // to be referenced when the conversion functions are called
+/// RAIL_InitTxPowerCurves(&txPowerCurvesConfig);
+///
+/// // Declare the structure used to configure the PA
+/// RAIL_TxPowerConfig_t txPowerConfig = { RAIL_TX_POWER_MODE_2P4_HP, 3300, 10 };
+///
+/// // And then init the PA. Here, it is assumed that 'railHandle' is a valid RAIL_Handle_t
+/// // that has already been initialized.
+/// RAIL_ConfigTxPower(railHandle, &txPowerConfig);
+///
+/// // Pick a dBm power to use: 100 deci-dBm = 10 dBm. See docs on RAIL_TxPower_t
+/// RAIL_TxPower_t power = 100;
+///
+/// // Get the config written by RAIL_ConfigTxPower to confirm what was actually set
+/// RAIL_GetTxPowerConfig(railHandle, &txPowerConfig);
+///
+/// // RAIL_ConvertDbmToRaw will be the weak version provided by Silicon Labs
+/// // by default, or the customer version, if overwritten.
+/// RAIL_TxPowerLevel_t powerLevel = RAIL_ConvertDbmToRaw(railHandle,
+///                                                       txPowerConfig.mode,
+///                                                       power);
+///
+/// // Write the result of the conversion to the PA power registers in terms
+/// // of raw power levels
+/// RAIL_SetTxPower(railHandle, powerLevel);
+/// @endcode
+///
+/// @note: all the lines following "RAIL_TxPower_t power = 100;" can be
+/// replaced with the provided utility function, \ref RAIL_SetTxPowerDbm.
+/// However, the full example here was provided for clarity. See the
+/// documentation on \ref RAIL_SetTxPowerDbm for more details.
+///
+/// @{
+
+/**
+ * Initialize TxPower Settings
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] config Instance which contains desired initial settings
+ *   for the TX amplifier.
+ * @return RAIL_Status_t indicating success or an error.
+ *
+ * These settings include the selection between the multiple TX amplifiers,
+ * voltage supplied to the TX power amplifier, and ramp times. This must
+ * be called before any transmit occurs, or \ref RAIL_SetTxPower is called.
+ * While we recommend always calling this function during initialization,
+ * it can also be called anytime if these settings need to change to adapt
+ * to a different application/protocol. This API will also reset TX Power to
+ * its minimum value, so \ref RAIL_SetTxPower must be called after calling this.
+ *
+ * At times, certain combinations of configurations cannot be achieved.
+ * This API attempts to get as close as possible to the requested settings. The
+ * following "RAIL_Get..." API can be used to determine what values were set.
+ */
+RAIL_Status_t RAIL_ConfigTxPower(RAIL_Handle_t railHandle,
+                                 const RAIL_TxPowerConfig_t *config);
+
+/**
+ * Get the TX power settings currently used in the amplifier
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[out] config Pointer to memory allocated to hold current TxPower
+ *   configuration structure.
+ * @return RAIL_TxPowerConfig_t RAIL status variable indicating whether
+ *   or not the get was successful.
+ *
+ * Note, this API does not return the current TX power - that is separately
+ * managed by the \ref RAIL_GetTxPower/\ref RAIL_SetTxPower API's. This API
+ * should be used to know exactly which values were set as a result of
+ * \ref RAIL_ConfigTxPower.
+ */
+RAIL_Status_t RAIL_GetTxPowerConfig(RAIL_Handle_t railHandle,
+                                    RAIL_TxPowerConfig_t *config);
+
+/**
+ * Set the TX power in units of raw units (see \ref rail_chip_specific.h for
+ * value ranges).
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] powerLevel Power in chip specific \ref RAIL_TxPowerLevel_t units.
+ * @return RAIL_Status_t indicating success or an error.
+ *
+ * In order to convert between decibels and the integer values that the
+ * registers take, call \ref RAIL_ConvertDbmToRaw. Silicon Labs provides
+ * a weak version of this function which works well with our boards. However
+ * a customer using his/her own custom board will want to characterize
+ * chip operation on that board and override the function to do the conversion
+ * appropriately from the desired dB values to raw integer values.
+ *
+ * Depending on the configuration used in \ref RAIL_ConfigTxPower, not all
+ * power levels are achievable. This API will get as close as possible to
+ * the desired power without exceeding it, and calling \ref RAIL_GetTxPower is
+ * the only way to know the exact value written.
+ *
+ * Calling this function before configuring the PA (i.e. before a successful
+ * call to \ref RAIL_ConfigTxPower) will cause an error to be returned.
+ */
+RAIL_Status_t RAIL_SetTxPower(RAIL_Handle_t railHandle,
+                              RAIL_TxPowerLevel_t powerLevel);
+
+/**
+ * Returns the current power setting of the PA.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return The chip specific \ref RAIL_TxPowerLevel_t value of the current
+ * transmit power.
+ *
+ * This API returns the raw value that was actually set by \ref RAIL_SetTxPower.
+ * Silicon Labs provides a weak version of \ref RAIL_ConvertRawToDbm that works
+ * with our boards to convert these raw values into actual output dBm values.
+ * However, if a customer is using a custom board, we recommend that he/she re-
+ * characterizes the relationship between raw and decibel values, and overrides
+ * the provided function with one more that more accurately reflects the actual
+ * relationship.
+ *
+ * Calling this function before configuring the PA (i.e. before a successful
+ * call to \ref RAIL_ConfigTxPower) will cause an error to be returned
+ * (RAIL_TX_POWER_LEVEL_INVALID).
+ */
+RAIL_TxPowerLevel_t RAIL_GetTxPower(RAIL_Handle_t railHandle);
+
+/**
+ * Converts raw values written to registers to decibel value (in units of
+ * deci-dBm).
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] mode PA mode for which to do the conversion.
+ * @param[in] powerLevel Raw amplifier register value to be converted to
+ *   deci-dBm.
+ * @return raw amplifier values converted to units of deci-dBm.
+ *
+ * A weak version of this function is provided by Silicon Labs that is tuned
+ * to provide accurate values for our boards. If the customer intends to use
+ * a custom board, the relationship between what is written to the Tx amplifier
+ * and the actual output power should be re-characterized and implemented in an
+ * overriding version of \ref RAIL_ConvertRawToDbm. For minimum code size and
+ * best speed use only raw values with the TxPower API and override this
+ * function with a smaller function. In the weak version provided with the RAIL
+ * library, railHandle is only used to indicate to the user from where the
+ * function was called, so it is OK to use either a real protocol handle, or one
+ * of the chip specific ones, such as \ref RAIL_EFR32_HANDLE.
+ *
+ * Although the definitions of this function may change, the signature
+ * must be as declared here.
+ */
+RAIL_TxPower_t RAIL_ConvertRawToDbm(RAIL_Handle_t railHandle,
+                                    RAIL_TxPowerMode_t mode,
+                                    RAIL_TxPowerLevel_t powerLevel);
+
+/**
+ * Converts the desired decibel value (in units of deci-dBm)
+ * to raw integer values used by the TX amplifier registers.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] mode PA mode for which to do the conversion.
+ * @param[in] power Desired dBm values in units of deci-dBm.
+ * @return deci-dBm value converted to a raw
+ *   integer value that can be used directly with \ref RAIL_SetTxPower.
+ *
+ * A weak version of this function is provided by Silicon Labs that is tuned
+ * to provide accurate values for our boards. If the customer intends to use
+ * a custom board, the relationship between what is written to the TX amplifier
+ * and the actual output power should be characterized and implemented in an
+ * overriding version of \ref RAIL_ConvertDbmToRaw. For minimum code size and
+ * best speed use only raw values with the TxPower API and override this
+ * function with a smaller function. In the weak version provided with the RAIL
+ * library, railHandle is only used to indicate to the user from where the
+ * function was called, so it is OK to use either a real protocol handle, or one
+ * of the chip specific ones, such as \ref RAIL_EFR32_HANDLE.
+ *
+ * Although the definitions of this function may change, the signature
+ * must be as declared here.
+ *
+ * @note This function is called from within the RAIL library for
+ *   comparison between channel limitations and current power. It will
+ *   throw an assert if you haven't called RAIL_InitTxPowerCurves
+ *   which initializes the mappings between raw power levels and
+ *   actual dBm powers. To avoid this assert, ensure that the
+ *   maxPower of all channel config entries is \ref RAIL_TX_POWER_MAX
+ *   or above, or override this function to always return 255.
+ */
+RAIL_TxPowerLevel_t RAIL_ConvertDbmToRaw(RAIL_Handle_t railHandle,
+                                         RAIL_TxPowerMode_t mode,
+                                         RAIL_TxPower_t power);
+
+/** @} */ // end of group PA
+
+/// Sets the TX power in terms of deci-dBm instead of raw power level.
+///
+/// @param[in] railHandle A RAIL instance handle.
+/// @param[in] power Desired deci-dBm power to be set.
+/// @return RAIL Status variable indicate whether setting the
+///   power was successful.
+///
+/// This is a utility function crafted for user convenience. Normally, to set TX
+/// power in dBm, the user would have to do the following:
+///
+/// @code{.c}
+/// RAIL_TxPower_t power = 100; // 100 deci-dBm, 10 dBm
+/// RAIL_TxPowerConfig_t txPowerConfig;
+/// RAIL_GetTxPowerConfig(railHandle, &txPowerConfig);
+/// // RAIL_ConvertDbmToRaw will be the weak version provided by Silicon Labs
+/// // by default, or the customer version, if overwritten.
+/// RAIL_TxPowerLevel_t powerLevel = RAIL_ConvertDbmToRaw(railHandle,
+///                                                       txPowerConfig.mode,
+///                                                       power);
+/// RAIL_SetTxPower(railHandle, powerLevel);
+/// @endcode
+///
+/// This function wraps all those calls in a single function with power passed in
+/// as a parameter.
+///
+RAIL_Status_t RAIL_SetTxPowerDbm(RAIL_Handle_t railHandle,
+                                 RAIL_TxPower_t power);
+
+/// Gets the TX power in terms of deci-dBm instead of raw power level.
+///
+/// @param[in] railHandle A RAIL instance handle.
+/// @return The current output power in deci-dBm
+///
+/// This is a utility function crafted for user convenience. Normally, to get TX
+/// power in dBm, the user would have to do the following:
+///
+/// @code{.c}
+/// RAIL_TxPowerLevel_t powerLevel = RAIL_GetTxPower(railHandle);
+/// RAIL_TxPowerConfig_t txPowerConfig;
+/// RAIL_GetTxPowerConfig(railHandle, &txPowerConfig);
+/// // RAIL_ConvertRawToDbm will be the weak version provided by Silicon Labs
+/// // by default, or the customer version, if overwritten.
+/// RAIL_TxPower_t power = RAIL_ConvertRawToDbm(railHandle,
+///                                             txPowerConfig.mode,
+///                                             power);
+/// return power;
+/// @endcode
+///
+/// This function wraps all those calls in a single function with power returned
+/// as the result.
+///
+RAIL_TxPower_t RAIL_GetTxPowerDbm(RAIL_Handle_t railHandle);
+
+/**
+ * Start a non-blocking transmit
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel Define the channel to transmit on.
+ * @param[in] options TX options to be applied to this transmit only.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this transmit appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call. If successfully
+ *   initiated, transmit completion or failure will be reported by a later
+ *   \ref RAIL_Config_t::eventsCallback with the appropriate \ref RAIL_Events_t.
+ *
+ * Will begin transmission of the payload previously loaded via
+ * \ref RAIL_WriteTxFifo() immediately, or right after a packet currently being
+ * received is completed.
+ *
+ * Returns an error if a previous transmit is still in progress.
+ * If changing channels, any ongoing packet reception is aborted.
+ *
+ * In multiprotocol you must ensure that you properly yield the radio after this
+ * operation completes. See \ref rail_radio_scheduler_yield for more details.
+ */
+RAIL_Status_t RAIL_StartTx(RAIL_Handle_t railHandle,
+                           uint16_t channel,
+                           RAIL_TxOptions_t options,
+                           const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Send a packet on a schedule, instead of immediately
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel Define the channel to transmit on.
+ * @param[in] options TX options to be applied to this transmit only.
+ * @param[in] config A pointer to the \ref RAIL_ScheduleTxConfig_t
+ *   structure containing when the transmit should occur.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this transmit appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call. If successfully
+ *   initiated, a transmit completion or failure will be reported by a later
+ *   \ref RAIL_Config_t::eventsCallback with the appropriate \ref RAIL_Events_t.
+ *
+ * Will begin transmission of the payload previously loaded via
+ * \ref RAIL_WriteTxFifo() at the scheduled time.
+ * The time (in microseconds) as well as whether that time is absolute or
+ * relative, is specified using the \ref RAIL_ScheduleTxConfig_t structure.
+ * Also specified in this structure is what to do if a scheduled transmit
+ * fires in the midst of receiving a packet.
+ *
+ * Returns an error if a previous transmit is still in progress.
+ * If changing channels, any ongoing packet reception is aborted.
+ *
+ * In multiprotocol you must ensure that you properly yield the radio after this
+ * operation completes. See \ref rail_radio_scheduler_yield for more details.
+ */
+RAIL_Status_t RAIL_StartScheduledTx(RAIL_Handle_t railHandle,
+                                    uint16_t channel,
+                                    RAIL_TxOptions_t options,
+                                    const RAIL_ScheduleTxConfig_t *config,
+                                    const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Start a non-blocking Transmit using CSMA
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel Define the channel to transmit on.
+ * @param[in] options TX options to be applied to this transmit only.
+ * @param[in] csmaConfig A pointer to the RAIL_CsmaConfig_t structure
+ *   describing the CSMA parameters to use for this transmit.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this transmit appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call. If successfully
+ *   initiated, a transmit completion or failure will be reported by a later
+ *   \ref RAIL_Config_t::eventsCallback with the appropriate \ref RAIL_Events_t.
+ *
+ * First performs the Carrier Sense Multiple Access (CSMA) algorithm and if
+ * the channel is deemed clear (RSSI below the specified threshold) it will
+ * commence transmission of the payload previously loaded via
+ * RAIL_WriteTxFifo().
+ * Packets can be received during CSMA backoff periods if receive is active
+ * throughout the CSMA process. This will happen either by starting the CSMA
+ * process while receive is already active, or if the csmaBackoff time in
+ * the \ref RAIL_CsmaConfig_t is less than the idleToRx time (set by
+ * RAIL_SetStateTiming()). If the csmaBackoff time is greater than the
+ * idleToRx time, then receive will only be active during CSMA's clear channel
+ * assessments.
+ *
+ * If the CSMA algorithm deems the channel busy, the \ref RAIL_Config_t::eventsCallback
+ * occurs with \ref RAIL_EVENT_TX_CHANNEL_BUSY, and the contents
+ * of the TX FIFO remain intact, untouched.
+ *
+ * Returns an error if a previous transmit is still in progress.
+ * If changing channels, any ongoing packet reception is aborted.
+ *
+ * In multiprotocol you must ensure that you properly yield the radio after this
+ * operation completes. See \ref rail_radio_scheduler_yield for more details.
+ */
+RAIL_Status_t RAIL_StartCcaCsmaTx(RAIL_Handle_t railHandle,
+                                  uint16_t channel,
+                                  RAIL_TxOptions_t options,
+                                  const RAIL_CsmaConfig_t *csmaConfig,
+                                  const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Start a non-blocking Transmit using LBT
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel Define the channel to transmit on.
+ * @param[in] options TX options to be applied to this transmit only.
+ * @param[in] lbtConfig A pointer to the RAIL_LbtConfig_t structure
+ *   describing the LBT parameters to use for this transmit.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this transmit appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call. If successfully
+ *   initiated, a transmit completion or failure will be reported by a later
+ *   \ref RAIL_Config_t::eventsCallback with the appropriate \ref RAIL_Events_t.
+ *
+ * First performs the Listen Before Talk (LBT) algorithm and if the channel
+ * is deemed clear (RSSI below the specified threshold) it will commence
+ * transmission of the payload previously loaded via RAIL_WriteTxFifo().
+ * Packets can be received during LBT backoff periods if receive is active
+ * throughout the LBT process. This will happen either by starting the LBT
+ * process while receive is already active, or if the lbtBackoff time in
+ * the \ref RAIL_LbtConfig_t is less than the idleToRx time (set by
+ * RAIL_SetStateTiming()). If the lbtBackoff time is greater than the
+ * idleToRx time, then receive will only be active during LBT's clear channel
+ * assessments.
+ *
+ * If the LBT algorithm deems the channel busy, the \ref RAIL_Config_t::eventsCallback occurs with
+ * \ref RAIL_EVENT_TX_CHANNEL_BUSY, and the contents
+ * of the TX FIFO remain intact, untouched.
+ *
+ * Returns an error if a previous transmit is still in progress.
+ * If changing channels, any ongoing packet reception is aborted.
+ *
+ * In multiprotocol you must ensure that you properly yield the radio after this
+ * operation completes. See \ref rail_radio_scheduler_yield for more details.
+ */
+RAIL_Status_t RAIL_StartCcaLbtTx(RAIL_Handle_t railHandle,
+                                 uint16_t channel,
+                                 RAIL_TxOptions_t options,
+                                 const RAIL_LbtConfig_t *lbtConfig,
+                                 const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Sets the CCA threshold in dBm
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] ccaThresholdDbm The CCA threshold in dBm.
+ * @return Status code indicating success of the function call.
+ *
+ * Unlike RAIL_StartCcaCsmaTx() or RAIL_StartCcaLbtTx(), which can cause a
+ * transmit, this function only modifies the CCA threshold. A possible
+ * use case for this function is to set the CCA threshold to invalid RSSI
+ * of -128 which blocks transmission by preventing clear channel assessments
+ * from succeeding.
+ */
+RAIL_Status_t RAIL_SetCcaThreshold(RAIL_Handle_t railHandle,
+                                   int8_t ccaThresholdDbm);
+
+/**
+ * Gets detailed information about the last packet transmitted.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in,out] pPacketDetails An application-provided pointer to store
+ *   RAIL_TxPacketDetails_t corresponding to the transmit event.
+ *   The isAck and timeSent fields totalPacketBytes and timePosition
+ *   must be initialized prior to each call:
+ *   - isAck true to obtain details about the most recent ACK transmit,
+ *     false to obtain details about the most recent app-initiated transmit.
+ *   - totalPacketBytes with the total number of bytes of the transmitted
+ *     packet for RAIL to use when calculating the specified timestamp.
+ *     This should account for all bytes sent over the air after the
+ *     Preamble and Sync word(s), including CRC bytes.
+ *   - timePosition with a \ref RAIL_PacketTimePosition_t value specifying
+ *     the packet position to put in the timeSent field on return.
+ *     This field will also be updated with the actual position corresponding
+ *     to the timeSent value filled in.
+ * @return \ref RAIL_STATUS_NO_ERROR if pPacketDetails was filled in,
+ *   or an appropriate error code otherwise.
+ *
+ * This function can only be called from callback context for either
+ * \ref RAIL_EVENT_TX_PACKET_SENT or \ref RAIL_EVENT_TXACK_PACKET_SENT
+ * events.
+ */
+RAIL_Status_t RAIL_GetTxPacketDetails(RAIL_Handle_t railHandle,
+                                      RAIL_TxPacketDetails_t *pPacketDetails);
+/**
+ * Prevent the radio from starting a transmit.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] enable Enable/Disable TX hold off.
+ * @return void.
+ *
+ * Enable TX hold off to prevent the radio from starting any transmits.
+ * Disable TX hold off to allow the radio to transmit again.
+ * Attempting to transmit with the TX hold off enabled will result in
+ * \ref RAIL_EVENT_TX_BLOCKED and/or \ref RAIL_EVENT_TXACK_BLOCKED
+ * events.
+ *
+ * @note This function does not affect a transmit that has already started.
+ *   To stop an already-started transmission, use RAIL_Idle() with
+ *   \ref RAIL_IDLE_ABORT.
+ */
+void RAIL_EnableTxHoldOff(RAIL_Handle_t railHandle, bool enable);
+
+/**
+ * Check whether or not TX hold off is enabled.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Returns true if TX hold off is enabled, false otherwise.
+ *
+ * TX hold off can be enabled/disabled using \ref RAIL_EnableTxHoldOff.
+ * Attempting to transmit with the TX hold off enabled will block the
+ * transmission and result in \ref RAIL_EVENT_TX_BLOCKED
+ * and/or \ref RAIL_EVENT_TXACK_BLOCKED events.
+ */
+bool RAIL_IsTxHoldOffEnabled(RAIL_Handle_t railHandle);
+
+/** @} */ // end of group Transmit
+
+/******************************************************************************
+ * Receive
+ *****************************************************************************/
+/**
+ * @addtogroup Receive
+ * @brief APIs related to packet receive
+ * @{
+ */
+
+/**
+ * Configures receive options.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] mask A bitmask containing which options should be modified.
+ * @param[in] options A bitmask containing desired configuration settings.
+ *   Bit positions for each option are found in the \ref RAIL_RxOptions_t.
+ * @return Status code indicating success of the function call.
+ *
+ * Configures the radio receive flow based on the list of available options.
+ * Only the options indicated by the mask parameter will be affected. Pass
+ * \ref RAIL_RX_OPTIONS_ALL to set all parameters.
+ * The previous settings may affect the current frame if a packet is
+ * received during this configuration.
+ */
+RAIL_Status_t RAIL_ConfigRxOptions(RAIL_Handle_t railHandle,
+                                   RAIL_RxOptions_t mask,
+                                   RAIL_RxOptions_t options);
+
+/**
+ * Start the receiver on a specific channel.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel The channel to listen on.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this receive appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call.
+ *
+ * This is a non-blocking function. Whenever a packet is received \ref RAIL_Config_t::eventsCallback
+ * will fire with \ref RAIL_EVENT_RX_PACKET_RECEIVED set. If you call
+ * this while not idle but with a different channel we will abort any ongoing
+ * receive or transmit operation.
+ */
+RAIL_Status_t RAIL_StartRx(RAIL_Handle_t railHandle,
+                           uint16_t channel,
+                           const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Schedules a receive window for some future time.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel A channel to listen on.
+ * @param[in] cfg The configuration structure to define the receive window.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this receive appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call.
+ *
+ * This API immediately changes the channel and schedules receive to start
+ * at the specified time and end at the given end time. If you do not specify
+ * an end time, you may call this API later with an end time as long as you set
+ * the start time to disabled. You can also terminate the receive
+ * operation immediately using the RAIL_Idle() function. Note that relative
+ * end times are always relative to the start unless no start time is
+ * specified. If changing channels, aborts any ongoing packet transmission or
+ * reception.
+ *
+ * In multiprotocol you must ensure that you properly yield the radio after this
+ * call. See \ref rail_radio_scheduler_yield for more details.
+ */
+RAIL_Status_t RAIL_ScheduleRx(RAIL_Handle_t railHandle,
+                              uint16_t channel,
+                              const RAIL_ScheduleRxConfig_t *cfg,
+                              const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Get basic information about a pending or received packet.
+ * This function can be used in any RX mode; it does not free up any
+ * internal resources.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] packetHandle A packet handle for the unreleased packet as
+ *   returned from a previous call, or sentinel values
+ *   \ref RAIL_RX_PACKET_HANDLE_OLDEST or \ref RAIL_RX_PACKET_HANDLE_NEWEST.
+ * @param[out] pPacketInfo An application-provided pointer to store
+ *   \ref RAIL_RxPacketInfo_t for the requested packet.
+ * @return The packet handle for the requested packet:
+ *   if packetHandle was one of the sentinel values, returns the actual
+ *   packet handle for that packet, otherwise returns packetHandle.
+ *   It may return \ref RAIL_RX_PACKET_HANDLE_INVALID to indicate an error.
+ *
+ * @note When getting info about an arriving packet that is not yet complete
+ *   (i.e. pPacketInfo->packetStatus == \ref RAIL_RX_PACKET_RECEIVING), keep
+ *   in mind its data is highly suspect because it has not yet passed any CRC
+ *   integrity checking. Also note the packet could be aborted, cancelled, or
+ *   fail momentarily, invalidating its data in Packet mode. Furthermore, there
+ *   is a small chance towards the end of packet reception that the filled-in
+ *   RAIL_RxPacketInfo_t could include not only packet data received so far,
+ *   but also some raw radio-appended info detail bytes that RAIL's
+ *   packet-completion processing will subsequently deal with. It's up to the
+ *   application to know its packet format well enough to avoid confusing such
+ *   info as packet data.
+ */
+RAIL_RxPacketHandle_t RAIL_GetRxPacketInfo(RAIL_Handle_t railHandle,
+                                           RAIL_RxPacketHandle_t packetHandle,
+                                           RAIL_RxPacketInfo_t *pPacketInfo);
+
+/**
+ * Convenience helper function to copy a full packet to a user-specified
+ * contiguous buffer.
+ *
+ * @param[out] pDest An application-provided pointer to a buffer of at
+ *   least pPacketInfo->packetBytes in size to store the packet data
+ *   contiguously. This buffer must never overlay RAIL's Rx FIFO buffer.
+ *   Exactly pPacketInfo->packetBytes of packet data will be written into it.
+ * @param[out] pPacketInfo
+ *   \ref RAIL_RxPacketInfo_t for the requested packet.
+ * @return void.
+ *
+ * @note This helper is intended to be expedient -- it does not check the
+ *   validity of its arguments, so don't pass either as NULL, and don't
+ *   pass a pDest pointer to a buffer that's too small for the packet's data.
+ * @note If only a portion of the packet is needed, use RAIL_PeekRxPacket()
+ *   instead.
+ */
+static inline
+void RAIL_CopyRxPacket(uint8_t *pDest,
+                       const RAIL_RxPacketInfo_t *pPacketInfo)
+{
+  memcpy(pDest, pPacketInfo->firstPortionData, pPacketInfo->firstPortionBytes);
+  if (pPacketInfo->lastPortionData != NULL) {
+    memcpy(pDest + pPacketInfo->firstPortionBytes,
+           pPacketInfo->lastPortionData,
+           pPacketInfo->packetBytes - pPacketInfo->firstPortionBytes);
+  }
+}
+
+/**
+ * Get detailed information about a ready packet received (one whose
+ * \ref RAIL_RxPacketStatus_t is among the RAIL_RX_PACKET_READY_ set).
+ * This function can be used in any RX mode; it does not free up any
+ * internal resources.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] packetHandle A packet handle for the unreleased packet as
+ *   returned from a previous call to RAIL_GetRxPacketInfo() or
+ *   RAIL_HoldRxPacket(), or sentinel values \ref RAIL_RX_PACKET_HANDLE_OLDEST
+ *   or \ref RAIL_RX_PACKET_HANDLE_NEWEST.
+ * @param[in,out] pPacketDetails An application-provided pointer to store
+ *   \ref RAIL_RxPacketDetails_t for the requested packet.
+ *   The timeReceived fields totalPacketBytes and timePosition must be
+ *   initialized prior to each call:
+ *   - totalPacketBytes with the total number of bytes of the received
+ *     packet for RAIL to use when calculating the specified timestamp.
+ *     This should account for all bytes received over the air after the
+ *     Preamble and Sync word(s), including CRC bytes.
+ *   - timePosition with a \ref RAIL_PacketTimePosition_t value specifying
+ *     the packet position to put in the timeReceived field on return.
+ *     This field will also be updated with the actual position corresponding
+ *     to the timeReceived value filled in.
+ * @return \ref RAIL_STATUS_NO_ERROR if pPacketDetails was filled in,
+ *   or an appropriate error code otherwise.
+ */
+RAIL_Status_t RAIL_GetRxPacketDetails(RAIL_Handle_t railHandle,
+                                      RAIL_RxPacketHandle_t packetHandle,
+                                      RAIL_RxPacketDetails_t *pPacketDetails);
+
+/**
+ * Place a temporary hold on this packet's data and information resources
+ * within RAIL.
+ * This shall only be called from within RAIL callback context.
+ * This function can be used in any RX mode.
+ *
+ * Normally when RAIL issues its callback indicating a packet is ready
+ * or aborted, it expects the application's callback to retrieve and
+ * copy (or discard) the packet's information and data, and will free up
+ * its internal packet data after the callback returns. This function
+ * tells RAIL to hold onto those resources after the callback returns in
+ * case the application wants to defer processing the packet to a later
+ * time, e.g. outside of callback context.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return The packet handle for the packet associated with the callback,
+ *   or \ref RAIL_RX_PACKET_HANDLE_INVALID if no such packet yet exists.
+ */
+RAIL_RxPacketHandle_t RAIL_HoldRxPacket(RAIL_Handle_t railHandle);
+
+/**
+ * Copies 'len' bytes of packet data starting from 'offset' from the
+ * receive FIFO. Those bytes remain valid for re-peeking.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] packetHandle A packet handle as returned from a previous
+ *   RAIL_GetRxPacketInfo() or RAIL_HoldRxPacket() call, or
+ *   sentinel values \ref RAIL_RX_PACKET_HANDLE_OLDEST
+ *   or \ref RAIL_RX_PACKET_HANDLE_NEWEST.
+ * @param[out] pDst A pointer to the location where the received bytes will
+ *   be copied. If NULL, no copying occurs.
+ * @param[in] len A number of packet data bytes to copy.
+ * @param[in] offset A byte offset within remaining packet data from which
+ *   to copy.
+ * @return Number of packet bytes copied.
+ *
+ * @note Peek does not permit peeking beyond the requested packet's
+ *   available packet data (though there is a small chance it might
+ *   for a \ref RAIL_RX_PACKET_HANDLE_NEWEST packet at the very end of
+ *   still being received). Nor can one peek into already-consumed data read
+ *   by RAIL_ReadRxFifo(). len and offset are relative to the remaining data
+ *   available in the packet, if any was already consumed by RAIL_ReadRxFifo().
+ */
+uint16_t RAIL_PeekRxPacket(RAIL_Handle_t railHandle,
+                           RAIL_RxPacketHandle_t packetHandle,
+                           uint8_t *pDst,
+                           uint16_t len,
+                           uint16_t offset);
+
+/**
+ * Release RAIL's internal resources for the packet.
+ * This must be called for any packet previously held via
+ * RAIL_HoldRxPacket(), and may optionally be called within
+ * callback context to release RAIL resources sooner than at
+ * callback completion time when not holding the packet.
+ * This function can be used in any RX mode.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] packetHandle A packet handle as returned from a previous
+ *   RAIL_HoldRxPacket() call, or sentinel values
+ *   \ref RAIL_RX_PACKET_HANDLE_OLDEST or \ref RAIL_RX_PACKET_HANDLE_NEWEST.
+ *   The latter might be used within RAIL callback context to explicitly
+ *   release the packet associated with the callback early, before it would
+ *   be released automatically by RAIL on callback return (unless explicitly
+ *   held).
+ * @return \ref RAIL_STATUS_NO_ERROR if the held packet was released
+ *   or an appropriate error code otherwise.
+ */
+RAIL_Status_t RAIL_ReleaseRxPacket(RAIL_Handle_t railHandle,
+                                   RAIL_RxPacketHandle_t packetHandle);
+
+/**
+ * Returns the current raw RSSI.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] wait if false returns instant RSSI with no checks.
+ * @return \ref RAIL_RSSI_INVALID if the receiver is disabled and an RSSI
+ *   value can't be obtained. Otherwise, return the RSSI in quarter dBm, dbm*4.
+ *
+ * Gets the current RSSI value. This value represents the current energy of the
+ * channel, it can change rapidly, and will be low if no RF energy is
+ * in the current channel. The function from the value reported to dBm is an
+ * offset dependent on the PHY and the PCB layout. Users should characterize the
+ * RSSI received on their hardware and apply an offset in the application to
+ * account for board and PHY parameters. 'Wait' argument doesn't guarantee
+ * a valid RSSI reading.'Wait' being true gives assurance that that the RSSI is
+ * current and not stale value from previous radio state. If GetRssi is called
+ * during RX-to-RX, RX-to-IDLE or RX-to-TX transition the RSSI is considered
+ * stale and \ref RAIL_RSSI_INVALID is returned if wait=true. 'Wait' being false
+ * will return either current RSSI or stale RSSI measurement (if called during
+ * RX-to-RX, RX-to-IDLE or RX-to-TX transition). \ref RAIL_RSSI_INVALID is
+ * returned if radio hasn't been in RX longer than 'idleToRx' time
+ * (see \ref RAIL_StateTiming_t), regardless of wait argument.
+ *
+ * In multiprotocol, this function returns \ref RAIL_RSSI_INVALID
+ * immediately if railHandle is not the current active \ref RAIL_Handle_t.
+ * Additionally 'wait' should never be set 'true' in multiprotocol
+ * as the wait time is not consistent, so scheduling a scheduler
+ * slot cannot be done accurately.
+ */
+int16_t RAIL_GetRssi(RAIL_Handle_t railHandle, bool wait);
+
+/**
+ * Starts the RSSI averaging over a specified time in us.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel The physical channel to set.
+ * @param[in] averagingTimeUs Averaging time in microseconds.
+ * @param[in] schedulerInfo Information to allow the radio scheduler to place
+ *   this operation appropriately. This is only used in multiprotocol version of
+ *   RAIL and may be set to NULL in all other versions.
+ * @return Status code indicating success of the function call.
+ *
+ * Starts a non-blocking hardware-based RSSI averaging mechanism. Only a single
+ * instance of RSSI averaging can be run at any time and the radio must be idle
+ * to start.
+ *
+ * In multiprotocol, this is a scheduled event. It will start when railHandle
+ * becomes active, and railHandle will need to stay active until the averaging
+ * completes. If the averaging is interrupted, calls to
+ * \ref RAIL_GetAverageRssi will return \ref RAIL_RSSI_INVALID.
+ *
+ * Also in multiprotocol, the user is required to call \ref RAIL_YieldRadio
+ * after this event completes (i.e. when \ref RAIL_EVENT_RSSI_AVERAGE_DONE
+ * occurs).
+ */
+RAIL_Status_t RAIL_StartAverageRssi(RAIL_Handle_t railHandle,
+                                    uint16_t channel,
+                                    RAIL_Time_t averagingTimeUs,
+                                    const RAIL_SchedulerInfo_t *schedulerInfo);
+
+/**
+ * Queries whether the RSSI averaging is done.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Returns true if done and false otherwise.
+ *
+ * This function can be used to poll for completion of the RSSI averaging
+ * to avoid relying on an interrupt-based callback.
+ */
+bool RAIL_IsAverageRssiReady(RAIL_Handle_t railHandle);
+
+/**
+ * Gets the RSSI averaged over specified time in us.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Return \ref RAIL_RSSI_INVALID if the receiver is disabled
+ *   an RSSI value can't be obtained. Otherwise, return the RSSI in
+ *   quarter dBm,dbm*4.
+ *
+ * Gets the hardware RSSI average after issuing RAIL_StartAverageRssi.
+ * It should be used after \ref RAIL_StartAverageRssi.
+ */
+int16_t RAIL_GetAverageRssi(RAIL_Handle_t railHandle);
+
+/******************************************************************************
+ * Address Filtering (RX)
+ *****************************************************************************/
+/**
+ * @addtogroup Address_Filtering Address Filtering
+ * @brief Configuration APIs for receive packet address filtering.
+ *
+ * The address filtering code examines the packet as follows.
+ *
+ * | `Bytes: 0 - 255` | `0 - 8`  | `0 - 255` | `0 - 8`  | `Variable` |
+ * |:----------------:|---------:|----------:|---------:|:----------:|
+ * | `Data0`          | `Field0` | `Data1`   | `Field1` | `Data2`    |
+ *
+ * In the above structure, anything listed as DataN is an optional section of
+ * bytes that RAIL will not process for address filtering. The FieldN segments
+ * reference-specific sections in the packet that will each be interpreted
+ * as an address during address filtering. The application may submit up to
+ * four addresses to attempt to match each field segment and each address may
+ * have a size of up to 8 bytes. To set up address filtering, first configure
+ * the locations and length of the addresses in the packet. Next, configure
+ * which combinations of matches in Field0 and Field1 should constitute an
+ * address match. Lastly, enter addresses into tables for each field and
+ * enable them. The first two of these are part of the \ref RAIL_AddrConfig_t
+ * structure while the second part is configured at runtime using the
+ * RAIL_SetAddressFilterAddress() API. A brief description of each
+ * configuration is listed below.
+ *
+ * For the first piece of configuration, the offsets and sizes of the fields
+ * are assumed fixed for the RAIL address filter. To set them, specify
+ * arrays for these values in the sizes and offsets entries in the
+ * \ref RAIL_AddrConfig_t structure. A size of zero indicates that a field is
+ * disabled. The start offset for a field is relative to the previous start
+ * offset and, if you're using FrameType decoding, the first start offset is
+ * relative to the end of the byte containing the frame type.
+ *
+ * Configuring which combinations of Field0 and Field1 constitute a match is
+ * the most complex portion of the address filter. The easiest way to think
+ * about this is with a truth table. If you consider each of the four possible
+ * address entries in a field, you can have a match on any one of those or a
+ * match for none of them. This can be represented as a 4-bit mask where 1
+ * indicates a match and 0 indicates no match. Representing the Field0 match
+ * options as rows and the Field1 options as columns results in a truth table
+ * as shown below.
+ *
+ * |          | 0000 | 0001 | 0010 | 0100 | 1000 |
+ * |----------|------|------|------|------|------|
+ * | __0000__ | bit0 | bit1 | bit2 | bit3 | bit4 |
+ * | __0001__ | bit5 | bit6 | bit7 | bit8 | bit9 |
+ * | __0010__ | bit10| bit11| bit12| bit13| bit14|
+ * | __0100__ | bit15| bit16| bit17| bit18| bit19|
+ * | __1000__ | bit20| bit21| bit22| bit23| bit24|
+ *
+ * Because this is only 25 bits, it can be represented in one 32-bit integer
+ * where 1 indicates a filter pass and 0 indicates a filter fail. This is the
+ * matchTable parameter in the configuration struct and is used during
+ * filtering. For common simple configurations two defines are provided with
+ * the truth tables as shown below. The first is \ref
+ * ADDRCONFIG_MATCH_TABLE_SINGLE_FIELD, which can be used if only using
+ * one address field (either field). If using two fields and want to
+ * force in the same address entry in each field, use the second define: \ref
+ * ADDRCONFIG_MATCH_TABLE_DOUBLE_FIELD. For more complex systems,
+ * create a valid custom table.
+ *
+ * @note Address filtering does not function reliably with PHYs that use a data
+ *   rate greater than 500 kbps. If this is a requirement, filter in software
+ *   for the time being.
+ *
+ * @{
+ */
+
+/**
+ * Configures address filtering.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] addrConfig The configuration structure, which defines how
+ *   addresses are setup in your packets.
+ * @return Status code indicating success of the function call.
+ *
+ * This function must be called to set up address filtering. You may call it
+ * multiple times but all previous information is wiped out each time you call
+ * and any configured addresses must be reset.
+ */
+RAIL_Status_t RAIL_ConfigAddressFilter(RAIL_Handle_t railHandle,
+                                       const RAIL_AddrConfig_t *addrConfig);
+
+/**
+ * Enables address filtering.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] enable An argument to indicate whether or not to enable address
+ *   filtering.
+ * @return True if address filtering was enabled to start with and false
+ *   otherwise.
+ *
+ * Only allow packets through that pass the current address filtering
+ * configuration. This does not reset or change the configuration so you can
+ * set that up before turning on this feature.
+ */
+bool RAIL_EnableAddressFilter(RAIL_Handle_t railHandle, bool enable);
+
+/**
+ * Returns whether address filtering is currently enabled.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return True if address filtering is enabled and false otherwise.
+ */
+bool RAIL_IsAddressFilterEnabled(RAIL_Handle_t railHandle);
+
+/**
+ * Resets the address filtering configuration.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return void.
+ *
+ * Resets all structures related to address filtering. This does not disable
+ * address filtering. It leaves the radio in a state where no packets
+ * pass filtering.
+ */
+void RAIL_ResetAddressFilter(RAIL_Handle_t railHandle);
+
+/**
+ * Sets an address for filtering in hardware.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] field Which address field you want to use for this address.
+ * @param[in] index Which match entry you want to place this address in for a
+ *   given field.
+ * @param[in] value A pointer to the address data. This must be at least as
+ *   long as the size specified in RAIL_ConfigAddressFilter().
+ * @param[in] enable A boolean to indicate whether this address should be
+ *   enabled immediately.
+ * @return Status code indicating success of the function call.
+ *
+ * This function loads the given address into hardware for filtering and
+ * starts filtering if you set the enable parameter to true. Otherwise,
+ * call RAIL_EnableAddressFilterAddress() to turn it on later.
+ */
+RAIL_Status_t RAIL_SetAddressFilterAddress(RAIL_Handle_t railHandle,
+                                           uint8_t field,
+                                           uint8_t index,
+                                           const uint8_t *value,
+                                           bool enable);
+
+/**
+ * Enables address filtering for the specified address.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] enable An argument to indicate whether or not to enable address
+ *   filtering.
+ * @param[in] field Which address field you want to enable the address in.
+ * @param[in] index Which match entry in the given field you want to enable.
+ * @return Status code indicating success of the function call.
+ */
+RAIL_Status_t RAIL_EnableAddressFilterAddress(RAIL_Handle_t railHandle,
+                                              bool enable,
+                                              uint8_t field,
+                                              uint8_t index);
+
+/** @} */ // end of group Address_Filtering
+
+/** @} */ // end of group Receive
+
+/******************************************************************************
+ * Auto Acking
+ *****************************************************************************/
+/// @addtogroup Auto_Ack Auto ACK
+/// @brief APIs for configuring auto ACK functionality
+///
+/// These APIs are used to configure the radio for auto acknowledgment
+/// features. Auto ACK inherently changes how the underlying state machine
+/// behaves so users should not modify RAIL_SetRxTransitions() and
+/// RAIL_SetTxTransitions() while using auto ACK features.
+///
+/// @code{.c}
+/// // Go to RX after ACK operation
+/// RAIL_AutoAckConfig_t autoAckConfig = {
+///   .enable = true,
+///   .ackTimeout = 1000,
+///   // "error" param ignored
+///   .rxTransitions = { RAIL_RF_STATE_RX, RAIL_RF_STATE_RX},
+///   // "error" param ignored
+///   .txTransitions = { RAIL_RF_STATE_RX, RAIL_RF_STATE_RX}
+/// };
+///
+/// RAIL_Status_t status = RAIL_ConfigAutoAck(railHandle, &autoAckConfig);
+///
+/// uint8_t ackData[] = {0x05, 0x02, 0x10, 0x00};
+///
+/// RAIL_Status_t status = RAIL_WriteAutoAckFifo(ackData, sizeof(ackData));
+/// @endcode
+///
+/// The acknowledgment transmits based on the frame format configured via
+/// the Radio Configurator. For example, if the frame format is using a variable
+/// length scheme, the ACK will be sent according to that scheme. If a 10-byte
+/// packet is loaded into the ACK, but the variable length field of the ACK
+/// payload specifies a length of 5, only 5 bytes will transmit for the ACK.
+/// The converse is also true, if the frame length is configured to be a fixed
+/// 10-byte packet but only 5 bytes are loaded into the ACK buffer, a TX
+/// underflow occurs during the ACK transmit.
+///
+/// Unlike in non-ACK mode, ACK mode will always return to a single
+/// state after all ACK sequences complete, regardless of whether
+/// the ACK was successfully received/sent or not. Read the documentation
+/// of RAIL_ConfigAutoAck for more detail on how that is configured. To
+/// not auto acknowledge a series of packets after transmit
+/// or receive, call RAIL_PauseTxAutoAck(true) or RAIL_PauseRxAutoAck(true).
+/// When auto acking is paused, after receiving or transmitting (also
+/// regardless of success) a packet, the radio transitions to the same single
+/// state it always defaults to while acking. To return to
+/// normal state transition logic outside of acking, you must call
+/// RAIL_ConfigAutoAck with the "enable" field false, and specify the
+/// desired transitions in the rxTransitions and txTransitions fields.
+/// To simply get out of a paused state and resume auto acking, call
+/// RAIL_PauseTxAutoAck(false) or RAIL_PauseRxAutoAck(false).
+///
+/// Applications can cancel the transmission of an ACK with
+/// RAIL_CancelAutoAck(). Conversely, applications can control if a transmit
+/// operation should wait for an ACK after transmitting by using
+/// the \ref RAIL_TX_OPTION_WAIT_FOR_ACK bit.
+///
+/// If the ACK payload is dynamic, the application must call
+/// RAIL_WriteAutoAckFifo() with the appropriate ACK payload after the
+/// application processes the receive. RAIL can auto ACK from the normal
+/// transmit buffer if RAIL_UseTxFifoForAutoAck() is called before the radio
+/// transmits the ACK. Ensure the transmit buffer contains data loaded by
+/// RAIL_WriteTxFifo().
+///
+/// Standard-based protocols that contain auto ACK functionality are normally
+/// configured in the protocol-specific configuration function. For example,
+/// RAIL_IEEE802154_Init() provides auto ACK configuration parameters in \ref
+/// RAIL_IEEE802154_Config_t and should only be configured through that
+/// function. It is not advisable to call both RAIL_IEEE802154_Init() and
+/// RAIL_ConfigAutoAck(). However, ACK modification functions are still valid to
+/// use with protocol-specific ACKs. To cancel a IEEE 802.15.4 ACK transmit, use
+/// RAIL_CancelAutoAck().
+///
+/// @{
+
+/// Configures and enable auto acknowledgment.
+///
+/// @param[in] railHandle A RAIL instance handle.
+/// @param[in] config Auto ACK configuration structure.
+/// @return Status code indicating success of the function call.
+///
+/// Configures the RAIL state machine to for hardware-accelerated auto
+/// acknowledgment. ACK timing parameters are defined in the configuration
+/// structure.
+///
+/// While auto acking is enabled, do not call the following RAIL functions:
+///   - RAIL_SetRxTransitions()
+///   - RAIL_SetTxTransitions()
+///
+/// Note, that if you are enabling auto ACK (i.e. "enable" field is true)
+/// The "error" fields of rxTransitions and txTransitions are ignored.
+/// After all ACK sequences, (success or fail) the state machine will return
+/// the radio to the "success" state. If you need information about the
+/// actual success of the ACK sequence, you can use RAIL events such as
+/// \ref RAIL_EVENT_TXACK_PACKET_SENT to make sure an ACK was sent, or
+/// \ref RAIL_EVENT_RX_ACK_TIMEOUT to make sure that an ACK was received
+/// within the specified timeout.
+///
+/// If you wish to set a certain turnaround time (i.e. txToRx and rxToTx
+/// in \ref RAIL_StateTiming_t), we recommend that you make txToRx lower than
+/// desired, in order to ensure you get to RX in time to receive the ACK.
+/// Silicon Labs recommends setting 10us lower than desired:
+///
+/// @code{.c}
+/// void setAutoAckStateTimings()
+/// {
+///   RAIL_StateTiming_t timings;
+///
+///   // User is already in auto ACK and wants a turnaround of 192us
+///   timings.rxToTx = 192;
+///   timings.txToRx = 192 - 10;
+///
+///   // Set other fields of timings...
+///   timings.idleToRx = 100;
+///   timings.idleToTx = 100;
+///   timings.rxSearchTimeout = 0;
+///   timings.txToRxSearchTimeout = 0;
+///
+///   RAIL_SetStateTiming(railHandle, &timings);
+/// }
+/// @endcode
+///
+/// As opposed to an explicit "Disable" API, simply set the "enable"
+/// field of the RAIL_AutoAckConfig_t to false. Then, auto ACK will be
+/// disabled and state transitions will be returned to the values set
+/// in \ref RAIL_AutoAckConfig_t. During this disable, the "ackTimeout" field
+/// isn't used.
+///
+RAIL_Status_t RAIL_ConfigAutoAck(RAIL_Handle_t railHandle,
+                                 const RAIL_AutoAckConfig_t *config);
+
+/**
+ * Returns the enable status of the auto ACK feature.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return true if auto ACK is enabled, false if disabled.
+ */
+bool RAIL_IsAutoAckEnabled(RAIL_Handle_t railHandle);
+
+/**
+ * Loads the auto ACK buffer with ACK data.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] ackData A pointer to ACK data to transmit.
+ * @param[in] ackDataLen Number of bytes of ACK data.
+ * @return Status code indicating success of the function call.
+ *
+ * If the ACK buffer is available for updates, load the ACK buffer with data.
+ */
+RAIL_Status_t RAIL_WriteAutoAckFifo(RAIL_Handle_t railHandle,
+                                    const uint8_t *ackData,
+                                    uint8_t ackDataLen);
+
+/**
+ * Pauses/resumes RX auto ACK functionality.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] pause Pause or resume RX auto acking.
+ * @return void.
+ *
+ * When RX auto acking is paused, the radio transitions to default
+ * state after receiving a packet and does not transmit an ACK.
+ * When RX auto ACK is resumed, the radio resumes automatically acking
+ * every successfully received packet.
+ */
+void RAIL_PauseRxAutoAck(RAIL_Handle_t railHandle,
+                         bool pause);
+
+/**
+ * Returns whether the RX auto ACK is paused.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return true if RX auto ACK is paused, false if not paused.
+ */
+bool RAIL_IsRxAutoAckPaused(RAIL_Handle_t railHandle);
+
+/**
+ * Pauses/resumes TX auto ACK functionality.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] pause Pause or resume TX auto acking.
+ * @return void.
+ *
+ * When TX auto acking is paused, the radio transitions to a default
+ * state after transmitting a packet and does not wait for an ACK. When TX
+ * auto ACK is resumed, the radio resumes automatically waiting for
+ * an ACK after a successful transmit.
+ */
+void RAIL_PauseTxAutoAck(RAIL_Handle_t railHandle, bool pause);
+
+/**
+ * Returns whether the TX auto ACK is paused.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return true if TX auto ACK is paused, false if not paused.
+ */
+bool RAIL_IsTxAutoAckPaused(RAIL_Handle_t railHandle);
+
+/**
+ * Modifies the upcoming ACK to use the TX Buffer.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Status code indicating success of the function call. This call will
+ *   fail if it is too late to modify the outgoing ACK.
+ *
+ * This function allows the application to use the normal TX buffer as the data
+ * source for the upcoming ACK. The ACK modification to use the TX buffer only
+ * applies to one ACK transmission.
+ *
+ * This function only returns true if the following conditions are met:
+ *   - Radio has not already decided to use the ACK buffer AND
+ *   - Radio is either looking for sync, receiving the packet after sync, or in
+ *     the Rx2Tx turnaround before the ACK is sent.
+ */
+RAIL_Status_t RAIL_UseTxFifoForAutoAck(RAIL_Handle_t railHandle);
+
+/**
+ * Cancels the upcoming ACK.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Status code indicating success of the function call. This call will
+ *   fail if it is too late to modify the outgoing ACK.
+ *
+ * This function allows the application to cancel the upcoming automatic
+ * acknowledgment.
+ *
+ * This function only returns true if the following conditions are met:
+ *   - Radio has not already decided to transmit the ACK AND
+ *   - Radio is either looking for sync, receiving the packet after sync or in
+ *     the Rx2Tx turnaround before the ACK is sent.
+ */
+RAIL_Status_t RAIL_CancelAutoAck(RAIL_Handle_t railHandle);
+
+/**
+ * Returns whether the radio is currently waiting for an ACK.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return True if radio is waiting for ACK, false if radio is not waiting for
+ *   an ACK.
+ *
+ * This function allows the application to query whether the radio is currently
+ * waiting for an ACK after a transmit operation.
+ */
+bool RAIL_IsAutoAckWaitingForAck(RAIL_Handle_t railHandle);
+
+/** @} */ // end of group Auto_Ack
+
+/******************************************************************************
+ * Calibration
+ *****************************************************************************/
+/// @addtogroup Calibration
+/// @brief APIs for calibrating the radio
+/// @{
+///
+/// These APIs can be used to calibrate the radio. The RAIL library
+/// determines which calibrations are necessary. Calibrations can
+/// be enabled/disabled with the RAIL_CalMask_t parameter.
+///
+/// Some calibrations produce values that can be saved and reapplied to
+/// save repetition of the calibration process.
+///
+/// Calibrations can either be run with \ref RAIL_Calibrate, or with the
+/// individual chip-specific calibration routines. An example for running code
+/// with \ref RAIL_Calibrate looks like:
+///
+/// @code{.c}
+/// static RAIL_CalValues_t calValues = RAIL_CALVALUES_UNINIT;
+///
+/// void RAILCb_Event(RAIL_Handle_t railHandle, RAIL_Events_t events) {
+///   // Omitting other event handlers
+///   if (events & RAIL_EVENT_CAL_NEEDED) {
+///     // Run all pending calibrations, and save the results
+///     RAIL_Calibrate(railHandle, &calValues, RAIL_CAL_ALL_PENDING);
+///   }
+/// }
+/// @endcode
+///
+/// Alternatively, if the image rejection calibration for your chip can be
+/// determined ahead of time, such as by running the calibration on a separate
+/// firmware image on each chip, then the following calibration process will
+/// result in smaller code.
+///
+/// @code{.c}
+/// static uint32_t imageRejection = IRCAL_VALUE;
+///
+/// void RAILCb_Event(RAIL_Handle_t railHandle, RAIL_Events_t events) {
+///   // Omitting other event handlers
+///   if (events & RAIL_EVENT_CAL_NEEDED) {
+///     RAIL_CalMask_t pendingCals = RAIL_GetPendingCal(railHandle);
+///     // Disable the radio if we have to do an offline calibration
+///     if (pendingCals & RAIL_CAL_TEMP_VC0) {
+///       RAIL_CalibrateTemp(railHandle);
+///     }
+///     if (pendingCals & RAIL_CAL_ONETIME_IRCAL) {
+///       RAIL_ApplyIrCalibration(railHandle, imageRejection);
+///     }
+///   }
+/// }
+/// @endcode
+
+/**
+ * Initialize RAIL Calibration
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] calEnable A bitmask of which calibrations to enable for callback
+ *   notification. The exact meaning of these bits is chip specific.
+ * @return Status code indicating success of the function call.
+ *
+ * Calibration initialization provides the calibration settings that
+ * correspond to the current radio configuration.
+ */
+RAIL_Status_t RAIL_ConfigCal(RAIL_Handle_t railHandle,
+                             RAIL_CalMask_t calEnable);
+
+/**
+ * Starts the calibration process.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in,out] calValues A structure of calibration values to apply.
+ *   If a valid calibration values structure is provided and the structure
+ *   contains valid calibration values, those values will be applied to the
+ *   hardware, and the RAIL library will cache those values for use again later.
+ *   If a valid calibration values structure is provided and the structure
+ *   contains a calibration value of \ref RAIL_CAL_INVALID_VALUE for the
+ *   desired calibration, the desired calibration will run, the calibration
+ *   values structure will be updated with a valid calibration value, and the
+ *   RAIL library will cache that value for use again later.
+ *   If a NULL pointer is provided, the desired calibration will run,
+ *   and the RAIL library will cache that value for use again later; however,
+ *   the valid calibration value will not be returned to the application.
+ * @param[in] calForce A mask to force specific calibration(s) to execute.
+ *   To run all pending calibrations, use the value \ref RAIL_CAL_ALL_PENDING.
+ *   Only the calibrations specified will run, even if not enabled during
+ *   initialization.
+ * @return Status code indicating success of the function call.
+ *
+ * If calibrations were performed previously and the application saves the
+ * calibration values (i.e. call this function with a calibration values
+ * structure containing calibration values of \ref RAIL_CAL_INVALID_VALUE
+ * before a reset), the application can later bypass the time it would normally
+ * take to recalibrate hardware by reusing previous calibration values (i.e.
+ * call this function with a calibration values structure containing valid
+ * calibration values after a reset).
+ *
+ * If multiple protocols are used, this function will return
+ * \ref RAIL_STATUS_INVALID_STATE if it is called and the given railHandle is
+ * not active. The caller must attempt to re-call this function later, in that
+ * case.
+ *
+ * @note Instead of this function, consider using the individual chip-specific
+ *   functions. Using the individual functions will allow for better
+ *   dead-stripping if not all calibrations are run.
+ * @note Some calibrations should only be executed when the radio is IDLE. See
+ *   chip-specific documentation for more details.
+ */
+RAIL_Status_t RAIL_Calibrate(RAIL_Handle_t railHandle,
+                             RAIL_CalValues_t *calValues,
+                             RAIL_CalMask_t calForce);
+
+/**
+ * Returns the current set of pending calibrations.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return A mask of all pending calibrations that the user has been asked to
+ *   perform.
+ *
+ * This function returns a full set of pending calibrations. The only way
+ * to clear pending calibrations is to perform them using the \ref
+ * RAIL_Calibrate() API with the appropriate list of calibrations.
+ */
+RAIL_CalMask_t RAIL_GetPendingCal(RAIL_Handle_t railHandle);
+
+/**
+ * Enable/Disable PA calibration
+ *
+ * @param[in] enable Enables/Disables PA calibration
+ * @return void.
+ *
+ * Enabling this will ensure that the PA power remains constant chip to chip.
+ * By default this feature is disabled after reset.
+ *
+ * @note this function should be called before \ref RAIL_ConfigTxPower() if this
+ *   feature is desired.
+ */
+void RAIL_EnablePaCal(bool enable);
+
+/** @} */ // end of group Calibration
+
+/******************************************************************************
+ * RF Sense Structures
+ *****************************************************************************/
+/**
+ * @addtogroup Rf_Sense RF Sense
+ * @{
+ */
+
+/**
+ * Starts/stops RF Sense functionality for use during low-energy sleep modes.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] band The frequency band(s) on which to sense the RF energy.
+ *   To stop RF Sense, specify \ref RAIL_RFSENSE_OFF.
+ * @param[in] senseTime The time (in microseconds) the RF energy must be
+ *   continually detected to be considered "sensed".
+ * @param[in] cb \ref RAIL_RfSense_CallbackPtr_t is called when the RF is
+ *   sensed. Set null if polling via \ref RAIL_IsRfSensed().
+ * @return The actual senseTime used, which may be different than
+ *   requested due to limitations of the hardware. If 0, RF sense was
+ *   disabled or could not be enabled (no callback will be issued).
+ *
+ * The EFR32 has the ability to sense the presence of RF Energy above -20 dBm
+ * within either or both the 2.4 GHz and Sub-GHz bands and trigger an event
+ * if that energy is continuously present for certain durations of time.
+ *
+ * @note After RF energy has been sensed, the RF Sense is automatically
+ *   disabled. RAIL_StartRfSense() must be called again to reactivate it.
+ *
+ * @note Packet reception is not guaranteed to work correctly once RF Sense is
+ *   enabled. To be safe, an application should turn this on only after idling
+ *   the radio to stop receive and turn it off before attempting to restart
+ *   receive. Since EM4 sleep causes the chip to come up through the reset
+ *   vector any wake from EM4 must also shut off RF Sense to ensure proper
+ *   receive functionality.
+ *
+ * @warning RF Sense functionality is only guaranteed from 0 to 85 degrees
+ *   Celsius. RF Sense should be disabled outside of this temperature range.
+ */
+RAIL_Time_t RAIL_StartRfSense(RAIL_Handle_t railHandle,
+                              RAIL_RfSenseBand_t band,
+                              RAIL_Time_t senseTime,
+                              RAIL_RfSense_CallbackPtr_t cb);
+
+/**
+ * Checks if the RF was sensed.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return true if RF was sensed since the last call to \ref RAIL_StartRfSense.
+ *   False otherwise.
+ *
+ * This function is useful if \ref RAIL_StartRfSense is called with a null
+ * callback. It is generally used after EM4 reboot but can be used any time.
+ */
+bool RAIL_IsRfSensed(RAIL_Handle_t railHandle);
+
+/** @} */ // end of group Rf_Sense
+
+/******************************************************************************
+ * Multiprotocol Structures
+ *****************************************************************************/
+/**
+ * @addtogroup Multiprotocol
+ * @brief Multiprotocol scheduler APIs to support multiple time-sliced PHYs.
+ * @{
+ */
+
+/**
+ * Yields the radio to other configurations
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return void.
+ *
+ * This function is used to indicate that the previous transmit or scheduled
+ * receive operation has completed. It must be used in multiprotocol RAIL since
+ * the scheduler assumes that any transmit or receive operation that is started
+ * by you can go on infinitely based on state transitions and your protocol.
+ * RAIL will not allow a lower priority tasks to run until this is called so it
+ * can negatively impact performance of those protocols if this is omitted or
+ * delayed. It is also possible to simply call the \ref RAIL_Idle() API to
+ * to both terminate the operation and idle the radio. In single protocol RAIL
+ * this API does nothing.
+ *
+ * See \ref rail_radio_scheduler_yield for more details.
+ */
+void RAIL_YieldRadio(RAIL_Handle_t railHandle);
+
+/**
+ * Get the status of the RAIL scheduler.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return \ref RAIL_SchedulerStatus_t status.
+ *
+ * This function can only be called from callback context after the
+ * \ref RAIL_EVENT_SCHEDULER_STATUS event occurs.
+ */
+RAIL_SchedulerStatus_t RAIL_GetSchedulerStatus(RAIL_Handle_t railHandle);
+
+/** @} */ // end of group Multiprotocol
+
+/******************************************************************************
+ * Diagnostic
+ *****************************************************************************/
+/**
+ * @addtogroup Diagnostic
+ * @brief APIs for diagnostic and test chip modes
+ * @{
+ */
+
+/**
+ * Enables or disables direct mode for RAIL.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] enable Whether or not to enable direct mode.
+ * @return \ref RAIL_STATUS_NO_ERROR on success and an error code on failure.
+ *
+ * @warning This API configures fixed pins for TX data in, RX data out,
+ *   RX clock out. There should be more control over these pins in the
+ *   future but they are currently fixed. Also, this API is not safe to
+ *   use in a true multiprotocol app.
+ *
+ * In this mode packets are output and input directly to the radio via GPIO
+ * and RAIL packet handling is ignored. On the EFR32, the DIN pin in TX is
+ * EFR32_PC10, which corresponds to EXP_HEADER15/WSTKP12, and the DOUT pin in
+ * RX is EFR32_PC11, which corresponds to EXP_HEADER16/WSTKP13.
+ */
+RAIL_Status_t RAIL_EnableDirectMode(RAIL_Handle_t railHandle,
+                                    bool enable);
+
+/**
+ * Sets the crystal tuning.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] tune A chip-dependent crystal capacitor bank tuning parameter.
+ * @return Status code indicating success of the function call.
+ *
+ * Tunes the crystal that the radio depends on to change the location of the
+ * center frequency for transmitting and receiving. This function will only
+ * succeed if the radio is idle at the time of the call.
+ *
+ * @note This function proportionally affects the entire chip's timing
+ *   across all its peripherals, including radio tuning and channel spacing.
+ *   A separate function, \ref RAIL_SetFreqOffset(), can be used to adjust
+ *   just the radio tuner without disturbing channel spacing or other chip
+ *   peripheral timing.
+ */
+RAIL_Status_t RAIL_SetTune(RAIL_Handle_t railHandle, uint32_t tune);
+
+/**
+ * Gets the crystal tuning.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return A chip-dependent crystal capacitor bank tuning parameter.
+ *
+ * Retrieves the current tuning value used by the crystal that the radio
+ * depends on.
+ */
+uint32_t RAIL_GetTune(RAIL_Handle_t railHandle);
+
+/**
+ * Gets the frequency offset.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Returns the measured frequency offset on a received packet.
+ *   The units are described in the \ref RAIL_FrequencyOffset_t
+ *   documentation. If this returns \ref RAIL_FREQUENCY_OFFSET_INVALID
+ *   it was called while the radio wasn't active and there is no way
+ *   to get the frequency offset.
+ *
+ * Retrieves the measured frequency offset used during the previous
+ * received packet, which includes the current radio frequency offset
+ * (see \ref RAIL_SetFreqOffset()). If the chip has not been in RX,
+ * it returns the nominal radio frequency offset.
+ */
+RAIL_FrequencyOffset_t RAIL_GetRxFreqOffset(RAIL_Handle_t railHandle);
+
+/**
+ * Sets the nominal radio frequency offset.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] freqOffset \ref RAIL_FrequencyOffset_t parameter (signed, 2's
+ *   complement).
+ * @return Status code indicating success of the function call.
+ *
+ * This is used to adjust the radio's tuning frequency slightly up or down.
+ * It might be used in conjunction with \ref RAIL_GetRxFreqOffset() after
+ * receiving a packet from a peer to adjust the tuner to better match the
+ * peer's tuned frequency.
+ *
+ * @note Unlike \ref RAIL_SetTune(), which affects the entire chip's
+ *   timing including radio tuning and channel spacing, this function
+ *   only affects radio tuning without disturbing channel spacing or
+ *   other chip peripheral timing.
+ */
+RAIL_Status_t RAIL_SetFreqOffset(RAIL_Handle_t railHandle,
+                                 RAIL_FrequencyOffset_t freqOffset);
+
+/**
+ * Starts transmitting a stream on a certain channel.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] channel A channel on which to emit a stream.
+ * @param[in] mode Choose the stream mode (PN9, and so on).
+ * @return Status code indicating success of the function call.
+ *
+ * Begins streaming onto the given channel. The sources can either be an
+ * unmodulated carrier wave, or an encoded stream of bits from a PN9 source.
+ * All ongoing radio operations will be stopped before transmission begins.
+ */
+RAIL_Status_t RAIL_StartTxStream(RAIL_Handle_t railHandle,
+                                 uint16_t channel,
+                                 RAIL_StreamMode_t mode);
+
+/**
+ * Stops stream transmission.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Status code indicating success of the function call.
+ *
+ * Halts the transmission started by RAIL_StartTxStream().
+ */
+RAIL_Status_t RAIL_StopTxStream(RAIL_Handle_t railHandle);
+
+/**
+ * Configures the verification of radio memory contents.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in,out] configVerify A configuration structure made available to
+ *   RAIL in order to perform radio state verification. This structure must be
+ *   allocated in application global read-write memory. RAIL may modify
+ *   fields within or referenced by this structure during its operation.
+ * @param[in] radioConfig A ptr to a radioConfig that is to be used as a
+ *   white list for verifying memory contents.
+ * @param[in] cb A callback that notifies the application of a mismatch in
+ *   expected vs actual memory contents. A NULL parameter may be passed in
+ *   if a callback is not provided by the application.
+ * @return \ref RAIL_STATUS_NO_ERROR if setup of the verification feature
+ *   successfully occurred.
+ *   \ref RAIL_STATUS_INVALID_PARAMETER is returned if the provided railHandle
+ *   or configVerify structures are invalid.
+ */
+RAIL_Status_t RAIL_ConfigVerification(RAIL_Handle_t railHandle,
+                                      RAIL_VerifyConfig_t *configVerify,
+                                      const uint32_t *radioConfig,
+                                      RAIL_VerifyCallbackPtr_t cb);
+
+/**
+ * Verifies radio memory contents.
+ *
+ * @param[in,out] configVerify A configuration structure made available to
+ *   RAIL in order to perform radio state verification. This structure must be
+ *   allocated in application global read-write memory. RAIL may modify
+ *   fields within or referenced by this structure during its operation.
+ * @param[in] durationUs The duration (in microseconds) for how long memory
+ *   verification should occur before returning to the application. A value of
+ *   RAIL_VERIFY_DURATION_MAX indicates that all memory contents should be
+ *   verified before returning to the application.
+ * @param[in] restart This flag only has meaning if a previous call of this
+ *   function returned \ref RAIL_STATUS_SUSPENDED. By restarting (true), the
+ *   verification process starts over from the beginning, or by resuming
+ *   where verification left off after being suspended (false), verification
+ *   can proceed towards completion.
+ * @return \ref RAIL_STATUS_NO_ERROR if the contents of all applicable
+ *   memory locations have been verified.
+ *   \ref RAIL_STATUS_SUSPENDED is returned if the provided test duration
+ *   expired but the time was not sufficient to verify all memory contents.
+ *   By calling \ref RAIL_Verify again, further verification will commence.
+ *   \ref RAIL_STATUS_INVALID_PARAMETER is returned if the provided
+ *   verifyConfig structure pointer is not configured for use by the active
+ *   RAIL handle.
+ *   \ref RAIL_STATUS_INVALID_STATE is returned if any of the verified
+ *   memory contents are different from their reference values.
+ */
+RAIL_Status_t RAIL_Verify(RAIL_VerifyConfig_t *configVerify,
+                          uint32_t durationUs,
+                          bool restart);
+
+/** @} */ // end of group Diagnostic
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/******************************************************************************
+ * Debug
+ *****************************************************************************/
+/**
+ * @addtogroup Debug
+ * @brief APIs for debugging
+ * @{
+ */
+
+/**
+ * Configures the debug mode for the radio library. Do not use this function
+ * unless instructed by Silicon Labs.
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] debugMode Debug mode to enter.
+ * @return Status code indicating success of the function call.
+ */
+RAIL_Status_t RAIL_SetDebugMode(RAIL_Handle_t railHandle, uint32_t debugMode);
+
+/**
+ * Returns the debug mode for the radio library. Do not use this function
+ * unless instructed by Silicon Labs.
+ * @param[in] railHandle A RAIL instance handle.
+ * @return Debug mode for the radio library.
+ */
+uint32_t RAIL_GetDebugMode(RAIL_Handle_t railHandle);
+
+/**
+ * Overrides the radio base frequency.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] freq A desired frequency in Hz.
+ * @return Status code indicating success of the function call.
+ *
+ * Sets the radio to transmit at the frequency given. This function can only
+ * be used while in \ref RAIL_DEBUG_MODE_FREQ_OVERRIDE. The given frequency
+ * needs to be close to the base frequency of the current PHY.
+ */
+RAIL_Status_t RAIL_OverrideDebugFrequency(RAIL_Handle_t railHandle,
+                                          uint32_t freq);
+
+/** @} */ // end of group Debug
+
+#endif//DOXYGEN_SHOULD_SKIP_THIS
+
+/******************************************************************************
+ * Assertion Callback
+ *****************************************************************************/
+/**
+ * @addtogroup Assertions
+ * @brief Callbacks called by assertions
+ *
+ * This assertion framework was implemented for the purpose of not only being
+ * able to assert that certain conditions be true in a block of code, but also
+ * to be able to handle them more appropriately. In previous implementations,
+ * the behavior upon a failed assert would be to hang in a while(1) loop.
+ * However, with the callback, each assert is given a unique error code so that
+ * they can be handled on a more case-by-case basis. For documentation on each
+ * of the errors, please see the rail_assert_error_codes.h file.
+ * RAIL_ASSERT_ERROR_MESSAGES[errorCode] gives the explanation of the error.
+ * With asserts built into the library, customers can choose how to handle each
+ * error inside the callback.
+ *
+ * @{
+ */
+
+/**
+ * Callback called upon failed assertion.
+ *
+ * @param[in] railHandle A RAIL instance handle.
+ * @param[in] errorCode Value passed in by the calling assertion API indicating
+ *   the RAIL error that is indicated by the failing assertion.
+ * @return void.
+ */
+void RAILCb_AssertFailed(RAIL_Handle_t railHandle,
+                         RAIL_AssertErrorCodes_t errorCode);
+
+/** @} */ // end of group Assertions
+
+/** @} */ // end of group RAIL_API
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __RAIL_H__