/**
******************************************************************************************************************************************************************************************
*@file                       dm_button_gpio.c
*@author         
*@data                       
*@version                    v1.0
*@par Copyright(c):
*
*@par History:
*     version:author,date,desc
*     v1.0   :create this file
*
*******************************************************************************************************************************************************************************************
*/
#include <stdint.h>
#include <stdbool.h>
#include "cpu.h"
#include "user_gpio.h"
#include "cpu_timer.h"
#include "user_timer.h"
#include "user_pwm.h"
#include "cpu_deepsleep.h"
#include "app_trace.h"
#include "sdk_include.h"

static rgb_env_t rgb_env;
struct fsm_timer *led_close_timer = NULL;
uint8_t pwm_on = 0;

void breath_led_init(void)
{
    memset(&rgb_env, 0, sizeof(rgb_env_t));
	led_close_timer = NULL;
}

static void breath_gpio_into_default_state(void)
{
	gpio_remap_config(rgb_env.rgb_param.r_pin, GPIO_Remap_GPIO);
	gpio_remap_config(rgb_env.rgb_param.g_pin, GPIO_Remap_GPIO);
	gpio_remap_config(rgb_env.rgb_param.b_pin, GPIO_Remap_GPIO);

	user_gpio_out(rgb_env.rgb_param.r_pin, DISABLE);
	user_gpio_out(rgb_env.rgb_param.g_pin, DISABLE);
	user_gpio_out(rgb_env.rgb_param.b_pin, DISABLE);
}

static void close_pwm_adjust_timer(UINT8 event,void *param)
{
    RGB_DEBUG("close timer !\n\r");
    breath_gpio_into_default_state();
	timer_enable_ctrl_cmd(TIMER2, TIMER_STOP);
    cpu_prevent_sleep_clear(TIMER2_ONGOING);
}

static void open_pwm_adjust_timer(UINT8 event,void *param)
{
	RGB_DEBUG("open timer !\n\r");
	timer_enable_ctrl_cmd(TIMER2, TIMER_START);
	cpu_prevent_sleep_set(TIMER2_ONGOING);
}


// 100Hz
timer_init_type_def TIMER_init;
void breath_pwm_adjust_callback(timer_idx_t id)
{
//【1】 40ms 调整一次
	rgb_env.duty_counter ++;
	if(rgb_env.duty_counter <= 50){
//【2】	呼吸灯逐渐变量
		if(rgb_env.duty_time <= 96)
			rgb_env.duty_time += 2;
	}else if(rgb_env.duty_counter <= 100){
//【3】 呼吸灯逐渐变暗
		if(rgb_env.duty_time >= 4)
			rgb_env.duty_time -= 2;
	}
	
//【4】 4s 调整一次颜色变化
	if(rgb_env.duty_counter == 100)
	{
		rgb_env.duty_counter = 0;
//【5】 三色灯颜色循环
		rgb_env.step ++;
		if(rgb_env.step >= 7){
			rgb_env.step = 0;
			rgb_env.duty_time = 2;
		}
		

		switch(rgb_env.step){// 绿 蓝 红 青 黄 紫 白
			case 0:
//【5】 三色灯PWM配置 WS8100支持单个PWM配置多路IO通道，同时输出
				user_pwm_config(rgb_env.rgb_param.r_pin,DISABLE);	
				user_pwm_config(rgb_env.rgb_param.g_pin,ENABLE);	// 绿
				user_pwm_config(rgb_env.rgb_param.b_pin,DISABLE);
				break;
			case 1:
				user_pwm_config(rgb_env.rgb_param.r_pin,DISABLE);
				user_pwm_config(rgb_env.rgb_param.g_pin,DISABLE);
				user_pwm_config(rgb_env.rgb_param.b_pin,ENABLE);	// 蓝
				break;
			case 2:
				user_pwm_config(rgb_env.rgb_param.r_pin,ENABLE);	// 红
				user_pwm_config(rgb_env.rgb_param.g_pin,DISABLE);
				user_pwm_config(rgb_env.rgb_param.b_pin,DISABLE);
				break;
			case 3:
				user_pwm_config(rgb_env.rgb_param.r_pin,DISABLE);
				user_pwm_config(rgb_env.rgb_param.g_pin,ENABLE);	// 绿
				user_pwm_config(rgb_env.rgb_param.b_pin,ENABLE);	// 蓝
				break;
			case 4:
				user_pwm_config(rgb_env.rgb_param.r_pin,ENABLE);	// 红
				user_pwm_config(rgb_env.rgb_param.g_pin,ENABLE);	// 绿
				user_pwm_config(rgb_env.rgb_param.b_pin,DISABLE);
				break;
			case 5:	
				user_pwm_config(rgb_env.rgb_param.r_pin,ENABLE);	// 红
				user_pwm_config(rgb_env.rgb_param.g_pin,DISABLE);
				user_pwm_config(rgb_env.rgb_param.b_pin,ENABLE);	// 蓝
				break;
			case 6:
				user_pwm_config(rgb_env.rgb_param.r_pin,ENABLE);	// 红
				user_pwm_config(rgb_env.rgb_param.g_pin,ENABLE);	// 绿
				user_pwm_config(rgb_env.rgb_param.b_pin,ENABLE);	// 蓝
				break;
		}

	}

	TIMER_init.TIMER_PWM_Hz = 10666;								//配置PWM时钟16000000 / 1500Hz
	TIMER_init.TIMER_PWM_duty_cycle = rgb_env.duty_time;			//配置PWM占空比0
	pwm_start(0,&TIMER_init);								//PWM初始化：时钟，占空比配置
}

/*****************************************************************************
 函 数 名  : rgb_breath_pwm_start
 功能描述  : PWM呼吸灯启动
 输入参数  : void  
 输出参数  : 无
*****************************************************************************/
void rgb_pwm_start(void)
{	
	RGB_DEBUG("rgb pwm start ");
	
//【1】设置默认参数
	breath_gpio_into_default_state();
	rgb_env.step 			= 0;
	rgb_env.duty_time 		= 2;
	rgb_env.duty_counter 	= 0;
	
//【2】配置呼吸灯pwm GPIO
	user_pwm_config(rgb_env.rgb_param.r_pin,DISABLE);
	user_pwm_config(rgb_env.rgb_param.g_pin,ENABLE);
	user_pwm_config(rgb_env.rgb_param.b_pin,DISABLE);
	
//【3】配置呼吸灯pwm 频率
	TIMER_init.TIMER_PWM_Hz = 10666;								//配置PWM时钟16000000 / 1500Hz
	TIMER_init.TIMER_PWM_duty_cycle = rgb_env.duty_time;			//配置PWM占空比0
	
//【4】启动PWM
	pwm_start(0,&TIMER_init);								//PWM初始化：时钟，占空比配置
	pwm_on = 1;
}			



void rgb_pwm_stop(void)
{

//【1】PWM是否已经停止
	if(pwm_on == 0)
		return;

	RGB_DEBUG("rgb pwm sop \n");
	
//【2】停止PWM调整时钟
	close_pwm_adjust_timer(0,NULL);
	
//【3】停止pwm
	pwm_stop(0);

//【4】配置呼吸灯pwm GPIO
	user_pwm_config(rgb_env.rgb_param.r_pin,ENABLE);
	user_pwm_config(rgb_env.rgb_param.g_pin,DISABLE);
	user_pwm_config(rgb_env.rgb_param.b_pin,DISABLE);
	
//【5】恢复PWM到默认
	breath_gpio_into_default_state();
	pwm_on = 0;
	
}			

/*****************************************************************************
 函 数 名  : pwm_breath_led_config
 功能描述  : pwm 呼吸灯示例代码 
 			 WS8100 timer 0 timer1 占用TIMER0_1 时钟
 			 WS8100 timer 2 timer3 占用TIMER2_3 时钟
 			 		TIMER0_1  		可用于实现2路PWM,
 输入参数  : void  
 输出参数  : 无
*****************************************************************************/
void pwm_breath_led_config(void)
{
	timer_config_t   rgb_timer_param;

	rgb_env.rgb_param.scan_interval		= 160000*4; 		// scan interval defaule 40ms (ms) 定时器周期
	rgb_env.rgb_param.scan_period		= 20;				// scan times		// 
	rgb_env.rgb_param.scan_duty_start	= 0;				// io row map		// 动态变化
	rgb_env.rgb_param.scan_duty_end		= 20;				// io row map		// 
	rgb_env.rgb_param.next_timer_cnt 	= 0;				// 持续多久切换到下一个周期 3秒
	rgb_env.rgb_param.r_pin				= GPIOC_Pin0;		// 由PD2 更换为PD0
	rgb_env.rgb_param.g_pin				= GPIOC_Pin1;		// 
	rgb_env.rgb_param.b_pin				= GPIOC_Pin2;		// 由PD3 更换为PD1
	rgb_env.step      							= 0;
	dbg_printf("rgb config \n");
	
//【1】 开启时钟

	system_clock_config(ws_timer0,ENABLE);
	system_clock_config(ws_timer1,ENABLE);


//【2】 开启中断
	nvic_init_type_def nvic_init_structure;
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
	nvic_init_structure.nvic_irq_channel_preemption_priority	= 1;
	nvic_init_structure.nvic_irq_channel_subpriority			= 0;
	nvic_init_structure.nvic_irq_channel_cmd					= ENABLE; 
	
//PWM中断
	nvic_init_structure.nvic_irq_channel						= Timer0_IRQn;
	nvic_init(&nvic_init_structure);

//Adjust Timer中断 
//用来调整PWM动态频率实现呼吸灯
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
	nvic_init_structure.nvic_irq_channel_preemption_priority	= 1;
	nvic_init_structure.nvic_irq_channel_subpriority			= 0;
	nvic_init_structure.nvic_irq_channel_cmd					= ENABLE; 
	nvic_init_structure.nvic_irq_channel						= Timer2_IRQn;
	nvic_init(&nvic_init_structure);
	

		
//【3】 timer 初始化
    rgb_timer_param.timer_idx 					= IDX_TIMER2;
	rgb_timer_param.timer_param.timer_period 	= rgb_env.rgb_param.scan_interval;
	
	timer_config(TIMER2, &rgb_timer_param, breath_pwm_adjust_callback);

//【4】 timer 使能
	timer_enable_ctrl_cmd(TIMER2, TIMER_START);
	cpu_prevent_sleep_set(TIMER2_ONGOING);

//【5】开启呼吸调整定时器
	open_pwm_adjust_timer(0,NULL);

//【6】 pwm 初始化并启动
	rgb_pwm_start();
}



//============================软件PWM 示例代码 ============================================
//=========================================================================================
//=========================================================================================
//=========================================================================================

/*****************************************************************************
 函 数 名  : user_soft_pwm_config
 功能描述  : 软件pwm配置
 输入参数  : gpio_pin GPIO_Pin          
             functional_state_t enable  高电平
 输出参数  : 无
 返 回 值  : 
*****************************************************************************/
void user_soft_pwm_config(gpio_pin GPIO_Pin, level hig)
{
	if(GPIO_Pin == GPIO_INVAILD)
		return;
	
	gpio_remap_config(GPIO_Pin,GPIO_Remap_GPIO);
	gpio_init(GPIO_Pin,GPIO_Mode_Output);
	if(hig){
		gpio_set(GPIO_Pin);
	}else{
		gpio_reset(GPIO_Pin);
	}
}
void breath_soft_adjust_callback(timer_idx_t id);

void soft_pwm_callback(timer_idx_t id)
{
// 周期为40ms
	rgb_env.run_counter ++;
	if((rgb_env.duty_time == rgb_env.run_counter)	//信号反转
		|| (rgb_env.run_counter == 100))			//信号复位
	{
		switch(rgb_env.step){// 绿 蓝 红 青 黄 紫 白
			case 0:
				gpio_reset(rgb_env.rgb_param.r_pin);	
				gpio_toggle(rgb_env.rgb_param.g_pin);	// 绿
				gpio_reset(rgb_env.rgb_param.b_pin);
				break;
			case 1:
				gpio_reset(rgb_env.rgb_param.r_pin);
				gpio_reset(rgb_env.rgb_param.g_pin);
				gpio_toggle(rgb_env.rgb_param.b_pin);	// 蓝
				break;
			case 2:
				gpio_toggle(rgb_env.rgb_param.r_pin);	// 红
				gpio_reset(rgb_env.rgb_param.g_pin);
				gpio_reset(rgb_env.rgb_param.b_pin);
				break;
			case 3:
				gpio_reset(rgb_env.rgb_param.r_pin);
				gpio_toggle(rgb_env.rgb_param.g_pin);	// 绿
				gpio_toggle(rgb_env.rgb_param.b_pin);	// 蓝
				break;
			case 4:
				gpio_toggle(rgb_env.rgb_param.r_pin);	// 红
				gpio_toggle(rgb_env.rgb_param.g_pin);	// 绿
				gpio_reset(rgb_env.rgb_param.b_pin);
				break;
			case 5: 
				gpio_toggle(rgb_env.rgb_param.r_pin);	// 红
				gpio_reset(rgb_env.rgb_param.g_pin);
				gpio_toggle(rgb_env.rgb_param.b_pin);	// 蓝
				break;
			case 6:
				gpio_toggle(rgb_env.rgb_param.r_pin);	// 红
				gpio_toggle(rgb_env.rgb_param.g_pin);	// 绿
				gpio_toggle(rgb_env.rgb_param.b_pin);	// 蓝
				break;
		}
	}
	
	if(rgb_env.run_counter == 100){	//复位计数器
		rgb_env.run_counter = 0;		// 1MS变化一次
		rgb_env.pwm_counter ++;
		if(rgb_env.pwm_counter == 40){
			rgb_env.pwm_counter = 0;
			breath_soft_adjust_callback(IDX_TIMER3);	//调整PWM
		}
	}
}

/*****************************************************************************
 函 数 名  : rgb_soft_pwm_start
 功能描述  : PWM呼吸灯启动
 输入参数  : void  
 输出参数  : 无
*****************************************************************************/


void breath_soft_adjust_callback(timer_idx_t id)
{
// 周期为40ms
	rgb_env.duty_counter ++;
	if(rgb_env.duty_counter <= 50){
		if(rgb_env.duty_time <= 96)
			rgb_env.duty_time += 2;
	}else if(rgb_env.duty_counter <= 100){
		if(rgb_env.duty_time >= 4)
			rgb_env.duty_time -= 2;
	}
	
	if(rgb_env.duty_counter == 100)
	{
		rgb_env.duty_counter = 0;
		
		rgb_env.step ++;
		if(rgb_env.step >= 7){
			rgb_env.step = 0;
			rgb_env.duty_time = 2;
		}

		switch(rgb_env.step){// 绿 蓝 红 青 黄 紫 白
			case 0:
				gpio_reset(rgb_env.rgb_param.r_pin);	
				gpio_set(rgb_env.rgb_param.g_pin);			// 绿
				gpio_reset(rgb_env.rgb_param.b_pin);
				break;
			case 1:
				gpio_reset(rgb_env.rgb_param.r_pin);
				gpio_reset(rgb_env.rgb_param.g_pin);
				gpio_set(rgb_env.rgb_param.b_pin);			// 蓝
				break;
			case 2:
				gpio_set(rgb_env.rgb_param.r_pin);			// 红
				gpio_reset(rgb_env.rgb_param.g_pin);
				gpio_reset(rgb_env.rgb_param.b_pin);
				break;
			case 3:
				gpio_reset(rgb_env.rgb_param.r_pin);
				gpio_set(rgb_env.rgb_param.g_pin);			// 绿
				gpio_set(rgb_env.rgb_param.b_pin);			// 蓝
				break;
			case 4:
				gpio_set(rgb_env.rgb_param.r_pin);			// 红
				gpio_set(rgb_env.rgb_param.g_pin);			// 绿
				gpio_reset(rgb_env.rgb_param.b_pin);
				break;
			case 5: 
				gpio_set(rgb_env.rgb_param.r_pin);			// 红
				gpio_reset(rgb_env.rgb_param.g_pin);
				gpio_set(rgb_env.rgb_param.b_pin);			// 蓝
				break;
			case 6:
				gpio_set(rgb_env.rgb_param.r_pin);			// 红
				gpio_set(rgb_env.rgb_param.g_pin);			// 绿
				gpio_set(rgb_env.rgb_param.b_pin);			// 蓝
				break;
		}
	}
}


void rgb_soft_pwm_start(void)
{	
	timer_config_t timer_param;
	uint32_t TIMER_PWM_Hz;
	RGB_DEBUG("rgb pwm start ");

//【2】设置默认参数
	breath_gpio_into_default_state();

//【3】配置呼吸灯pwm GPIO

	dbg_printf("r::%x \n",rgb_env.rgb_param.r_pin);
	dbg_printf("g::%x \n",rgb_env.rgb_param.g_pin);
	dbg_printf("b::%x \n",rgb_env.rgb_param.b_pin);
	
	user_soft_pwm_config(rgb_env.rgb_param.r_pin,LOW);
	user_soft_pwm_config(rgb_env.rgb_param.g_pin,HIGHT);
	user_soft_pwm_config(rgb_env.rgb_param.b_pin,LOW);

	rgb_env.step 			= 0;
	rgb_env.duty_time 		= 2;
	rgb_env.duty_counter 	= 0;
	rgb_env.run_counter 	= 0;
	
	
//【4】配置呼吸灯pwm 频率
	TIMER_PWM_Hz = 1000;										    // 1000Hz

	//【6】 初始化定时器参数以及注册回调函数
	timer_param.timer_idx					= IDX_TIMER3;							// timer 0
	timer_param.timer_param.timer_period	= 16000000/(TIMER_PWM_Hz*100);			// 100 ms
	timer_config(TIMER3, &timer_param, soft_pwm_callback);
	user_timer_set(IDX_TIMER3,ENABLE);
	pwm_on = 1;
}			




void user_soft_pwm_breath_example(void)
{
	dbg_block_printf("\nsoft pwm breath example \n");
	
//	user_time_cfg_parameter_t  timer_param;							//定时器

	rgb_env.rgb_param.scan_interval 	= 160000*4; 		// scan interval defaule 40ms (ms) 定时器周期
	rgb_env.rgb_param.scan_period		= 20;				// scan times		// 
	rgb_env.rgb_param.scan_duty_start	= 0;				// io row map		// 动态变化
	rgb_env.rgb_param.scan_duty_end 	= 20;				// io row map		// 
	rgb_env.rgb_param.next_timer_cnt	= 0;				// 持续多久切换到下一个周期 3秒
	rgb_env.rgb_param.r_pin 			= GPIOC_Pin0;		// 由PD2 更换为PD0
	rgb_env.rgb_param.g_pin 			= GPIOC_Pin1;		// 
	rgb_env.rgb_param.b_pin 			= GPIOC_Pin2;		// 由PD3 更换为PD1
	rgb_env.step						= 0;


//【1】 开启定时器0 时钟	呼吸灯调整定时器
	system_clock_config(ws_timer2,ENABLE);

//【2】 开启定时器3 时钟	软件PWM定时器	
	system_clock_config(ws_timer3,ENABLE);

//【3】 开启定时器2 中断
	nvic_init_type_def nvic_init_structure;
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
	nvic_init_structure.nvic_irq_channel_preemption_priority	= 1;
	nvic_init_structure.nvic_irq_channel_subpriority			= 0;
	nvic_init_structure.nvic_irq_channel_cmd					= ENABLE; 
	nvic_init_structure.nvic_irq_channel 						= Timer2_IRQn;
	nvic_init(&nvic_init_structure);
	
//【4】 开启定时器3 中断
	nvic_init_structure.nvic_irq_channel						= Timer3_IRQn;
	nvic_init(&nvic_init_structure);

//【5】 初始化定时器参数以及注册回调函数
//	timer_param.timer_idx 					= IDX_TIMER2;
//	timer_param.timer_param.timer_period 	= rgb_env.rgb_param.scan_interval;	
//	timer_config(TIMER2, &timer_param, breath_soft_adjust_callback);
//	user_timer_set(IDX_TIMER2,ENABLE);

//【6】 启动软pwm
//	rgb_soft_pwm_start();

//【6】 硬件pwm
	pwm_breath_led_config();


}





