#include "LEDS.h"

#define LEDS_GPIO GPIOB
#define LEDS_CLOCK GPIO_Pin_3
#define LEDS_ENABLE GPIO_Pin_4
#define LEDS_DATA GPIO_Pin_5
#define LEDS_STROBE GPIO_Pin_6

#define LEDS_PWM_PERIOD ((48000000 / 500000 ) - 1)
#define LEDS_TIMER_PERIOD ((48000000 / 48000 ) - 1)
#define LEDS_FUNC_TIMER_PERIOD ((48000000 / 1000 ) - 1)

#define LEDS_DISPBUFFER_SIZE 48		//pocet timeslotu
#define LEDS_COLORBUFFER_SIZE 39	//pocet LED

volatile uint32_t LEDS_DispBuffer[LEDS_DISPBUFFER_SIZE];
volatile uint32_t LEDS_ColorBuffer[LEDS_COLORBUFFER_SIZE];	//LED1-LED36,LED_TL1-LED_TL3

void LEDS_DispBuffer_Preset(void);
void LEDS_Button(uint32_t button, uint16_t color);	//button = 1-3;
LEDS_ColorBuff_2_DispBuff(void);
void LEDS_PWM_Init(void);
void LEDS_FUNC_TIMER_Init(void);
void LEDS_TIMER_Init(void);
uint32_t vykon2hodnota (uint32_t vykon);

volatile uint8_t pokus=0;

void LEDS_Init(void)
{
	GPIO_InitTypeDef GP;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
	GP.GPIO_Pin = LEDS_CLOCK|LEDS_ENABLE|LEDS_DATA|LEDS_STROBE;
	GP.GPIO_Mode = GPIO_Mode_OUT;
	GP.GPIO_OType = GPIO_OType_PP;
	GP.GPIO_Speed = GPIO_Speed_Level_3;
	GPIO_Init(LEDS_GPIO, &GP);

	GPIO_ResetBits(LEDS_GPIO,LEDS_DATA);
	GPIO_ResetBits(LEDS_GPIO,LEDS_CLOCK);
	GPIO_ResetBits(LEDS_GPIO,LEDS_STROBE);
	GPIO_SetBits(LEDS_GPIO,LEDS_ENABLE);


	/*for(uint32_t i=0;i<32;i++)
	{
		GPIO_ResetBits(LEDS_GPIO,LEDS_CLOCK);
		GPIO_SetBits(LEDS_GPIO,LEDS_CLOCK);
	}
	GPIO_ResetBits(LEDS_GPIO,LEDS_STROBE);
			GPIO_SetBits(LEDS_GPIO,LEDS_STROBE);
			GPIO_SetBits(LEDS_GPIO,LEDS_DATA);*/

	LEDS_PWM_Init();
	LEDS_TIMER_Init();

	LEDS_SetPWM(100);
	LEDS_FUNC_TIMER_Init();


	LEDS_DispBuffer_Preset();

	LEDS_ColorBuffer[0]=0x7000c0;
	LEDS_ColorBuffer[1]=0x8000b0;
	LEDS_ColorBuffer[2]=0x9000a0;
	LEDS_ColorBuffer[3]=0xa00090;
	LEDS_ColorBuffer[4]=0xb00080;
	LEDS_ColorBuffer[5]=0xc00070;
	LEDS_ColorBuffer[6]=0xd01060;
	LEDS_ColorBuffer[7]=0xe02050;
	LEDS_ColorBuffer[8]=0xf03040;
	LEDS_ColorBuffer[9]=0xf04030;
	LEDS_ColorBuffer[10]=0xe05020;
	LEDS_ColorBuffer[11]=0xd06010;
	LEDS_ColorBuffer[12]=0xc07000;
	LEDS_ColorBuffer[13]=0xb08000;
	LEDS_ColorBuffer[14]=0xa09000;
	LEDS_ColorBuffer[15]=0x90a000;
	LEDS_ColorBuffer[16]=0x80b000;
	LEDS_ColorBuffer[17]=0x70c000;
	LEDS_ColorBuffer[18]=0x60d010;
	LEDS_ColorBuffer[19]=0x50e020;
	LEDS_ColorBuffer[20]=0x40f030;
	LEDS_ColorBuffer[21]=0x30f040;
	LEDS_ColorBuffer[22]=0x20e050;
	LEDS_ColorBuffer[23]=0x10d060;
	LEDS_ColorBuffer[24]=0x00c070;
	LEDS_ColorBuffer[25]=0x00b080;
	LEDS_ColorBuffer[26]=0x00a090;
	LEDS_ColorBuffer[27]=0x0090a0;
	LEDS_ColorBuffer[28]=0x0080b0;
	LEDS_ColorBuffer[29]=0x0070c0;
	LEDS_ColorBuffer[30]=0x1060d0;
	LEDS_ColorBuffer[31]=0x2050e0;
	LEDS_ColorBuffer[32]=0x3040f0;
	LEDS_ColorBuffer[33]=0x4030f0;
	LEDS_ColorBuffer[34]=0x5020e0;
	LEDS_ColorBuffer[35]=0x6010d0;

	LEDS_ColorBuffer[36]=0xff;

	LEDS_ColorBuffer[37]=0xff;

	LEDS_ColorBuffer[38]=0xff;

	LEDS_ColorBuff_2_DispBuff();
}

void LEDS_PWM_Init(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	GPIO_InitTypeDef GP;

	uint16_t TimerPeriod = 0;
	uint16_t Channel1Pulse = 0, Channel2Pulse = 0;

	GPIO_StructInit(&GP);

	GP.GPIO_Pin = LEDS_ENABLE;
	GP.GPIO_Mode = GPIO_Mode_AF;
	GP.GPIO_Speed = GPIO_Speed_Level_3;
	GP.GPIO_OType = GPIO_OType_PP;
	GP.GPIO_PuPd = GPIO_PuPd_UP ;
	GPIO_Init(LEDS_GPIO, &GP);

	GPIO_PinAFConfig(LEDS_GPIO,  GPIO_PinSource4, GPIO_AF_1);

	// TIM3 clock enable
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

	/* Time Base configuration */
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = LEDS_PWM_PERIOD;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

	/* Channel 1 Configuration in PWM mode */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
	TIM_OCInitStructure.TIM_Pulse = 0;	//LEDS OFF

	TIM_OC1Init(TIM3, &TIM_OCInitStructure);

	TIM_Cmd(TIM3, ENABLE);

	TIM_CtrlPWMOutputs(TIM3, ENABLE);
}

void LEDS_SetPWM(uint32_t value)
{
	TIM_SetCompare1(TIM3,(uint16_t) (((uint32_t) value * (LEDS_PWM_PERIOD - 1)) / 100));
}

void LEDS_TIMER_Init(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = LEDS_TIMER_PERIOD;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;


	TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);

	TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE);

	/* Enable the TIM3 gloabal Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPriority =1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	/* TIM3 enable counter */
	TIM_Cmd(TIM14, ENABLE);
}

void TIM14_IRQHandler(void)
{
	static uint32_t cnt=0;			//pocitadlo timeslotu
	static uint32_t prescaler=0;	//preddelicka pro casovac

	if (TIM_GetITStatus(TIM14, TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM14, TIM_IT_Update);
pokus++;
		switch(cnt)	//nastaveni delky pulzu - prvni pulz kratky, posledni nejdelsi
		{			//delka pulzu se nastavuje vzdy na nasledujici krok
			case 5:		prescaler=2; break;
			case 11:	prescaler=4; break;
			case 17:	prescaler=6; break;
			case 23:	prescaler=8; break;
			case 29:	prescaler=10; break;
			case 35:	prescaler=12; break;
			case 41:	prescaler=14; break;
			case 47:	prescaler=0; break;
		}
		TIM_PrescalerConfig(TIM14,prescaler,TIM_PSCReloadMode_Update);

		GPIO_SetBits(LEDS_GPIO,LEDS_STROBE);
		GPIO_ResetBits(LEDS_GPIO,LEDS_STROBE);
		for(uint32_t i=0;i<32;i++)		//32 bitu pro LED driver - nastavit DMA a SPI
		{
			if(LEDS_DispBuffer[cnt]&1<<i)GPIO_SetBits(LEDS_GPIO,LEDS_DATA);
			else GPIO_ResetBits(LEDS_GPIO,LEDS_DATA);
			GPIO_SetBits(LEDS_GPIO,LEDS_CLOCK);
			GPIO_ResetBits(LEDS_GPIO,LEDS_CLOCK);
		}

		cnt++;
		if(cnt>=LEDS_DISPBUFFER_SIZE)cnt=0;

	}
}

//vymaze LEDS_DispBuffer a nachysta data pro anody
void LEDS_DispBuffer_Preset(void)
{
	for(uint32_t i=0;i<LEDS_DISPBUFFER_SIZE;i+=6)
	{
		LEDS_DispBuffer[i]=(uint32_t)(1<<2);	//A1
		LEDS_DispBuffer[i+1]=(uint32_t)(1<<1);	//A2
		LEDS_DispBuffer[i+2]=(uint32_t)(1<<4);	//A3
		LEDS_DispBuffer[i+3]=(uint32_t)(1<<3);	//A4
		LEDS_DispBuffer[i+4]=(uint32_t)(1<<0);	//A5
		LEDS_DispBuffer[i+5]=0;					//tma
	}
}

void LEDS_Button(uint32_t button, uint16_t color)	//button = 1-3
{
	LEDS_ColorBuffer[button+35]=color;	//pozice LED_TL1 je na 36, LED_TL2 na 37 a LED_TL3 na 38
}

LEDS_ColorBuff_2_DispBuff(void)
{
	volatile uint32_t LEDxR=0;
	volatile uint32_t LEDxG=0;
	volatile uint32_t LEDxB=0;

	LEDS_DispBuffer_Preset();

	for(uint32_t m=0;m<9;m++)	//RGB1 - RGB9
	{
		for(uint32_t n=0;n<4;n++)	//vyber anody A1 - A4
		{
			//vyjmuti hornich 3 bitu kazde barvy RGB kodu
			LEDxR=(((LEDS_ColorBuffer[n+m*4])&0x00f00000)>>21);
			LEDxG=(((LEDS_ColorBuffer[n+m*4])&0x0000f000)>>13);
			LEDxB=(((LEDS_ColorBuffer[n+m*4])&0x000000f0)>>5);

			for(uint32_t p=0;p<8;p++)	//vyber timeslotu 0 - 7
			{
				if(LEDxR){LEDxR--;LEDS_DispBuffer[p*6+n]|=1<<(31-m*3);}
				if(LEDxG){LEDxG--;LEDS_DispBuffer[p*6+n]|=1<<(30-m*3);}
				if(LEDxB){LEDxB--;LEDS_DispBuffer[p*6+n]|=1<<(29-m*3);}
			}
		}
	}

	for(uint32_t m=0;m<9;m++)	//RGB1 - RGB9
	{
		//LED tlacitko 1
		//vyjmuti hornich 3 bitu kazde barvy RGB kodu
		LEDxR=(((LEDS_ColorBuffer[36])&0x00f00000)>>21);
		LEDxG=(((LEDS_ColorBuffer[36])&0x0000f000)>>13);
		LEDxB=(((LEDS_ColorBuffer[36])&0x000000f0)>>5);
		for(uint32_t p=0;p<8;p++)	//vyber timeslotu 0 - 7
		{
			if(LEDxR){LEDxR--;LEDS_DispBuffer[p*6+4]|=1<<(31-1*3);}
			if(LEDxG){LEDxG--;LEDS_DispBuffer[p*6+4]|=1<<(30-1*3);}
			if(LEDxB){LEDxB--;LEDS_DispBuffer[p*6+4]|=1<<(29-1*3);}
		}

		//LED tlacitko 2
		//vyjmuti hornich 3 bitu kazde barvy RGB kodu
		LEDxR=(((LEDS_ColorBuffer[37])&0x00f00000)>>21);
		LEDxG=(((LEDS_ColorBuffer[37])&0x0000f000)>>13);
		LEDxB=(((LEDS_ColorBuffer[37])&0x000000f0)>>5);
		for(uint32_t p=0;p<8;p++)	//vyber timeslotu 0 - 7
		{
			if(LEDxR){LEDxR--;LEDS_DispBuffer[p*6+4]|=1<<(31-0*3);}
			if(LEDxG){LEDxG--;LEDS_DispBuffer[p*6+4]|=1<<(30-0*3);}
			if(LEDxB){LEDxB--;LEDS_DispBuffer[p*6+4]|=1<<(29-0*3);}
		}

		//LED tlacitko 3
		//vyjmuti hornich 3 bitu kazde barvy RGB kodu
		LEDxR=(((LEDS_ColorBuffer[38])&0x00f00000)>>21);
		LEDxG=(((LEDS_ColorBuffer[38])&0x0000f000)>>13);
		LEDxB=(((LEDS_ColorBuffer[38])&0x000000f0)>>5);
		for(uint32_t p=0;p<8;p++)	//vyber timeslotu 0 - 7
		{
			if(LEDxR){LEDxR--;LEDS_DispBuffer[p*6+4]|=1<<(31-8*3);}
			if(LEDxG){LEDxG--;LEDS_DispBuffer[p*6+4]|=1<<(30-8*3);}
			if(LEDxB){LEDxB--;LEDS_DispBuffer[p*6+4]|=1<<(29-8*3);}
		}
	}
}

void LEDS_FUNC_TIMER_Init(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

	TIM_TimeBaseStructure.TIM_Prescaler = 20;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = LEDS_FUNC_TIMER_PERIOD;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

	TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

	TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);

	NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	TIM_Cmd(TIM6, ENABLE);
}

void TIM6_DAC_IRQHandler(void)
{
	 if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM6, TIM_IT_Update);

		uint32_t temp=LEDS_ColorBuffer[35];
		for(uint32_t i=0;i<35;i++)
		{
			LEDS_ColorBuffer[35-i]=LEDS_ColorBuffer[34-i];
		}
		LEDS_ColorBuffer[0]=temp;
		LEDS_ColorBuff_2_DispBuff();
	}
}

void LEDS_GreenRedGraph(uint32_t value)	//27 LED => 5-31
{
	uint32_t val=vykon2hodnota(value);
	LEDS_ColorBuffer[0]=0xff;
	LEDS_ColorBuffer[1]=0xff;
	LEDS_ColorBuffer[2]=0xff;
	LEDS_ColorBuffer[3]=0xff;
	LEDS_ColorBuffer[4]=0xff;
	LEDS_ColorBuffer[5]=0x60f000;
	LEDS_ColorBuffer[6]=0x70e000;
	LEDS_ColorBuffer[7]=0x70e000;
	LEDS_ColorBuffer[8]=0x80d000;
	LEDS_ColorBuffer[9]=0x80d000;
	LEDS_ColorBuffer[10]=0x90c000;
	LEDS_ColorBuffer[11]=0x90c000;
	LEDS_ColorBuffer[12]=0xa0b000;
	LEDS_ColorBuffer[13]=0xa0b000;
	LEDS_ColorBuffer[14]=0xb0a000;
	LEDS_ColorBuffer[15]=0xb0a000;
	LEDS_ColorBuffer[16]=0xc09000;
	LEDS_ColorBuffer[17]=0xc09000;
	LEDS_ColorBuffer[18]=0xd08000;
	LEDS_ColorBuffer[19]=0xd08000;
	LEDS_ColorBuffer[20]=0xe07000;
	LEDS_ColorBuffer[21]=0xe07000;
	LEDS_ColorBuffer[22]=0xf06000;
	LEDS_ColorBuffer[23]=0xf06000;
	LEDS_ColorBuffer[24]=0xf00000;
	LEDS_ColorBuffer[25]=0xf00000;
	LEDS_ColorBuffer[26]=0xf00000;
	LEDS_ColorBuffer[27]=0xf00000;
	LEDS_ColorBuffer[28]=0xff0000;
	LEDS_ColorBuffer[29]=0xff0000;
	LEDS_ColorBuffer[30]=0xff0000;
	LEDS_ColorBuffer[31]=0xff0000;
	LEDS_ColorBuffer[32]=0xff;
	LEDS_ColorBuffer[33]=0xff;
	LEDS_ColorBuffer[34]=0xff;
	LEDS_ColorBuffer[35]=0xff;

	for(uint32_t i=0;i<(27-val);i++)
	{
		LEDS_ColorBuffer[31-i]=0;
	}
	LEDS_ColorBuff_2_DispBuff();
}

uint32_t vykon2hodnota (uint32_t vykon)
{
	uint32_t value=0;
	if(vykon>3485)value=27;
	else if(vykon>3351)value=26;
	else if(vykon>3217)value=25;
	else if(vykon>3083)value=24;
	else if(vykon>2949)value=23;
	else if(vykon>2815)value=22;
	else if(vykon>2681)value=21;
	else if(vykon>2547)value=20;
	else if(vykon>2413)value=19;
	else if(vykon>2279)value=18;
	else if(vykon>2145)value=17;
	else if(vykon>2011)value=16;
	else if(vykon>1877)value=15;
	else if(vykon>1743)value=14;
	else if(vykon>1609)value=13;
	else if(vykon>1475)value=12;
	else if(vykon>1341)value=11;
	else if(vykon>1207)value=10;
	else if(vykon>1073)value=9;
	else if(vykon>939)value=8;
	else if(vykon>805)value=7;
	else if(vykon>671)value=6;
	else if(vykon>537)value=5;
	else if(vykon>403)value=4;
	else if(vykon>269)value=3;
	else if(vykon>135)value=2;
	else if(vykon>1)value=1;
	else value=0;
	return value;
}
