Multi-Level Frequency Modulation#
MFM configuration routines.
Note
This feature is only supported on EFR32xG23 devices.
This feature can be used to directly control the TX interpolation filter input to allow for a more flexible frequency modulation scheme than the standard MODEM. When doing this, the MFM buffer is treated as an array of 8-bit signed data used as normalized frequency deviation to the SYNTH frequency to directly control the interpolation filter input. No support for frame handling, coding, nor shaping is supported. Only compatible with FSK modulations.
The functions in this group configure RAIL Multi-Level Frequency Modulation (MFM) hardware acceleration features.
To configure MFM functionality, the application must first set up a RAIL instance with RAIL_Init() and other setup functions. Before enabling MFM, a ping-pong buffer (called buffer0 and buffer1 below) must be configured via RAIL_SetMfmPingPongFifo() and populated with the initial buffer content. MFM is enabled by setting RAIL_TxDataSource_t::TX_MFM_DATA using RAIL_ConfigData() and is activated when transmit is started by RAIL_StartTx(). Once transmitting the data in the ping-pong buffers, RAIL will manage them so it looks like a continuous transmission to the receiver. Every time one of the ping-pong buffers has been transmitted, RAIL_EVENT_MFM_TX_BUFFER_DONE is triggered so the application can update the data in that buffer without the need to start/stop the transmission. RAIL_EVENT_MFM_TX_BUFFER_DONE can be enable with RAIL_ConfigEvents(). Use RAIL_StopTx() to finish transmitting.
#define MFM_RAW_BUF_WORDS 128
extern RAIL_Handle_t railHandle;
uint8_t txCount = 0;
uint32_t mfmPingPongBuffers[2][MFM_RAW_BUF_WORDS];
typedef struct mfmConfigApp {
RAIL_MFM_PingPongBufferConfig_t buffer;
RAIL_StateTiming_t timings;
RAIL_DataConfig_t dataConfig;
} mfmConfigApp_t;
static mfmConfigApp_t mfmConfig = {
.buffer = {
.pBuffer0 = (&mfmPingPongBuffers[0]),
.pBuffer1 = (&mfmPingPongBuffers[1]),
.bufferSizeWords = MFM_RAW_BUF_WORDS,
},
.timings = {
.idleToTx = 100,
.idleToRx = 0,
.rxToTx = 0,
.txToRx = 0,
.rxSearchTimeout = 0,
.txToRxSearchTimeout = 0
},
.dataConfig = {
.txSource = TX_MFM_DATA,
.rxSource = RX_PACKET_DATA,
.txMethod = PACKET_MODE,
.rxMethod = PACKET_MODE,
},
};
// Main RAIL events handler callback
static void RAILCb_Event(RAIL_Handle_t railHandle, RAIL_Events_t events)
{
// Increment TX counter
if (events & RAIL_EVENT_MFM_BUF_DONE) {
txCount++;
return;
}
}
}
void mfmInit(void)
{
// initialize MFM
uint32_t idx;
uint32_t *pDst0 = mfmConfig.buffer.pBuffer0;
uint32_t *pDst1 = mfmConfig.buffer.pBuffer1;
for (idx = 0; idx < (mfmConfig.buffer.bufferSizeWords / 4); idx++) {
pDst0[4 * idx + 0] = 0x755A3100;
pDst1[4 * idx + 0] = 0x755A3100;
pDst0[4 * idx + 1] = 0x315A757F;
pDst1[4 * idx + 1] = 0x315A757F;
pDst0[4 * idx + 2] = 0x8BA6CF00;
pDst1[4 * idx + 2] = 0x8BA6CF00;
pDst0[4 * idx + 3] = 0xCFA68B81;
pDst1[4 * idx + 3] = 0xCFA68B81;
}
RAIL_Status_t status;
status = RAIL_SetMfmPingPongFifo(railHandle, &mfmConfig.buffer);
assert(status == RAIL_STATUS_NO_ERROR);
status = RAIL_SetStateTiming(railHandle, &mfmConfig.timings);
assert(status == RAIL_STATUS_NO_ERROR);
mfmConfig.dataConfig.txSource = TX_MFM_DATA;
status = RAIL_ConfigData(railHandle, &mfmConfig.dataConfig);
assert(status == RAIL_STATUS_NO_ERROR);
// start transmitting
status = RAIL_StartTx(railHandle, 0, 0, NULL);
assert(status == RAIL_STATUS_NO_ERROR);
}
void mfmDeInit(void)
{
RAIL_Status_t status;
status = RAIL_StopTx(railHandle, RAIL_STOP_MODES_ALL);
assert(status == RAIL_STATUS_NO_ERROR);
mfmConfig.dataConfig.txSource = TX_PACKET_DATA;
status = RAIL_ConfigData(railHandle, &mfmConfig.dataConfig);
assert(status == RAIL_STATUS_NO_ERROR);
}
Note
This feature is only supported on EFR32xG23 devices.
This feature can be used to directly control the TX interpolation filter input to allow for a more flexible frequency modulation scheme than the standard MODEM. When doing this, the MFM buffer is treated as an array of 8-bit signed data used as normalized frequency deviation to the SYNTH frequency to directly control the interpolation filter input. No support for frame handling, coding, nor shaping is supported. Only compatible with FSK modulations.
The functions in this group configure RAIL Multi-Level Frequency Modulation (MFM) hardware acceleration features.
To configure MFM functionality, the application must first set up a RAIL instance with sl_rail_init() and other setup functions. Before enabling MFM, a ping-pong buffer (called buffer0 and buffer1 below) must be configured via sl_rail_set_mfm_ping_pong_fifo() and populated with the initial buffer content. MFM is enabled by setting sl_rail_tx_data_source_t::SL_RAIL_TX_DATA_SOURCE_MFM_DATA using sl_rail_config_tx_data() and is activated when transmit is started by sl_rail_start_tx(). Once transmitting the data in the ping-pong buffers, RAIL will manage them so it looks like a continuous transmission to the receiver. Every time one of the ping-pong buffers has been transmitted, SL_RAIL_EVENT_MFM_TX_BUFFER_DONE is triggered so the application can update the data in that buffer without the need to start/stop the transmission. SL_RAIL_EVENT_MFM_TX_BUFFER_DONE can be enable with sl_rail_config_events(). Use sl_rail_stop_tx() to finish transmitting.
#define MFM_RAW_BUF_WORDS 128
extern sl_rail_handle_t rail_handle;
uint8_t tx_count = 0;
uint32_t mfm_ping_pong_buffers[2][MFM_RAW_BUF_WORDS];
typedef struct mfm_config_app {
sl_rail_mfm_ping_pong_buffer_config_t buffer;
sl_rail_state_timing_t timings;
sl_rail_tx_data_config_t tx_data_config;
} mfm_config_app_t;
static mfm_config_app_t mfm_config = {
.buffer = {
.p_buffer_0 = (&mfm_ping_pong_buffers[0]),
.p_buffer_1 = (&mfm_ping_pong_buffers[1]),
.buffer_words = MFM_RAW_BUF_WORDS,
},
.timings = {
.idle_to_tx = 100,
.idle_to_rx = 0,
.rx_to_tx = 0,
.tx_to_rx = 0,
.rxsearch_timeout = 0,
.tx_to_rxsearch_timeout = 0
},
.tx_data_config = {
.tx_source = SL_RAIL_TX_DATA_SOURCE_MFM_DATA;
.tx_method = SL_RAIL_DATA_METHOD_PACKET_MODE,
},
};
// Main RAIL events handler callback
static void events_handler(sl_rail_handle_t rail_handle, sl_rail_events_t events)
{
// Increment TX counter
if (events & SL_RAIL_EVENT_MFM_BUF_DONE) {
tx_count++;
return;
}
}
}
void mfm_init(void)
{
// initialize MFM
uint32_t idx;
uint32_t *p_dst_0 = mfm_config.buffer.p_buffer_0;
uint32_t *p_dst_1 = mfm_config.buffer.p_buffer_1;
for (idx = 0; idx < (mfm_config.buffer.buffer_words / 4); idx++) {
p_dst_0[4 * idx + 0] = 0x755A3100;
p_dst_1[4 * idx + 0] = 0x755A3100;
p_dst_0[4 * idx + 1] = 0x315A757F;
p_dst_1[4 * idx + 1] = 0x315A757F;
p_dst_0[4 * idx + 2] = 0x8BA6CF00;
p_dst_1[4 * idx + 2] = 0x8BA6CF00;
p_dst_0[4 * idx + 3] = 0xCFA68B81;
p_dst_1[4 * idx + 3] = 0xCFA68B81;
}
sl_rail_status_t status;
status = sl_rail_set_mfm_ping_pong_fifo(rail_handle, &mfm_config.buffer);
assert(status == SL_RAIL_STATUS_NO_ERROR);
status = sl_rail_set_state_timing(rail_handle, &mfm_config.timings);
assert(status == SL_RAIL_STATUS_NO_ERROR);
mfm_config.tx_data_config.tx_source = SL_RAIL_TX_DATA_SOURCE_MFM_DATA;
status = sl_rail_config_tx_data(rail_handle, &mfm_config.tx_data_config);
assert(status == SL_RAIL_STATUS_NO_ERROR);
// start transmitting
status = sl_rail_start_tx(rail_handle, 0, 0, NULL);
assert(status == SL_RAIL_STATUS_NO_ERROR);
}
void mfm_deinit(void)
{
sl_rail_status_t status;
status = sl_rail_stop_tx(rail_handle, SL_RAIL_STOP_MODES_ALL);
assert(status == SL_RAIL_STATUS_NO_ERROR);
mfm_config.tx_data_config.tx_source = SL_RAIL_TX_DATA_SOURCE_PACKET_DATA;
status = sl_rail_config_tx_data(rail_handle, &mfm_config.tx_data_config);
assert(status == SL_RAIL_STATUS_NO_ERROR);
}
Modules#
RAIL_MFM_PingPongBufferConfig_t
sl_rail_mfm_ping_pong_buffer_config_t
Functions#
Set MFM ping-pong buffer.
Set MFM ping-pong buffer.
Function Documentation#
RAIL_SetMfmPingPongFifo#
RAIL_Status_t RAIL_SetMfmPingPongFifo (RAIL_Handle_t railHandle, const RAIL_MFM_PingPongBufferConfig_t * config)
Set MFM ping-pong buffer.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| RAIL_Handle_t | [in] | railHandle | A handle of RAIL instance. |
| const RAIL_MFM_PingPongBufferConfig_t * | [in] | config | A non-NULL pointer to the MFM ping-pong buffer configuration structure. |
Returns
Status code indicating success of the function call.
DeprecatedRAIL 2.x synonym of sl_rail_set_mfm_ping_pong_fifo().
sl_rail_set_mfm_ping_pong_fifo#
sl_rail_status_t sl_rail_set_mfm_ping_pong_fifo (sl_rail_handle_t rail_handle, const sl_rail_mfm_ping_pong_buffer_config_t * p_config)
Set MFM ping-pong buffer.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_rail_handle_t | [in] | rail_handle | A real RAIL instance handle. |
| const sl_rail_mfm_ping_pong_buffer_config_t * | [in] | p_config | A non-NULL pointer to the MFM ping-pong buffer configuration structure. |
Returns
Status code indicating success of the function call.