/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include "erm_drv.h"
#include "erm_reg.h"

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

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

/*******************************************************************************
 * the globals
 ******************************************************************************/

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

void ErmDrv_Init(ErmDrvType *obj, struct _ErmRegType_ *ermReg)
{
    obj->reg = ermReg;
}

void ErmDrv_GetDefaultConfig(ErmDrv_ChnErrConfigType *userConfig)
{
    uint8_t chnNum;
    uint8_t ctrlChnNum;

    for(chnNum = 0; chnNum < ERMDRV_CH_TOTAL_NUM; chnNum++)
    {
        /* ERM channel Irq enable, default: false */
        userConfig->chnIrq[chnNum] = false;
        /* ERM channel error status, default: false */
        userConfig->chnEvent[chnNum] = false;
    }

    for(ctrlChnNum = 0; ctrlChnNum < ERMDRV_CH_CTRL_TOTAL_NUM; ctrlChnNum++)
    {
        /* ERM channel 0~3 control error address, default: 0 */
        userConfig->chnStatus[ctrlChnNum].errAddr = 0;
        /* ERM channel 0~3 control error position, default: 0 */
        userConfig->chnStatus[ctrlChnNum].errPos = 0;
        /* ERM channel 0~3 control recover error num, default: 0 */
        userConfig->chnStatus[ctrlChnNum].errRecoverNum = 0;
    }
}

void ErmDrv_SetChnErrIrqEnable(ErmDrvType *obj, ErmDrv_ChnNumType chnNum, bool enable)
{
    switch(chnNum)
    {
    case ERMDRV_CH0_RECOVER_SRAM_IRQ:
        /* set ERM enable SRAM single bit recover channel */
        ErmReg_SetCr0Escie0(obj->reg, (uint8_t)enable);
        break;
    case ERMDRV_CH0_NONRECOVER_SRAM_IRQ:
        /* set ERM enable SRAM multi bits non-recover channel */
        ErmReg_SetCr0Encie0(obj->reg, (uint8_t)enable);
        break;
    case ERMDRV_CH1_RECOVER_FTFC_IRQ:
        /* set ERM enable FTFC single bit recover channel */
        ErmReg_SetCr0Escie1(obj->reg, (uint8_t)enable);
        break;
    case ERMDRV_CH1_NONRECOVER_FTFC_IRQ:
        /* set ERM enable FTFC multi bits non-recover channel */
        ErmReg_SetCr0Encie1(obj->reg, (uint8_t)enable);
        break;
    default:
        break;
    }
}

bool ErmDrv_GetChnErrIrqEnable(ErmDrvType *obj, ErmDrv_ChnNumType chnNum)
{
    switch(chnNum)
    {
    case ERMDRV_CH0_RECOVER_SRAM_IRQ:
        /* get ERM enable SRAM single bit recover channel status */
        return (bool)ErmReg_GetCr0Escie0(obj->reg);
    case ERMDRV_CH0_NONRECOVER_SRAM_IRQ:
        /* get ERM enable SRAM multi bits non-recover channel status */
        return (bool)ErmReg_GetCr0Encie0(obj->reg);
    case ERMDRV_CH1_RECOVER_FTFC_IRQ:
        /* get ERM enable FTFC single bit recover channel status */
        return (bool)ErmReg_GetCr0Escie1(obj->reg);
    case ERMDRV_CH1_NONRECOVER_FTFC_IRQ:
        /* get ERM enable FTFC multi bits non-recover channel status */
        return (bool)ErmReg_GetCr0Encie1(obj->reg);
    default:
        return ERMDRV_CH_TOTAL_NUM;
    }
}

bool ErmDrv_GetChnErrInfoStatus(ErmDrvType *obj, ErmDrv_ChnNumType chnNum)
{
    switch(chnNum)
    {
    case ERMDRV_CH0_RECOVER_SRAM_IRQ:
        /* get ERM enable SRAM single bit recover channel status */
        return (bool)ErmReg_GetSrSbc0(obj->reg);
    case ERMDRV_CH0_NONRECOVER_SRAM_IRQ:
        /* get ERM enable SRAM multi bits non-recover channel status */
        return (bool)ErmReg_GetSrNce0(obj->reg);
    case ERMDRV_CH1_RECOVER_FTFC_IRQ:
        /* get ERM enable FTFC single bit recover channel status */
        return (bool)ErmReg_GetSrSbc1(obj->reg);
    case ERMDRV_CH1_NONRECOVER_FTFC_IRQ:
        /* get ERM enable FTFC multi bits non-recover channel status */
        return (bool)ErmReg_GetSrNce1(obj->reg);
    default:
        return ERMDRV_CH_TOTAL_NUM;
    }
}

void ErmDrv_ClrChnErrInfoStatus(ErmDrvType *obj, ErmDrv_ChnNumType chnNum)
{
    switch(chnNum)
    {
    case ERMDRV_CH0_RECOVER_SRAM_IRQ:
        /* clear ERM enable SRAM single bit recover channel */
        ErmReg_SetSrSbc0(obj->reg, 0x01);
        break;
    case ERMDRV_CH0_NONRECOVER_SRAM_IRQ:
        /* clear ERM enable SRAM multi bits non-recover channel */
        ErmReg_SetSrNce0(obj->reg, 0x01);
        break;
    case ERMDRV_CH1_RECOVER_FTFC_IRQ:
        /* clear ERM enable FTFC single bit recover channel */
        ErmReg_SetSrSbc1(obj->reg, 0x01);
        break;
    case ERMDRV_CH1_NONRECOVER_FTFC_IRQ:
        /* clear ERM enable FTFC multi bits non-recover channel */
        ErmReg_SetSrNce1(obj->reg, 0x01);
        break;
    default:
        break;
    }
}

void ErmDrv_GetChnNumCfg(ErmDrvType *obj, ErmDrv_ChnNumInfoType *chnNumInfo, ErmDrv_CtrlChnNumType ctrlChnNum)
{
    if(ctrlChnNum == ERMDRV_CH0)
    {
        /* Get channel 0 error address */
        chnNumInfo->errAddr = ErmReg_GetCh0St0Adr0(obj->reg);
        /* Get channel 0 error position */
        chnNumInfo->errPos = ErmReg_GetCh0St1Syn0(obj->reg);
        /* Get channel 0 error total num */
        chnNumInfo->errRecoverNum = ErmReg_GetCh0St2CorrCnt0(obj->reg);
    }
    else if(ctrlChnNum == ERMDRV_CH1)
    {
        /* Get channel 0 error address */
        chnNumInfo->errAddr = ErmReg_GetCh1St0Adr1(obj->reg);
        /* Get channel 0 error position */
        chnNumInfo->errPos = ErmReg_GetCh1St1Syn1(obj->reg);
        /* Get channel 0 error total num */
        chnNumInfo->errRecoverNum = ErmReg_GetCh1St2CorrCnt1(obj->reg);
    }
    else
    {
        return;
    }
}

void ErmDrv_ClrChnNumCfg(ErmDrvType *obj, ErmDrv_CtrlChnNumType ctrlChnNum)
{
    if(ctrlChnNum == ERMDRV_CH0)
    {
        /* Clear channel 0 error total num */
        ErmReg_SetCh0St2CorrCnt0(obj->reg, ERMDRV_RECOVER_ERRNUM_CLR);
    }
    else if(ctrlChnNum == ERMDRV_CH1)
    {
        /* Clear channel 1 error total num */
        ErmReg_SetCh1St2CorrCnt1(obj->reg);
    }
    else
    {
        return;
    }
}
