/*
 * 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 "eim_drv.h"
#include "eim_reg.h"

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

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

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

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

#define     EIM_LENGTH_CHK                  (8)
#define     EIM_LENGTH_DATA                 (32)
#define     EIM_LENGTH_ADDR                 (32)


uint8_t arr_data2reg_chk[EIM_LENGTH_CHK]   = {
    0, 1, 3, 7, 15, 31,                                            /* REG_DATA */
    31,                                                            /* REG_ADDR */
    7                                                              /* REG_CHK  */
}; 

uint8_t arr_data2reg_data[EIM_LENGTH_DATA] = {
    2, 4, 5, 6, 8, 9, 10, 11, 12,                                  /* REG_DATA */
    13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 
    24, 25, 26, 27, 28, 29, 30,
    0, 1, 2, 3, 4, 5                                               /* REG_ADDR */

};

uint8_t arr_data2reg_addr[EIM_LENGTH_ADDR] = {
    6, 7, 8, 9, 10, 11, 12, 13, 14, 15,                            /* REG_ADDR */
    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 
    26, 27, 28, 29, 30,
    0, 1, 2, 3, 4, 5, 6                                            /* REG_CHK  */
};



uint8_t arr_reg2data_chk[EIM_LENGTH_CHK]   = {
    25, 26, 27, 28, 29, 30, 31,                                    /* REG_ADDR */
    7                                                              /* REG_CHK  */
}; 

uint8_t arr_reg2data_data[EIM_LENGTH_DATA] = {
    0, 1,                                                          /* REG_CHK  */
    0,                                                             /* REG_DATA */
    2,                                                             /* REG_CHK  */
    1, 2, 3,                                                       /* REG_DATA */
    3,                                                             /* REG_CHK  */
    4, 5, 6, 7, 8, 9, 10,                                          /* REG_DATA */
    4,                                                             /* REG_CHK  */
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,    /* REG_DATA */
    5                                                              /* REG_CHK  */
                                   
};

uint8_t arr_reg2data_addr[EIM_LENGTH_ADDR] = {
    26, 27, 28, 29, 30, 31,                                        /* REG_DATA */
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,          /* REG_ADDR */
    16, 17, 18, 19, 20, 21, 22, 23, 24,
    6                                                              /* REG_CHK  */
};

static void EimDrv_RegToDataConvert(EimDrv_SramType *sramType, EimDrv_SramType *sramType_temp)
{
    uint8_t i;
    uint8_t length = EIM_LENGTH_CHK;

    for (i = 0; i < length; i++)
    {
        if ((sramType_temp->data_h >> i) & 0x01)
        {
            if ( i <= 6 )                   sramType->data_m |= 1 << arr_reg2data_chk[i];
            if (i > 6 && i < length )       sramType->data_h |= 1 << arr_reg2data_chk[i];
        }
    }

    length = EIM_LENGTH_DATA;
    for (i = 0; i < length; i++)
    {
        if ((sramType_temp->data_l >> i) & 0x01)
        {
            if (i <= 1 )                    sramType->data_h |= 1 << arr_reg2data_data[i];
            if (i == 2 )                    sramType->data_l |= 1 << arr_reg2data_data[i];
            if (i == 3 )                    sramType->data_h |= 1 << arr_reg2data_data[i];
            if (i > 3 && i <= 6 )           sramType->data_l |= 1 << arr_reg2data_data[i];
            if (i == 7 )                    sramType->data_h |= 1 << arr_reg2data_data[i];
            if (i > 7 && i <= 14 )          sramType->data_l |= 1 << arr_reg2data_data[i];
            if (i == 15 )                   sramType->data_h |= 1 << arr_reg2data_data[i];
            if (i > 16 && i <= 30 )         sramType->data_l |= 1 << arr_reg2data_data[i];
            if (i == 31 )                   sramType->data_h |= 1 << arr_reg2data_data[i];
        }
    }

    length = EIM_LENGTH_ADDR;
    for (i = 0; i < length; i++)
    {
        if ((sramType_temp->data_m >> i) & 0x01)
        {
            if (i <= 5 )                    sramType->data_l |= 1 << arr_reg2data_addr[i];
            if (i > 5 && i <= 30 )          sramType->data_m |= 1 << arr_reg2data_addr[i];
            if (i == 31 )                   sramType->data_h |= 1 << arr_reg2data_addr[i];
        }
    }
}

static void EimDrv_DataToRegConvert(EimDrv_SramType *sramType, EimDrv_SramType *sramType_temp)
{
    uint8_t i;
    uint8_t length = EIM_LENGTH_CHK;

    for (i = 0; i < length; i++)
    {
        if ((sramType->data_h >> i) & 0x01)
        {
            if (i <= 5 )                    sramType_temp->data_l |= 1 << arr_data2reg_chk[i];
            if (i > 5 && i <= 6 )           sramType_temp->data_m |= 1 << arr_data2reg_chk[i];
            if (i > 6 && i < length )       sramType_temp->data_h |= 1 << arr_data2reg_chk[i];
        }
    }

    length = EIM_LENGTH_DATA;
    for (i = 0; i < length; i++)
    {
        if ((sramType->data_l >> i) & 0x01)
        {
            if (i <= 26 )                   sramType_temp->data_l |= 1 << arr_data2reg_data[i];
            if (i > 26 && i < length )      sramType_temp->data_m |= 1 << arr_data2reg_data[i];
        }
    }

    length = EIM_LENGTH_ADDR;
    for (i = 0; i < length; i++)
    {
        if ((sramType->data_m >> i) & 0x01)
        {
            if (i <= 24 )                    sramType_temp->data_m |= 1 << arr_data2reg_addr[i];
            if (i > 24 && i < length )       sramType_temp->data_h |= 1 << arr_data2reg_addr[i];
        }
    }
}

void EimDrv_Init(EimDrvType *obj, struct _EimRegType_ *eimReg)
{
    obj->reg = eimReg;
}

void EimDrv_GetDefaultConfig(EimDrv_ChnCfgType *userConfig)
{
    /* Get Error in global enable status, default: false */
    userConfig->globalEnable = false;

    /* Get Error in channel num enable status, default: false */
    userConfig->chnNumStatus = false;

    /* Get Error in sram data high, default: 0 */
    userConfig->accSramCfg.data_h = 0;
    /* Get Error in sram data middle, default: 0 */
    userConfig->accSramCfg.data_m = 0;
    /* Get Error in sram data low, default: 0 */
    userConfig->accSramCfg.data_l = 0;
}

bool EimDrv_GetChnGlobalEnable(EimDrvType *obj)
{
    /* Get Error in global enable */
    return EimReg_GetCrGeiEn(obj->reg);
}

void EimDrv_EnableGlobalChn(EimDrvType *obj, bool enable)
{
    /* Config Error in global enable */
    EimReg_SetCrGeiEn(obj->reg, (uint8_t)enable);
}

bool EimDrv_GetChnNumEnable(EimDrvType *obj)
{
    /* Get Error in channel num enable */
    return (bool)EimReg_GetChEnCh0(obj->reg);
}

void EimDrv_EnableChannel(EimDrvType *obj, bool enable)
{
    /* Set Error in channel num enable */
    EimReg_SetChEnCh0(obj->reg, (uint8_t)enable);
}

void EimDrv_GetSramErrInStatus(EimDrvType *obj, EimDrv_SramType *sramType)
{
    EimDrv_SramType sramType_temp = {0};

    /* get error in access sram data high  */
    sramType_temp.data_h = EimReg_GetCh0DataH(obj->reg);
    /* get error in access sram data middle */
    sramType_temp.data_m = EimReg_GetCh0DataM(obj->reg);
    /* get error in access sram low */
    sramType_temp.data_l = EimReg_GetCh0DataL(obj->reg);

    EimDrv_RegToDataConvert(sramType, &sramType_temp);
}

void EimDrv_SetSramErrInStatus(EimDrvType *obj, EimDrv_SramType *sramType)
{
    EimDrv_SramType sramType_temp = {0};

    EimDrv_DataToRegConvert(sramType, &sramType_temp);

    /* set error in access sram data high  */
    EimReg_SetCh0DataH(obj->reg, sramType_temp.data_h);
    /* set error in access sram data middle */
    EimReg_SetCh0DataM(obj->reg, sramType_temp.data_m);
    /* set error in access sram low */
    EimReg_SetCh0DataL(obj->reg, sramType_temp.data_l);
}
