1.1.4.2 Using The Library

The RF215 library builds on top of an SPI peripheral library (PLIB) to communicate with the RF215 transceiver, which implements 802.15.4 SUN PHY layeres. However, the underlying use of the SPI port is abstracted to the user, and library provides a modem-like interface with data transmission and reception functions and configuration parameters that can be read/written.

Data service access is done in asynchronous mode, requiring some callbacks to be set in order to let the library to provide communication events to the user.

Management service access is done in synchronous mode, and the get/set functions provide the results as part of the returned/referenced parameters.

Example application to send data through RF and wait for a response

#include "app.h"
#include "driver/rf215/drv_rf215.h"

#define APP_TIME_BTW_MSG_US 5000

typedef enum
{
    /* Application's state machine's initial state. */
    APP_STATE_INIT=0,
    APP_STATE_RUNNING,
    APP_PLC_STATE_ERROR,

} APP_STATES;

DRV_RF215_TX_REQUEST_OBJ txReqObj;
DRV_HANDLE rf215Handle;
DRV_RF215_TX_HANDLE rfTxHandle;
APP_STATES appState;
uint32_t txTotalCount, txOkCount, rxOkCount, rxBadFcsCount
uint8_t psduTx[DRV_RF215_MAX_PSDU_LEN];

static void APP_UpdateTxData()
{
    /* Update TX data content */
    uint16_t dataLen = txReqObj.psduLen - DRV_RF215_FCS_LEN;
    for (uint16_t k = 0; k < dataLen; k++)
    {
        psduTx[k] = (uint8_t) (k + dataLen);
    }
}

static void APP_TxCfmHandler (
    DRV_RF215_TX_HANDLE txHandle,
    DRV_RF215_TX_CONFIRM_OBJ *cfmObj,
    uintptr_t context)
{
    if (txHandle != rfTxHandle)
    {
        return;
    }

    txTotalCount++;
    if (cfmObj->txResult == RF215_TX_SUCCESS)
    {
        txOkCount++;
    }

    if (txReqObj.psduLen < DRV_RF215_MAX_PSDU_LEN)
    {
        txReqObj.psduLen++;
    }
    else
    {
        txReqObj.psduLen = DRV_RF215_FCS_LEN + 1;
    }

    /* Update TX data */
    APP_UpdateTxData();
}

static void APP_RxIndHandler(DRV_RF215_RX_INDICATION_OBJ* ind, uintptr_t ctxt)
{
    if (ind->fcsOk == true)
    {
        DRV_RF215_TX_RESULT txResult;

        /* Update TX time and send new TX request */
        txReqObj.time = ind->timeIni + SYS_TIME_USToCount(ind->ppduDurationUS + APP_TIME_BTW_MSG_US);
        rfTxHandle = DRV_RF215_TxRequest(rf215Handle, &txReqObj, &txResult);

        rxOkCount++;
    }
    else
    {
        rxBadFcsCount++;
    }
}

void APP_PLC_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appState = APP_STATE_INIT;
    rf215Handle = DRV_HANDLE_INVALID;

    /* Initialize TX request object */
    txReqObj.cancelByRx = false;
    txReqObj.ccaMode = PHY_CCA_MODE_3;
    txReqObj.modScheme = FSK_FEC_OFF;
    txReqObj.txPwrAtt = 0;
    txReqObj.psduLen = DRV_RF215_FCS_LEN + 1;
    txReqObj.timeMode = TX_TIME_ABSOLUTE;
    txReqObj.time = SYS_TIME_Counter64Get() + SYS_TIME_MSToCount(10);
    txReqObj.psdu = psduTx;

    APP_UpdateTxData();
}

void APP_PLC_Tasks ( void )
{   
    /* Check the application's current state. */
    switch ( appState )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            SYS_STATUS rf215Status = DRV_RF215_Status(sysObj.drvRf215);
            if (rf215Status == SYS_STATUS_READY)
            {
                rf215Handle = DRV_RF215_Open(DRV_RF215_INDEX_0, RF215_TRX_ID_RF09);
                if (rf215Handle != DRV_HANDLE_INVALID)
                {
                    DRV_RF215_TX_RESULT txResult;

                    DRV_RF215_RxIndCallbackRegister(rf215Handle, APP_RxIndHandler, 0);
                    DRV_RF215_TxCfmCallbackRegister(rf215Handle, APP_TxCfmHandler, 0);

                    rfTxHandle = DRV_RF215_TxRequest(rf215Handle, &txReqObj, &txResult);

                    appState = APP_STATE_RUNNING;
                }
            }
            else if (rf215Status == SYS_STATUS_ERROR)
            {
                appState = APP_STATE_ERROR;
            }

            break;
        }

        case APP_STATE_RUNNING:
        {
            break;
        }

        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}