/**
  ******************************************************************************
  * File Name          : TIM.c
  * Description        : This file provides code for the configuration
  *                      of the TIM instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tim.h"

/* USER CODE BEGIN 0 */
uint8_t WS2812B_CRR_Value[LED_COUNT*24+1] = {10};

uint8_t WS2812B_DATA[LED_COUNT*3] = {0};
/* USER CODE END 0 */

/* TIM2 init function */
void MX_TIM2_Init(void)
{
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
  LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);

  /* TIM2 DMA Init */
  
  /* TIM2_UP Init */
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_LOW);

  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_CIRCULAR);

  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_HALFWORD);

  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE);

  /* TIM2 interrupt Init */
  NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM2_IRQn);

  TIM_InitStruct.Prescaler = 1;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 39;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(TIM2, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM2);
  LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH2);
  TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
  TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
  TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
  TIM_OC_InitStruct.CompareValue = 0;
  TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
  LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct);
  LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2);
  LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM2);
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
    /**TIM2 GPIO Configuration    
    PA1     ------> TIM2_CH2 
    */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
  LL_TIM_InitTypeDef TIM_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);

  /* TIM3 interrupt Init */
  NVIC_SetPriority(TIM3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(TIM3_IRQn);

  TIM_InitStruct.Prescaler = 6399;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 9999;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(TIM3, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM3);
  LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
  LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM3);

}

/* USER CODE BEGIN 1 */
void TIM2_DMA_Config(void)
{
	LL_DMA_InitTypeDef  DMA_InitStruct = {0};

	DMA_InitStruct.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
	DMA_InitStruct.NbData = (LED_COUNT*24+1);
	DMA_InitStruct.MemoryOrM2MDstAddress = (uint32_t)WS2812B_CRR_Value;
	DMA_InitStruct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
	DMA_InitStruct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
	DMA_InitStruct.PeriphOrM2MSrcAddress = (uint32_t)&(TIM2->CCR2);
	DMA_InitStruct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
	DMA_InitStruct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
	DMA_InitStruct.Mode = LL_DMA_MODE_CIRCULAR;
	DMA_InitStruct.Priority = LL_DMA_PRIORITY_LOW;
	LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2,&DMA_InitStruct);
	
	LL_DMA_ClearFlag_TC2(DMA1);
	LL_DMA_EnableIT_TC(DMA1,LL_DMA_CHANNEL_2);
	
	LL_TIM_EnableDMAReq_UPDATE(TIM2);
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); 

}

void WS2812_Data_Transfer(uint8_t *src , uint32_t len)
{
	uint8_t i = 0;
	uint32_t bits = 0;
	uint32_t bytes = 0;
	
	while(len--)
	{
		for(i = 0;i<8;i++)
		{
			WS2812B_CRR_Value[bits] = (((*(src+bytes))<<i)&0x80)? ONE : Zero;
			bits++;
		}
		bytes++;
	}
	WS2812B_CRR_Value[bits] = 0;
	
	
	LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
	LL_TIM_EnableCounter(TIM2);
	
}

void WS2812_Light_One_By_One(uint8_t corlor,uint8_t light_level)
{
	uint8_t i = 0;
	memset(WS2812B_DATA,0,sizeof(WS2812B_DATA));
	
	
	for(i = 0; i<(LED_COUNT+1) ; i++)
	{
		WS2812_Data_Transfer(WS2812B_DATA,sizeof(WS2812B_DATA));            //�ϵ�ʱLED��˸���ʱ��
		LL_mDelay(60);
		
		if(i<LED_COUNT){
			WS2812B_DATA[i*3+corlor]=light_level;
		}
	}
	
}


void WS2812_Light_Custom(uint8_t red,uint8_t green , uint8_t blue) 		// R,G,B brightness level 0-255
{
	uint8_t i = 0;
	memset(WS2812B_DATA,0,sizeof(WS2812B_DATA));
	LL_mDelay(1);
	for(i = 0; i<(LED_COUNT) ; i++)			// LED elements 0 -- Max LED Count
	{
		WS2812B_DATA[3*i] = green;				// Green brightness level
		WS2812B_DATA[3*i+1] = red;				// Red brightness level
		WS2812B_DATA[3*i+2] = blue;				// Blue brightness level
	}
	WS2812_Data_Transfer(WS2812B_DATA,sizeof(WS2812B_DATA));
}

/*
��ɫ˵��
��0
�̣�1
�죺2
����3
�ƣ�4
�ϣ�5
�ࣺ6
�ף�7
������˸��8
*/
void WS2812_Light_All( uint8_t color)
{
	switch( color )
	{
		case 0 : WS2812_Light_Custom( 0,0,0);break;										// 000 = Dark mode
		case 1 : WS2812_Light_Custom( 0,Light_Level,0 );break;							// 010 = Green
		case 2 : WS2812_Light_Custom( Light_Level,0,0 );break;							// 100 = Red
		case 3 : WS2812_Light_Custom( 0,0,Light_Level );break;							// 001 = Blue
		case 4 : WS2812_Light_Custom( Light_Level,Light_Level,0 );break;				// 110 = Yellow
		case 5 : WS2812_Light_Custom( Light_Level,0,Light_Level );break;				// 101 = Pink
		case 6 : WS2812_Light_Custom( 0,Light_Level,Light_Level );break;				// 011 = Cyan
		case 7 : WS2812_Light_Custom( Light_Level,Light_Level,Light_Level );break;	// 111 = White
		case 8 : WS2812_Light_Custom( Light_Level,0,0 );LL_mDelay(300);WS2812_Light_Custom( 0,0,Light_Level );LL_mDelay(300); break;
	}
}

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/