/*******************************************************************************
 * the includes
 ******************************************************************************/
#include "canuser.h"
#include "appTask.h"
#include "can_message.h"

/*******************************************************************************
 * the defines
 ******************************************************************************/


#define CAN_BUFFER_FIFO_SIZE (16u)

/*******************************************************************************
* the typedefs
******************************************************************************/
typedef enum
{
    UDS_MSG_IDX_STD_RX_PHYS,
    UDS_MSG_IDX_STD_RX_FUNC,
    UDS_MSG_IDX_STD_RX_TEST1,
    UDS_MSG_IDX_STD_RX_TEST2,
    UDS_MSG_IDX_STD_TX_TEST1,
    UDS_MSG_IDX_STD_TX,
    UDS_MSG_IDX_STD_TEST1,
    UDS_MSG_IDX_STD_TEST2,

    UDS_MSG_IDX_NUM
} Uds_MsgIdIdxType;

typedef struct
{
    FlexCan_FrameStructureType rxMsg[CAN_BUFFER_FIFO_SIZE];
    FlexCan_FrameStructureType txMsg[CAN_BUFFER_FIFO_SIZE];
    uint8_t                    wrIdx;
    uint8_t                    rdIdx;
} FlexCan_DataInfoType;

/*******************************************************************************
* the globals
******************************************************************************/
extern UdsType udsObj;
extern McuType mcu;
FlexCan_DataInfoType         flexCan_DataInfo;
FlexCanDrv_ControllerCfgType flexCanCfg;
FlexCanDrvType*              flexCanDrv_DemoObj;
uint8_t                      flexCanBoot_EnhanceRxFFCnt = 0;
uint8_t                      txMsgBuf[8]                = {0};

/*******************************************************************************
* the const
******************************************************************************/

const FlexCanDrv_MsgCfgType msgCfgObj[UDS_MSG_IDX_NUM] = {
    {UDS_MSG_IDX_STD_RX_PHYS,  1, UDS_PHYS_RECV_MSG_ID, false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true,  0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_PHYS */
    {UDS_MSG_IDX_STD_RX_FUNC,  1, UDS_FUNC_RECV_MSG_ID, false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true,  0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_FUNC */
    {UDS_MSG_IDX_STD_RX_TEST1, 1, APP_RX_TEST1_MSG_ID,  false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true,  0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_FUNC */
    {UDS_MSG_IDX_STD_RX_TEST2, 1, APP_RX_TEST2_MSG_ID,  false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true,  0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_FUNC */
    {UDS_MSG_IDX_STD_TX,       1, UDS_PHYS_RESP_MSG_ID, false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
    {UDS_MSG_IDX_STD_TEST1,    1, APP_TX_TEST1_MSG_ID,  false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
    {UDS_MSG_IDX_STD_TEST2,    1, APP_TX_TEST2_MSG_ID,  false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
};

 /*******************************************************************************
 * the functions
 ******************************************************************************/
 

void CAN_ORed_0_31_MB_Handler(void)
{
    uint8_t               i = 0;
    FlexCanDrv_MsgObjType msgObj;

    for(i = 0; i < flexCanCfg.msgNum; i++)
    {
        msgObj.msgBufId = i;

        if(FlexCanDrv_GetMsgObjFlag(flexCanDrv_DemoObj, &msgObj))
        {
            if(flexCanCfg.msgCfg[i].msgType == FLEXCANDRV_MSGTYPE_RX)
            {
                /* clear message buffer interrupt flag */
                FlexCanDrv_ClearMsgObjFlag(flexCanDrv_DemoObj, &msgObj);

                /* get the new message data */
                FlexCanDrv_GetRxMsg(flexCanDrv_DemoObj, &msgObj);

                memcpy(flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].data, msgObj.data, msgObj.dlc);
                flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].id  = msgObj.msgId;
                flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].len = msgObj.dlc;
                flexCan_DataInfo.wrIdx++;
                if(flexCan_DataInfo.wrIdx >= CAN_BUFFER_FIFO_SIZE)
                {
                    flexCan_DataInfo.wrIdx = 0;
                }
            }
            else
            {
                /* clear message buffer interrupt flag */
                FlexCanDrv_ClearMsgObjFlag(flexCanDrv_DemoObj, &msgObj);
            }
        }
    }
}

bool FlexCanBoot_ReadoutMsg(FlexCan_FrameStructureType *pRxMsgObj)
{
    bool ret = false;

    if(flexCan_DataInfo.wrIdx != flexCan_DataInfo.rdIdx)
    {
        memcpy(pRxMsgObj, &flexCan_DataInfo.rxMsg[flexCan_DataInfo.rdIdx], sizeof(FlexCan_FrameStructureType));
        flexCan_DataInfo.rdIdx++;
        if(flexCan_DataInfo.rdIdx >= CAN_BUFFER_FIFO_SIZE)
        {
            flexCan_DataInfo.rdIdx = 0;
        }

        ret = true;
    }

    return ret;
}

int8_t FlexCanBoot_TxMessage(uint32_t msgId, const uint8_t *pData, uint8_t size)
{
    FlexCanDrv_MsgObjType txMsgObj;
    uint8_t               msgIdx = 0, i = 0;

    for(i = 0; i < flexCanCfg.msgNum; i++)
    {
        if(msgId == flexCanCfg.msgCfg[i].msgId)
        {
            msgIdx = i;
            break;
        }
    }

    txMsgObj.msgBufId = flexCanCfg.msgCfg[msgIdx].msgBufId;
    txMsgObj.dlc      = size;
    txMsgObj.msgId    = flexCanCfg.msgCfg[msgIdx].msgId;
    memcpy(&txMsgObj.data[0], pData, size);

    FlexCanDrv_SetTxMsg(flexCanDrv_DemoObj, &txMsgObj);
    /* transmit standard CAN Tx message */
    FlexCanDrv_TransmitMsg(flexCanDrv_DemoObj, &txMsgObj);

    return 0;
}

void FlexCanBoot_Init(void)
{
    uint32_t busClockFreq = 0;

    /* CAN init */
    memset(&flexCan_DataInfo, 0, sizeof(flexCan_DataInfo));
    memset(&flexCanCfg, 0, sizeof(flexCanCfg));

    flexCanDrv_DemoObj = &mcu.flexCanDrv;

    /* set CAN0.RX */
    PinsDrv_SetMuxModeSel(&mcu.ptb, 15, PINSDRV_MUX_ALT6);

    /* set CAN0.TX */
    PinsDrv_SetMuxModeSel(&mcu.ptb, 14, PINSDRV_MUX_ALT6);

        /* get CAN controller default configuration */
    FlexCanDrv_GetDefaultCfg(&flexCanCfg);
    flexCanCfg.msgNum = sizeof(msgCfgObj) / sizeof(FlexCanDrv_MsgCfgType);
    flexCanCfg.msgCfg = msgCfgObj;

    flexCanCfg.clkSrc               = FLEXCANDRV_CLKSRC_CHICLK;
    flexCanCfg.fdEnable             = false;
    flexCanCfg.fdISOEnable          = false;
    flexCanCfg.msgBufDataLenSel     = FLEXCANDRV_MB_SIZE_BYTE_8;
    flexCanCfg.individualMaskEnable = true;

    if(flexCanCfg.clkSrc == FLEXCANDRV_CLKSRC_CHICLK)
    {
        ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_APB, &busClockFreq);
    }
    else
    {
        ClockDrv_GetFreq(&mcu.clockDrv, CLOCKDRV_SOSC_DIV, &busClockFreq);
    }

    if(flexCanCfg.fdEnable == true)
    {
        FlexCanDrv_BitTimingCalc(&flexCanCfg.fdBitTiming,
                                 busClockFreq, /* module clock source: 16M */
                                 2000000,      /* baudrate: 2M */
                                 7500,         /* sample point: 75% */
                                 2000,         /* SJW: 20% */
                                 1);           /* FD bit timing */
    }

    FlexCanDrv_BitTimingCalc(&flexCanCfg.bitTiming,
                             busClockFreq, /* module clock source: 16M */
                             500000,       /* baudrate: 500K */
                             7500,         /* sample point: 75% */
                             2500,         /* SJW: 20% */
                             0);           /* classic CAN bit timing */

    /* initialize CAN module */
    FlexCanDrv_Configure(flexCanDrv_DemoObj, &flexCanCfg);

    /* enable all CAN mailbox interrupt */
    IrqDrv_EnableIrq(CAN_ORed_0_31_MB_IRQn);
    IrqDrv_EnableIrq(CAN_ORed_32_63_MB_IRQn);
}

void TxTestMsg(uint8_t *pdata)
{
    uint8_t txMsgBuf[8] = {0};
    if (pdata != NULL)
    {
        memcpy(txMsgBuf,pdata,8);
    }

    FlexCanBoot_TxMessage(APP_TX_TEST1_MSG_ID, txMsgBuf, 8);
    //SEGGER_RTT_printf(0,"test data\n");
}

void CANMsgTask(void)//1ms task
{
    static uint16_t msg_counter=0;
    FlexCan_FrameStructureType rxMsg;
    msg_counter++;
    if (msg_counter % 100 == 0)
    {
        TxTestMsg(NULL);
    }
    
    if (msg_counter >= 1000)
    {
        msg_counter = 0;
    }
    /* Handler user routine */
    if(FlexCanBoot_ReadoutMsg(&rxMsg) == true)
    {
        if((rxMsg.id == UDS_PHYS_RECV_MSG_ID) || (rxMsg.id == UDS_FUNC_RECV_MSG_ID))
        {
            IsoTp_HandleIncomingCanMsg(&udsObj.isotp, rxMsg.id, rxMsg.data, rxMsg.len);
        }
        else
        {
            //scm_canmatrix_Receive(&scm_canmatrix_rx,rxMsg.data,rxMsg.id,rxMsg.len);
            //参考
        }
    }

    Uds_Run(&udsObj);
}
