/*
 * @file psm_ina230.c
 *
 *  @brief This file contains the driver function of power sense monitor INA230
 *
 *	@copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "psm_ina230.h"
#include <stdio.h>
#include "psm_register_map.h"
#include "main.h"
#include <string.h>
extern I2C_HandleTypeDef hi2c1;

psm_ina230_dev_t ps_psm_hdl = {0};
psm_ina230_dev_t pwr_psm_core1 = {0};
psm_ina230_dev_t pwr_psm_core2 = {0};
psm_ina230_dev_t pwr_psm_ps1 = {0};
psm_ina230_dev_t pwr_psm_ps2 = {0};
psm_ina230_dev_t pwr_psm_edge1 = {0};
psm_ina230_dev_t pwr_psm_edge2 = {0};
psm_ina230_dev_t pwr_psm_io = {0};

// interrupt handle TO DO

/*********************************************************************/
/* Static function declarations */
/**
 * @brief validate the device structure pointer
 * This API is used to validate the device structure pointer for null conditions.
 * @param[in] ina230_hdl         : Structure instance of psm_ina230.
 * @return Result of API execution status
 * @retval zero -> Success / -ve value -> Error.
 */

/**
 * @brief This API is used for i2c read.
 */
uint8_t ina230_i2c_read(void* intf_hdl, uint16_t slv_addr, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef*)intf_hdl;
    int8_t sts = INA230_ERR;
    memset(data, 0, len);
    if(HAL_I2C_Master_Transmit(hi2c, (uint16_t)slv_addr, &reg_addr, 1, 500) == HAL_OK)
    {
        HAL_Delay(20);
        if(HAL_I2C_Master_Receive(hi2c,(uint16_t)slv_addr, data, len, 500) == HAL_OK)
        {
            sts = INA230_SCS;
        }
        else
        {
            sts =INA230_E_COM_FAIL;
        }
    }
    else
    {
        sts =INA230_E_COM_FAIL;
    }
    return sts;
}

/**
 * @brief This API is used for i2c write.
 */
uint8_t ina230_i2c_write(void* intf_hdl, uint16_t slv_addr, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef*)intf_hdl;
    int8_t sts = INA230_ERR;
    uint8_t t_data[3] = {0};
    t_data[0]=reg_addr;
    t_data[1]=data[0];
    t_data[2]=data[1];
    if(data==NULL)
    {
        sts = HAL_I2C_Master_Transmit(hi2c, (uint16_t)slv_addr, t_data, len, 500);
        return sts;
    }
    if(HAL_I2C_Master_Transmit(hi2c, (uint16_t)slv_addr, t_data, 3, 500) == HAL_OK)
    {
        sts=INA230_SCS;
    }
    else
    {
        sts =INA230_E_COM_FAIL;
    }
    return sts;
}

static  int8_t null_ptr_check_ina230(ina230_dev_ptr_t ina230_hdl);

/**
 * @brief  Write access to INA230 register.
 */
e_ina230_sts ina230_writereg(ina230_dev_ptr_t ina230_hdl, uint8_t reg, uint16_t data)
{
    e_ina230_sts sts = INA230_ERR;
    uint8_t dt[2] = {0};
    dt[0] = data >> 8;
    dt[1] = data & 0xff;
    sts=ina230_hdl->write(ina230_hdl->io_intf_hdle,ina230_hdl->slave_address,reg,dt,2);
    return(sts);
}
/**
 * @brief API to read and write the data to register to self test .
 */
e_ina230_sts ina230_self_test(ina230_dev_ptr_t ina230_hdl)
{
    e_ina230_sts sts =INA230_ERR;
    uint16_t data = 0;
    uint16_t write_data =0x4127;
    uint16_t read_data = 0;
    sts =ina230_readreg(ina230_hdl,INA230_REG_CONFIG,&data);
    if (sts==INA230_SCS)
    {
        ina230_writereg( ina230_hdl, INA230_REG_CONFIG , write_data);
        ina230_readreg(ina230_hdl,INA230_REG_CONFIG,&read_data);
    }
    if (write_data == read_data)
    {
        sts= INA230_SCS;
    }
    else
    {
        sts = INA230_ERR;

    }
    ina230_writereg(ina230_hdl, INA230_REG_CONFIG ,data);
    return sts;
}

/**
 * @brief  Read access to INA230 register.
 */
e_ina230_sts ina230_readreg(ina230_dev_ptr_t ina230_hdl, uint8_t reg, uint16_t* data)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint8_t dt[2] = {0};
        if(ina230_hdl->read(ina230_hdl->io_intf_hdle,ina230_hdl->slave_address,reg,dt,2) == INA230_SCS)
        {
            (*data) = (uint16_t)((dt[0] << 8) | dt[1]);
            sts=INA230_SCS;
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return sts;
}

/**
 * @brief  Initialize the INA230 and configure the needed hardware resources.
 */
e_ina230_sts ina230_init(ina230_dev_ptr_t ina230_hdl)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        sts=ina230_reset(ina230_hdl);
        ina230_set_calibration(ina230_hdl,DEF_CALIB);
//        switch(ina230_hdl->alert_pin_function)
//        {
//        case ALERT_FUNCTION_BOL:
//        case ALERT_FUNCTION_BUL:
//            ina230_setvbusthreshold(ina230_hdl,ina230_hdl->vbus_threshold);
//            break;
//        case ALERT_FUNCTION_SOL:
//        case ALERT_FUNCTION_SUL:
//            ina230_set_current_threshold(ina230_hdl,ina230_hdl->current_threshold);
//            break;
//        case ALERT_FUNCTION_POL:
//            ina230_setpowerthreshold(ina230_hdl,ina230_hdl->power_threshold);
//            break;
//        default :
//            break;
//        }
//        ina230_set_alertfunction(ina230_hdl,ina230_hdl->alert_pin_function);
  }
    return (sts);
}

/**
 * @brief  De-Initialize the INA230 and configure the needed hardware resources
 */
e_ina230_sts ina230_deinit(ina230_dev_ptr_t ina230_hdl)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        sts=ina230_reset(ina230_hdl);
    }
    return (sts);
}

/**
 * @brief  Read the INA230 die identifier
 */
uint16_t ina230_read_id(ina230_dev_ptr_t ina230_hdl)
{
    uint16_t device_id;
    ina230_readreg(ina230_hdl, INA230_REG_ID,&device_id);
    return device_id;
}
#if 0
/**
 * @brief  Enable/Disable the ALERT interrupt
 */
static uint8_t ina230_int(ina230_dev_ptr_t ina230_hdl)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t apol = 0;

        apol = (ina230_readreg(ina230_hdl,INA230_REG_MASK_ENABLE,&apol) & INA230_REG_MASK_ENABLE_APOL_Msk);
        if(sts==INA230_SCS)
        {
            if (apol == INA230_REG_MASK_ENABLE_APOL)
            {

                uint8_t active_high=0x01;
                uint8_t alert = 0;
                alert=(alert & (0xFE));
                alert=(alert | (active_high));

                sts=ina230_hdl->write(ina230_hdl->io_intf_hdle,ina230_hdl->slave_address,INA230_REG_MASK_ENABLE,&alert,1); //ALERT pin is active high
            }
            else
            {

                uint8_t active_low=0;
                uint8_t alert;
                alert=(alert & (0xFF));
                alert=(alert | (active_low));
                sts=ina230_hdl->write(ina230_hdl->io_intf_hdle,ina230_hdl->slave_address,INA230_REG_MASK_ENABLE,&alert,1); //ALERT pin is active LOW (default)
            }
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (sts);
}
#endif

/**
 * @brief  Generate a system reset
 */
e_ina230_sts ina230_reset(ina230_dev_ptr_t ina230_hdl)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t cfg = 0;

        cfg |= INA230_REG_CFG_RESET;
        sts=ina230_writereg(ina230_hdl, INA230_REG_CONFIG, cfg);
    }
    return sts;
}

/**
 * @brief  Program the INA230 calibration register
 */
e_ina230_sts ina230_set_calibration(ina230_dev_ptr_t ina230_hdl, uint16_t calibration)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        sts = ina230_writereg(ina230_hdl, INA230_REG_CALIBRATION, calibration);
    }

    return sts;
}

/**
 * @brief  Read programmed calibration value
 */
uint16_t ina230_get_calibration(ina230_dev_ptr_t ina230_hdl)
{
    uint16_t calibration = 0;

    calibration = null_ptr_check_ina230(ina230_hdl);
    if (calibration != INA230_OK)
    {
        calibration = INA230_E_NULL_PTR;
    }
    else
    {
        ina230_readreg(ina230_hdl, INA230_REG_CALIBRATION,&calibration);
    }
    return (calibration);
}

/**
 *  @brief  Configure the Alert pin behavior
 */
e_ina230_sts ina230_alert_pinconfig(ina230_dev_ptr_t ina230_hdl,ina230_alert_pinconfig_ptr_t alert_pin_cfg_vd)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t mask_en = 0;

        sts = ina230_readreg(ina230_hdl, INA230_REG_MASK_ENABLE,&mask_en);
        if(sts==INA230_SCS)
        {

            mask_en = (mask_en & ((uint16_t)~(INA230_REG_MASK_ENABLE_APOL_Msk))) | (alert_pin_cfg_vd->polarity<< INA230_REG_MASK_ENABLE_APOL_Pos);
            mask_en = (mask_en & ((uint16_t)~(INA230_REG_MASK_ENABLE_LEN_Msk))) | (alert_pin_cfg_vd->latch_enable << INA230_REG_MASK_ENABLE_LEN_Pos);
            sts = ina230_writereg(ina230_hdl, INA230_REG_MASK_ENABLE, mask_en);
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return sts;
}

/**
 * @brief  Set the alert function
 */
e_ina230_sts ina230_set_alertfunction(ina230_dev_ptr_t ina230_hdl, ina230_af_t alertfunction)
{
    e_ina230_sts sts = INA230_ERR;
    uint16_t mask_en = 0;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts!= INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {

        sts = ina230_readreg(ina230_hdl, INA230_REG_MASK_ENABLE,&mask_en);
        if(sts==INA230_SCS)
        {

            switch(alertfunction)
            {
            case ALERT_FUNCTION_NONE:
                mask_en = (mask_en & (0x041F));
                break;
            case ALERT_FUNCTION_SOL:
                mask_en =(mask_en & (0x041F)) | 0x8000;
                break;
            case ALERT_FUNCTION_SUL:
                mask_en =(mask_en & (0x041F)) | 0x4000;
                break;
            case ALERT_FUNCTION_BOL:
                mask_en =(mask_en & (0x041F)) | 0x2000;
                break;
            case ALERT_FUNCTION_BUL:
                mask_en =(mask_en & (0x041F))  | 0x1000;
                break;
            case ALERT_FUNCTION_POL:
                mask_en =(mask_en & (0x041F))  | 0x0800;
                break;
            default:
                break;
            }
            sts= ina230_writereg(ina230_hdl, INA230_REG_MASK_ENABLE, mask_en);
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return sts;
}

/**
 * @brief  Get the programmed alert function
 */
e_ina230_sts ina230_get_alertfunction(ina230_dev_ptr_t ina230_hdl,ina230_af_t alert_function)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts!= INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t mask_en = 0;
        sts = ina230_readreg(ina230_hdl, INA230_REG_MASK_ENABLE,&mask_en);
        if(sts==INA230_SCS)
        {
            if ((mask_en & INA230_REG_MASK_ENABLE_POL) == INA230_REG_MASK_ENABLE_POL)
            {
                alert_function = ALERT_FUNCTION_POL;
            }
            else if ((mask_en & INA230_REG_MASK_ENABLE_BUL) == INA230_REG_MASK_ENABLE_BUL)
            {
                alert_function = ALERT_FUNCTION_BUL;
            }
            else if ((mask_en & INA230_REG_MASK_ENABLE_BOL) == INA230_REG_MASK_ENABLE_BOL)
            {
                alert_function = ALERT_FUNCTION_BOL;
            }
            else if ((mask_en & INA230_REG_MASK_ENABLE_SUL) == INA230_REG_MASK_ENABLE_SUL)
            {
                alert_function = ALERT_FUNCTION_SUL;
            }
            else if ((mask_en & INA230_REG_MASK_ENABLE_SOL) == INA230_REG_MASK_ENABLE_SOL)
            {
                alert_function = ALERT_FUNCTION_SOL;
            }
            else
            {
                alert_function = ALERT_FUNCTION_NONE;
            }
            sts=alert_function;
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (sts);
}

/**
 * @brief  Program the VBus threshold
 */
e_ina230_sts ina230_setvbusthreshold(ina230_dev_ptr_t ina230_hdl, float vbusthreshold)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        val = vbusthreshold / BUS_VOLTAGE_LSB;
        sts=ina230_writereg(ina230_hdl, INA230_REG_ALERT_LIMIT,val);
    }
    return (sts);
}

/**
 * @brief  Get the VBUS threshold
 */
uint16_t ina230_getvbusthreshold(ina230_dev_ptr_t ina230_hdl)
{

    uint16_t  sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        uint32_t vbus_threshold = 0;
        sts = ina230_readreg(ina230_hdl, INA230_REG_ALERT_LIMIT,&val);
        if(sts==INA230_SCS)
        {
            vbus_threshold = (val * BUS_VOLTAGE_LSB);
            vbus_threshold = DIV_ROUND_CLOSEST(vbus_threshold, 1000);
            sts=(uint16_t)vbus_threshold;
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (sts);
}

/**
 * @brief  set the current threshold
 */
e_ina230_sts ina230_set_current_threshold(ina230_dev_ptr_t ina230_hdl, float current)
{
    e_ina230_sts sts = INA230_ERR;

    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        val = (current*RSHUNT)/VSHUNT_DIV;
        sts=ina230_writereg(ina230_hdl, INA230_REG_ALERT_LIMIT, val);
    }
    return (sts);
}

/**
 * @brief  Program the VShunt threshold
 */
e_ina230_sts ina230_setvshuntthreshold(ina230_dev_ptr_t ina230_hdl, float vshuntthreshold)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        val = vshuntthreshold / VSHUNT_DIV;
        sts=ina230_writereg(ina230_hdl, INA230_REG_ALERT_LIMIT, val);
    }
    return (sts);
}

/**
 * @brief  Get the VShunt threshold
 */
int16_t ina230_getshuntthreshold(ina230_dev_ptr_t ina230_hdl)
{
    uint16_t vshunt_threshold = 0;
    int16_t sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        sts = ina230_readreg(ina230_hdl, INA230_REG_ALERT_LIMIT,&val);
        if(sts==INA230_SCS)
        {
            vshunt_threshold = DIV_ROUND_CLOSEST(val, VSHUNT_DIV);
            sts= INA230_SCS;
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (vshunt_threshold);
}

/**
 * @brief  Program the Power threshold
 */
e_ina230_sts ina230_setpowerthreshold(ina230_dev_ptr_t ina230_hdl, uint32_t powerthreshold)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        val = powerthreshold / POWER_LSB;
        sts=ina230_writereg(ina230_hdl, INA230_REG_ALERT_LIMIT, val);
    }
    return (sts);

}

/**
 * @brief  Get the Power threshold
 */
uint32_t ina230_getpowerthreshold(ina230_dev_ptr_t ina230_hdl)
{

    uint32_t sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
        uint32_t power_threshold = 0;
        ina230_readreg(ina230_hdl, INA230_REG_ALERT_LIMIT,&val);
        if(sts==INA230_SCS)
        {
            power_threshold = (uint32_t)(val *POWER_LSB);
            sts=power_threshold;
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (sts);
}

/**
 * @brief  Stop the conversion on the selected voltage input
 */
e_ina230_sts ina230_stopconversion(ina230_dev_ptr_t ina230_hdl)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t cfg = 0;
        sts = ina230_readreg(ina230_hdl, INA230_REG_CONFIG,&cfg);
        if(sts==INA230_SCS)
        {
            cfg = (cfg & ((uint16_t)~(INA230_REG_CFG_MODE_Msk)));
            sts=ina230_writereg(ina230_hdl, INA230_REG_CONFIG, cfg);
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (sts);
}

/**
 * @brief  Read the bus voltage
 */
float ina230_get_vbus(ina230_dev_ptr_t ina230_hdl )
{
    uint8_t sts = INA230_ERR;
    float vbus = 0;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t val = 0;
       HAL_Delay(5);
        sts = ina230_readreg(ina230_hdl, INA230_REG_VBUS,&val);
        if(sts==INA230_SCS)
        {
            vbus = (val * BUS_VOLTAGE_LSB);
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (vbus);
}

/**
 * @brief  Read the shunt voltage
 */
float ina230_get_vshunt(ina230_dev_ptr_t ina230_hdl)
{
    uint16_t sts = INA230_ERR;
    uint16_t val = 0;
    float vshunt =0;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        HAL_Delay(5);
        sts = ina230_readreg(ina230_hdl, INA230_REG_VSHUNT,&val);
        if(sts==INA230_SCS)
        {
            vshunt =val* VSHUNT_DIV;
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (vshunt);
}

/**
 * @brief  Read the power value
 */
uint32_t ina230_get_power(ina230_dev_ptr_t ina230_hdl)
{
    uint32_t sts = INA230_ERR;
    uint16_t val = 0;
    uint32_t power =0;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        HAL_Delay(5);
        sts = ina230_readreg(ina230_hdl, INA230_REG_PWR, &val);
        if(sts == INA230_SCS)
        {
                power = val * POWER_LSB;
        }
        else
        {
            sts = INA230_E_READ_FAIL;
        }
    }
    return (power);
}

/**
 * @brief  Read the current value
 */
float ina230_get_current(ina230_dev_ptr_t ina230_hdl)
{
    uint16_t temp = 0;
    uint8_t sts = INA230_ERR;
    float current = 0;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        HAL_Delay(5);
        sts = ina230_readreg(ina230_hdl, INA230_REG_CURRENT,&temp);
        if(sts == INA230_SCS && temp < 3000)
        {
                current = ((temp*CURR_MULTIPLIER)/1000.0);
        }
        else
        {
            sts = INA230_E_READ_FAIL;
        }
    }
    return (current);
}

static const uint16_t aMode[INA230_OPERATING_MODE_MAX][INA230_VOLTAGE_INPUT_MAX] = 
{
        {
                INA230_MODE_TRIGGERED_VSHUNT,
                INA230_MODE_TRIGGERED_VBUS,
                INA230_MODE_TRIGGERED_ALL
        },
        {
                INA230_MODE_CONTINOUS_VSHUNT,
                INA230_MODE_CONTINOUS_VBUS,
                INA230_MODE_CONTINOUS_ALL
        }
};

static const uint16_t aflags[INA230_FLAG_MAX] =
{
        INA230_REG_MASK_ENABLE_AFF,
        INA230_REG_MASK_ENABLE_CVRF,
        INA230_REG_MASK_ENABLE_OVF
};

/**
 * @brief  Launch the conversion on the selected voltage input
 */
e_ina230_sts ina230_startconversion(ina230_dev_ptr_t ina230_hdl, ina230_inputsignal_t inputsignal, ina230_operatingmode_t mode)
{
    e_ina230_sts sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t cfg = 0;
        sts = ina230_readreg(ina230_hdl, INA230_REG_CONFIG,&cfg);
        if(sts==INA230_SCS)
        {
            cfg = (cfg & ((uint16_t)~(INA230_REG_CFG_MODE_Msk))) | aMode[mode][inputsignal];
            sts=ina230_writereg(ina230_hdl, INA230_REG_CONFIG, cfg);
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return (sts);
}

/**
 * @brief  Read the designed flag value
 */
uint8_t ina230_get_flag(ina230_dev_ptr_t ina230_hdl, ina230_flag_t flag)
{
    uint8_t sts = INA230_ERR;
    sts = null_ptr_check_ina230(ina230_hdl);
    if (sts != INA230_OK)
    {
        sts = INA230_E_NULL_PTR;
    }
    else
    {
        uint16_t flags = 0;
        sts = ina230_readreg(ina230_hdl, INA230_REG_MASK_ENABLE,&flags) & REG_MASK_ENABLE_FLAGS_Msk;
        if(sts==INA230_SCS)
        {
            sts= ((aflags[flag] & flags) == aflags[flag]);
        }
        else
        {
            sts=INA230_E_READ_FAIL;
        }
    }
    return sts;
}

/**
 * @brief This API is used to validate the device structure pointer for null conditions.
 */
static  int8_t null_ptr_check_ina230(ina230_dev_ptr_t ina230_hdl)
{
    int8_t sts = INA230_ERR;
    if ((ina230_hdl == NULL) || (ina230_hdl->read == NULL) || (ina230_hdl->write == NULL))
    {
        sts=INA230_E_NULL_PTR;
    }
    else
    {
        sts=INA230_OK;
    }
    return sts;
}

/**
 * @brief init payload board power sensor monitor
 */
void ps_temp_sensor_init(uint8_t ahw_id)
{
    switch(ahw_id)
    {
    case PSM_INA230_PS:
    {
        ps_psm_hdl.io_intf_hdle = &hi2c1;
        ps_psm_hdl.slave_address = 0x82;
        ps_psm_hdl.write = ina230_i2c_write;
        ps_psm_hdl.read =  ina230_i2c_read;
        ina230_init(&ps_psm_hdl);
    }
        break;

    default:
        break;
    }
}

/**
 * @brief init power board power sensor monitor
 */
void pwr_brd_psm_sensor_init(uint8_t ahw_id)
{
    switch(ahw_id)
    {
    case PSM_INA230_CORE_BRD_A:
    {
        pwr_psm_core1.io_intf_hdle = &hi2c1;
        pwr_psm_core1.slave_address = 0x82;
        pwr_psm_core1.write = ina230_i2c_write;
        pwr_psm_core1.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_core1);
    }
    break;

    case PSM_INA230_CORE_BRD_B:
    {
        pwr_psm_core2.io_intf_hdle = &hi2c1;
        pwr_psm_core2.slave_address = 0x80;
        pwr_psm_core2.write = ina230_i2c_write;
        pwr_psm_core2.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_core2);
    }
    break;

    case PSM_INA230_PS_1:
    {
        pwr_psm_ps1.io_intf_hdle = &hi2c1;
        pwr_psm_ps1.slave_address = 0x84;
        pwr_psm_ps1.write = ina230_i2c_write;
        pwr_psm_ps1.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_ps1);
    }
    break;

    case PSM_INA230_PS_2:
    {
        pwr_psm_ps2.io_intf_hdle = &hi2c1;
        pwr_psm_ps2.slave_address = 0x86;
        pwr_psm_ps2.write = ina230_i2c_write;
        pwr_psm_ps2.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_ps2);
    }
    break;

    case PSM_INA230_EDGE_1:
    {
        pwr_psm_edge1.io_intf_hdle = &hi2c1;
        pwr_psm_edge1.slave_address = 0x92;
        pwr_psm_edge1.write = ina230_i2c_write;
        pwr_psm_edge1.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_edge1);
    }
    break;

    case PSM_INA230_EDGE_2_IN_SUPPLY:
    {
        pwr_psm_edge2.io_intf_hdle = &hi2c1;
        pwr_psm_edge2.slave_address = 0x88;
        pwr_psm_edge2.write = ina230_i2c_write;
        pwr_psm_edge2.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_edge2);
    }
    break;

    case PSM_INA230_IO_BRD_IN_SUPPLY:
    {
        pwr_psm_io.io_intf_hdle = &hi2c1;
        pwr_psm_io.slave_address = 0x8E;
        pwr_psm_io.write = ina230_i2c_write;
        pwr_psm_io.read =  ina230_i2c_read;
        ina230_init(&pwr_psm_io);
    }
    break;

    default:
        break;
    }
}
