/*
 * @file pwr_brd.c
 */
#include "string.h"
#include "main.h"
#include "pwr_brd.h"
#include "mcp23008_gpio_expander.h"
#include "mcp9843.h"
#include "psm_ina230.h"
#include "adm1176.h"
#include "adc7291.h"

extern I2C_HandleTypeDef hi2c1;
extern s_mcp23008 hgpio_exp_pwr_u3;
extern s_mcp23008 hgpio_exp_pwr_u19;
extern s_mcp23008 hgpio_exp_pwr_u20;

extern s_adm1176_drv_cb hsc_ps1_sply;
extern s_adm1176_drv_cb hsc_ps2_sply;
extern s_adm1176_drv_cb hsc_es1_sply;
extern s_adm1176_drv_cb hsc_es2_sply;
extern s_adm1176_drv_cb hsc_es1_heat_sply;
extern s_adm1176_drv_cb hsc_es2_heat_sply;
extern s_adm1176_drv_cb hsc_io_brd_sply;
extern s_adm1176_drv_cb hsc_io_heat_coil_top1;
extern s_adm1176_drv_cb hsc_io_heat_coil_top2;
extern s_adm1176_drv_cb hsc_io_heat_coil_bot1;
extern s_adm1176_drv_cb hsc_io_heat_coil_bot2;

extern psm_ina230_dev_t pwr_psm_core1;
extern psm_ina230_dev_t pwr_psm_core2;
extern psm_ina230_dev_t pwr_psm_ps1;
extern psm_ina230_dev_t pwr_psm_ps2;
extern psm_ina230_dev_t pwr_psm_edge1;
extern psm_ina230_dev_t pwr_psm_edge2;
extern psm_ina230_dev_t pwr_psm_io;

extern ad7291_dev_t hgpio_ps1_adc_U9;
extern ad7291_dev_t hgpio_ps2_adc_U10;
extern ad7291_dev_t hgpio_oring_circuit_adc_U12;

uint8_t reg_data[2]={0};
uint8_t addr = 0;
uint8_t pwr_sts = MCP23008_SCS;

/*
 *  PWR_BOARD init gpio expander function
 */
uint8_t pwr_brd_gpio_exp_self_test()
{

    pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_1);
    HAL_Delay(1);
    pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_2);
    HAL_Delay(1);
    pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_3);
    HAL_Delay(1);

    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|SSD_HEAT_TOP1_EN|
            SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN|CORE_PCB_SEN_ALERT,MCP23008_GPIO_OUTPUT);
    pwr_sts |= mcp23008_self_test(&hgpio_exp_pwr_u3);
    if(pwr_sts == MCP23008_SCS)
    {
        printf("GPIO_EXPANDER = U3 SELF TEST SUCCESS \n\n\r");
    }
    else
    {
        printf("GPIO_EXPANDER = U3 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
    }

    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u19,PS1_PCB_SEN_ALERT|PS2_PCB_SEN_ALERT| \
            PAY_LOAD1_ALERT|PAY_LOAD2_ALERT|IO_PCB_SEN_ALERT|E1_PCB_SEN_ALERT|
            CORE2_PCB_SEN_ALERT|E2_PCB_SEN_ALERT,MCP23008_GPIO_OUTPUT);
    pwr_sts |= mcp23008_self_test(&hgpio_exp_pwr_u19);
    if(pwr_sts == MCP23008_SCS)
    {
        printf("GPIO_EXPANDER = U19 SELF TEST SUCCESS \n\n\r");
    }
    else
    {
        printf("GPIO_EXPANDER = U19 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
    }

    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u20, UART4_IN1_RE|UART4_IN1_DE| \
            UART4_IN2_RE|UART4_IN2_DE|CORE_IO2_EXPD_INT2_U19, MCP23008_GPIO_OUTPUT);
    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u20, PAY_LOAD1_ALERT3, MCP23008_GPIO_INPUT);
    pwr_sts |= mcp23008_self_test(&hgpio_exp_pwr_u20);
    if(pwr_sts == MCP23008_SCS)
    {
        printf("GPIO_EXPANDER = U20 SELF TEST SUCCESS \n\n\r");
    }
    else
    {
        printf("GPIO_EXPANDER = U20 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
        printf("\033[1;31mI2C COMMUNICATION FAIL\033[0m \n\n\r");
    }
    return pwr_sts;
}


/*
 *  Power_Board Hotswap Controller get temperature function
 */
uint8_t pwr_brd_get_hsc_tempreature(hsc_sns_info_s *hsc_info_s)
{
    hsc_info_s->hsc_crnt = 0;
    hsc_info_s->hsc_vlt = 0;
    if(hsc_info_s != NULL)
    {
        pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_1);
        HAL_Delay(1);
        pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|SSD_HEAT_TOP1_EN|
                SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN|CORE_PCB_SEN_ALERT,MCP23008_GPIO_OUTPUT);
        pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|SSD_HEAT_TOP1_EN|
                SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN|CORE_PCB_SEN_ALERT,MCP23008_GPIO_HIGH);
        if(pwr_sts == MCP23008_SCS)
        {
            printf("GPIO_EXPANDER = U3 SUCCESS \n\n\r");
        }

        pwr_brd_hsc_init(HSC_ADM1176_PS_1_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_ps1_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_ps1_sply);
        printf("PS_1 ADM1176 U4 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("PS_1 ADM1176 U4 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_PS_2_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_ps2_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_ps2_sply);
        printf("PS_2 ADM1176 U7 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("PS_2 ADM1176 U7 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init( HSC_ADM1176_EDGE_1_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt  = adm1176_read_current(&hsc_es1_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_es1_sply);

        printf("EDGE_1 ADM1176 U11 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("EDGE_1 ADM1176 U11 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_EDGE_2_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_es2_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_es2_sply);
        printf("EDGE_2 ADM1176 U14 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("EDGE_2 ADM1176 U14 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_io_brd_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_io_brd_sply);

        printf("IO_BRD ADM1176 U17 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("IO_BRD ADM1176 U17 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_EDGE_1_HEAT_COIL);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_es1_heat_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_es1_heat_sply);

        printf("ES_1 HEAT COIL ADM1176 U25 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("ES_1 HEAT COIL ADM1176 U25 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);


        pwr_brd_hsc_init(HSC_ADM1176_EDGE_2_HEAT_COIL);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_es2_heat_sply);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_es2_heat_sply);

        printf("ES_2 HEAT COIL ADM1176 U28 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("ES_2 HEAT COIL ADM1176 U28 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_TOP_1);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_io_heat_coil_top1);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_io_heat_coil_top1);

        printf("IO HEAT COIL TOP1 ADM1176 U18 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("IO HEAT COIL TOP1 ADM1176 U18 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_TOP_2);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_io_heat_coil_top2);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_io_heat_coil_top2);
        printf("IO HEAT COIL TOP2 ADM1176 U32 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("IO HEAT COIL TOP2 ADM1176 U32 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_BOTTOM_1);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_io_heat_coil_bot1);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_io_heat_coil_bot1);
        printf("IO HEAT COIL BOT1 ADM1176 U34 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("IO HEAT COIL BOT1 ADM1176 U34 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);

        pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_BOTTOM_2);
        HAL_Delay(1);
        hsc_info_s->hsc_crnt = adm1176_read_current(&hsc_io_heat_coil_bot2);
        hsc_info_s->hsc_vlt = adm1176_read_voltage(&hsc_io_heat_coil_bot2);
        printf("IO HEAT COIL BOT2 ADM1176 U36 HSC VOLTAGE  : %f\n\r",hsc_info_s->hsc_vlt);
        printf("IO HEAT COIL BOT2 ADM1176 U36 HSC CURRENT  : %f\n\n\r",hsc_info_s->hsc_crnt);
    }
    else
    {
        pwr_sts = MCP23008_NULL_PTR;
    }
    return pwr_sts;
}

/*
 *  Power_Board Power Sensor Monitoring get temperature function
 */
uint8_t pwr_brd_get_psm_tempreature(hsc_sns_info_s *hsc_info_s)
{
    if(hsc_info_s != NULL)
    {
        pwr_brd_psm_sensor_init(PSM_INA230_CORE_BRD_A);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg           = ina230_get_vbus(&pwr_psm_core1);
        hsc_info_s->vshunt_voltage     = ina230_get_vshunt(&pwr_psm_core1);
        hsc_info_s->psm_power          = ina230_get_power(&pwr_psm_core1);
        hsc_info_s->psm_current        = ina230_get_current(&pwr_psm_core1);
        printf("CORE_BRD_A INA230 U5 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("CORE_BRD_A INA230 U5 PSM VSHUNT   : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("CORE_BRD_A INA230 U5 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("CORE_BRD_A INA230 U5 psm current  : %f\n\n\r",hsc_info_s->psm_current);

        pwr_brd_psm_sensor_init(PSM_INA230_CORE_BRD_B);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg           = ina230_get_vbus(&pwr_psm_core2);
        hsc_info_s->vshunt_voltage     = ina230_get_vshunt(&pwr_psm_core2);
        hsc_info_s->psm_power          = ina230_get_power(&pwr_psm_core2);
        hsc_info_s->psm_current        = ina230_get_current(&pwr_psm_core2);
        printf("CORE_BRD_B INA230 U8 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("CORE_BRD_B INA230 U8 PSM VSHUNT   : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("CORE_BRD_B INA230 U8 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("CORE_BRD_B INA230 U8 psm current  : %f\n\n\r",hsc_info_s->psm_current);

        pwr_brd_psm_sensor_init(PSM_INA230_PS_1);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg           = ina230_get_vbus(&pwr_psm_ps1);
        hsc_info_s->vshunt_voltage     = ina230_get_vshunt(&pwr_psm_ps1);
        hsc_info_s->psm_power          = ina230_get_power(&pwr_psm_ps1);
        hsc_info_s->psm_current        = ina230_get_current(&pwr_psm_ps1);
        printf("PS_1 INA230 U21 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("PS_1 INA230 U21 PSM VSHUNT   : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("PS_1 INA230 U21 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("PS_1 INA230 U21 psm current  : %f\n\n\r",hsc_info_s->psm_current);

        pwr_brd_psm_sensor_init(PSM_INA230_PS_2);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg           = ina230_get_vbus(&pwr_psm_ps2);
        hsc_info_s->vshunt_voltage     = ina230_get_vshunt(&pwr_psm_ps2);
        hsc_info_s->psm_power          = ina230_get_power(&pwr_psm_ps2);
        hsc_info_s->psm_current        = ina230_get_current(&pwr_psm_ps2);
        printf("PS_2 INA230 U22 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("PS_2 INA230 U22 PSM VSHUNT   : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("PS_2 INA230 U22 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("PS_2 INA230 U22 psm current  : %f\n\n\r",hsc_info_s->psm_current);

        pwr_brd_psm_sensor_init(PSM_INA230_EDGE_1);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg          = ina230_get_vbus(&pwr_psm_edge1);
        hsc_info_s->vshunt_voltage    = ina230_get_vshunt(&pwr_psm_edge1);
        hsc_info_s->psm_power         = ina230_get_power(&pwr_psm_edge1);
        hsc_info_s->psm_current       = ina230_get_current(&pwr_psm_edge1);
        printf("EDGE_1 INA230 U23 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("EDGE_1 INA230 U23 PSM POWER    : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("EDGE_1 INA230 U23 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("EDGE_1 INA230 U23 psm current  : %f\n\n\r",hsc_info_s->psm_current);

        pwr_brd_psm_sensor_init(PSM_INA230_EDGE_2_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg          = ina230_get_vbus(&pwr_psm_edge2);
        hsc_info_s->vshunt_voltage    = ina230_get_vshunt(&pwr_psm_edge2);
        hsc_info_s->psm_power         = ina230_get_power(&pwr_psm_edge2);
        hsc_info_s->psm_current       = ina230_get_current(&pwr_psm_edge2);
        printf("EDGE_2 INA230 U26 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("EDGE_2 INA230 U26 PSM VSHUNT   : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("EDGE_2 INA230 U26 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("EDGE_2 INA230 U26 psm current  : %f\n\n\r",hsc_info_s->psm_current);

        pwr_brd_psm_sensor_init(PSM_INA230_IO_BRD_IN_SUPPLY);
        HAL_Delay(1);
        hsc_info_s->vbus_vlg          = ina230_get_vbus(&pwr_psm_io);
        hsc_info_s->vshunt_voltage    = ina230_get_vshunt(&pwr_psm_io);
        hsc_info_s->psm_power         = ina230_get_power(&pwr_psm_io);
        hsc_info_s->psm_current       = ina230_get_current(&pwr_psm_io);
        printf("IO_BRD INA230 U29 PSM VOLTAGE  : %f\n\r",hsc_info_s->vbus_vlg);
        printf("IO_BRD INA230 U29 PSM VSHUNT   : %f\n\r",hsc_info_s->vshunt_voltage);
        printf("IO_BRD INA230 U29 PSM POWER    : %d\n\r",(int)hsc_info_s->psm_power);
        printf("IO_BRD INA230 U29 psm current  : %f\n\n\r",hsc_info_s->psm_current);
    }
    else
    {
        pwr_sts = MCP23008_NULL_PTR;
    }
    return pwr_sts;
}

/*
 *  PWR_BOARD self test init function
 */
void pwr_brd_adc7291_self_test()
{
    pwr_brd_adc7291_init(ADC_AD7291_PS_1);
    HAL_Delay(1);
    pwr_sts = ad7291_self_test(&hgpio_ps1_adc_U9);
    if(pwr_sts == AD7291_SCS)
    {
        printf("PS_1 ADC7291 = U3 SELF TEST SUCCESS \n\n\r");
    }
    else
    {
        printf("PS_1 ADC7291 = U3 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
    }

    pwr_brd_adc7291_init(ADC_AD7291_PS_2);
    HAL_Delay(1);
    pwr_sts = ad7291_self_test(&hgpio_ps2_adc_U10);
    if(pwr_sts == AD7291_SCS)
    {
        printf("PS_2 ADC7291 = U10 SELF TEST SUCCESS \n\n\r");
    }
    else
    {
        printf("PS_2 ADC7291 = U10 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
    }

    pwr_brd_adc7291_init(ADC_AD7291_ORING_CIRCUIT);
    HAL_Delay(1);
    pwr_sts = ad7291_self_test(&hgpio_oring_circuit_adc_U12);
    if(pwr_sts == AD7291_SCS)
    {
        printf("ORING_BRD ADC7291 = U12 SELF TEST SUCCESS \n\n\r");
    }
    else
    {
        printf("ORING_BRD ADC7291 = U12 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
    }
}

/**
 * @Power board power supply test function.
 */
void power_board_supply_test(uint8_t* case_id, uint8_t on_off)
{
    if(case_id != NULL)
    {
        switch(*case_id)
        {
        case PS1_ON:
        {
            addr = ADM1176_U4;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case PS1_OFF:
        {
            addr = ADM1176_U4;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case PS2_ON:
        {
            addr = ADM1176_U7;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case PS2_OFF:
        {
            addr = ADM1176_U7;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case ES1_ON:
        {
            addr = ADM1176_U11;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case ES1_OFF:
        {
            addr = ADM1176_U11;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case ES2_ON:
        {
            addr = ADM1176_U14;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case ES2_OFF:
        {
            addr = ADM1176_U14;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case IO_ON:
        {
            addr = ADM1176_U17;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }
        break;
        case IO_OFF:
        {
            addr = ADM1176_U17;
            reg_data[0]=CONTROL;
            reg_data[1]=on_off;
        }   break;
        default:
            printf("Invalid CASE ID \n\n\r");
        }
    }
    else
    {
        pwr_sts = MCP23008_NULL_PTR;
    }
    pwr_sts = HAL_I2C_Master_Transmit(&hi2c1,addr,reg_data,2,I2C_TEST_TIMEOUT);
    if(pwr_sts != HAL_OK)
    {
        printf("\033[1;31mI2C COMMUNICATION FAIL\033[0m \n\n\r");
        printf("ADM1176 GATE ENABLE \033[1;31mFAIL \033[0m\n\n\r");
    }
    else
    {
        printf("ADM1176 GATE ENABLE SUCCESS\n\n\r");
    }
}

/**
 * @Power board power sensor self test function.
 */
uint8_t pwr_brd_sensor_self_test(uint8_t *sns_tst_id)
{
    pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_1);
    HAL_Delay(1);
    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|SSD_HEAT_TOP1_EN|
            SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN,MCP23008_GPIO_OUTPUT);
    pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|SSD_HEAT_TOP1_EN|
            SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN,MCP23008_GPIO_HIGH);

    if(sns_tst_id != NULL)
    {
        switch(*sns_tst_id)
        {

        /*
         * Power Sensor Monitoring Self Test Function
         */
        case PSM_TEST:
        {
            pwr_brd_psm_sensor_init(PSM_INA230_CORE_BRD_A);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_core1);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U5 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U5 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_psm_sensor_init(PSM_INA230_CORE_BRD_B);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_core2);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U8 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U8 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_psm_sensor_init(PSM_INA230_PS_1);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_ps1);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U21 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U21 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_psm_sensor_init(PSM_INA230_PS_2);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_ps2);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U22 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U22 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_psm_sensor_init(PSM_INA230_EDGE_1);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_edge1);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U23 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U23 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_psm_sensor_init(PSM_INA230_EDGE_2_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_edge2);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U26 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U26 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_psm_sensor_init(PSM_INA230_IO_BRD_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts = ina230_self_test(&pwr_psm_io);
            if(pwr_sts == INA230_SCS)
            {
                printf("PSM = U29 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("PSM = U29 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
        }
        break;

        /*
         * Hotswap Controller Self Test Function
         */
        case HSC_TEST:
        {
            pwr_brd_hsc_init(HSC_ADM1176_PS_1_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts |= adm1176_self_test(&hsc_ps1_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U4 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U4 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_PS_2_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_ps2_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U7 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U7 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_EDGE_1_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_es1_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U11 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U11 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }

            pwr_brd_hsc_init(HSC_ADM1176_EDGE_1_HEAT_COIL);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_es1_heat_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U25 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U25 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }

            pwr_brd_hsc_init(HSC_ADM1176_EDGE_2_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_es2_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U14 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U14 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }

            pwr_brd_hsc_init(HSC_ADM1176_EDGE_2_HEAT_COIL);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_es2_heat_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U28 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U28 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_IN_SUPPLY);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_io_brd_sply);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U17 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U17 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_TOP_1);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_io_heat_coil_top1);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U18 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U18 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_TOP_2);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_io_heat_coil_top2);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U32 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U32 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_BOTTOM_1);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_io_heat_coil_bot1);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U34 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U34 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
            pwr_brd_hsc_init(HSC_ADM1176_IO_BRD_HEAT_COIL_BOTTOM_2);
            HAL_Delay(1);
            pwr_sts = adm1176_self_test(&hsc_io_heat_coil_bot2);
            if(pwr_sts == ADM1176_SCS)
            {
                printf("HSC = U36 SELF TEST SUCCESS \n\n\r");
            }
            else
            {
                printf("HSC = U36 SELF TEST \033[1;31mFAIL \033[0m \n\n\r");
            }
        }
        break;
        default:
            printf("INVALID TEST ID \n\n\r");
            break;
        }
    }
    else
    {
        pwr_sts = INA230_NULL_PTR;
    }
    return pwr_sts;
}


/**
 * @Power board TOP and BOTTOM test function.
 */
void power_board_top_bot_supply_test(uint8_t* case_id, uint8_t on_off)
{
    /*
     * U3 => This GPIO_EXPANDER enables power to the ADM1176 sensor.
     * It can open and close the gate for the power supply.
     */
    pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_1);
    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|
            SSD_HEAT_TOP1_EN|SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN,MCP23008_GPIO_OUTPUT);
    pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u3,E1_SSD0_HEAT_EN|E2_SSD0_HEAT_EN|
            SSD_HEAT_TOP1_EN|SSD_HEAT_TOP2_EN|SSD_HEAT_BOT1_EN|SSD_HEAT_BOT2_EN,MCP23008_GPIO_HIGH);

    if(pwr_sts == MCP23008_SCS)
    {
        printf("GPIO_EXPANDER = U3 SUCCESS \n\n\r");

        if(case_id != NULL)
        {
            switch(*case_id)
            {
            case IO1_TOP_ON:
            {
                addr = ADM1176_U18;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO1_TOP_OFF:
            {
                addr = ADM1176_U18;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO2_TOP_ON:
            {
                addr = ADM1176_U32;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO2_TOP_OFF:
            {
                addr = ADM1176_U32;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO1_BOT_ON:
            {
                addr = ADM1176_U34;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO1_BOT_OFF:
            {
                addr = ADM1176_U34;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO2_BOT_ON:
            {
                addr = ADM1176_U36;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case IO2_BOT_OFF:
            {
                addr = ADM1176_U36;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case SSD1_HEAT_ON:
            {
                addr = ADM1176_U25;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case SSD1_HEAT_OFF:
            {
                addr = ADM1176_U25;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case SSD2_HEAT_ON:
            {
                addr = ADM1176_U28;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            case SSD2_HEAT_OFF:
            {
                addr = ADM1176_U28;
                reg_data[0]=CONTROL;
                reg_data[1]=on_off;
            }
            break;
            default:
                printf("Invalid CASE ID\n\r");
            }
        }
        else
        {
            pwr_sts = MCP23008_NULL_PTR;
        }
    }
    else
    {
        printf("GPIO_EXPANDER = U3 \033[1;31mFAIL \033[0m\n\n\r");
    }
    pwr_sts = HAL_I2C_Master_Transmit(&hi2c1,addr,reg_data,2,I2C_TEST_TIMEOUT);
    if(pwr_sts!=HAL_OK)
    {
        printf("\033[1;31mI2C COMMUNICATION FAIL\033[0m \n\n\r");
        printf("HEAT ENABLE GPIO EXPANDER WRITE GATE SEQUENCE \033[1;31mFAIL \033[0m\n\n\r");
    }
    else
    {
        printf("HEAT ENABLE GPIO EXPANDER WRITE GATE SEQUENCE SUCCESS\n\n\r");
    }
}

/*
 *  PWR_BOARD UART_RS_485 IC Test function
 */
void uart_rs485_test(uint8_t* test_id)
{
    /*
     * This GPIO EXPANDER Power enable the UART RS_485
     */
    pwr_brd_gpio_exp_test_init(GPIO_EXP_MCP23008_PWR_BRD_3);
    HAL_Delay(1);
    pwr_sts |= mcp23008_set_direction(&hgpio_exp_pwr_u20, UART4_IN1_RE|UART4_IN1_DE| \
            UART4_IN2_RE|UART4_IN2_DE, MCP23008_GPIO_OUTPUT);

    if(test_id != NULL)
    {
        if(test_id[0] == RS485_U1)
        {
            switch(test_id[1])
            {
            case RS485_TX:
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN1_RE,MCP23008_GPIO_HIGH);
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN1_DE,MCP23008_GPIO_HIGH);
                if(pwr_sts == MCP23008_SCS)
                {
                    printf("RS485 UART TX SEQUENCE WRITE SUCCESS \n\n\r");
                }
                else
                {
                    printf("\033[1;31mRS485 UART TX SEQUENCE WRITE FAIL\033[0m \n\n\r");
                }
                break;

            case RS485_RX:
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN1_RE,MCP23008_GPIO_LOW);
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN1_DE,MCP23008_GPIO_LOW);
                if(pwr_sts == MCP23008_SCS)
                {
                    printf("RS485 UART TX SEQUENCE WRITE SUCCESS \n\n\r");
                }
                else
                {
                    printf("\033[1;31mRS485 UART TX SEQUENCE WRITE FAIL\033[0m \n\n\r");
                }
                break;
            default:
                printf("Invalid CASE ID\n\r");
            }

        }
        else if(test_id[0] == RS485_U16)
        {
            switch(test_id[1])
            {
            case RS485_TX:
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN2_RE,MCP23008_GPIO_HIGH);
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN2_DE,MCP23008_GPIO_HIGH);
                if(pwr_sts == MCP23008_SCS)
                {
                    printf("RS485 UART TX SEQUENCE WRITE SUCCESS \n\n\r");
                }
                else
                {
                    printf("\033[1;31mRS485 UART TX SEQUENCE WRITE FAIL\033[0m \n\n\r");
                }
                break;

            case RS485_RX:
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN2_RE,MCP23008_GPIO_LOW);
                pwr_sts |= mcp23008_write_pin(&hgpio_exp_pwr_u20,UART4_IN2_DE,MCP23008_GPIO_LOW);
                if(pwr_sts == MCP23008_SCS)
                {
                    printf("RS485 UART RX SEQUENCE WRITE SUCCESS \n\n\r");
                }
                else
                {
                    printf("\033[1;31mRS485 UART RX SEQUENCE WRITE FAIL\033[0m \n\n\r");
                }
                break;
            default:
                printf("Invalid CASE ID\n\r");
            }
        }
    }
    else
    {
        pwr_sts = MCP23008_NULL_PTR;
    }
}
