//
// Created by dell on 24-12-20.
// TMP112A Temperature Sensor Driver Implementation
//

#include "tmp112.h"

/* Private function prototypes */
static i2c_result_t tmp112a_write_register(uint8_t reg_addr, uint16_t value);
static i2c_result_t tmp112a_read_register(uint8_t reg_addr, uint16_t *value);
static float tmp112a_raw_to_celsius(uint16_t raw_data);
static uint16_t tmp112a_celsius_to_raw(float temperature);

/*!
    \brief      初始化TMP112A传感器
    \param[in]  none
    \param[out] none
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_init(void) {
    i2c_result_t i2c_status;
    
    /* 配置传感器为默认设置 */
    i2c_status = tmp112a_config(TMP112A_CONFIG_DEFAULT);
    if (i2c_status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 等待配置生效 */
    delay_ms(1);
    
    return TMP112A_STATUS_SUCCESS;
}

/*!
    \brief      配置TMP112A传感器
    \param[in]  config: 配置值
    \param[out] none
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_config(uint16_t config) {
    i2c_result_t status = tmp112a_write_register(TMP112A_CONFIG_REG, config);
    return (status == I2C_RESULT_SUCCESS) ? TMP112A_STATUS_SUCCESS : TMP112A_STATUS_ERROR;
}

/*!
    \brief      读取温度
    \param[in]  none
    \param[out] result: 结果结构体指针
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_read_temperature(tmp112a_result_t *result) {
    uint16_t raw_data;
    i2c_result_t status;
    
    if (result == NULL) {
        return TMP112A_STATUS_INVALID_PARAM;
    }
    
    /* 读取温度寄存器 */
    status = tmp112a_read_register(TMP112A_TEMP_REG, &raw_data);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 解析温度数据 */
    result->raw_data = raw_data;
    result->temperature_c = tmp112a_raw_to_celsius(raw_data);
    result->temperature_f = result->temperature_c * 9.0f / 5.0f + 32.0f;
    
    /* 检查温度范围 */
    if (result->temperature_c < TMP112A_TEMP_MIN || result->temperature_c > TMP112A_TEMP_MAX) {
        return TMP112A_STATUS_OUT_OF_RANGE;
    }
    
    /* 检查报警标志 */
    uint16_t config_reg;
    status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg);
    if (status == I2C_RESULT_SUCCESS) {
        result->alert_flag = (config_reg & TMP112A_CONFIG_AL) ? true : false;
    } else {
        result->alert_flag = false;
    }
    
    return TMP112A_STATUS_SUCCESS;
}

void tmp112a_get_raw_temperature_value(uint8_t *value) {
    // i2c_read_16bits(TMP112A_ADDR, TMP112A_TEMP_REG, value);
    i2c_read(TMP112A_ADDR, TMP112A_TEMP_REG, value, 2);
    return;
}

/*!
    \brief      设置温度阈值
    \param[in]  low_temp: 低温阈值 (°C)
    \param[in]  high_temp: 高温阈值 (°C)
    \param[out] none
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_set_thresholds(float low_temp, float high_temp) {
    uint16_t low_raw, high_raw;
    i2c_result_t status;
    
    /* 参数验证 */
    if (low_temp < TMP112A_TEMP_MIN || low_temp > TMP112A_TEMP_MAX ||
        high_temp < TMP112A_TEMP_MIN || high_temp > TMP112A_TEMP_MAX ||
        low_temp >= high_temp) {
        return TMP112A_STATUS_INVALID_PARAM;
    }
    
    /* 转换温度为原始值 */
    low_raw = tmp112a_celsius_to_raw(low_temp);
    high_raw = tmp112a_celsius_to_raw(high_temp);
    
    /* 写入低温阈值 */
    status = tmp112a_write_register(TMP112A_TLOW_REG, low_raw);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 写入高温阈值 */
    status = tmp112a_write_register(TMP112A_THIGH_REG, high_raw);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    return TMP112A_STATUS_SUCCESS;
}

/*!
    \brief      进入关机模式
    \param[in]  none
    \param[out] none
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_shutdown(void) {
    uint16_t config_reg;
    i2c_result_t status;
    
    /* 读取当前配置 */
    status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 设置关机位 */
    config_reg |= TMP112A_CONFIG_SD;
    
    /* 写回配置 */
    status = tmp112a_write_register(TMP112A_CONFIG_REG, config_reg);
    return (status == I2C_RESULT_SUCCESS) ? TMP112A_STATUS_SUCCESS : TMP112A_STATUS_ERROR;
}

/*!
    \brief      退出关机模式
    \param[in]  none
    \param[out] none
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_wakeup(void) {
    uint16_t config_reg;
    i2c_result_t status;
    
    /* 读取当前配置 */
    status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 清除关机位 */
    config_reg &= ~TMP112A_CONFIG_SD;
    
    /* 写回配置 */
    status = tmp112a_write_register(TMP112A_CONFIG_REG, config_reg);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 等待传感器启动 */
    delay_ms(1);
    
    return TMP112A_STATUS_SUCCESS;
}

/*!
    \brief      单次转换
    \param[in]  none
    \param[out] result: 结果结构体指针
    \retval     tmp112a_status_t
*/
tmp112a_status_t tmp112a_one_shot(tmp112a_result_t *result) {
    uint16_t config_reg;
    i2c_result_t status;
    uint8_t timeout = 100; // 100ms超时
    
    if (result == NULL) {
        return TMP112A_STATUS_INVALID_PARAM;
    }
    
    /* 读取当前配置 */
    status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 启动单次转换 */
    config_reg |= TMP112A_CONFIG_OS;
    status = tmp112a_write_register(TMP112A_CONFIG_REG, config_reg);
    if (status != I2C_RESULT_SUCCESS) {
        return TMP112A_STATUS_ERROR;
    }
    
    /* 等待转换完成 */
    do {
        delay_ms(1);
        status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg);
        if (status != I2C_RESULT_SUCCESS) {
            return TMP112A_STATUS_ERROR;
        }
        timeout--;
    } while ((config_reg & TMP112A_CONFIG_OS) && timeout > 0);
    
    if (timeout == 0) {
        return TMP112A_STATUS_TIMEOUT;
    }
    
    /* 读取转换结果 */
    return tmp112a_read_temperature(result);
}

/*!
    \brief      获取状态字符串
    \param[in]  status: 状态码
    \param[out] none
    \retval     const char* 状态字符串
*/
const char* tmp112a_get_status_string(tmp112a_status_t status) {
    switch (status) {
        case TMP112A_STATUS_SUCCESS:
            return "SUCCESS";
        case TMP112A_STATUS_ERROR:
            return "ERROR";
        case TMP112A_STATUS_TIMEOUT:
            return "TIMEOUT";
        case TMP112A_STATUS_INVALID_PARAM:
            return "INVALID_PARAM";
        case TMP112A_STATUS_OUT_OF_RANGE:
            return "OUT_OF_RANGE";
        default:
            return "UNKNOWN";
    }
}

/* Private Functions Implementation */

/*!
    \brief      写入寄存器
    \param[in]  reg_addr: 寄存器地址
    \param[in]  value: 写入值
    \param[out] none
    \retval     i2c_result_t
*/
static i2c_result_t tmp112a_write_register(uint8_t reg_addr, uint16_t value) {
    uint8_t data[2];
    data[0] = (value >> 8) & 0xFF;
    data[1] = value & 0xFF;

    return i2c_write_16bits(TMP112A_ADDR, reg_addr, data);
}

/*!
    \brief      读取寄存器
    \param[in]  reg_addr: 寄存器地址
    \param[out] value: 读取值指针
    \retval     i2c_result_t
*/
static i2c_result_t tmp112a_read_register(uint8_t reg_addr, uint16_t *value) {
    uint8_t data[2];
    i2c_result_t status;

    if (value == NULL) {
        return I2C_RESULT_INVALID_PARAM;
    }

    status = i2c_read_16bits(TMP112A_ADDR, reg_addr, data);
    if (status == I2C_RESULT_SUCCESS) {
        *value = ((uint16_t)data[0] << 8) | data[1];
    }

    return status;
}

/*!
    \brief      将原始数据转换为摄氏度
    \param[in]  raw_data: 原始数据
    \param[out] none
    \retval     float 温度值(°C)
*/
static float tmp112a_raw_to_celsius(uint16_t raw_data) {
    int16_t temp_raw;

    /* TMP112A使用12位分辨率，数据在高12位 */
    temp_raw = (int16_t)(raw_data >> 4);

    /* 处理负数 */
    if (temp_raw & 0x800) {
        temp_raw |= 0xF000; // 符号扩展
    }

    /* 转换为摄氏度 */
    return (float)temp_raw * TMP112A_TEMP_RESOLUTION;
}

/*!
    \brief      将摄氏度转换为原始数据
    \param[in]  temperature: 温度值(°C)
    \param[out] none
    \retval     uint16_t 原始数据
*/
static uint16_t tmp112a_celsius_to_raw(float temperature) {
    int16_t temp_raw;

    /* 转换为原始值 */
    temp_raw = (int16_t)(temperature / TMP112A_TEMP_RESOLUTION);

    /* 移位到高12位 */
    return (uint16_t)(temp_raw << 4);
}
