#include "bsp_led.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
#include "stdint.h"
#include "public_diy.h"

/* led define */
	/*
		STM32F103C8 LED口线分配：
			LED1       : PC13 (低电平点亮，高电平熄灭)
			LED2       : 
			LED3       : 
			LED4       : 
	*/
/* 按键口对应的RCC时钟 */
// #define RCC_ALL_LED 	(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB)	
#define RCC_GPIO_LED1	RCC_APB2Periph_GPIOC
#define GPIO_PORT_LED1  GPIOC
#define GPIO_PIN_LED1	GPIO_Pin_13

#define RCC_GPIO_LED2	RCC_APB2Periph_GPIOB
#define GPIO_PORT_LED2  GPIOB
#define GPIO_PIN_LED2	GPIO_Pin_9

/* RGB彩灯 */
// RGB 彩灯 渐变定时器
#define TIM_RGB_LED		TIM3
// Red
#define RCC_GPIO_RGB_RED	RCC_APB2Periph_GPIOA
#define GPIO_PORT_RGB_RED  	GPIOA
#define GPIO_PIN_RGB_RED  	GPIO_Pin_6
// Green
#define RCC_GPIO_RGB_GREEN	 RCC_APB2Periph_GPIOA
#define GPIO_PORT_RGB_GREEN  GPIOA
#define GPIO_PIN_RGB_GREEN   GPIO_Pin_7
// Blue
#define RCC_GPIO_RGB_BLUE	RCC_APB2Periph_GPIOB
#define GPIO_PORT_RGB_BLUE  GPIOB
#define GPIO_PIN_RGB_BLUE  	GPIO_Pin_0



/*************************************************************************************
 * @brief    开启led
 * @param[in/out] led_no【参数注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_led_on(uint8_t led_no)
{
	if (led_no == (LED1))
	{
		// STM32F103C8T6开发板 1是亮，0是灭
		// GPIO_PORT_LED1->BRR = GPIO_PIN_LED1;
		GPIO_PORT_LED1->BSRR |= GPIO_PIN_LED1;
	}
//	if (led_no == (LED2))
//	{
//		// STM32F103C8T6开发板 1是亮，0是灭
//		GPIO_PORT_LED2->BSRR |= GPIO_PIN_LED2;
//	}
}
/*************************************************************************************
 * @brief    关闭Led
 * @param[in/out] _no  【参数注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_led_off(uint8_t led_no)
{
	if(led_no == LED1)
	{
		// STM32F103C8T6开发板 1是亮，0是灭
		GPIO_PORT_LED1->BRR = GPIO_PIN_LED1;
	}
//    else if(led_no == LED2)
//    {
//        GPIO_PORT_LED2->BRR = GPIO_PIN_LED2;
//    }
    else
    {
        ;
    }

}
/*************************************************************************************
 * @brief    led状态切换
 * @param[in/out] led_no【参数注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_led_toggle(uint8_t led_no)
{
	if (led_no == LED1)
	{
		GPIO_PORT_LED1->ODR ^= GPIO_PIN_LED1;
	}
//	else if (led_no == LED2)
//	{
//		GPIO_PORT_LED2->ODR ^= GPIO_PIN_LED2;
//	}
    else
    {
        ;
    }
}
/*************************************************************************************
 * @brief    获取led当前的电平状态
 * @return uint8_t     【返回值注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
uint8_t bsp_get_led_ttlState(led_type_enum led_no)
{
	uint8_t retVal = 0;
    if(led_no == (LED1))
	{
		// STM32F103C8T6开发板 1是亮，0是灭
		// GPIO_PORT_LED1->BRR = GPIO_PIN_LED1;
		retVal = GPIO_PORT_LED1->ODR & GPIO_PIN_LED1;
	}
//	else if(led_no == (LED2))
//	{
//		// STM32F103C8T6开发板 1是亮，0是灭
//		retVal = GPIO_PORT_LED2->ODR & GPIO_PIN_LED2;
//	}
	return retVal;
}


/*************************************************************************************
 * @brief    初始化Led
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
// void bsp_led1_init(void)
// {
// 	GPIO_InitTypeDef GPIO_InitStructure;
// 	/* 打开GPIO时钟 */
// 	RCC_APB2PeriphClockCmd(RCC_GPIO_LED1, ENABLE);

// 	/*
// 		配置所有的LED指示灯GPIO为推挽输出模式
// 		由于将GPIO设置为输出时，GPIO输出寄存器的值缺省是0，因此会驱动LED点亮.
// 		这是我不希望的，因此在改变GPIO为输出前，先关闭LED指示灯
// 	*/
//     bsp_led_off(LED1);

//     /* LED 1*/
// 	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED1;
// 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		/* 设为 输出推挽模式 */
// 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	/* IO口最大速度 */
// 	GPIO_Init(GPIO_PORT_LED1, &GPIO_InitStructure);
// }

void bsp_led2_init(void)
{
	// GPIO_InitTypeDef GPIO_InitStructure;
	/* 打开GPIO时钟 */
	// RCC_APB2PeriphClockCmd(RCC_GPIO_LED2, ENABLE);

	// /*
	// 	配置所有的LED指示灯GPIO为推挽输出模式
	// 	由于将GPIO设置为输出时，GPIO输出寄存器的值缺省是0，因此会驱动LED点亮.
	// 	这是我不希望的，因此在改变GPIO为输出前，先关闭LED指示灯
	// */
    // bsp_led_off(LED2);
    // /* LED 2*/
	// GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED2;
	// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		/* 设为 输出推挽模式 */
	// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	/* IO口最大速度 */
	// GPIO_Init(GPIO_PORT_LED2, &GPIO_InitStructure);
}
/*************************************************************************************
 * @brief    RGB 红灯初始化
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_RGB_RedInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量

	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);			//开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_GPIO_RGB_RED, ENABLE);			//开启GPIOA的时钟
	
	// Red
	/*GPIO初始化*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RGB_RED;		//GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIO_PORT_RGB_RED, &GPIO_InitStructure);							//将PA6引脚初始化为复用推挽输出	
	
	/*配置时钟源*/
	TIM_InternalClockConfig(TIM_RGB_LED);		//选择TIM3为内部时钟，若不调用此函数，TIM默认也为内部时钟
	
	/*时基单元初始化*/
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频，选择不分频，此参数用于配置滤波器时钟，不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式，选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 255 - 1;					//计数周期，即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;				//预分频器，即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器，高级定时器才会用到
	TIM_TimeBaseInit(TIM_RGB_LED, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit，配置TIM2的时基单元
	
	/*输出比较初始化*/
	TIM_OCStructInit(&TIM_OCInitStructure);							//结构体初始化，若结构体没有完整赋值
																	//则最好执行此函数，给结构体所有成员都赋一个默认值
																	//避免结构体初值不确定的问题
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//输出比较模式，选择PWM模式1
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//输出极性，选择为高，若选择极性为低，则输出高低电平取反
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值
	TIM_OC1Init(TIM_RGB_LED, &TIM_OCInitStructure);						//将结构体变量交给TIM_OC1Init，配置TIM2的输出比较通道1

	/*TIM使能*/
	TIM_Cmd(TIM_RGB_LED, ENABLE);			//使能TIM，定时器开始运行
}

/*************************************************************************************
 * @brief    RGB 绿灯初始化
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_RGB_GreenInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量

	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);			//开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_GPIO_RGB_RED, ENABLE);			//开启GPIOA的时钟

	/*GPIO 绿灯 初始化*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RGB_GREEN;		//GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIO_PORT_RGB_GREEN, &GPIO_InitStructure);							//将PA7引脚初始化为复用推挽输出	
		
	/*配置时钟源*/
	TIM_InternalClockConfig(TIM_RGB_LED);		//选择TIM3为内部时钟，若不调用此函数，TIM默认也为内部时钟
	
	/*时基单元初始化*/
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频，选择不分频，此参数用于配置滤波器时钟，不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式，选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 255 - 1;					//计数周期，即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;				//预分频器，即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器，高级定时器才会用到
	TIM_TimeBaseInit(TIM_RGB_LED, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit，配置TIM2的时基单元
	
	/*输出比较初始化*/
	TIM_OCStructInit(&TIM_OCInitStructure);							//结构体初始化，若结构体没有完整赋值
																	//则最好执行此函数，给结构体所有成员都赋一个默认值
																	//避免结构体初值不确定的问题
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//输出比较模式，选择PWM模式1
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//输出极性，选择为高，若选择极性为低，则输出高低电平取反
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值
	TIM_OC2Init(TIM_RGB_LED, &TIM_OCInitStructure);						//将结构体变量交给TIM_OC1Init，配置TIM2的输出比较通道1
	
	/*TIM使能*/
	TIM_Cmd(TIM_RGB_LED, ENABLE);			//使能TIM，定时器开始运行
}
/*************************************************************************************
 * @brief    RGB 蓝灯初始化
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_RGB_BlueInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量

	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);			//开启TIM2的时钟
	RCC_APB2PeriphClockCmd(RCC_GPIO_RGB_BLUE, ENABLE);			//开启GPIOB的时钟
	/*GPIO初始化*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_RGB_BLUE;		//GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIO_PORT_RGB_BLUE, &GPIO_InitStructure);							//将PA6引脚初始化为复用推挽输出	
																	//受外设控制的引脚，均需要配置为复用模式		
	/*配置时钟源*/
	TIM_InternalClockConfig(TIM_RGB_LED);		//选择TIM3为内部时钟，若不调用此函数，TIM默认也为内部时钟
	/*时基单元初始化*/
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频，选择不分频，此参数用于配置滤波器时钟，不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式，选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 255 - 1;					//计数周期，即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;				//预分频器，即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器，高级定时器才会用到
	TIM_TimeBaseInit(TIM_RGB_LED, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit，配置TIM2的时基单元
	
	/*输出比较初始化*/
	TIM_OCStructInit(&TIM_OCInitStructure);							//结构体初始化，若结构体没有完整赋值
																	//则最好执行此函数，给结构体所有成员都赋一个默认值
																	//避免结构体初值不确定的问题
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//输出比较模式，选择PWM模式1
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//输出极性，选择为高，若选择极性为低，则输出高低电平取反
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值
	TIM_OC3Init(TIM_RGB_LED, &TIM_OCInitStructure);						//将结构体变量交给TIM_OC3Init，配置TIM2的输出比较通道3
	
	/*TIM使能*/
	TIM_Cmd(TIM_RGB_LED, ENABLE);			//使能TIM，定时器开始运行
}
/*************************************************************************************
 * @brief    修改可以改变亮暗的led的亮度 红灯
 * @param[in/out] val  【参数注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_changeBrightness_RGB_Red(uint8_t val)
{
	TIM_SetCompare1(TIM_RGB_LED, val);
}
/*************************************************************************************
 * @brief    修改可以改变亮暗的led的亮度 绿灯
 * @param[in/out] val  【参数注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_changeBrightness_RGB_Green(uint8_t val)
{
	TIM_SetCompare2(TIM_RGB_LED, val);
}
/*************************************************************************************
 * @brief    修改可以改变亮暗的led的亮度 蓝灯
 * @param[in/out] val  【参数注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void bsp_changeBrightness_RGB_Blue(uint8_t val)
{ 
	TIM_SetCompare3(TIM_RGB_LED, val);
}
