/******************************************************************************/
/* Williams Advanced Engineering Limited                     Copyright(C) 2021*/
/* Grove                                                  All rights reserved */
/*                                                                            */
/******************************************************************************/


#include "Ios_CanConfig.h"
#include "Ios_DefineCatalog.h"

/*----------------------------------------------------------------------------*/
/* LOCAL VARIABLE DEFINITIONS                                                 */
/*----------------------------------------------------------------------------*/

/* Debug Code - Can be removed when finished */
uint16 uCANMdeCtrl0 = 0;
uint16 uCANMdeCtrl1 = 0;
uint16 uCANPLMdeCtrl0 = 0;

uint16 uCANCtrlReg0 = 0;
uint16 uCANCtrlReg1 = 0;

uint16 uCANIDUnitReg0 = 0;
uint16 uCANIDUnitReg1 = 0;

uint8 CANOverwrite = 0;

uint16 uCANMainStatusReg0 = 0;
uint16 uCANMainStatusReg1 = 0;

/*----------------------------------------------------------------------------*/
/*  FUNCTION : fnIosISOSpiCtrlInitialise                                      */
/*  DESC     : Initialise spi driver                                          */
/*  PARAMS   : none                                                           */
/*  RETURNS  : none                                                           */
/*----------------------------------------------------------------------------*/
uint8 fnIosCANWakeUpSpiCtrlInitialise(void)
{
    uint8 bCANWakeUpSpiInitialized = FALSE;
    spi_config_reg_t tSpiConfigReg;

    spi2GetConfigValue(&tSpiConfigReg, CurrentValue);

    bCANWakeUpSpiInitialized = ((tSpiConfigReg.CONFIG_GCR1 & 0x01000000U) == 0x01000000U);

    return(bCANWakeUpSpiInitialized);
}


/*----------------------------------------------------------------------------*/
/*  FUNCTION : fnIosCANWakeUpPolledTransfer                                   */
/*  DESC     : Transfer data on spi bus                                       */
/*  PARAMS   : bSendBuffer                                                    */
/*           : bReceiveBuffer                                                 */
/*           : uByteCount                                                     */
/*  RETURNS  : XST_SUCCESS/XST_FAILURE  or other error flag                   */
/*-------------------------------------- -------------------------------------*/
uint32 fnIosCANWakeUpPolledTransfer( uint16 *ptbSendBuffer, uint16 *ptbReceiveBuffer, uint32 uByteCount)
{
    //* Set return flag to device not found
    uint32  iStatus;
    spiDAT1_t dataconfig1_t;

    dataconfig1_t.CS_HOLD = TRUE;
    dataconfig1_t.WDEL    = TRUE;
    dataconfig1_t.DFSEL   = SPI_FMT_0;
    dataconfig1_t.CSNR    = 0xFE;

    if((ptbSendBuffer != NULL) && (ptbReceiveBuffer != NULL) && (uByteCount > 0))
    {
        //gioSetBit(spiPORT2,SPI2_CS0_PIN,LOW); //Set CS low

        iStatus = spiTransmitAndReceiveData(spiREG2, &dataconfig1_t, uByteCount, ptbSendBuffer, ptbReceiveBuffer); // Transfer data to device

        //gioSetBit(spiPORT2,SPI2_CS0_PIN,HIGH); // Release CS
    }
    return (iStatus);
}

/*----------------------------------------------------------------------------*/
/*  FUNCTION : fnIosCANWakeUpModeControl                                      */
/*  DESC     : Initialise the CAN controller for normal operation             */
/*  PARAMS   : none                                                           */
/*  RETURNS  : none                                                           */
/*----------------------------------------------------------------------------*/
uint8 fnIosCANWakeUpModeControl(void)
{
    uint16 bCmdBuf[4] = {0}; // 0 - Register Address, 1 - Register Data
    uint16 bRxBuf [4] = {0};
    uint16 uReadReg = 0;
    uint8 ConfigStatus = FALSE;
    uint8 StateFlowLoop = 0, i =0;
    uint32 wDelayCntr = 0;

    for(StateFlowLoop = 0; StateFlowLoop < 5; StateFlowLoop++)
    {
        /* Quick clear of the command and receive buffer */
        for(i=0; i < 4; i++)
        {
            bCmdBuf[i] = 0xFF;
            bRxBuf[i] = 0xFF;
        }

        bCmdBuf[0] = (uint16)((MODE_CONTROL_REG << 1) & 0xFF); //Register Address (Shifted by 1 due to the 0 bit being read only)

        bCmdBuf[1] = (uint16)((CAN_NORMAL_MODE) & 0xFF); //Register Data

        fnIosCANWakeUpPolledTransfer(bCmdBuf, bRxBuf, sizeof(bCmdBuf)/sizeof(uint16)); //Transmits SPI Data

        for(wDelayCntr = 0; wDelayCntr < 0xFFFF; wDelayCntr++);// Delay between config write and read back

        /* Quick clear of the command and receive buffer */
        for(i=0; i < 4; i++)
        {
            bCmdBuf[i] = 0xFF;
            bRxBuf[i] = 0xFF;
        }

        bCmdBuf[0] = (uint16)(((MODE_CONTROL_REG << 1) | (READ_REG_COMMAND)) & 0xFF); //Read back register command

        fnIosCANWakeUpPolledTransfer(bCmdBuf, bRxBuf, sizeof(bCmdBuf)/sizeof(uint16)); //Transmits SPI Data

        uReadReg = (uint16)(((bRxBuf[0] << 8) | bRxBuf[1]) & CAN_READ_MASK); //Reads back the Response from the read command

        uCANMdeCtrl0 = uReadReg; //Stores the Read back to a global parameter

        if (uReadReg == CAN_NORMAL_MODE)
        {
            //If the Mode control read has been correctly configured breaks the loop
            ConfigStatus = TRUE;
            break;
        }
    }

    return(ConfigStatus);
}


/*----------------------------------------------------------------------------*/
/*  FUNCTION : fnIosCANWakeUpModeActive                                       */
/*  DESC     : Initialise the CAN controller transceiver                      */
/*  PARAMS   : none                                                           */
/*  RETURNS  : none                                                           */
/*----------------------------------------------------------------------------*/
uint8 fnIosCANWakeUpModeActive(void)
{
    uint16 bCmdBuf[4] = {0}; // 0 - Register Address, 1 - Register Data
    uint16 bRxBuf [4] = {0};
    uint16 uReadReg = 0;
    uint8 ConfigStatus = FALSE;
    uint8 StateFlowLoop = 0, i =0;
    uint32 wDelayCntr = 0;

    for(StateFlowLoop = 0; StateFlowLoop < 5; StateFlowLoop++)
    {
        /* Quick clear of the command and receive buffer */
        for(i=0; i < 4; i++)
        {
            bCmdBuf[i] = 0xFF;
            bRxBuf[i] = 0xFF;
        }

        bCmdBuf[0] = (uint16)((CAN_CONTROL_REG << 1) & 0xFF); //Register Address (Shifted by 1 due to the 0 bit being read only)

        bCmdBuf[1] = (uint16)((CAN_ACTIVE_MODE) & 0xFF); //Register Data

        fnIosCANWakeUpPolledTransfer(bCmdBuf, bRxBuf, sizeof(bCmdBuf)/sizeof(uint16)); //Transmits SPI Data

        for(wDelayCntr = 0; wDelayCntr < 0xFFFF; wDelayCntr++);// Delay between config write and read back

        /* Quick clear of the command and receive buffer */
        for(i=0; i < 4; i++)
        {
            bCmdBuf[i] = 0xFF;
            bRxBuf[i] = 0xFF;
        }

        bCmdBuf[0] = (uint16)(((CAN_CONTROL_REG << 1) | (READ_REG_COMMAND)) & 0xFF); //Read back register command

        fnIosCANWakeUpPolledTransfer(bCmdBuf, bRxBuf, sizeof(bCmdBuf)/sizeof(uint16)); //Transmits SPI Data

        uReadReg = (uint16)(((bRxBuf[0] << 8) | bRxBuf[1]) & CAN_READ_MASK); //Reads back the Response from the read command

        uCANCtrlReg0 = uReadReg; //Stores the Read back to a global parameter
            //wcu_printf("fnIosCANWakeUpModeActive Ctrl CAN%i val:%02x:\n", uCanControllerID, uCANCtrlReg0);

        if (uReadReg == CAN_ACTIVE_MODE)
        {
            //If the Can Reg read has been correctly configured breaks the loop
            ConfigStatus = TRUE;
            break;
        }
    }
    return(ConfigStatus);
}

/*----------------------------------------------------------------------------*/
/*  FUNCTION : fnIosCANWakeUpModeControl                                      */
/*  DESC     : Initialise the CAN controller transceiver                      */
/*  PARAMS   : none                                                           */
/*  RETURNS  : none                                                           */
/*----------------------------------------------------------------------------*/
uint8 fnIosCANWakeUpIDAcquire(void)
{
    uint16 bCmdBuf[4] = {0}; // 0 - Register Address, 1 - Register Data
    uint16 bRxBuf [4] = {0};
    uint16 uReadReg = 0;
    uint8 ConfigStatus = FALSE;
    uint8 StateFlowLoop = 0, i =0;
    uint32 wDelayCntr = 0;

    for(StateFlowLoop = 0; StateFlowLoop < 5; StateFlowLoop++)
    {
        /* Quick clear of the command and receive buffer */
        for(i=0; i < 4; i++)
        {
            bCmdBuf[i] = 0xFF;
            bRxBuf[i] = 0xFF;
        }

        bCmdBuf[0] = (uint16)(((ID_UNIT_REG << 1) | (READ_REG_COMMAND)) & 0xFF); //Read back register command

        fnIosCANWakeUpPolledTransfer(bCmdBuf, bRxBuf, sizeof(bCmdBuf)/sizeof(uint16)); //Transmits SPI Data

        uReadReg = (uint16)(((bRxBuf[0] << 8) | bRxBuf[1]) & CAN_READ_MASK); //Reads back the Response from the read command

        uCANIDUnitReg0 = uReadReg; //Stores the Read back to a global parameter

        if (uReadReg == CAN_EXPECTED_ID)
        {
            //If the ID read has been correctly configured breaks the loop
            ConfigStatus = TRUE;
            break;
        }
    }
    return(ConfigStatus);
}

/*----------------------------------------------------------------------------*/
/*  FUNCTION : fnIosCANConfigWakeUp                                           */
/*  DESC     : Configures the CAN controllers with an SPI wake up             */
/*  PARAMS   : none                                                           */
/*  RETURNS  : none                                                           */
/*----------------------------------------------------------------------------*/
void fnIosCANConfigWakeUp(void)
{
    uint8 uCANWakeUpSPIStatus = 0;
    uint32 wDelayCntr = 0;

    uCANWakeUpSPIStatus = fnIosCANWakeUpSpiCtrlInitialise(); //Setups the PS SPI 1

    if (uCANWakeUpSPIStatus == TRUE)
    {

        fnIosCANWakeUpModeControl(); //Sets the CAN Controller to Normal Mode
        for(wDelayCntr = 0; wDelayCntr < 0xFFFF; wDelayCntr++);// Delay between config write and read back

        fnIosCANWakeUpModeActive();
        for(wDelayCntr = 0; wDelayCntr < 0xFFFF; wDelayCntr++);// Delay between config write and read back

    }
}

/**
 * @brief Read the CAN status register
 *
 * @param uCanControllerID ID of CAN device CAN1
 */
void fnIosCANWakeUpMainStatusAcquire(void)
{
    uint16 bCmdBuf[4] = {0}; // 0 - Register Address, 1 - Register Data
    uint16 bRxBuf [4] = {0};
    uint16 uReadReg = 0;
    uint8 i = 0;

    /* Quick clear of the command and receive buffer */
    for(i=0; i < 4; i++)
    {
        bCmdBuf[i] = 0xFF;
        bRxBuf[i] = 0xFF;
    }

    bCmdBuf[0] = (uint16)(((MAIN_STATUS_REG << 1) | (READ_REG_COMMAND)) & 0xFF); //Read back register command

    fnIosCANWakeUpPolledTransfer(bCmdBuf, bRxBuf, sizeof(bCmdBuf)/sizeof(uint16)); //Transmits SPI Data

    uReadReg = (uint16)(((bRxBuf[0] << 8) | bRxBuf[1]) & CAN_READ_MASK); //Reads back the Response from the read command

    uCANMainStatusReg0 = uReadReg; //Stores the Read back to a global parameter
    //wcu_printf("fnIosCANWakeUpMainStatusAcquire status val:%02x:\n", uCANMainStatusReg0);

}
