//------------------------------------------------------------------------------
void dllk_setupAsndFilter(tEdrvFilter* pFilter_p)
{
    ami_setUint16Be(&pFilter_p->aFilterValue[12], C_DLL_ETHERTYPE_EPL);
    ami_setUint16Be(&pFilter_p->aFilterMask[12], 0xFFFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[14], kMsgTypeAsnd);
    ami_setUint8Be(&pFilter_p->aFilterMask[14], 0xFF);
    pFilter_p->fEnable = TRUE;
}
//------------------------------------------------------------------------------
void dllk_setupPresFilter(tEdrvFilter* pFilter_p, BOOL fEnable_p)
{
    ami_setUint48Be(&pFilter_p->aFilterValue[0], C_DLL_MULTICAST_PRES);
    ami_setUint48Be(&pFilter_p->aFilterMask[0], C_DLL_MACADDR_MASK);
    ami_setUint16Be(&pFilter_p->aFilterValue[12], C_DLL_ETHERTYPE_EPL);
    ami_setUint16Be(&pFilter_p->aFilterMask[12], 0xFFFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[14], kMsgTypePres);
    ami_setUint8Be(&pFilter_p->aFilterMask[14], 0xFF);
    pFilter_p->fEnable = fEnable_p;
}
//------------------------------------------------------------------------------
void dllkfilter_setupPresFilter(tEdrvFilter* pFilter_p, BOOL fEnable_p)
{
    // Check parameter validity
    ASSERT(pFilter_p != NULL);

    ami_setUint48Be(&pFilter_p->aFilterValue[0], C_DLL_MULTICAST_PRES);
    ami_setUint48Be(&pFilter_p->aFilterMask[0], C_DLL_MACADDR_MASK);
    ami_setUint16Be(&pFilter_p->aFilterValue[12], C_DLL_ETHERTYPE_EPL);
    ami_setUint16Be(&pFilter_p->aFilterMask[12], 0xFFFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[14], kMsgTypePres);
    ami_setUint8Be(&pFilter_p->aFilterMask[14], 0xFF);
    pFilter_p->fEnable = fEnable_p;
}
//------------------------------------------------------------------------------
void dllk_setupPreqFilter(tEdrvFilter* pFilter_p, UINT nodeId_p, tEdrvTxBuffer* pBuffer_p, UINT8* pMacAdrs_p)
{
    OPLK_MEMCPY(&pFilter_p->aFilterValue[0], pMacAdrs_p, 6);
    ami_setUint48Be(&pFilter_p->aFilterMask[0], C_DLL_MACADDR_MASK);
    ami_setUint16Be(&pFilter_p->aFilterValue[12], C_DLL_ETHERTYPE_EPL);
    ami_setUint16Be(&pFilter_p->aFilterMask[12], 0xFFFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[14], kMsgTypePreq);
    ami_setUint8Be(&pFilter_p->aFilterMask[14], 0xFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[15], (UINT8)nodeId_p);
    ami_setUint8Be(&pFilter_p->aFilterMask[15], 0xFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[16], C_ADR_MN_DEF_NODE_ID);
    ami_setUint8Be(&pFilter_p->aFilterMask[16], 0xFF);
    pFilter_p->pTxBuffer = pBuffer_p;
    pFilter_p->fEnable = FALSE;
}
//------------------------------------------------------------------------------
void dllk_setupSoaUnspecReqFilter(tEdrvFilter* pFilter_p, UINT nodeId_p, tEdrvTxBuffer* pBuffer_p)
{
    ami_setUint48Be(&pFilter_p->aFilterValue[0], C_DLL_MULTICAST_SOA);
    ami_setUint48Be(&pFilter_p->aFilterMask[0], C_DLL_MACADDR_MASK);
    ami_setUint16Be(&pFilter_p->aFilterValue[12], C_DLL_ETHERTYPE_EPL);
    ami_setUint16Be(&pFilter_p->aFilterMask[12], 0xFFFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[14], kMsgTypeSoa);
#if defined(CONFIG_INCLUDE_MASND)
    // Ignore bit4 of message type to react on both Asnd and AInv frames
    ami_setUint8Be(&pFilter_p->aFilterMask[14], 0xF7);
#else
    ami_setUint8Be(&pFilter_p->aFilterMask[14], 0xFF);
#endif
    ami_setUint8Be(&pFilter_p->aFilterValue[20], kDllReqServiceUnspecified);
    ami_setUint8Be(&pFilter_p->aFilterMask[20], 0xFF);
    ami_setUint8Be(&pFilter_p->aFilterValue[21], (UINT8)nodeId_p);
    ami_setUint8Be(&pFilter_p->aFilterMask[21], 0xFF);
    pFilter_p->pTxBuffer = pBuffer_p;
    pFilter_p->fEnable = FALSE;
}
//------------------------------------------------------------------------------
tOplkError dllk_deleteNodeFilter(tDllkNodeInfo* pIntNodeInfo_p, tDllNodeOpType nodeOpType_p,
                                 BOOL fUpdateEdrv_p)
{
    tOplkError      ret = kErrorOk;
    BYTE            bPresFilterFlags = 0;

    switch (nodeOpType_p)
    {
        case kDllNodeOpTypeFilterPdo:
            bPresFilterFlags = DLLK_FILTER_FLAG_PDO;
            break;

        case kDllNodeOpTypeFilterHeartbeat:
            bPresFilterFlags = DLLK_FILTER_FLAG_HB;
            break;

        default:
            ret = kErrorDllInvalidParam;
            goto Exit;
    }

    pIntNodeInfo_p->presFilterFlags &= ~bPresFilterFlags;

    if (fUpdateEdrv_p != FALSE)
    {
        if ((pIntNodeInfo_p->presFilterFlags & (DLLK_FILTER_FLAG_PDO | DLLK_FILTER_FLAG_HB)) == 0)
        {
#if CONFIG_DLL_PRES_FILTER_COUNT < 0
            if (dllkInstance_g.usedPresFilterCount > 0)
                dllkInstance_g.usedPresFilterCount--;

            if (dllkInstance_g.usedPresFilterCount == 0)
            {
                // disable PRes Rx filter
                dllkInstance_g.aFilter[DLLK_FILTER_PRES].fEnable = FALSE;
                ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                       DLLK_FILTER_PRES, EDRV_FILTER_CHANGE_STATE);
                if (ret != kErrorOk)
                    goto Exit;
            }

#else
            UINT handle;

            for (handle = DLLK_FILTER_PRES; handle < DLLK_FILTER_COUNT; handle++)
            {
                if (ami_getUint8Le(&dllkInstance_g.aFilter[handle].aFilterValue[16]) ==
                                                pIntNodeInfo_p->nodeId)
                {
                    ami_setUint8Be(&dllkInstance_g.aFilter[handle].aFilterValue[16], C_ADR_INVALID);
                    dllkInstance_g.aFilter[handle].fEnable = FALSE;

                    ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT,
                                           handle, EDRV_FILTER_CHANGE_STATE);
                    if (ret != kErrorOk)
                        goto Exit;
                    break;
                }
            }
#endif
        }
    }
Exit:
    return ret;
}
//------------------------------------------------------------------------------
static tOplkError setupLocalNodeCn(void)
{
    tOplkError      ret = kErrorOk;

#if (CONFIG_DLL_PRES_FILTER_COUNT >= 0)
    UINT            handle;

#if (NMT_MAX_NODE_ID > 0)
    UINT            index;
    tDllkNodeInfo*  pIntNodeInfo;
#endif
#endif

    dllkfilter_setupPreqFilter(&dllkInstance_g.aFilter[DLLK_FILTER_PREQ],
                               dllkInstance_g.dllConfigParam.nodeId,
                               &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES],
                               edrv_getMacAddr());

    // setup PRes filter
#if CONFIG_DLL_PRES_FILTER_COUNT < 0
    if (dllkInstance_g.usedPresFilterCount > 0)
        dllkfilter_setupPresFilter(&dllkInstance_g.aFilter[DLLK_FILTER_PRES], TRUE);
    else
        dllkfilter_setupPresFilter(&dllkInstance_g.aFilter[DLLK_FILTER_PRES], FALSE);

#else
    for (handle = DLLK_FILTER_PRES; handle < DLLK_FILTER_COUNT; handle++)
    {
        dllkfilter_setupPresFilter(&dllkInstance_g.aFilter[handle], FALSE);
        ami_setUint8Be(&dllkInstance_g.aFilter[handle].aFilterMask[16], 0xFF);
    }

    handle = DLLK_FILTER_PRES;
#if NMT_MAX_NODE_ID > 0
    for (index = 0, pIntNodeInfo = &dllkInstance_g.aNodeInfo[0];
         index < tabentries (dllkInstance_g.aNodeInfo);
         index++, pIntNodeInfo++)
    {
        if ((pIntNodeInfo->presFilterFlags & (DLLK_FILTER_FLAG_PDO | DLLK_FILTER_FLAG_HB)) != 0)
        {
            ami_setUint8Be(&dllkInstance_g.aFilter[handle].aFilterValue[16],
                           pIntNodeInfo->nodeId);
            dllkInstance_g.aFilter[handle].fEnable = TRUE;
            handle++;
            if (handle >= DLLK_FILTER_COUNT)
                break;
        }
    }
#endif
#endif

#if (CONFIG_DLL_PROCESS_SYNC == DLL_PROCESS_SYNC_ON_TIMER)
    ret = synctimer_setCycleLen(dllkInstance_g.dllConfigParam.cycleLen);
    if (ret != kErrorOk)
        return ret;

    ret = synctimer_setLossOfSyncTolerance(dllkInstance_g.dllConfigParam.lossOfFrameTolerance);
    if (ret != kErrorOk)
        return ret;
#endif

#if CONFIG_DLL_PRES_CHAINING_CN != FALSE
    dllkInstance_g.fPrcEnabled = FALSE;
    dllkInstance_g.syncReqPrevNodeId = 0;
#endif

    return ret;
}