/**
 * \file
 * \brief sm6218模块驱动源文件
 * 
 * \internal
 * \par modification history:
 * - 1.00 25-04-15, first implementation.
 * \endinternal
 */

#include "sm6218.h"
#include "main.h"

// 保存配置完成后的设备
static zlg_sm6218_device_t *p_dev1 = NULL;

/**
 * \brief sm6218读数据
 */
static int __sm6218_read_data(zlg_sm6218_device_t *p_dev, uint16_t memaddr, uint16_t memsize, uint8_t *p_data, uint16_t size)
{
    HAL_StatusTypeDef i2c_status;
    i2c_status = HAL_I2C_Mem_Read(p_dev->hi2c, (p_dev->sm6218_addr<<1), memaddr, memsize, p_data, size, 3000);
    if(i2c_status != HAL_OK) {
        return -1;
    }
    return 0;
}

/**
 * \brief sm6218写数据
 */
static int __sm6218_write_data(zlg_sm6218_device_t *p_dev, uint16_t memaddr, uint16_t memsize, uint8_t *p_data, uint16_t size)
{
    HAL_StatusTypeDef i2c_status;
    i2c_status = HAL_I2C_Mem_Write(p_dev->hi2c, (p_dev->sm6218_addr<<1), memaddr, memsize, p_data, size, 3000);
    if(i2c_status != HAL_OK) {
        return -1;
    }
    return 0;
}

/**
 * \brief 将读取到的寄存器值转为温度值
 */
static float __sm6218_reg_to_temp(uint8_t *p_data)
{
    uint32_t temp = 0;
    
    temp |= p_data[0] ;
    temp |= p_data[1] << 8;
    temp |= p_data[2] << 16;
    
    
    //当前测量温度为负温度值
    if(temp >= 8388608){
        return (-(float)((16777216 - temp)/(float)(0x1<<13)));
    } else {
        return ((float)(temp/(float)(0x1<<13)));
    }
}

/**
 * \brief 获取寄存器通道的温度值
 */
int sm6218_get_temp(zlg_sm6218_device_t *p_dev, uint16_t memaddr, int8_t chan, float *p_data)
{
    int ret = 0;
    float    temp_buff[8] = {0};
    uint8_t  rx_buff[24] = {0};

    if ( p_dev == NULL || p_data == NULL) {
        return SM6218_VALUE_ERROR;
    }
    if (chan < 0 || chan > 7) {
        return SM6218_VALUE_ERROR;
    }
    
    ret = __sm6218_read_data(p_dev, memaddr, 1, &rx_buff[0], SM6218_TEMP_LEN);
    if (ret < 0) {
        return SM6218_FUN_ERROR;
    }
    
    switch (chan) {
        case 0:
            temp_buff[0] = __sm6218_reg_to_temp(&rx_buff[0]);
            *p_data = temp_buff[0];
            break;
        case 1:
            temp_buff[1] = __sm6218_reg_to_temp(&rx_buff[3]);
            *p_data = temp_buff[1];
            break;
        case 2:
            temp_buff[2] = __sm6218_reg_to_temp(&rx_buff[6]);
            *p_data = temp_buff[2];
            break;
        case 3:
            temp_buff[3] = __sm6218_reg_to_temp(&rx_buff[9]);
            *p_data = temp_buff[3];
            break;
        case 4:
            temp_buff[4] = __sm6218_reg_to_temp(&rx_buff[12]);
            *p_data = temp_buff[4];
            break;
        case 5:
            temp_buff[5] = __sm6218_reg_to_temp(&rx_buff[15]);
            *p_data = temp_buff[5];
            break;
        case 6:
            temp_buff[6] = __sm6218_reg_to_temp(&rx_buff[18]);
            *p_data = temp_buff[6];
            break;
        case 7:
            temp_buff[7] = __sm6218_reg_to_temp(&rx_buff[21]);
            *p_data = temp_buff[7];
            break;
        default:
            break;
    }

    return SM6218_FUN_OK;
}

/**
 * \brief 获取寄存器通道的电压值
 */
int sm6218_get_vol(zlg_sm6218_device_t *p_dev, uint16_t memaddr, int8_t chan, float *p_data)
{
    int ret = 0;
    float    temp_buff[8] = {0};
    uint8_t  rx_buff[24] = {0};

    if ( p_dev == NULL || p_data == NULL) {
        return SM6218_VALUE_ERROR;
    }
    if (chan < 0 || chan > 7) {
        return SM6218_VALUE_ERROR;
    }
    
    ret = __sm6218_read_data(p_dev, memaddr, 1, &rx_buff[0], SM6218_VOL_LEN);
    if (ret < 0) {
        return SM6218_FUN_ERROR;
    }
    
    switch (chan) {
        case 0:
            temp_buff[0] = __sm6218_reg_to_temp(&rx_buff[0]);
            *p_data = temp_buff[0];
            break;
        case 1:
            temp_buff[1] = __sm6218_reg_to_temp(&rx_buff[3]);
            *p_data = temp_buff[1];
            break;
        case 2:
            temp_buff[2] = __sm6218_reg_to_temp(&rx_buff[6]);
            *p_data = temp_buff[2];
            break;
        case 3:
            temp_buff[3] = __sm6218_reg_to_temp(&rx_buff[9]);
            *p_data = temp_buff[3];
            break;
        case 4:
            temp_buff[4] = __sm6218_reg_to_temp(&rx_buff[12]);
            *p_data = temp_buff[4];
            break;
        case 5:
            temp_buff[5] = __sm6218_reg_to_temp(&rx_buff[15]);
            *p_data = temp_buff[5];
            break;
        case 6:
            temp_buff[6] = __sm6218_reg_to_temp(&rx_buff[18]);
            *p_data = temp_buff[6];
            break;
        case 7:
            temp_buff[7] = __sm6218_reg_to_temp(&rx_buff[21]);
            *p_data = temp_buff[7];
            break;
        default:
            break;
    }

    return SM6218_FUN_OK;
}

/**
 * \brief 获取寄存器通道的冷端温度
 */
int sm6218_get_cold_temp(zlg_sm6218_device_t *p_dev, uint16_t memaddr, int8_t chan, float *p_data)
{
    int ret = 0;
    float    temp_buff[8] = {0};
    uint8_t  rx_buff[24] = {0};

    if ( p_dev == NULL || p_data == NULL) {
        return SM6218_VALUE_ERROR;
    }
    if (chan < 0 || chan > 7) {
        return SM6218_VALUE_ERROR;
    }
    
    ret = __sm6218_read_data(p_dev, memaddr, 1, &rx_buff[0], SM6218_COLD_LEN);
    if (ret < 0) {
        return SM6218_FUN_ERROR;
    }
    
    switch (chan) {
        case 0:
            temp_buff[0] = __sm6218_reg_to_temp(&rx_buff[0]);
            *p_data = temp_buff[0];
            break;
        case 1:
            temp_buff[1] = __sm6218_reg_to_temp(&rx_buff[3]);
            *p_data = temp_buff[1];
            break;
        case 2:
            temp_buff[2] = __sm6218_reg_to_temp(&rx_buff[6]);
            *p_data = temp_buff[2];
            break;
        case 3:
            temp_buff[3] = __sm6218_reg_to_temp(&rx_buff[9]);
            *p_data = temp_buff[3];
            break;
        case 4:
            temp_buff[4] = __sm6218_reg_to_temp(&rx_buff[12]);
            *p_data = temp_buff[4];
            break;
        case 5:
            temp_buff[5] = __sm6218_reg_to_temp(&rx_buff[15]);
            *p_data = temp_buff[5];
            break;
        case 6:
            temp_buff[6] = __sm6218_reg_to_temp(&rx_buff[18]);
            *p_data = temp_buff[6];
            break;
        case 7:
            temp_buff[7] = __sm6218_reg_to_temp(&rx_buff[21]);
            *p_data = temp_buff[7];
            break;
        default:
            break;
    }

    return SM6218_FUN_OK;
}

/**
 * \brief 设置通道配置
 */
int sm6218_config_set(zlg_sm6218_device_t *p_dev, uint8_t *config)
{
    int     ret;
    
    if (p_dev == NULL) {
        return SM6218_VALUE_ERROR;
    }
    
    ret = __sm6218_write_data(p_dev, SM6218_CONFIG_ADDR, 1, config, SM6218_CONFIG_LEN);
    if (ret < 0) {
        return SM6218_FUN_ERROR;
    }
    
    return SM6218_FUN_OK;
}

/**
 * \brief 设置通道采样速率
 */
int sm6218_speed_set(zlg_sm6218_device_t *p_dev, uint8_t *config)
{
    int     ret;
    
    if (p_dev == NULL) {
        return SM6218_VALUE_ERROR;
    }
    
    ret = __sm6218_write_data(p_dev, SM6218_SPEED_ADDR, 1, config, SM6218_SPEED_LEN);
    if (ret < 0) {
        return SM6218_FUN_ERROR;
    }
    
    return SM6218_FUN_OK;
}

/**
 * \brief 获取寄存器通道的温度值 (4Byte)
 */
int sm6218_get_temp_4b(zlg_sm6218_device_t *p_dev, uint16_t memaddr, int8_t chan, float *p_data)
{
    int      i;
    int      ret = 0;
    float    temp_buff[8] = {0};
    uint8_t  rx_buff[32] = {0};
    uint32_t temp_u32[8];

    if ( p_dev == NULL || p_data == NULL) {
        return SM6218_VALUE_ERROR;
    }
    if (chan < 0 || chan > 7) {
        return SM6218_VALUE_ERROR;
    }
    
    ret = __sm6218_read_data(p_dev, memaddr, 1, &rx_buff[0], SM6218_TEMP_4B_LEN);
    if (ret < 0) {
        return SM6218_FUN_ERROR;
    }
    
    for (i = 0;i < 8;i++) {               
        memcpy(&temp_u32[i],&rx_buff[i * 4],4);
        temp_buff[i] =  *(float *)&temp_u32[i];
    }
    
    *p_data = temp_buff[chan];
    

    return SM6218_FUN_OK;
}





/** end of file **/