/**
 * @file icm42688.h
 * @brief ICM-42688/ICM-42670 IMU 驱动 - Linux I2C 用户空间实现
 * @date 2025-11-26
 * @platform Avaota F1 (V821 / RISC-V)
 * 
 * ICM-42688 是一款高性能 6 轴 IMU，支持 I2C 接口
 * - 3 轴加速度计：±2g, ±4g, ±8g, ±16g
 * - 3 轴陀螺仪：±15.625°/s ~ ±2000°/s
 * - 温度传感器
 */

#ifndef ICM42688_H
#define ICM42688_H

#include <cstdint>
#include <string>

// ICM-42688 寄存器定义
#define ICM42688_WHO_AM_I       0x75
#define ICM42688_DEVICE_ID      0x47  // ICM-42688
#define ICM42670_DEVICE_ID      0x67  // ICM-42670

#define ICM42688_PWR_MGMT0      0x4E  // 电源管理
#define ICM42688_GYRO_CONFIG0   0x4F  // 陀螺仪配置
#define ICM42688_ACCEL_CONFIG0  0x50  // 加速度计配置
#define ICM42688_TEMP_DATA1     0x1D  // 温度数据寄存器起始地址

/**
 * @brief ICM-42688 IMU 类
 * 
 * 使用 Linux I2C 用户空间 API 与 ICM-42688 通信
 */
class ICM42688 {
public:
    /**
     * @brief 加速度计量程
     */
    enum class AccelScale {
        AFS_16G = 0,  // ±16g
        AFS_8G  = 1,  // ±8g
        AFS_4G  = 2,  // ±4g
        AFS_2G  = 3   // ±2g
    };
    
    /**
     * @brief 陀螺仪量程
     */
    enum class GyroScale {
        GFS_2000DPS  = 0,  // ±2000°/s
        GFS_1000DPS  = 1,  // ±1000°/s
        GFS_500DPS   = 2,  // ±500°/s
        GFS_250DPS   = 3,  // ±250°/s
        GFS_125DPS   = 4,  // ±125°/s
        GFS_62_5DPS  = 5,  // ±62.5°/s
        GFS_31_25DPS = 6,  // ±31.25°/s
        GFS_15_625DPS = 7  // ±15.625°/s
    };
    
    /**
     * @brief 输出数据率 (ODR)
     */
    enum class ODR {
        ODR_32KHZ  = 0x01,
        ODR_16KHZ  = 0x02,
        ODR_8KHZ   = 0x03,
        ODR_4KHZ   = 0x04,
        ODR_2KHZ   = 0x05,
        ODR_1KHZ   = 0x06,  // 推荐使用
        ODR_200HZ  = 0x07,
        ODR_100HZ  = 0x08,
        ODR_50HZ   = 0x09,
        ODR_25HZ   = 0x0A,
        ODR_12_5HZ = 0x0B
    };
    
    /**
     * @brief 构造函数
     * @param i2c_device I2C 设备路径，如 "/dev/i2c-0"
     * @param address I2C 地址，0x68 (AD0=GND) 或 0x69 (AD0=VCC)
     */
    ICM42688(const std::string& i2c_device, uint8_t address = 0x68);
    
    /**
     * @brief 析构函数
     */
    ~ICM42688();
    
    /**
     * @brief 初始化 IMU
     * @return true 成功，false 失败
     */
    bool init();
    
    /**
     * @brief 读取传感器数据
     * @return true 成功，false 失败
     */
    bool read_sensor();
    
    /**
     * @brief 获取加速度计 X 轴数据
     * @return 加速度 (m/s²)
     */
    float get_accel_x();
    
    /**
     * @brief 获取加速度计 Y 轴数据
     * @return 加速度 (m/s²)
     */
    float get_accel_y();
    
    /**
     * @brief 获取加速度计 Z 轴数据
     * @return 加速度 (m/s²)
     */
    float get_accel_z();
    
    /**
     * @brief 获取陀螺仪 X 轴数据
     * @return 角速度 (°/s)
     */
    float get_gyro_x();
    
    /**
     * @brief 获取陀螺仪 Y 轴数据
     * @return 角速度 (°/s)
     */
    float get_gyro_y();
    
    /**
     * @brief 获取陀螺仪 Z 轴数据
     * @return 角速度 (°/s)
     */
    float get_gyro_z();
    
    /**
     * @brief 获取温度
     * @return 温度 (°C)
     */
    float get_temperature();
    
    /**
     * @brief 读取所有传感器数据（便捷方法）
     * @param temp_c 温度 (°C)
     * @param ax 加速度 X (m/s²)
     * @param ay 加速度 Y (m/s²)
     * @param az 加速度 Z (m/s²)
     * @param gx 陀螺仪 X (°/s)
     * @param gy 陀螺仪 Y (°/s)
     * @param gz 陀螺仪 Z (°/s)
     * @return true 成功，false 失败
     */
    bool read_sensors(float& temp_c, float& ax, float& ay, float& az, 
                      float& gx, float& gy, float& gz);
    
private:
    // I2C 设备信息
    std::string m_i2c_device;  // I2C 设备路径
    uint8_t m_address;         // I2C 地址
    int m_fd;                  // I2C 文件描述符
    
    // 传感器原始数据
    int16_t m_ax, m_ay, m_az;  // 加速度计原始值
    int16_t m_gx, m_gy, m_gz;  // 陀螺仪原始值
    int16_t m_temp;            // 温度原始值
    
    // 缩放因子
    float m_accel_scale;       // 加速度计缩放因子 (g)
    float m_gyro_scale;        // 陀螺仪缩放因子 (°/s)
    
    // 常量
    static constexpr float G = 9.80665f;           // 重力加速度 (m/s²)
    static constexpr float TEMP_SCALE = 333.87f;   // 温度缩放因子
    static constexpr float TEMP_OFFSET = 21.0f;    // 温度偏移
    
    /**
     * @brief 写入寄存器
     * @param reg 寄存器地址
     * @param value 写入的值
     * @return true 成功，false 失败
     */
    bool write_register(uint8_t reg, uint8_t value);
    
    /**
     * @brief 读取单个寄存器
     * @param reg 寄存器地址
     * @return 读取的值（失败返回 0）
     */
    uint8_t read_register(uint8_t reg);
    
    /**
     * @brief 读取多个寄存器
     * @param reg 起始寄存器地址
     * @param count 读取字节数
     * @param data 数据缓冲区
     * @return true 成功，false 失败
     */
    bool read_registers(uint8_t reg, uint8_t count, uint8_t* data);
};

#endif // ICM42688_H
