

#include "canuser.h"
#include "scm_canmatrix-binutil.h"
#include "can_message.h"
#include "hwctrl.h"
/*******************************************************************************
 * the typedefs
 ******************************************************************************/
typedef enum
{
    UDS_MSG_IDX_STD_RX_PHYS,
    UDS_MSG_IDX_STD_RX_FUNC,
    UDS_MSG_IDX_STD_HOST_REQ1,
    UDS_MSG_IDX_STD_HOST_REQ2,
    UDS_MSG_IDX_STD_PHYS_RESP,
    UDS_MSG_IDX_STD_ECU_STATUS,
    UDS_MSG_IDX_STD_ECU_DEBUG1,
    UDS_MSG_IDX_STD_ECU_DEBUG2,
    UDS_MSG_IDX_STD_ECU_DEBUG3,
    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;

typedef struct
{
    uint8_t ECU_HeatStatus:4;//0
    uint8_t ECU_FanStatus:4;
    uint8_t ECU_AnmoStatus:4;//1
    uint8_t reverse14:4;
    uint8_t ECU_MOTOR1_STATUS:2;//2
    uint8_t ECU_MOTOR2_STATUS:2;
    uint8_t ECU_MOTOR3_STATUS:2;
    uint8_t ECU_MOTOR4_STATUS:2;
    uint8_t ECU_MOTOR5_STATUS:2;//3
    uint8_t ECU_MOTOR6_STATUS:2;//4
    uint8_t reverse34:4;
    uint8_t reverse[4];
}ECU_status_Type;

typedef struct
{
    uint8_t ECU_Power;
    uint8_t ECU_MOTOR_C1;
    uint8_t ECU_MOTOR_C2;
    uint8_t ECU_MOTOR_C3;
    uint8_t ECU_HEAT_C1;
    uint8_t ECU_HEAT_C2;
    uint8_t reverse[2];
}ECU_Debug1_Type;
typedef struct
{
    uint16_t ECU_MOTOR_POS1;
    uint16_t ECU_MOTOR_POS2;
    uint16_t ECU_MOTOR_POS3;
    uint16_t ECU_MOTOR_POS4;
}ECU_Debug2_Type;
typedef struct
{
    uint16_t ECU_MOTOR_POS5;
    uint16_t ECU_MOTOR_POS6;
    uint8_t ECU_HALL1:1;
    uint8_t ECU_HALL2:1;
    uint8_t ECU_HALL3:1;
    uint8_t ECU_HALL4:1;
    uint8_t ECU_HALL5:1;
    uint8_t ECU_HALL6:1;
    uint8_t reverse46:2;
    uint8_t reverse[3];
}ECU_Debug3_Type;

typedef struct
{
    uint8_t HOST_KEY1:1;//0
    uint8_t HOST_KEY2:1;
    uint8_t HOST_KEY3:1;
    uint8_t HOST_KEY4:1;
    uint8_t HOST_KEY5:1;
    uint8_t HOST_KEY6:1;
    uint8_t HOST_KEY7:1;
    uint8_t HOST_KEY8:1;
    uint8_t HOST_KEY9:1;//1
    uint8_t HOST_KEY10:1;
    uint8_t HOST_KEY11:1;
    uint8_t HOST_KEY12:1;
    uint8_t HOST_KEY13:1;
    uint8_t HOST_KEY14:1;
    uint8_t HOST_KEY15:1;
    uint8_t HOST_KEY16:1;
    uint8_t HOST_HeatReq:4;//2
    uint8_t HOST_FanReq:4;
    uint8_t HOST_AnmoReq:4;//3
    uint8_t reverse34:4;
    uint8_t reverse[3];
    uint8_t HOST_DebugMode:1;//7
    uint8_t reverse71:7;
}HOST_Req1_Type;

/*******************************************************************************
 * the globals
 ******************************************************************************/
FlexCanDrv_ControllerCfgType flexCanCfg;
FlexCan_DataInfoType         flexCan_DataInfo;
FlexCanDrvType*              flexCanDrv_DemoObj;
static uint8_t txMsgBuf1[8] = {0};
static uint8_t txMsgBuf2[8] = {0};
static uint8_t txMsgBuf3[8] = {0};
static uint8_t txMsgBuf4[8] = {0};
static uint8_t rxMsgBuf1[8] = {0};
static uint8_t rxMsgBuf2[8] = {0};
static uint8_t debugMode;

CAN_MESSAGE CAN_D_scm_state;


/*******************************************************************************
 * 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_HOST_REQ1, 1, APP_RX_HOST_REQ1_MSG_ID, false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true,  0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_FUNC */
    {UDS_MSG_IDX_STD_HOST_REQ2, 1, APP_RX_HOST_REQ2_MSG_ID, false, FLEXCANDRV_MSGTYPE_RX, DLC_BYTE_8, false, true,  0xFFFFFFFF}, /* CAN_MSGOBJ_STD_RX_FUNC */
    {UDS_MSG_IDX_STD_PHYS_RESP, 1, UDS_PHYS_RESP_MSG_ID,    false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
    {UDS_MSG_IDX_STD_ECU_STATUS,1, APP_TX_ECU_STATUS_MSG_ID,false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
    {UDS_MSG_IDX_STD_ECU_DEBUG1,1, APP_TX_ECU_DEBUG1_MSG_ID,false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
    {UDS_MSG_IDX_STD_ECU_DEBUG2,1, APP_TX_ECU_DEBUG2_MSG_ID,false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
    {UDS_MSG_IDX_STD_ECU_DEBUG3,1, APP_TX_ECU_DEBUG3_MSG_ID,false, FLEXCANDRV_MSGTYPE_TX, DLC_BYTE_8, false, false, 0xFFFFFFFF}, /* CAN_MSGOBJ_STD_TX */
};


void GetRxMsgData(uint16_t msgId, uint8_t* pData, uint8_t Size)
{
    if (msgId == APP_RX_HOST_REQ1_MSG_ID)
    {
        memcpy(pData, rxMsgBuf1, Size);
    }
}

void SetTxMsgData(uint16_t msgId, uint8_t* pData, uint8_t Size)
{
    if (msgId == APP_TX_ECU_STATUS_MSG_ID)
    {
        memcpy(txMsgBuf1, pData, Size);
    }
}

static void RxMsgProcess(void)
{
    //HOST_Req1_Type* prxMsgBuf1 = (HOST_Req1_Type*)rxMsgBuf1;
    //debugMode = prxMsgBuf1->HOST_DebugMode;
}

static void TxMessage(CAN_MESSAGE* msg)
{
    FlexCanBoot_TxMessage(msg->MsgId, msg->Data, msg->DLC);
}
void MsgTask(UdsType *obj)//1ms task
{
    static uint16_t msg_counter=0;
    FlexCan_FrameStructureType rxMsg;

    //tx
    msg_counter++;
    if (msg_counter >= 50)
    {
        msg_counter = 0;
        scm_canmatrix_tx.SCM_STATE.test1 = (uint8_t)adcResult[0];
        scm_canmatrix_tx.SCM_STATE.test2 = (uint8_t)adcResult[1];
        scm_canmatrix_tx.SCM_STATE.test3 = (uint8_t)adcResult[2];
        scm_canmatrix_tx.SCM_STATE.test4 = (uint8_t)adcResult[3];
        scm_canmatrix_tx.SCM_STATE.test5 = (uint8_t)adcResult[4];
        Pack_SCM_STATE_CANmatrix(&scm_canmatrix_tx.SCM_STATE,&CAN_D_scm_state);
        TxMessage(&CAN_D_scm_state);
        if (debugMode!=0)
        {
            FlexCanBoot_TxMessage(APP_TX_ECU_DEBUG1_MSG_ID, txMsgBuf2, 8);
            FlexCanBoot_TxMessage(APP_TX_ECU_DEBUG2_MSG_ID, txMsgBuf3, 8);
            FlexCanBoot_TxMessage(APP_TX_ECU_DEBUG3_MSG_ID, txMsgBuf4, 8);
        }
        
    }

    //rx
    /* 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(&obj->isotp, rxMsg.id, rxMsg.data, rxMsg.len);
        }
        else
        {
            scm_canmatrix_Receive(&scm_canmatrix_rx,rxMsg.data,rxMsg.id,rxMsg.len);
        }
    }
    RxMsgProcess();

    //uds stack
    Uds_Run(obj);

}

/************************************* CAN *****************************************/
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(McuType *obj)
{
    uint32_t busClockFreq = 0;

    /* CAN init */
    memset(&flexCan_DataInfo, 0, sizeof(flexCan_DataInfo));
    memset(&flexCanCfg, 0, sizeof(flexCanCfg));
    SEGGER_RTT_printf(0,"-----FlexCanDrv_INIT-----\n");
    /* get CAN controller default configuration */
    FlexCanDrv_GetDefaultCfg(&flexCanCfg);

    flexCanCfg.msgNum = sizeof(msgCfgObj) / sizeof(FlexCanDrv_MsgCfgType);
    flexCanCfg.msgCfg = msgCfgObj;

    flexCanDrv_DemoObj = &obj->flexCanDrv0;

    /* set PTE4 as MUX 5 - CAN0.RX */
    PinsDrv_SetMuxModeSel(&obj->ptb, 0, PINSDRV_MUX_ALT5);

    /* set PTE5 as MUX 5 - CAN0.TX */
    PinsDrv_SetMuxModeSel(&obj->ptb, 1, PINSDRV_MUX_ALT5);

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

    if(flexCanCfg.clkSrc == FLEXCANDRV_CLKSRC_CHICLK)
    {
        ClockDrv_GetFreq(&obj->clockDrv, CLOCKDRV_APB, &busClockFreq);
    }
    else
    {
        ClockDrv_GetFreq(&obj->clockDrv, CLOCKDRV_SOSC_DIV2, &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 enhance rx fifo interrupt */
    FlexCanDrv_SetEnhanceRxFFIsr(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_DAIE, true);
    IrqDrv_EnableIrq(CAN0_ERxFIFO_IRQn);
}



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;
}


uint8_t flexCanBoot_EnhanceRxFFCnt = 0;
void CAN0_ERxFIFO_Handler(void)
{
    if(FlexCanDrv_GetEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_DAIE) == true)
    {
        if(FlexCanDrv_GetEnhanceRxFFIsFull(flexCanDrv_DemoObj) == false)
        {
        }

        if(FlexCanDrv_GetEnhanceRxFFIsEmpty(flexCanDrv_DemoObj) == false)
        {
            FlexCanDrv_MsgObjType rxMsgObj;

            flexCanBoot_EnhanceRxFFCnt = FlexCanDrv_GetEnhanceRxFFMsgNums(flexCanDrv_DemoObj);

            if(flexCanBoot_EnhanceRxFFCnt > 0)
            {
                FlexCanDrv_GetEnhanceRxFifoMsg(flexCanDrv_DemoObj, &rxMsgObj);
                memcpy(flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].data, rxMsgObj.data, rxMsgObj.dlc);
                flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].id  = rxMsgObj.msgId;
                flexCan_DataInfo.rxMsg[flexCan_DataInfo.wrIdx].len = rxMsgObj.dlc;
                flexCan_DataInfo.wrIdx++;
                if(flexCan_DataInfo.wrIdx >= CAN_BUFFER_FIFO_SIZE)
                {
                    flexCan_DataInfo.wrIdx = 0;
                }
            }
        }
    }

    if(FlexCanDrv_GetEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_WMMIE) == true)
    {
        FlexCanDrv_ClearEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_WMMIE);
    }

    if(FlexCanDrv_GetEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_OVFIE) == true)
    {
        FlexCanDrv_ClearEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_OVFIE);
    }

    if(FlexCanDrv_GetEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_UFWIE) == true)
    {
        FlexCanDrv_ClearEnhanceRxFFIsrFlag(flexCanDrv_DemoObj, FLEXCANDRV_ENHANCERXFF_ISR_SRC_UFWIE);
    }
}
