1.2.3 Using the Data Link Layer Module

The following code shows a basic example on how to use Meters And Mode DLL:


// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

static const uint8_t appDataTxDataBuffer[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

APP_DATA appData;

static CACHE_ALIGN uint8_t appDataRxDataBuffer[CACHE_ALIGNED_SIZE_GET(APP_PLC_BUFFER_SIZE)];

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

static void APP_TxTimeout_Callback (uintptr_t context)
{
    SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Tx Timeout expired\r\n");
}

static void APP_DLL_DataIndication_callback(DLL_DATA_IND_PARAMS *indParams)
{
    SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "DLL_DATA_INDICATION: DSAP=%hhu, ECC=%hhu, SrcAddr=0x"
            "%02X%02X%02X%02X%02X%02X, LSDU=0x", indParams->dsap, indParams->ecc,
            indParams->srcAddress.address[0], indParams->srcAddress.address[1], indParams->srcAddress.address[2],
            indParams->srcAddress.address[3], indParams->srcAddress.address[4], indParams->srcAddress.address[5]);

    for (uint8_t i = 0; i < indParams->lsduLen; i++)
    {
        SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "%02X", indParams->lsdu[i]);
    }

    SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "\r\n");

    memcpy(appDataRxDataBuffer, indParams->lsdu, indParams->lsduLen);
}

static void APP_DLL_DataConfirm_callback(DLL_DATA_CONFIRM_PARAMS *cfmParams)
{
    SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "DLL_DATA_CONFIRM (Result %hhu)\r\n", cfmParams->txStatus);
    SYS_TIME_TimerDestroy(appData.txTimeoutHandle);
}

static void APP_DLL_EventIndication_callback(DLL_EVENT_IND_PARAMS *indParams)
{
    SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "DLL_EVENT_INDICATION: Id=%hhu, Value=0x", indParams->eventId);

    for (uint8_t i = 0; i < indParams->eventValue.length; i++)
    {
        SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "%02X", indParams->eventValue.value[i]);
    }

    SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "\r\n");
}

// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

void APP_Initialize ( void )
{
    /* IDLE state is used to signal when application is started */
    appData.state = APP_STATE_INIT;

    /* Configure DLL Data Request parameters */
    appData.drParams.ecc = DLL_ECC_DISABLED;
    appData.drParams.lsdu = (uint8_t *)appDataTxDataBuffer;
    appData.drParams.lsduLen = sizeof(appDataTxDataBuffer);

    appData.drParams.dsap = DLL_DSAP_APPLICATION_FRAME;
    appData.drParams.serviceClass = SERVICE_CLASS_RA;
    appData.drParams.maxResponseLen = 122;

    appData.drParams.dstAddress.routeSize = TEST_NUM_REPETERS + 1;

    /* First Address in the route (Node A) */
    appData.drParams.dstAddress.macAddress[0].address[0] = 0x00;
    appData.drParams.dstAddress.macAddress[0].address[1] = 0xAA;
    appData.drParams.dstAddress.macAddress[0].address[2] = 0x00;
    appData.drParams.dstAddress.macAddress[0].address[3] = 0xAA;
    appData.drParams.dstAddress.macAddress[0].address[4] = 0x00;
    appData.drParams.dstAddress.macAddress[0].address[5] = 0xAA;
}

void APP_Tasks ( void )
{
    /* Refresh WDG */
    CLEAR_WATCHDOG();

    /* Check the application's current state. */
    switch ( appData.state )
    {
        case APP_STATE_INIT:
        {
            DLL_DataIndicationCallbackRegister(APP_DLL_DataIndication_callback);
            DLL_DataConfirmCallbackRegister(APP_DLL_DataConfirm_callback);
            DLL_EventIndicationCallbackRegister(APP_DLL_EventIndication_callback);

            /* Set MAC address */
            const DLL_IB_VALUE value = {
                .length = 6,
                .value = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
            };

            DLL_SetRequest(MAC_ACA_ADDRESS_IB, 0, &value);

            appData.state = APP_STATE_TX_FRAME;

            break;
        }

        case APP_STATE_TX_FRAME:
        {
            if (DLL_GetStatus() == DLL_STATUS_READY)
            {
                DLL_DataRequest(&appData.drParams);
                SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "DLL_DATA_REQUEST\r\n");

                /* Start timer to detect TX timeout */
                uint32_t txTimeoutUS = DLL_GetTxTimeout();
                appData.txTimeoutHandle = SYS_TIME_CallbackRegisterUS(APP_TxTimeout_Callback, 0, txTimeoutUS, SYS_TIME_SINGLE);
                SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Tx Timeout started: %u us\r\n", txTimeoutUS);

                appData.state = APP_STATE_WAITING;
            }

            break;
        }

        case APP_STATE_WAITING:
        {
            break;
        }

        /* The default state should never be executed. */
        default:
        {
            break;
        }
    }
}