/**
 * @file htr3236.c
 * @brief HTR3236 36-Channel LED PWM Driver Implementation for XMOS
 * @version 1.1
 */

#include "htr3236.h"
#include <xccompat.h>

#include <platform.h>

out port p_htr3235_sdb = PORT_HTR3236_SDB; /* 连接到HTR3236的SDB引脚，用于控制其电源状态 */

/*=========================================================================
    Gamma 校正查找表
    -----------------------------------------------------------------------*/

static const uint8_t gamma_table_32[32] = {
    0, 1, 2, 4, 6, 10, 13, 18,
    22, 28, 33, 39, 46, 53, 61, 69,
    78, 86, 96, 106, 116, 126, 138, 149,
    161, 173, 186, 199, 212, 226, 240, 255
};

static const uint8_t gamma_table_64[64] = {
    0, 1, 2, 3, 4, 5, 6, 7,
    8, 10, 12, 14, 16, 18, 20, 22,
    24, 26, 29, 32, 35, 38, 41, 44,
    47, 50, 53, 57, 61, 65, 69, 73,
    77, 81, 85, 89, 94, 99, 104, 109,
    114, 119, 124, 129, 134, 140, 146, 152,
    158, 164, 170, 176, 182, 188, 195, 202,
    209, 216, 223, 230, 237, 244, 251, 255
};

/*=========================================================================
    内部函数
    -----------------------------------------------------------------------*/

/**
 * @brief 写单字节到寄存器
 */
static int write_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, uint8_t data)
{
    uint8_t buf[2] = {reg, data};
    size_t n;

    i2c.write(dev->i2c_addr, buf, 2, n, 1);

    if (n == 0)
    {
        return I2C_REGOP_DEVICE_NACK;
    }
    if (n < 2)
    {
        return I2C_REGOP_INCOMPLETE;
    }

    return I2C_REGOP_SUCCESS;	
}

/**
 * @brief 写多字节到寄存器 (支持自动地址递增)
 */
static int write_reg_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_reg, 
                          const uint8_t *data, uint8_t len)
{
    uint8_t buf[36 + 1];
    size_t n;

    buf[0] = start_reg;
    
    for (int i = 0; i < len; i++) {
        buf[i + 1] = data[i];
    }

    i2c.write(dev->i2c_addr, buf, len + 1, n, 1);

    if (n == 0)
    {
        return I2C_REGOP_DEVICE_NACK;
    }
    if (n < 2)
    {
        return I2C_REGOP_INCOMPLETE;
    }

    return I2C_REGOP_SUCCESS;
}

/**
 * @brief 读取寄存器值
 */
static int read_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, i2c_regop_res_t &result)
{
    uint8_t a_reg[1] = {reg};
    uint8_t data[1] = {0};
    size_t n;
    i2c_res_t res;

    unsafe
    {
        res = i2c.write(dev->i2c_addr, a_reg, 1, n, 0);

        if (n != 1)
        {
            result = I2C_REGOP_DEVICE_NACK;
            i2c.send_stop_bit();
            return 0;
        }

        res = i2c.read(dev->i2c_addr, data, 1, 1);
    }

    if (res == I2C_ACK)
    {
        result = I2C_REGOP_SUCCESS;
    }
    else
    {
        result = I2C_REGOP_DEVICE_NACK;
    }
    return data[0];
}



/*=========================================================================
    API 函数实现
    -----------------------------------------------------------------------*/

void htr3236_init(htr3236_t *dev, uint8_t addr)
{
    dev->i2c_addr = addr;
    
    // 默认 SDB 拉高，使能芯片
    //htr3236_hw_enable(dev);
}

void htr3236_hw_enable(htr3236_t *dev)
{
    p_htr3235_sdb <: 1;
}

void htr3236_hw_disable(htr3236_t *dev)
{
    p_htr3235_sdb <: 0;
}

int htr3236_software_wake(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
    return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_NORMAL_OP);
}

int htr3236_software_shutdown(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
    return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_SHUTDOWN_SOFT);
}

int htr3236_software_reset(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
    return write_reg(dev, i2c, HTR3236_REG_RESET, 0x00);
}

int htr3236_set_pwm(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel, uint8_t brightness)
{
    if (channel < 1 || channel > 36) {
        return -1;
    }
    
    uint8_t reg = HTR3236_REG_PWM_START + (channel - 1);
    return write_reg(dev, i2c, reg, brightness);
}

int htr3236_set_pwm_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch, 
                         const uint8_t *values, uint8_t len)
{
    if (start_ch < 1 || start_ch > 36 || len == 0) {
        return -1;
    }
    
    // 检查是否会超出寄存器范围
    if (start_ch + len - 1 > 36) {
        return -1;
    }
    
    uint8_t start_reg = HTR3236_REG_PWM_START + (start_ch - 1);
    return write_reg_bulk(dev, i2c, start_reg, values, len);
}

int htr3236_set_led_config(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel,
                           htr3236_current_t current, uint8_t enable)
{
    if (channel < 1 || channel > 36) {
        return -1;
    }
    
    uint8_t reg = HTR3236_REG_LED_CTRL_START + (channel - 1);
    uint8_t data = (enable ? 1 : 0) | (current << 1);
    
    return write_reg(dev, i2c, reg, data);
}

int htr3236_set_led_config_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch,
                                const uint8_t *configs, uint8_t len)
{
    if (start_ch < 1 || start_ch > 36 || len == 0) {
        return -1;
    }
    
    // 检查是否会超出寄存器范围
    if (start_ch + len - 1 > 36) {
        return -1;
    }
    
    uint8_t start_reg = HTR3236_REG_LED_CTRL_START + (start_ch - 1);
    return write_reg_bulk(dev, i2c, start_reg, configs, len);
}

int htr3236_update(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
    // 写入任意值到更新寄存器使配置生效
    return write_reg(dev, i2c, HTR3236_REG_PWM_UPDATE, 0x00);
}

int htr3236_global_enable(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t enable)
{
    uint8_t data = enable ? 1 : 0;
    return write_reg(dev, i2c, HTR3236_REG_GLOBAL_CTRL, data);
}

int htr3236_set_frequency(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), htr3236_freq_t freq)
{
    uint8_t data = (freq == HTR3236_FREQ_22KHZ) ? 1 : 0;
    return write_reg(dev, i2c, HTR3236_REG_FREQ_SET, data);
}

uint8_t htr3236_gamma_32(uint8_t index)
{
    if (index >= 32) {
        index = 31;
    }
    return gamma_table_32[index];
}

uint8_t htr3236_gamma_64(uint8_t index)
{
    if (index >= 64) {
        index = 63;
    }
    return gamma_table_64[index];
}