#include "drv_rgb_pwm.h"
#include "string.h"

#ifdef RGB_ENABLE 

static struct rgb_pwm_drv g_rgb_circle_pwm_drv, g_rgb_strip_pwm_drv;

/**
 * @brief 将RGB颜色数组设置为PWM占空比数组
 * 
 * @param[in] drv RGB PWM驱动实例
 * @param[in] array RGB颜色数组，每个元素为32位ARGB格式
 * @param[in] count 数组中颜色的数量
 * @return rt_err_t 错误码，RT_EOK表示成功，-RT_ERROR表示失败
 */
static rt_err_t rgb_pwm_set_color(struct rgb_pwm_drv *drv, uint32_t *array, uint16_t count)
{
    uint16_t *buff = drv->array;

    rt_memset(drv->array, 0, RGB_DRV_PWM_ARRAY_LEN * sizeof(uint16_t));

    if (!drv || !buff || !array || count == 0) {
        rt_kprintf("func: %s, invalid parameter.\r\n", __func__);
        return -RT_ERROR;
    }

    if (count > drv->max_count) {
        rt_kprintf("func: %s, count %d exceeds max_count %d.\r\n", __func__, count, drv->max_count);
        return -RT_ERROR;
    }
    if (count > RGB_DRV_PWM_LED_COUNT) {
        rt_kprintf("func: %s, count %d exceeds LED count %d.\r\n", __func__, count, RGB_DRV_PWM_LED_COUNT);
        return -RT_ERROR;
    }

    uint32_t end_index = RGB_DRV_PWM_REST_LEN + (count * RGB_DRV_PWM_COLOR_BITS);
    if ((end_index + RGB_DRV_PWM_STOP_LEN) > RGB_DRV_PWM_ARRAY_LEN) {
        return -RT_ERROR;
    }

    for (rt_uint16_t i = 0; i < count; i++) {
        uint32_t color = array[i];

        uint8_t r = (uint8_t)((color & 0x00ff0000) >> 16);
        uint8_t g = (uint8_t)((color & 0x0000ff00) >> 8);
        uint8_t b = (uint8_t)((color & 0x000000ff) >> 0);        

        uint16_t offset = RGB_DRV_PWM_REST_LEN + (i * RGB_DRV_PWM_COLOR_BITS);
        if ((offset + RGB_DRV_PWM_COLOR_BITS) > RGB_DRV_PWM_ARRAY_LEN) {
            return -RT_ERROR;
        }

        for (int j = 0; j < 8; j++) {
            buff[offset + j] = ((g << j) & 0x80) ? RGB_DRV_REG_HIGH : RGB_DRV_REG_LOW;
            buff[offset + j + 8] = ((r << j) & 0x80) ? RGB_DRV_REG_HIGH : RGB_DRV_REG_LOW;
            buff[offset + j + 16] = ((b << j) & 0x80) ? RGB_DRV_REG_HIGH : RGB_DRV_REG_LOW;
        }
    }
    for (uint32_t i = 0; i < RGB_DRV_PWM_STOP_LEN; i++) {
        buff[end_index + i] = RGB_DRV_REG_END;
    }

    return RT_EOK;
}

/**
 * @brief 将RGB颜色数组设置为PWM占空比数组
 * 
 * @param[in] drv RGB PWM驱动实例
 * @param[in] rgb RGB PWM数组配置结构，包含颜色数组和数量
 * @return rt_err_t 错误码，RT_EOK表示成功，-RT_ERROR表示失败
 */
static rt_err_t rgb_pwm_write(struct rgb_pwm_drv *drv, struct rgb_pwm_config *rgb)
{
    struct rt_pwm_configuration cfg;

    rt_memset((void *)&cfg, 0, sizeof(cfg));

    if (!drv || !rgb || !drv->pwm_dev) {
        rt_kprintf("func: %s, invalid parameter.\r\n", __func__);
        return -RT_ERROR;
    }

    // memset((void *)&cfg, 0, sizeof(cfg));
    cfg.channel = drv->channel;
    cfg.period = RGB_DRV_PWM_PERIOD;
    cfg.pulse = RGB_DRV_PWM_PULSE_PERIOD;
    cfg.dma_data = drv->array;
    cfg.data_len = RGB_DRV_PWM_REST_LEN + (rgb->count * RGB_DRV_PWM_COLOR_BITS) + RGB_DRV_PWM_STOP_LEN;
    if (cfg.data_len > RGB_DRV_PWM_ARRAY_LEN) {
        rt_kprintf("func: %s, data_len %d exceeds array len %d.\r\n", __func__, cfg.data_len, RGB_DRV_PWM_ARRAY_LEN);
        return -RT_ERROR;
    }
    
    rt_err_t err = rt_device_control((struct rt_device *)drv->pwm_dev, PWM_CMD_SET, (void *)&cfg);
    if (err != RT_EOK) {
        rt_kprintf("func: %s, PWM_CMD_SET failed with error %d.\r\n", __func__, err);
        return -RT_ERROR;
    }

    err = rt_device_control((struct rt_device *)drv->pwm_dev, PWM_CMD_ENABLE, (void *)&cfg);
    if (err != RT_EOK) {
        rt_kprintf("func: %s, PWM_CMD_ENABLE failed with error %d.\r\n", __func__, err);
        return -RT_ERROR;
    }   

    uint32_t transfer_time_ms = (cfg.data_len * 2) / 1000 + 2;
    rt_thread_mdelay(transfer_time_ms);
    
    rt_memset((void *)&cfg, 0, sizeof(cfg));
    cfg.channel = drv->channel;
    err = rt_device_control((struct rt_device *)drv->pwm_dev, PWM_CMD_DISABLE, (void *)&cfg);
    if (err != RT_EOK) {
        rt_kprintf("func: %s, PWM_CMD_DISABLE failed with error %d.\r\n", __func__, err);
        return -RT_ERROR;
    }   

    return RT_EOK;
}

/**
 * @brief 控制RGB PWM设备
 * 
 * @param[in] dev RGB PWM设备指针
 * @param[in] cmd 控制命令，如PWM_CMD_ENABLE、PWM_CMD_DISABLE等
 * @param[in] arg 控制参数，如配置结构体指针
 * @return rt_err_t 错误码，RT_EOK表示成功，-RT_ERROR表示失败
 */
static rt_err_t rgb_pwm_control(rt_device_t dev, int cmd, void *arg)
{
    struct rgb_pwm_drv *drv = (struct rgb_pwm_drv *)dev->user_data;

    if (drv->mutex) {
        rt_mutex_take(drv->mutex, RT_WAITING_FOREVER);
    }

    struct rgb_pwm_config *rgb = (struct rgb_pwm_config *)arg;

    if (!rgb || !rgb->array || rgb->count > drv->max_count || rgb->count > RGB_DRV_PWM_LED_COUNT) {
        rt_kprintf("func: %s, invalid rgb config.\r\n", __func__);
        return -RT_ERROR;
    }

    rt_kprintf("func: %s, rgb->count: %d\n", __func__, rgb->count);

    rt_err_t err = rgb_pwm_set_color(drv, rgb->array, rgb->count);
    if (err != RT_EOK) {
        rt_kprintf("func: %s, rgb_pwm_color_to_pwm failed.\r\n", __func__);
        return -RT_ERROR;
    }

    err = rgb_pwm_write(drv, rgb);
    if (err != RT_EOK) {
        rt_kprintf("func: %s, rgb_pwm_write failed.\r\n", __func__);
        return -RT_ERROR;
    }

    if (drv->mutex) {
        rt_mutex_release(drv->mutex);
    }

    return RT_EOK;
}

#ifdef RGB_CIRCLE_ENABLE

/**
 * @brief 初始化RGB PWM环型灯设备
 * @return int 初始化结果，RT_EOK表示成功，-RT_ERROR表示失败
 */
static int rgb_circle_pwm_init(void)
{
    struct rgb_pwm_drv *drv = &g_rgb_circle_pwm_drv;

    drv->mutex = rt_mutex_create("rgb_circle_mutex", RT_IPC_FLAG_PRIO);
    if (!drv->mutex) {
        rt_kprintf("func: %s, failed to create RGB circle mutex\n", __func__);
        return -RT_ERROR;
    }

    drv->pwm_dev = (struct rt_device_pwm *)rt_device_find(RGB_CIRCLE_PWM_NAME);
    if (!drv->pwm_dev) {
        rt_kprintf("func: %s, failed to find RGB circle PWM device\n", __func__);
        return -RT_ERROR;
    }    
    
    drv->dev.control = (rt_err_t (*)(rt_device_t, int, void *))rgb_pwm_control;
    drv->dev.user_data = drv; 
    drv->max_count = RGB_CIRCLE_RGB_NUM; 
    drv->channel = RGB_CIRCLE_PWM_CH; 
    drv->dev_name = RGB_CIRCLE_DRV_NAME;

    if (rt_device_register(&drv->dev, drv->dev_name, RT_DEVICE_FLAG_RDWR)) {
        rt_kprintf("func: %s, %s register failed\n", __func__, drv->dev_name);
        return -RT_ERROR;
    }

    return RT_EOK;
}

/**
 * @brief 初始化RGB PWM环型灯设备
 */
INIT_COMPONENT_EXPORT(rgb_circle_pwm_init);

#endif /* RGB_CIRCLE_ENABLE */

#ifdef RGB_STRIP_ENABLE

/**
 * @brief 初始化RGB PWM条形灯设备
 * @return int 初始化结果，RT_EOK表示成功，-RT_ERROR表示失败
 */
static int rgb_strip_pwm_init(void)
{
    struct rgb_pwm_drv *drv = &g_rgb_strip_pwm_drv;

    drv->mutex = rt_mutex_create("rgb_strip_mutex", RT_IPC_FLAG_PRIO);
    if (!drv->mutex) {
        rt_kprintf("func: %s, failed to create RGB strip mutex\n", __func__);
        return -RT_ERROR;
    }

    drv->pwm_dev = (struct rt_device_pwm *)rt_device_find(RGB_STRIP_PWM_NAME);
    if (!drv->pwm_dev) {
        rt_kprintf("func: %s, failed to find RGB PWM device.\r\n", __func__);
        return -RT_ERROR;
    }    
    
    drv->dev.control = (rt_err_t (*)(rt_device_t, int, void *))rgb_pwm_control;
    drv->dev.user_data = drv; 
    drv->max_count = RGB_STRIP_RGB_NUM; 
    drv->channel = RGB_STRIP_PWM_CH; 
    drv->dev_name = RGB_STRIP_DRV_NAME;

    if (rt_device_register(&drv->dev, drv->dev_name, RT_DEVICE_FLAG_RDWR)) {
        rt_kprintf("func: %s, register %s failed\n", __func__, drv->dev_name);
        return -RT_ERROR;
    }

    return RT_EOK;
}

/**
 * @brief 注册RGB PWM条形灯设备初始化函数
 */
//INIT_COMPONENT_EXPORT(rgb_strip_pwm_init);

#endif /* RGB_STRIP_ENABLE */

#endif /* RGB_ENABLE */


