/******************************************************************************
版权所有：	
文件名称：	aht20.c
文件版本：	01.01
创建作者:	Ewen
创建日期：	2025-11-10
功能说明：	aht20驱动程序。
其它说明：
修改记录：

/*------------------------------ 头文件 ---------------------------------------
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <errno.h>
#include "head.h"

#ifdef TMP_CHIP_AHT20
/*------------------------------ 宏定义 ---------------------------------------
*/

#define I2C_DEV         "/dev/i2c-5"
// 以下定义见AHT20 datasheet
// AHT20 设备地址
#define AHT20_I2C_ADDR  0x38

// AHT20 命令字
#define AHT20_CMD_INIT  0xBE
#define AHT20_CMD_MEAS  0xAC
#define AHT20_CMD_RESET 0xBA

/*------------------------------ 全局变量 -------------------------------------
*/
struct aht20 aht20;

int g_aht20_fd;

/*------------------------------ 函数声明 -------------------------------------
*/

// AHT20 初始化
static int _aht20_init(int fd) {
    uint8_t init_cmd[3] = {AHT20_CMD_INIT, 0x08, 0x00};
    
    if (write(fd, init_cmd, sizeof(init_cmd)) != sizeof(init_cmd)) 
    {
        printf("Failed to send init command: %s\n", strerror(errno));

        return -1;
    }
    
    return 0;
}

// AHT20 软复位
static int _aht20_soft_reset(int fd) {
    uint8_t reset_cmd = AHT20_CMD_RESET;
    
    if (write(fd, &reset_cmd, sizeof(reset_cmd)) != sizeof(reset_cmd)) 
    {
        printf("Failed to send reset command: %s\n", strerror(errno));
        return -1;
    }
    
    return 0;
}

// 读取温湿度数据
static int _aht20_read_data(int fd, float* temperature, float* humidity) 
{
    uint8_t cmd[3] = {AHT20_CMD_MEAS, 0x33, 0x00};
    uint8_t data[6] = {0};
    uint32_t temp_raw = 0, humi_raw = 0;
    
    // 发送测量命令
    if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
        printf("Failed to send measure command: %s\n", strerror(errno));

        return -1;
    }
    
    // 等待测量完成（最多100ms）
    int timeout = 0;
    while (timeout < 100) {
        msleep(1);
        if (read(fd, data, 1) == 1) {
            if (!(data[0] & 0x80)) {  // 检查忙标志位
                break;
            }
        }
        timeout++;
    }
    
    if (timeout >= 100) {
        printf("AHT20 measurement timeout\r\n");
        return -1;
    }
    
    // 读取测量数据
    if (read(fd, data, sizeof(data)) != sizeof(data)) {
        printf("Failed to read measurement data: %s\r\n", strerror(errno));

        return -1;
    }
    
    // 检查数据状态位
    if ((data[0] & 0x68) != 0x08) {
        printf("AHT20 data not ready or invalid\r\n");
        return -1;
    }
    
    // 解析湿度数据（20位）
    humi_raw = ((uint32_t)data[1] << 12) | 
               ((uint32_t)data[2] << 4) | 
               ((uint32_t)data[3] >> 4);
    
    // 解析温度数据（20位）
    temp_raw = (((uint32_t)data[3] & 0x0F) << 16) | 
               ((uint32_t)data[4] << 8) | 
               data[5];
    
    // 转换为实际值
    *humidity = (float)humi_raw * 100.0 / (1 << 20);
    *temperature = (float)temp_raw * 200.0 / (1 << 20) - 50.0;
    
    return 0;
}

int aht20_init(void)
{
    memset(&aht20, 0, sizeof(aht20));

    // 打开I2C设备
    g_aht20_fd = open(I2C_DEV, O_RDWR);
    if (g_aht20_fd < 0) {
        printf("Failed to open I2C device %s: %s\n", I2C_DEV, strerror(errno));

        return -1;
    }

    // 设置从设备地址
    if (ioctl(g_aht20_fd, I2C_SLAVE, AHT20_I2C_ADDR) < 0) {
        printf("Failed to set I2C slave address: %s\n", strerror(errno));
        close(g_aht20_fd);

        return -1;
    }

    _aht20_soft_reset(g_aht20_fd);
    msleep(100);

    if(_aht20_init(g_aht20_fd) == 0)
    {
        printf("aht20 init success!\r\n");
    }
    else
    {
        printf("aht20 init failed!\r\n");
        close(g_aht20_fd);
        g_aht20_fd = -1;

        return -1;
    }

    aht20.us0 = bsp_ustimer_get_origin();

    return 0;
}

int aht20_exit(void)
{
    if(g_aht20_fd >= 0)
    {
        close(g_aht20_fd);
        g_aht20_fd = -1;
    }

    return 0;
}


void aht20_task(void)
{
    if(bsp_ustimer_get_duration(aht20.us0) < USTIMER_SEC*5 || g_aht20_fd < 0)
    {
        return;
    }

    aht20.us0 = bsp_ustimer_get_origin();
    _aht20_read_data(g_aht20_fd, &aht20.temp, &aht20.humi);
    // printf("aht20.temp=%.3f ℃, aht20.humi=%.3f %%RH\r\n", aht20.temp, aht20.humi);
}

float aht20_get_temp(void)
{
    if(g_aht20_fd < 0)
    {
        // 校准系数判断 温度低于-85℃时为异常状态，温度补偿系数默认改为1.0,
        // 因此此处在初始化失败时返回-100.0℃
        return -100.0;
    }

    return aht20.temp;
}

float aht20_get_humi(void)
{
    return aht20.humi;
}

#endif /* TMP_CHIP_AHT20 */