#include "ws2812.h"
#include <string.h>

#include "onechip_include_header.h"

static  struct str_ws2812 lihgt_ctrl = {0};     //灯带控制结构
static uint32_t tick = 0;

/********************************************************************
 * void ws2812_0()
 *
 *描述：灯带0信号
 *参数：无
 *返回：无
 *其他：无
 ********************************************************************/
static void ws2812_0()
{
	GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)sysinf.rgb_band_port; 
	uint32_t GPIO_Pin_RESET = sysinf.rgb_band_pin << 16;
	uint32_t GPIO_Pin_SET = sysinf.rgb_band_pin;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;

}

/********************************************************************
 * void ws2812_1()
 *
 *描述：灯带1信号
 *参数：无
 *返回：无
 *其他：无
 ********************************************************************/
static void ws2812_1()
{
  	GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)sysinf.rgb_band_port; 
	uint32_t GPIO_Pin_RESET = sysinf.rgb_band_pin << 16;
	uint32_t GPIO_Pin_SET = sysinf.rgb_band_pin;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_SET;
	
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;  
  
	GPIOx->BSRR = (uint32_t)GPIO_Pin_RESET;
}

/********************************************************************
 * void ws2812_set_rgb(uint32_t rgb)
 *
 *描述：设置灯珠RGB颜色
 *参数：uint32_t rgb:颜色， 低24位有效
 *返回：无
 *其他：无
 ********************************************************************/
void ws2812_set_rgb(uint32_t rgb)
{
    for(int i = 0; i < 24; i++)
    {
        if(rgb & 0x800000)
        {
            ws2812_1();
        }
        else
        {
            ws2812_0();
        }
        rgb <<= 1;
    }
}


/********************************************************************
 * void light_set(uint8_t mode_select, uint16_t speed_ms, uint32_t rgb_color, uint8_t channel)
 *
 *描述：设置灯带
 *参数：uint8_t mode_select：模式
 *参数：uint16_t speed_ms：变化周期
 *参数：uint32_t rgb_color:颜色， 低24位有效
 *参数：uint8_t channel：通道，0左，1右
 *返回：无
 *其他：无
 ********************************************************************/
void light_set(uint8_t mode_select, uint16_t speed_ms, uint32_t rgb_color, uint8_t channel)
{
    channel = channel ? 1 : 0;

    if(lihgt_ctrl.light_color[channel] != rgb_color)
        tick = 0;

    lihgt_ctrl.light_mode[channel] = mode_select;
    lihgt_ctrl.light_speed[channel] = speed_ms;
    lihgt_ctrl.light_color[channel] = rgb_color;

    //两边步调同步
    if(lihgt_ctrl.light_mode[0] == lihgt_ctrl.light_mode[1])
    {
        lihgt_ctrl.breath_count[0] = lihgt_ctrl.breath_count[1];
        lihgt_ctrl.breath_dir[0] = lihgt_ctrl.breath_dir[1];
        lihgt_ctrl.light_color_use[0] = lihgt_ctrl.light_color_use[1];
    }
}


/********************************************************************
 * void light_refresh(uint32_t rgb_left, uint32_t rgb_right)
 *
 *描述：刷新灯带
 *参数：uint32_t rgb_left:左边颜色
 *参数：uint32_t rgb_right:右边颜色
 *返回：无
 *其他：无
 ********************************************************************/
void light_refresh(uint32_t rgb_left, uint32_t rgb_right)
{
    for(int i = 0; i < WS2812_NUM; i++)
    {
        ws2812_set_rgb(rgb_right);
    }

    for(int i = 0; i < WS2812_NUM; i++)
    {
        ws2812_set_rgb(rgb_left);
    }
}

/********************************************************************
 * void light_ctrl()
 *
 *描述：刷新控制调度
 *参数：无
 *返回：无
 *其他：无
 ********************************************************************/
void light_ctrl()
{
    uint32_t r_g_b = 0; //r/g/b单色分量

    //计算颜色
    for(int i = 0; i < 2; i++)
    {
        switch (lihgt_ctrl.light_mode[i])
        {
            case MODE_NORMAL:   //常亮，只改变一次
                if(lihgt_ctrl.light_color_use[i] != lihgt_ctrl.light_color[i])     //未刷新
                {
                    lihgt_ctrl.light_color_use[i] = lihgt_ctrl.light_color[i];
                }
                break;

            case MODE_BLINK:    //闪烁，一个周期反转一次
                if(tick % lihgt_ctrl.light_speed[i])
                    break;

                if(lihgt_ctrl.light_color_use[i])
                    lihgt_ctrl.light_color_use[i] = 0;
                else
                    lihgt_ctrl.light_color_use[i] = lihgt_ctrl.light_color[i];
                break;
            
            case MODE_BREATH:   //呼吸灯 y = x*x *r_g_b
                lihgt_ctrl.light_color_use[i] = 0;

                for(int j = 0; j < 3; j++)
                {
                    //计算分量
                    r_g_b = (lihgt_ctrl.light_color[i] >> (j * 8))  & 0xFF;
                    if(r_g_b)
                    {
                        r_g_b = (uint32_t)(r_g_b * lihgt_ctrl.breath_count[i] * lihgt_ctrl.breath_count[i] / BREATH_NUM / BREATH_NUM);  //y = x*x*r_g_b
                        lihgt_ctrl.light_color_use[i] |= (r_g_b << (j * 8));
                    }
                }

                //方向和x处理，x++，x--
                if(lihgt_ctrl.breath_dir[i])
                {
                    if(lihgt_ctrl.breath_count[i] == BREATH_NUM)
                        lihgt_ctrl.breath_dir[i] = 0;
                    else
                        lihgt_ctrl.breath_count[i]++;
                }
                else
                {
                    if(lihgt_ctrl.breath_count[i] == 0)
                        lihgt_ctrl.breath_dir[i] = 1;
                    else
                        lihgt_ctrl.breath_count[i]--;
                }

                break;
            default:
                break;
        }
    }

    tick += 50; //ms计时
    //刷新灯带
    light_refresh(lihgt_ctrl.light_color_use[0], lihgt_ctrl.light_color_use[1]);
}
