#include "header.h"

void set_xy(int16_t x, int16_t y)
{
    if (x > MAX_X) x = 0 ;
    if (y > MAX_Y) y = 0 ;
    akt_x = x;
    akt_y = y;
}

void draw_picture(uint16_t LENGTH, uint16_t HEIGHT, const char picture[HEIGHT][LENGTH], uint16_t x_pos, uint16_t y_pos)

{
	uint16_t cntx = 0;
	uint16_t cnty= 0;
	uint16_t x1;
	uint16_t zx=0;
	uint16_t zy=0;
	uint16_t y1 = y_pos;
	uint16_t y2 = y1+(zoom_y*HEIGHT);
	uint16_t x11 = x_pos;
	uint16_t x2 = x11+(zoom_x*LENGTH);
	uint16_t temp;
	    if (y1 > y2) {
	        temp = y1;
	        y1 = y2;
	        y2 = temp;
	    }
	    while (y1 < y2)
	    {
	    	for(zy=0;zy<=zoom_y-1;zy++)
	    	{
	    		       	x1 = x11;
	    				cntx = 0;
	    		        while (x1 < x2)
	    		        {
	    		        	for(zx=0;zx<=zoom_x-1;zx++)
	    		        	{
	    		        		set_pixel(x1+zx, y1+zy,picture[cnty][cntx]);
	    		            }
	    		        	for(zx=0;zx<=zoom_x-1;zx++){x1++;}
	    		        	cntx++;
	    		        }

	    	}
	    	for(zy=0;zy<=zoom_y-1;zy++){y1++;}
	        cnty++;
	    }
}

void draw_picture_center(uint8_t LENGTH, uint8_t HEIGHT, const char picture[HEIGHT][LENGTH])

{
	uint8_t cntx = 0;
	uint8_t cnty= 0;
	uint8_t x1;
	uint8_t zx=0;
	uint8_t zy=0;
	uint8_t y1 = (MAX_Y/2)-(zoom_y*HEIGHT/2);
	uint8_t y2 = y1+(zoom_y*HEIGHT);
	uint8_t x11 = (MAX_X/2)-(zoom_x*LENGTH/2);
	uint8_t x2 = x11+(zoom_x*LENGTH);
	int16_t temp;
	    if (y1 > y2) {
	        temp = y1;
	        y1 = y2;
	        y2 = temp;
	    }
	    while (y1 < y2)
	    {
	    	for(zy=0;zy<=zoom_y-1;zy++)
	    	{
	    		       	x1 = x11;
	    				cntx = 0;
	    		        while (x1 < x2)
	    		        {
	    		        	for(zx=0;zx<=zoom_x-1;zx++)
	    		        	{
	    		        		set_pixel(x1+zx, y1+zy,picture[cnty][cntx]);
	    		            }
	    		        	for(zx=0;zx<=zoom_x-1;zx++){x1++;}
	    		        	cntx++;
	    		        }

	    	}
	    	for(zy=0;zy<=zoom_y-1;zy++){y1++;}
	        cnty++;
	    }
}


void write_character_dyn(uint8_t c, uint8_t color)
{
	uint8_t row, column;
	uint8_t *adr, *temp_adr;
	uint8_t pattern, i, j;
	uint8_t *symbol = &active_font[(c+ 1 )*CHARACTER_HEIGHT];  // base address of the character
	uint16_t eff_x, eff_y;
    eff_y = akt_y;
    row = CHARACTER_HEIGHT;
    while (row--) {          // entire height
    	eff_x = akt_x;
	  pattern = *symbol++;    // data of the line
	  adr = temp_adr;
	  column = CHARACTER_LENGTH;
	  while (column--) {
           temp_adr = adr = (uint8_t *) (image + (eff_x+eff_y*IMAGEWIDTH));
      i= 0 ;
      while (i < zoom_y) {    // zoom y
                j = 0 ;
          while (j < zoom_x) {    // zoom x
        if ((eff_x+j) <= MAX_X && (eff_y+i) <= MAX_Y) {
            if (pattern & 0x80 ) {
                if (draw_mode & VG) *adr = color;  //  draw the foreground
            } else {
                if (draw_mode & HG) *adr = background; // paint background
            }
                  adr++;
              }
                    j++;
                } // while(j)
          temp_adr += IMAGEWIDTH;
          adr = temp_adr;
                i++;
            } // while(i)
      pattern <<= 1 ;  // next pixel
      eff_x += zoom_x;
        } // while(column)
  eff_y += zoom_y;  // next line
    } // while(line)
}


void write_string_center(int8_t *s, uint8_t color)
{
uint8_t c;
    c= 0 ; while (s[c]) c++;
    akt_x = (MAX_X - c * CHARACTER_LENGTH*zoom_x)/ 2 ;
    akt_y = (MAX_Y / 2)-(16 * zoom_y)/2;
    while (c = *s++) {
        write_character_dyn(c,color);
  akt_x += CHARACTER_LENGTH*zoom_x;
    }
}

void write_string(int8_t *s, uint16_t x_pos, uint16_t y_pos, uint8_t color)
{
uint8_t c;
    c= 0 ; while (s[c]) c++;
    if(((c * CHARACTER_LENGTH*zoom_x) + x_pos)> MAX_X)
    {akt_x = MAX_X - (c * CHARACTER_LENGTH*zoom_x);}
    akt_x = x_pos;
    akt_y = y_pos;
    while (c = *s++) {
        write_character_dyn(c,color);
  akt_x += CHARACTER_LENGTH*zoom_x;
    }
}

void write_uint(uint8_t character, uint16_t x_pos, uint16_t y_pos, uint8_t color)
{
	uint8_t c;
	        	uint8_t tmp1;
	        	uint8_t tmp2;
	        	uint8_t tmp3;

	        	if(character < 10)
	        	{
	        		c=1;
	        		akt_x = x_pos;
	        		akt_y = y_pos;

	        		write_character_dyn(32,color);
	        		akt_x += CHARACTER_LENGTH*zoom_x;

	        		write_character_dyn(32,color);
	        		akt_x += CHARACTER_LENGTH*zoom_x;

	        		write_character_dyn(character+48,color);
	        		akt_x += CHARACTER_LENGTH*zoom_x;
	        	}

	        	if(character >= 10 && character <100)
									{
										c=2;
										tmp1 = character/10;
										tmp2 = character - tmp1 * 10;

										akt_x = x_pos;
										akt_y = y_pos;

										write_character_dyn(32,color);		//pro zarovnani cifer
										akt_x += CHARACTER_LENGTH*zoom_x;

										write_character_dyn(tmp1+48,color);
										akt_x += CHARACTER_LENGTH*zoom_x;

										write_character_dyn(tmp2+48,color);
										akt_x += CHARACTER_LENGTH*zoom_x;
									}
	        	if(character >= 100 && character <1000)
	        										{
	        											c=3;
	        											tmp1 = character/100;
	        											tmp2 = (character - tmp1*100)/10;
	        											tmp3 = character - tmp1 * 100 - tmp2 * 10;

	        											akt_x = x_pos;
	        											akt_y = y_pos;

	        											write_character_dyn(tmp1+48,color);
	        											akt_x += CHARACTER_LENGTH*zoom_x;

	        											write_character_dyn(tmp2+48,color);
	        											akt_x += CHARACTER_LENGTH*zoom_x;

	        											write_character_dyn(tmp3+48,color);
	        											akt_x += CHARACTER_LENGTH*zoom_x;
	        										}
}

void write_uint_center(uint8_t character, uint8_t color)//opravit zarovnani podle write_uint
{
	uint8_t c;
	uint8_t tmp1;
	uint8_t tmp2;

	if(character < 10)
	{
		c=1;
		akt_x = (MAX_X - c * CHARACTER_LENGTH*zoom_x)/ 2 ;
		write_character_dyn(character+48,color);
		akt_x += CHARACTER_LENGTH*zoom_x;
	}

	if(character >= 10 && character <100)
	{
		c=2;
		tmp1 = character/10;
		tmp2 = character - tmp1 * 10;
		akt_x = (MAX_X - c * CHARACTER_LENGTH*zoom_x)/ 2 ;

		write_character_dyn(tmp1+48,color);
		akt_x += CHARACTER_LENGTH*zoom_x;

		write_character_dyn(tmp2+48,color);
		akt_x += CHARACTER_LENGTH*zoom_x;
	}
}


void set_pixel(uint16_t x, uint16_t y, uint8_t color)
{
    if (x <= MAX_X && y <= MAX_Y && x >= 0 && y >= 0)
        image[(x + y*IMAGEWIDTH)] = color;
}



void horizontal_line(uint16_t x1, uint16_t x2, uint16_t y, uint8_t color)
{
uint16_t temp;
uint8_t *adr;
    if (x1 > MAX_X) x1 = MAX_X;
    if (x2 > MAX_X) x2 = MAX_X;
    if (y > MAX_Y) y = MAX_Y;

    if (x1 > x2) {
        temp = x1;
        x1 = x2;
        x2 = temp;
    }
    adr = (image + (x1+y*IMAGEWIDTH));
    while (x1 <= x2) {
        *adr = color;
        adr++;
        x1++;
    }
}

int16_t sgn(int16_t x){
    return (x > 0 ) ? 1 : (x < 0 ) ? - 1 : 0 ;
}

void draw_line(int16_t xstart, int16_t ystart, int16_t xend, int16_t yend, int8_t color)//draw a line
{
int16_t x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;

    dx = xend - xstart;
    dy = yend - ystart;
    incx = sgn(dx);
    incy = sgn(dy);
    if (dx< 0 ) dx = -dx;
    if (dy< 0 ) dy = -dy;

    if (dx>dy){
        pdx=incx; pdy= 0 ;
        ddx=incx; ddy=incy;
        es =dy;   el =dx;
    } else {
        pdx= 0 ;    pdy=incy;
        ddx=incx; ddy=incy;
        es =dx;   el =dy;
    }

    x = xstart;
    y = ystart;
    err = el/ 2 ;
    set_pixel(x,y, color);

    for (t= 0 ; t<el; ++t) {
        err -= es;
        if (err< 0 ) {
            err += el;
            x += ddx;
            y += ddy;
        } else {
            x += pdx;
            y += pdy;
        }
        set_pixel(x,y, color);
    }
}

void draw_rectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int8_t color)
{
    draw_line(x1, y1, x1, y2, color);  // left vertical
    draw_line(x2, y1, x2, y2, color);  // right vertical
    draw_line(x1, y1, x2, y1, color);  // above
    draw_line(x1, y2, x2, y2, color);  // below
}

void fill_rectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int8_t color)//fill rectangle
{
int16_t temp;
    if (y1 > y2) {
        temp = y1;
        y1 = y2;
        y2 = temp;
    }
    while (y1 <= y2) {
        horizontal_line(x1, x2, y1, color);
        y1++;
    }
}

void color_display(uint8_t color)
{
	fill_rectangle( 0 , 0 ,MAX_X,MAX_Y,color);//fill rectangle
}

void usart_init (void)
{
	GPIO_InitTypeDef GPIO_InitStruct; // this is for the GPIO pins used as TX and RX
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef NVIC_InitStructure; // this is used to configure the NVIC (nested vector interrupt controller)

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // Pins 6 (TX) and 7 (RX) are used

	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // the pins are configured as alternate function so the USART peripheral has access to them
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	// this defines the IO speed and has nothing to do with the baudrate!
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;	// this defines the output type as push pull mode (as opposed to open drain)
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;	// this activates the pullup resistors on the IO pins
	GPIO_Init(GPIOB, &GPIO_InitStruct);	// now all the values are passed to the GPIO_Init() function which sets the GPIO registers

	/* The RX and TX pins are now connected to their AF
	* so that the USART1 can take over control of the
	* pins
	*/
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1); //
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

	/* Now the USART_InitStruct is used to define the
	* properties of USART1
	*/
	USART_InitStruct.USART_BaudRate = 9600;	// the baudrate is set to the value we passed into this init function
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;// we want the data frame size to be 8 bits (standard)
	USART_InitStruct.USART_StopBits = USART_StopBits_1;	// we want 1 stop bit (standard)
	USART_InitStruct.USART_Parity = USART_Parity_No;	// we don't want a parity bit (standard)
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // we don't want flow control (standard)
	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // we want to enable the transmitter and the receiver
	USART_Init(USART1, &USART_InitStruct);	// again all the properties are passed to the USART_Init function which takes care of all the bit setting

	/* Here the USART1 receive interrupt is enabled
	* and the interrupt controller is configured
	* to jump to the USART1_IRQHandler() function
	* if the USART1 receive interrupt occurs
	*/
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // enable the USART1 receive interrupt

	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	// we want to configure the USART1 interrupts
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;// this sets the priority group of the USART1 interrupts
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	// this sets the subpriority inside the group
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	// the USART1 interrupts are globally enabled
	NVIC_Init(&NVIC_InitStructure);	// the properties are passed to the NVIC_Init function which takes care of the low level stuff

	// finally this enables the complete USART1 peripheral
	USART_Cmd(USART1, ENABLE);
}


void dec_hex(int dec_num)   // Prevod dekadickeho cisla na hexa(v char)
{
	int dh_rem[50];
	int dh_i=0, dh_length=0, dh_cnt = 0;

	if (dec_num < 10)
	{
		dh_vysledek[dh_cnt] = '0';
		dh_cnt++;
	}


	while(dec_num > 0)
	{
		dh_rem[dh_i]=dec_num%16;
		dec_num=dec_num/16;
		dh_i++;
		dh_length++;
	}

	for(dh_i = dh_length - 1; dh_i>=0; dh_i--)
	{
		switch(dh_rem[dh_i])
		{
			case 10:
			dh_vysledek[dh_cnt] = 'A';
			dh_cnt++;
			break;
			case 11:
			dh_vysledek[dh_cnt] = 'B';
			dh_cnt++;
			break;
			case 12:
			dh_vysledek[dh_cnt] = 'C';
			dh_cnt++;
			break;
			case 13:
			dh_vysledek[dh_cnt] = 'D';
			dh_cnt++;
			break;
			case 14:
			dh_vysledek[dh_cnt] = 'E';
			dh_cnt++;
			break;
			case 15:
			dh_vysledek[dh_cnt] = 'F';
			dh_cnt++;
			break;
			default :
			dh_vysledek[dh_cnt] = (char)(dh_rem[dh_i] + 48);
			dh_cnt++;
			break;
		}
	}
}

// this is the interrupt request handler (IRQ) for ALL USART1 interrupts
void USART1_IRQHandler(void){
// check if the USART1 receive interrupt flag was set
if( USART_GetITStatus(USART1, USART_IT_RXNE) ){

	r_data = USART1->DR; // the character from the USART1 data register is saved in r_data


	if(state_id == 1)
	{
		state_id++;usart_connected = 1;
	}
	if(state_id == 7)
	{
		state_id++;usart_connected = 1;
	}

	if(r_data == id_atmel)
	{
		if(Modul_State == MEASURING_CARD || Modul_State == NO_CONNECTION)
		{
			state_id = 1;
			Modul_State = MEASURING_CARD;
			TIM_Cmd(TIM1, DISABLE);
			TIM_SetCounter(TIM1, 0);
		}

	}
	if(r_data == id_pc)
	{
		if(Modul_State == PC_CONNECTED || Modul_State == NO_CONNECTION)
		{
			state_id = 7;
			Modul_State = PC_CONNECTED;
			command_ready = 0;
			TIM_Cmd(TIM1, DISABLE);
			TIM_SetCounter(TIM1, 0);
		}
	}
	if(Modul_State == PC_CONNECTED)
	{
		if(r_data == '$')
		{
			TIM_Cmd(TIM1, DISABLE);
			TIM_SetCounter(TIM1, 0);
		}
	}

	if(state_id > 1 && state_id < 7)
	{
		buff[state_id-2] = r_data;
		state_id++;
		if(state_id == 6)
		{
			state_id = 0;
			if(start == 0)
			{
				start = 1;
			}
		}
	}
	if(state_id > 7)
		{
		buff_command[state_id-8] = r_data;
			state_id++;
			if(state_id == (BUFF_CMD_LENGTH + 8))//puv18
			{
				if(zero==0)
				{
					checksum_received[0] = buff_command[BUFF_CMD_LENGTH-2];
					checksum_received[1] = buff_command[BUFF_CMD_LENGTH-1];
					//tady spocitat checksum, pokud bude souhlasit, budou dale zpracovany prikazy, pokud ne, zpracovani prikazu preskocim


					for(xxx=0; xxx<25; xxx++)//kontrolni vypsani celeho bufferu (bez P - hlavicky)
					{
						cb1[xxx] = buff_command[xxx];

					}
					for(xxx=25; xxx<BUFF_CMD_LENGTH; xxx++)
					{
						cb2[xxx-25] = buff_command[xxx];

					}

					//vypocet a kontrola checksum
					for (for_chcksum = 0; for_chcksum < (BUFF_CMD_LENGTH - 3); for_chcksum++)
					{
						chsum ^= buff_command[for_chcksum];
					}

					dec_hex(chsum);//prevedeme chsum z desitkove soustavy do hexa a vysledek ulozime do dh_vysledek;
					checksum_computed[0] = dh_vysledek[0];
					checksum_computed[1] = dh_vysledek[1];
					chsum = 0;

					if(checksum_received[0] == checksum_computed[0] && checksum_received[1] == checksum_computed[1])
					{
						command_ready = 1;
					}
				}


				state_id = 0;
				if(start == 0)
				{
					start = 1;
				}
			}
		}
	}
}

void send_string(const char *s)
{
	while(*s)
	{
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		USART_SendData(USART1, *s++);
	}
}

void USART(void)//pro vyslani adresoveho znaku 0x53 = "S"
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    if(Modul_State != PC_CONNECTED)
    {
    	USART_SendData(USART1, 0x53);
    	TIM_Cmd(TIM1, ENABLE);
    }
    if(Modul_State == PC_CONNECTED)
	{
		USART_SendData(USART1, 0x24);
		TIM_Cmd(TIM1, ENABLE);
	}

}

static void fsmc_init( void )
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef    TIM_InitStruct;
	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
	FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;
	/* Enable GPIOs clock */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE , ENABLE);
	/* Enable FSMC clock */
	RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

	GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FSMC);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
	FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
	FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
	FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
	FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
	FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
	FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
	FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
	FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
	FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 0 ;
	FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0 ;
	FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 24 ;	//168MHz / 24 = 7MHz
	FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0x04 ;
	FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0x0f ;
	FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0x0f ;
	FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A;
	FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
	FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
	FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
}

void init_dma2_0( void )
{
	RCC->AHB1ENR   |= 0x00400000 ;   // activate DMA2
	DMA2->LIFCR = 0xfd ;             // Delete all int flags
	DMA2_Stream0->CR = 0x490 ;       // 8bit mode address mode PINC = 0, MINC = 1
	DMA2_Stream0->NDTR = H_LINE_LEN;
	akt_picture_address = (uint32_t)&imagememory;
	DMA2_Stream0->PAR = (uint32_t)akt_picture_address;
	DMA2_Stream0->M0AR = (uint32_t)(TFT_ADR + HSYNC_ADR_MASK - THP);
	NVIC_EnableIRQ(DMA2_Stream0_IRQn);
	NVIC_SetPriority(DMA2_Stream0_IRQn, 5 );
	DMA2_Stream0->CR |= 0x1 ;
	__enable_irq();
}

void DMA2_Stream0_IRQHandler( void )
{
	__enable_irq ();
	DMA2->LIFCR = 0xfd ;             //Clear all int flags
	if (line_cnt >= V_LEN)
	{
		line_cnt = 0 ;
		akt_picture_address = (uint32_t)&imagememory;
	}
	if (line_cnt < TVP)
	{
		DMA2_Stream0->M0AR = (uint32_t)(TFT_ADR + HSYNC_ADR_MASK - THP);
	}
	else
	{
		DMA2_Stream0->M0AR = (uint32_t)(TFT_ADR + HSYNC_ADR_MASK + VSYNC_ADR_MASK - THP);
	}
	if (line_cnt < Y_START_POS)
	{
		DMA2_Stream0->CR = 0x490 ;  // 8bit mode address mode PINC = 0, MINC = 1
		DMA2_Stream0->PAR = (uint32_t)&black_pixel;
	}
	else
	{
		DMA2_Stream0->CR = 0x690 ;  // 8bit mode address mode PINC = 1, MINC = 1
		DMA2_Stream0->PAR = (uint32_t)akt_picture_address;
		akt_picture_address += (IMAGEWIDTH);
	}
	DMA2_Stream0->NDTR = H_LINE_LEN;
	line_cnt++;
	DMA2_Stream0->CR |= 0x1 ;
}


void pong_move_plates(int hodnota1, int hodnota2, int plate_height, int plate_width)
{
	if(pong_start[1] == 0)
	{
		plate_start = SIZE_Y - plate_height / 2 - 1 - 2;			//the strat y position of plate - vztazeno ke stredu plejtu
		plate1 = plate2 = plate_start;								//the strat y position of plate - vztazeno ke stredu plejtu
	}

	if(pong_start[1] != 0)
	{
		plate1 = plate_start - hodnota1;
		plate2 = plate_start - hodnota2;
	}

	if(plate1 - plate_height/2 <= pong_size_y + 2){plate1 = pong_size_y + 1 + plate_height/2;}//osetreni, aby plate1 nevyjel nahoru ven z pole
	if(plate2 - plate_height/2 <= pong_size_y + 2){plate2 = pong_size_y + 1 + plate_height/2;}//osetreni, aby plate2 nevyjel nahoru ven z pole


	if(plate1 != l_plate1)
	{
		if(pong_start[1] != 0)
		{
			fill_rectangle((int16_t)(2), (int16_t)(l_plate1 - plate_height/2), (int16_t)(plate_width + 1), (int16_t)(l_plate1 + plate_height/2), BLACK);//fill rectangle
		}
		fill_rectangle((int16_t)(2), (int16_t)(plate1 - plate_height/2), (int16_t)(plate_width + 1), (int16_t)(plate1 + plate_height/2), GREEN);//fill rectangle
	}
	if(plate2 != l_plate2)
	{
		if(pong_start[1] != 0)
		{
			fill_rectangle((int16_t)(SIZE_X - 2 - plate_width), (int16_t)(l_plate2 - plate_height/2), (int16_t)(SIZE_X - 3), (int16_t)(l_plate2 + plate_height/2), BLACK);//fill rectangle
		}
		fill_rectangle((int16_t)(SIZE_X - 2 - plate_width), (int16_t)(plate2 - plate_height/2), (int16_t)(SIZE_X - 3), (int16_t)(plate2 + plate_height/2), GREEN);//fill rectangle
	}

	l_plate1 = plate1;
	l_plate2 = plate2;

	if(pong_start[1] == 0)
	{pong_start[1] = 1;}
}


void measure_draw_bar(int var1, int var2, int bar_width)
{
	var1 = (int)(0.1 * var1);
	var2 = (int)(0.2 * var2);

	if(var1 > 204){var1 = 204;}
	if(var2 > 204){var2 = 204;}

	bar_start = (SIZE_Y-1)-low_high;			//the strat y position of bar - vztazeno k horni hrane baru
	bar1 = bar_start - var1;				//vypocet aktualni hodnoty bar1
	bar2 = bar_start - var2;					//vypocet aktualni hodnoty bar1

	if(bar1 <= top_bound){bar1 = top_bound;}//osetreni, aby bar1 nevyjel nahoru ven z pole
	if(bar2 <= top_bound){bar2 = top_bound;}//osetreni, aby bar2 nevyjel nahoru ven z pole
	if(bar1 > bar_start){bar1 = bar_start;}//osetreni, aby bar1 nevyjel dolu ven z pole
	if(bar2 > bar_start){bar2 = bar_start;}//osetreni, aby bar2 nevyjel dolu ven z pole

	switch(actual_bar)
	{
	case 0:
		if(bar1 != l_bar1)
		{	//vymazani minule hodnoty bar1
			fill_rectangle((int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 +(bar_width-1)*0 + (ln_space+1)*0), (int16_t)(l_bar1), (int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 + (bar_width-1)*(0+1) + (ln_space+1)*0), (int16_t)((SIZE_Y-1)-low_high), BLACK);//fill rectangle
			//vykresleni nove hodnoty l_bar1
			fill_rectangle((int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 +(bar_width-1)*0 + (ln_space+1)*0), (int16_t)(bar1), (int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 + (bar_width-1)*(0+1) + (ln_space+1)*0), (int16_t)((SIZE_Y-1)-low_high), GREEN);//fill rectangle
		}
		l_bar1 = bar1;
		actual_bar = 1;
		break;

	case 1:
		if(bar2 != l_bar2)
		{	//vymazani minule hodnoty bar2
			fill_rectangle((int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 +(bar_width-1)*1 + (ln_space+1)*1), (int16_t)(l_bar2), (int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 + (bar_width-1)*(1+1) + (ln_space+1)*1), (int16_t)((SIZE_Y-1)-low_high), BLACK);//fill rectangle
			//vykresleni nove hodnoty l_bar2
			fill_rectangle((int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 +(bar_width-1)*1 + (ln_space+1)*1), (int16_t)(bar2), (int16_t)((SIZE_X/2)-1 - (bar_width * cnt_ln + (cnt_ln-1)*ln_space )/2 + (bar_width-1)*(1+1) + (ln_space+1)*1), (int16_t)((SIZE_Y-1)-low_high), YELLOW);//fill rectangle
		}
		l_bar2 = bar2;
		actual_bar = 0;
		break;
	}


	if(var1 < 40){mf1++;}
	if(var2 < 40){mf2++;}

	if(actual_force_cnt2 == 4)
	{
		switch(actual_force_cnt)
			{
			case 0:

				zoom_x = zoom_y = 3;
				write_uint((uint8_t)(var1), 18, 180, GREEN);//vypsani aktualni sily

				if(max_force1 < var1 && var1 > 40)
				{
					max_force1 = var1;
					max_force1_active = 1;
				}

				actual_force_cnt = 1;
				break;


			case 1:

				zoom_x = zoom_y = 3;
				write_uint((uint8_t)(var2), 230, 180, YELLOW);//vypsani aktualni sily

				if(max_force2 < var2 && var2 > 40)
				{
					max_force2 = var2;
					max_force2_active = 1;
				}

				actual_force_cnt = 2;
				break;


			case 2:
				if(max_force1_active == 1)
				{
					zoom_x = zoom_y = 2;
					write_uint((uint8_t)max_force1, 45, 60, GREEN);
					max_force1_active = 0;
				}
				if(mf1 > 60 && var1 < 20)
				{
					zoom_x = zoom_y = 2;
					max_force1 = 0;
					write_string( "   " , 45, 60 ,DIM_YELLOW);
					mf1 = 0;
				}
				actual_force_cnt = 3;
				break;

			case 3:
				if(max_force2_active == 1)
				{
					zoom_x = zoom_y = 2;
					write_uint((uint8_t)max_force2, 220, 60, YELLOW);
					max_force2_active = 0;
				}
				if(mf2 > 60 && var2 < 20)
				{
					zoom_x = zoom_y = 2;
					max_force2 = 0;
					write_string( "   " , 220, 60 ,DIM_YELLOW);
					mf2 = 0;
				}
				actual_force_cnt = 0;
				break;

			}
		actual_force_cnt2 = 0;
	}
	actual_force_cnt2++;

}


void pong_move_ball(int pong_ball, int pong_step, int plate_height, int plate_width)
{	zoom_x = zoom_y = 1;

	if(l_ball_pos_x >= (SIZE_X - 1 - pong_ball) && course == 0){course = 0; pong_start[0] = 0; pong_out = 1; pong_score[0]++;}
	if(l_ball_pos_x >= (SIZE_X - 1 - pong_ball) && course == 1){course = 0; pong_start[0] = 0; pong_out = 1; pong_score[0]++;}
	if(l_ball_pos_x <= 1 && course == 3){course = 0; pong_start[0] = 0; pong_out = 1; pong_score[1]++;}//l_ball_pos_x <= 1 - kvuli ramecku
	if(l_ball_pos_x <= 1 && course == 2){course = 0; pong_start[0] = 0; pong_out = 1; pong_score[1]++;}
	//kdyz narazi do plejtu z uzke strany
	if(((l_ball_pos_x) <= (3 + plate_width)) && (l_ball_pos_y + pong_ball) == (plate2-plate_height/2)){course = 0; pong_start[0] = 0; pong_out = 1;pong_score[1]++;}
	if(((l_ball_pos_x) >= (SIZE_X - 2 - plate_width)) && ((l_ball_pos_y + pong_ball) == (plate2-plate_height/2))){course = 0; pong_start[0] = 0; pong_out = 1;pong_score[0]++;}
	if(((l_ball_pos_x) <= (2 + plate_width)) && (l_ball_pos_y -1) == (plate2+plate_height/2)){course = 0; pong_start[0] = 0; pong_out = 1;pong_score[1]++;}
	if(((l_ball_pos_x) >= (SIZE_X - 2 - plate_width)) && ((l_ball_pos_y - 1) == (plate2+plate_height/2))){course = 0; pong_start[0] = 0; pong_out = 1;pong_score[0]++;}

	if(pong_start[0] == 0)
	{
		ball_pos_x = 150;//SIZE_X / 2 - pong_ball/2 -1;
		ball_pos_y = 120;//SIZE_Y / 2 - pong_ball/2 -1;
	}
	if(pong_out == 1)
	{	pong_outt = 1;
		fill_rectangle((int16_t)(l_ball_pos_x), (int16_t)(l_ball_pos_y), (int16_t)(l_ball_pos_x + pong_ball - 1), (int16_t)(l_ball_pos_y + pong_ball - 1), BLACK);//fill rectangle
		pong_out = 0;
	}

	if(pong_start[0] != 0)
	{

	switch(course)
	{
		case 0:
		ball_pos_x = ball_pos_x + pong_step;
		ball_pos_y = ball_pos_y + pong_step;
		break;

		case 1:
		ball_pos_x = ball_pos_x + pong_step;
		ball_pos_y = ball_pos_y - pong_step;
		break;

		case 2:
		ball_pos_x = ball_pos_x - pong_step;
		ball_pos_y = ball_pos_y - pong_step;
		break;

		case 3:
		ball_pos_x = ball_pos_x - pong_step;
		ball_pos_y = ball_pos_y + pong_step;
		break;

	}

	if((ball_pos_x + pong_ball) > (SIZE_X -1))
	{ball_pos_x = SIZE_X - 1 - pong_ball;}
	if((ball_pos_y + pong_ball) > (SIZE_Y -1))
	{ball_pos_y = SIZE_Y - 1 - pong_ball;}
	if((ball_pos_x) <= 0)
	{ball_pos_x = 0;}
	if((ball_pos_y) <= pong_size_y)
	{ball_pos_y = pong_size_y;}

	fill_rectangle((int16_t)(l_ball_pos_x), (int16_t)(l_ball_pos_y), (int16_t)(l_ball_pos_x + pong_ball - 1), (int16_t)(l_ball_pos_y + pong_ball - 1), BLACK);//fill rectangle
	}
	fill_rectangle((int16_t)(ball_pos_x), (int16_t)(ball_pos_y), (int16_t)(ball_pos_x + pong_ball - 1), (int16_t)(ball_pos_y + pong_ball - 1), YELLOW);//fill rectangle

	write_uint((uint8_t)pong_score[0], 50, 2, YELLOWISH_GREEN);
	write_uint((uint8_t)pong_score[1], 230, 2, YELLOWISH_GREEN);
	l_ball_pos_x = ball_pos_x;
	l_ball_pos_y = ball_pos_y;

	if(ball_pos_y >= (SIZE_Y - 1 - pong_ball) && course == 0)
	{course = 1;}

	if(ball_pos_y <= pong_size_y && course == 2)
	{course = 3;}

	if(ball_pos_y >= (SIZE_Y - 1 - pong_ball) && course == 3)
	{course = 2;}

	if(ball_pos_y <= pong_size_y && course == 1)
	{course = 0;}

	//KOLIZE
	if((ball_pos_x) >= (SIZE_X - 2 - 2 * plate_width))
	{
		if((ball_pos_y + pong_ball) >= (plate2-plate_height/2) && (ball_pos_y + pong_ball) <= (plate2+plate_height/2) && course == 0)//kdyz spodni hrana ball je vetsi nebo rovna vrchni hrane plate
		{course = 3;}
		if((ball_pos_y) >= (plate2-plate_height/2) && (ball_pos_y) <= (plate2+plate_height/2) && course == 1)//kdyz spodni hrana ball je vetsi nebo rovna vrchni hrane plate
		{course = 2;}
	}

	if((ball_pos_x) <= (3 + pong_ball))
	{
		if((ball_pos_y + pong_ball) >= (plate1-plate_height/2) && (ball_pos_y + pong_ball) <= (plate1 + plate_height/2) && course == 3)//kdyz spodni hrana ball je vetsi nebo rovna vrchni hrane plate
		{course = 0;}
		if((ball_pos_y) >= (plate1-plate_height/2) && (ball_pos_y) <= (plate1+plate_height/2) && course == 2)//kdyz spodni hrana ball je vetsi nebo rovna vrchni hrane plate
		{course = 1;}
	}

	if(pong_start[0] == 0)
	{
		pong_start[0] = 1; pong_out =0;
	}

	if (pong_score[0] == 3 && pong_score[1] == 0 || pong_score[0] == 0 && pong_score[1] == 3 || pong_score[0] == 10 || pong_score[1] == 10)//pokud bude stav score 3:0, nebo 0:3, usuzuji, ze nikdo nehraje a hodim game over
	{
		PROGRAM_STATE = 3;
		pong_game_active = 0;
	}
}


uint8_t character;

int main( void )
{
	fsmc_init();
	init_dma2_0();
	usart_init();

	active_font = (uint8_t *)cp850_font_8x16;
	draw_mode = VG + HG;
	background = BLACK;
	color_display(BLACK);//delete display
	Timer5Init();Timer1Init();

	do{} while ( 1 );
}


void Timer2Init() //kazdych 20ms
{
	TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBase_InitStructure.TIM_Period = 40-1;
	TIM_TimeBase_InitStructure.TIM_Prescaler = 42000-1;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBase_InitStructure);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
	NVIC_Init(&NVIC_InitStructure);
	TIM_Cmd(TIM2, ENABLE);
}

void Timer3Init() //kazdych 500ms
{
	TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBase_InitStructure.TIM_Period = 20-1;
	TIM_TimeBase_InitStructure.TIM_Prescaler = 42000-1;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBase_InitStructure);
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
	NVIC_Init(&NVIC_InitStructure);
	TIM_Cmd(TIM3, ENABLE);
}

void Timer4Init() //kazdou sekundu, pomocny timer pro mereni
{
	TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBase_InitStructure.TIM_Period = 2000-1;
	TIM_TimeBase_InitStructure.TIM_Prescaler = 21000-1;
	TIM_TimeBaseInit(TIM4, &TIM_TimeBase_InitStructure);
	TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
	NVIC_Init(&NVIC_InitStructure);
	TIM_Cmd(TIM4, ENABLE);
}

void Timer5Init() //kazdych 100ms
{
	TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBase_InitStructure.TIM_Period = 80-1;
	TIM_TimeBase_InitStructure.TIM_Prescaler = 42000-1;
	TIM_TimeBaseInit(TIM5, &TIM_TimeBase_InitStructure);
	TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
	NVIC_Init(&NVIC_InitStructure);
	TIM_Cmd(TIM5, ENABLE);
}

void Timer7Init() //kazdych ms
{
	TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
	TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBase_InitStructure.TIM_Period = 4000-1;
	TIM_TimeBase_InitStructure.TIM_Prescaler = 525-1;
	TIM_TimeBaseInit(TIM7, &TIM_TimeBase_InitStructure);
	TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
	NVIC_Init(&NVIC_InitStructure);
	TIM_Cmd(TIM7, ENABLE);

}

void Timer1Init() //kazdych 1000ms
{
	TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
	TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBase_InitStructure.TIM_Period = 8400-1;
	TIM_TimeBase_InitStructure.TIM_Prescaler = 10000-1;
	TIM_TimeBaseInit(TIM1, &TIM_TimeBase_InitStructure);
	TIM_ClearFlag(TIM1,TIM_FLAG_Update);
	TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
	NVIC_Init(&NVIC_InitStructure);
	TIM_Cmd(TIM1, ENABLE);
}

//pokud je Modul_State roven NO_CONNECTION, anebo MEASURING_CARD, a po seriove lince neprijde
//odpoved od merici karty (kdyz pretekl timer), zmeni se Modul_State na NO_CONNECTION
void TIM1_UP_TIM10_IRQHandler(void)
{
  TIM_ClearFlag(TIM1,TIM_FLAG_Update);//Clear the update flag into the interrupt

  Modul_State = NO_CONNECTION;
}

void TIM7_IRQHandler(void)//kazdych ms
{
	measure_draw_bar((int)(ey[0]), (int)(ey[1]), ln_width);//0.2 a 0.4

	TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
}

void TIM5_IRQHandler(void)//kazdych 100ms
{
USART();

if(Modul_State == PC_CONNECTED)//pokud je pripojen PC
{

	if(Modul_State == PC_CONNECTED && temp_done == 0)//probehne jen pri prvnim spojeni s PC
	        	{
	        		TIM_Cmd(TIM2, DISABLE);
	        		TIM_Cmd(TIM3, DISABLE);
	        		TIM_Cmd(TIM4, DISABLE);
	        		TIM_Cmd(TIM7, DISABLE);
	        		temp_done = 1;
	        		no_connection_first_run = 0;
	        		Last_Modul_State = Modul_State;
	        		draw_mode = VG;     // only draw the foreground
	        	}

	if(command_ready == 1)//pokud je prijmuty cely buffer_command
	{
		command_code = (buff_command[0] - '0')*10 + buff_command[1] - '0';

		switch(command_code)
		{
		case 0:	//reserved
			break;

		case 1://delete display
			color_display(BLACK);
			break;


		case 2://color display

			command_color = (buff_command[3] - '0')*10 + buff_command[4] - '0';
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}

			if(cmd_color >= 0 && cmd_color <= 15)
			{color_display(cmd_color);}
			break;


		case 3://set color pixel

			command_x1 = (buff_command[3] - '0')*100 + (buff_command[4] - '0')*10 + (buff_command[5] - '0');
			command_y1 = (buff_command[7] - '0')*100 + (buff_command[8] - '0')*10 + (buff_command[9] - '0');
			command_color = (buff_command[11] - '0')*10 + buff_command[12] - '0';
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}
			if(cmd_color >= 0 && cmd_color <= 15)
			{
				if(command_x1 >= 0 && command_x1 <= MAX_X)
				{
					if(command_y1 >= 0 && command_y1 <= MAX_Y)
					{
						set_pixel(command_x1, command_y1, cmd_color);
					}
				}
			}

			break;


		case 4://horizontal line

			command_x1 = (buff_command[3] - '0')*100 + (buff_command[4] - '0')*10 + (buff_command[5] - '0');
			command_x2 = (buff_command[7] - '0')*100 + (buff_command[8] - '0')*10 + (buff_command[9] - '0');
			command_y1 = (buff_command[11] - '0')*100 + (buff_command[12] - '0')*10 + (buff_command[13] - '0');
			command_color = (buff_command[15] - '0')*10 + buff_command[16] - '0';
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}
			if(cmd_color >= 0 && cmd_color <= 15)
			{
				if((command_x1 >= 0 && command_x1 <= MAX_X) && (command_x2 >= 0 && command_x2 <= MAX_X))
				{
					if(command_y1 >= 0 && command_y1 <= MAX_Y)
					{
						horizontal_line(command_x1, command_x2, command_y1, cmd_color);
					}
				}
			}

			break;


		case 5://line

			command_x1 = (buff_command[3] - '0')*100 + (buff_command[4] - '0')*10 + (buff_command[5] - '0');
			command_y1 = (buff_command[7] - '0')*100 + (buff_command[8] - '0')*10 + (buff_command[9] - '0');
			command_x2 = (buff_command[11] - '0')*100 + (buff_command[12] - '0')*10 + (buff_command[13] - '0');
			command_y2 = (buff_command[15] - '0')*100 + (buff_command[16] - '0')*10 + (buff_command[17] - '0');
			command_color = (buff_command[19] - '0')*10 + buff_command[20] - '0';
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}
			if(cmd_color >= 0 && cmd_color <= 15)
			{
				if((command_x1 >= 0 && command_x1 <= MAX_X) && (command_x2 >= 0 && command_x2 <= MAX_X))
				{
					if((command_y1 >= 0 && command_y1 <= MAX_Y) && (command_y2 >= 0 && command_y2 <= MAX_Y))
					{
						draw_line(command_x1, command_y1, command_x2, command_y2, cmd_color);
					}
				}
			}

			break;




		case 6://draw rectangle

			command_x1 = (buff_command[3] - '0')*100 + (buff_command[4] - '0')*10 + (buff_command[5] - '0');
			command_y1 = (buff_command[7] - '0')*100 + (buff_command[8] - '0')*10 + (buff_command[9] - '0');
			command_x2 = (buff_command[11] - '0')*100 + (buff_command[12] - '0')*10 + (buff_command[13] - '0');
			command_y2 = (buff_command[15] - '0')*100 + (buff_command[16] - '0')*10 + (buff_command[17] - '0');
			command_color = (buff_command[19] - '0')*10 + buff_command[20] - '0';
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}
			if(cmd_color >= 0 && cmd_color <= 15)
			{
				if((command_x1 >= 0 && command_x1 <= MAX_X) && (command_x2 >= 0 && command_x2 <= MAX_X))
				{
					if((command_y1 >= 0 && command_y1 <= MAX_Y) && (command_y2 >= 0 && command_y2 <= MAX_Y))
					{
						draw_rectangle(command_x1, command_y1, command_x2, command_y2, cmd_color);
					}
				}
			}

			break;



		case 7://fill rectangle

			command_x1 = (buff_command[3] - '0')*100 + (buff_command[4] - '0')*10 + (buff_command[5] - '0');
			command_y1 = (buff_command[7] - '0')*100 + (buff_command[8] - '0')*10 + (buff_command[9] - '0');
			command_x2 = (buff_command[11] - '0')*100 + (buff_command[12] - '0')*10 + (buff_command[13] - '0');
			command_y2 = (buff_command[15] - '0')*100 + (buff_command[16] - '0')*10 + (buff_command[17] - '0');
			command_color = (buff_command[19] - '0')*10 + buff_command[20] - '0';
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}
			if(cmd_color >= 0 && cmd_color <= 15)
			{
				if((command_x1 >= 0 && command_x1 <= MAX_X) && (command_x2 >= 0 && command_x2 <= MAX_X))
				{
					if((command_y1 >= 0 && command_y1 <= MAX_Y) && (command_y2 >= 0 && command_y2 <= MAX_Y))
					{
						fill_rectangle(command_x1, command_y1, command_x2, command_y2, cmd_color);
					}
				}
			}

			break;



		case 8://write centered string

			if(buff_command[3] == '"')
			{
				for(temp5=0; temp5<CMD_TEXT; temp5++)
				{
					command_text[temp5] = buff_command[temp5 + 4];

					if(buff_command[temp5 + 4] == '"')
					{
						command_text[temp5] = '\0';
						temp5--;
						break;
					}
					if(temp5 == (CMD_TEXT - 1))
					{
						command_text[temp5] = '\0';
						temp5--;
						break;
					}



				}
				if(buff_command[temp5 + 6] == ',')
				{
					command_zoom_x = (buff_command[temp5 + 6 + 1] - '0');
					if(buff_command[temp5 + 6 + 2] == ',')
					{
						command_color = (buff_command[temp5 + 6 + 3] - '0')*10 + buff_command[temp5 + 6 + 4] - '0';
					}
				}

			}

			if(command_color >= 0 && command_color <= 15)
			{
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}

				if(command_zoom_x >=1 && command_zoom_x<=9)
				{
					zoom_x = zoom_y = command_zoom_x;
					write_string_center((int8_t*)(command_text), BLACK);
					write_string_center((int8_t*)(command_text), cmd_color);
				}
			}

			break;



		case 9://write string

			if(buff_command[3] == '"')
			{
				for(temp5=0; temp5<CMD_TEXT; temp5++)
				{
					command_text[temp5] = buff_command[temp5 + 4];

					if(buff_command[temp5 + 4] == '"')
					{
						command_text[temp5] = '\0';
						temp5--;
						break;
					}
					if(temp5 == (CMD_TEXT - 1))
					{
						command_text[temp5] = '\0';
						temp5--;
						break;
					}



				}
				if(buff_command[temp5 + 6] == ',')
				{
					command_zoom_x = (buff_command[temp5 + 6 + 1] - '0');
					if(buff_command[temp5 + 6 + 2] == ',')
					{
						command_x1 = (buff_command[temp5 + 6 + 3] - '0')*100 + (buff_command[temp5 + 6 + 4] - '0')*10 + (buff_command[temp5 + 6 + 5] - '0');
						if(buff_command[temp5 + 6 + 6] == ',')
						{
							command_y1 = (buff_command[temp5 + 6 + 7] - '0')*100 + (buff_command[temp5 + 6 + 8] - '0')*10 + (buff_command[temp5 + 6 + 9] - '0');
							if(buff_command[temp5 + 6 + 10] == ',')
							{
									command_color = (buff_command[temp5 + 6 + 11] - '0')*10 + buff_command[temp5 + 6 + 12] - '0';
							}
						}
					}
				}

			}

			if(command_color >= 0 && command_color <= 15)
			{
			switch(command_color)
			{
				case 0: cmd_color = BLACK; break;
				case 1: cmd_color = DIM_GREEN; break;
				case 2: cmd_color = MEDIUM_GREEN; break;
				case 3: cmd_color = GREEN; break;
				case 4: cmd_color = DIM_RED; break;
				case 5: cmd_color = DIM_YELLOW; break;
				case 6: cmd_color = GREENISH_YELLOW; break;
				case 7: cmd_color = REDDISH_GREEN; break;
				case 8: cmd_color = MEDIUM_RED; break;
				case 9: cmd_color = REDDISH_YELLOW; break;
				case 10: cmd_color = MEDIUM_YELLOW; break;
				case 11: cmd_color = YELLOWISH_GREEN; break;
				case 12: cmd_color = RED; break;
				case 13: cmd_color = GREENISH_RED; break;
				case 14: cmd_color = YELLOWISH_RED; break;
				case 15: cmd_color = YELLOW; break;
			}

				if(command_zoom_x >=1 && command_zoom_x<=9)
				{
					if((command_x1 >= 0 && command_x1 <= MAX_X) && (command_y1 >= 0 && command_y1 <= MAX_Y))
					{
						zoom_x = zoom_y = command_zoom_x;
						write_string((int8_t*)(command_text), command_x1, command_y1, BLACK);
						write_string((int8_t*)(command_text), command_x1, command_y1, cmd_color);
					}
				}
			}

			break;


		}
		command_ready = 0;
}


	if(buff_command[0] == 'E')//prijde pri vypnuti aplikace na PC
		{
			buff_command[0] = '0';
			temp_done = 0;
			Modul_State = NO_CONNECTION;
		}

}

if(Modul_State == NO_CONNECTION)//pokud neprijde na zacatku odpoved od merici desky, ani od pc
	        	{
					if(no_connection_first_run == 0)
					{
						TIM_Cmd(TIM2, DISABLE);
						TIM_Cmd(TIM3, DISABLE);
						TIM_Cmd(TIM4, DISABLE);
						TIM_Cmd(TIM7, DISABLE);
						if(Last_Modul_State == MEASURING_CARD)
						{
							color_display(BLACK);//delete display//aby zustala nakreslena data na displeji
						}

						no_connection_first_run = 1;
						temp_done = 0;
						temp2_done = 0;

						measure_game = 0;
						TIM_Cmd(TIM7, DISABLE);
						TIM_SetCounter(TIM7, 0);
						SECONDS_TIMER_STATE = 0;
						count_seconds = 0;

						pong_game_active = 0;
						pong_start[0] = 0;
						pong_start[1] = 0;
						plate1 = 0;
						plate2 = 0;
						l_plate1 = 1;
						l_plate2 = 1;

						PROGRAM_STATE = 0;
						LAST_PROGRAM_STATE = 20;
						draw_mode = VG + HG; //foreground + background
						Last_Modul_State = Modul_State;
					}
	        	}

//////////////////////////////////////////////////////////////////////////////////////////
if(Modul_State == MEASURING_CARD)//pokud pripojena merici deska
{

	if(Modul_State == MEASURING_CARD && temp2_done == 0)//probehne jen pri prvnim spojeni s PC
		        	{
						Timer2Init();Timer4Init();
		        		color_display(BLACK);//delete display
		        		temp2_done = 1;
		        		no_connection_first_run = 0;
		        		draw_mode = VG + HG; //foreground + background
		        		Last_Modul_State = Modul_State;
		        	}


        		uint16_t ADvalue1 = (uint16_t)((buff[0] << 8) | (buff[1] & 0xFF));
        		uint16_t ADvalue2 = (uint16_t)((buff[2] << 8) | (buff[3] & 0xFF));
        		int32_t hodnota1 = (int32_t)round((500 / (double)1023) * ADvalue1) - OffsetLeft;
        		int32_t hodnota2 = (int32_t)round((500 / (double)1023) * ADvalue2) - OffsetRight;

        		if(start == 1)//jen pri prvnim behu programu
        		{
        			start = 8;
        			OffsetLeft = hodnota1 + 12;
        			OffsetRight = hodnota2 + 12;
        			hodnota1 = 0;
        			hodnota2 = 0;
        		}
        		hodnota2 = hodnota2 * 2;
        		hodnota1 = hodnota1 * 2 * 3;

        		if(hodnota1 < 0){hodnota1 = 0;}
        		if(hodnota2 < 0){hodnota2 = 0;}
        		//int pokus = hodnota1;



        	/////////////////////////////////////////////////////////////////////////////
			//verze 1.5     28.12.2013
			//pravy snimac (hodnota2), reseni teplotni zavislosti a chybneho referencniho napeti pro pravy kanal
			//levy snimac (hodnota1), reseni teplotni zavislosti a zakmitavani po pusteni snimace
        		copy_hodnota1 = hodnota1;
				copy_hodnota2 = hodnota2;

				hodnota1_prumer = 0;
				hodnota2_prumer = 0;
				min_hodnota1 = 500;
				min_hodnota2 = 500;
				max_hodnota1 = 0;
				max_hodnota2 = 0;

			for (i = 0; i <= memlen - 2; i++)//ulozeni poslednich x vzorku do pameti
			{
				mem1[i] = mem1[i + 1];
				if (mem1[i] < min_hodnota1)
				{ min_hodnota1 = mem1[i]; }
				if (mem1[i] > max_hodnota1)
				{ max_hodnota1 = mem1[i]; }

				mem2[i] = mem2[i + 1];
				if (mem2[i] < min_hodnota2)
				{ min_hodnota2 = mem2[i]; }
				if (mem2[i] > max_hodnota2)
				{ max_hodnota2 = mem2[i]; }
			}
			mem1[memlen - 1] = copy_hodnota1_minula;
			mem2[memlen - 1] = copy_hodnota2_minula;

			if (mem1[memlen - 1] < min_hodnota1)
			{ min_hodnota1 = mem1[memlen - 1]; }
			if (mem1[memlen - 1] > max_hodnota1)
			{ max_hodnota1 = mem1[memlen - 1]; }

			if (mem2[memlen - 1] < min_hodnota2)
			{ min_hodnota2 = mem2[memlen - 1]; }
			if (mem2[memlen - 1] > max_hodnota2)
			{ max_hodnota2 = mem2[memlen - 1]; }//^^^zjisteni minimalni a maximalni hodnoty poslednich x vzorku^^^

			if ((max_hodnota1 - min_hodnota1) <= 80)//pokud je rozmezi kmitani posl x vzorku mensi nez 80, spocitam prumer
			{
				for (i = 0; i <= memlen - 1; i++)
				{
					hodnota1_prumer = hodnota1_prumer + mem1[i];
				}
				hodnota1_prumer = hodnota1_prumer / memlen;//prumerna hodnota minulych x vzorku, ktere minimalne kmitaly
				kompenzace1 = hodnota1_prumer;  //pokud x poslednich vzorku minimalne kmitalo, tak nastavim kompenzaci, jako prumernou
												//hodnotu techto nekmitavych vzorku
				kompenzovana1 = 0;              //pokud vzorky minimalne kmitaly, predpokladame, ze neni snimac stisknuty => 0
				stisk1 = 0;
			}

			else//pokud poslednich x vzorku v pameti zakmitavalo vice, provedeme kompenzacni vypocet
			{
				int bigger_than = 0;

				if (copy_hodnota1 < kompenzace1)//pokud je hodnota snimace mensi nez prumerna hodnota, povazuju ji za prum. hodnotu
				{ copy_hodnota1 = kompenzace1; }

				//pokud je hodnota snimace vetsi nez prumerna hodnota a je aktivni stav fall, aktivuje se stav stisk
				if (copy_hodnota1 > (kompenzace1 + 10) && fall1 == 1)
				{ stisk1 = 1; }

				 for(i = 0; i<20 ;i++)
				{
					if (mem1[memlen - 2 - i] > (kompenzace1) && abs(copy_hodnota1_minula - kompenzace1) < 8)
					{
						bigger_than++;
					}
				}

				if (bigger_than >= 13)
				{ fall1 = 1; }
				//pokud je 5 vzorku z 8 poslednich zkoumanych vetsi nez prumer a soucasne se aktualni hodnota pohybuje kolem prumeru,
				//aktivuje se stav fall2

				kompenzovana1 = copy_hodnota1_minula - kompenzace1;//vypocet kompenzovane hodnoty rozdilem hodnoty snimace a kompenzace
			}

			if ((max_hodnota2 - min_hodnota2) <= 70)//pokud je rozmezi kmitani posl x vzorku mensi nez 20, spocitam prumer
			{
				for (i = 0; i <= memlen - 1; i++)
				{
					hodnota2_prumer = hodnota2_prumer + mem2[i];
				}
				hodnota2_prumer = hodnota2_prumer / memlen;//prumerna hodnota minulych x vzorku, ktere minimalne kmitaly
				kompenzace2 = hodnota2_prumer;  //pokud x poslednich vzorku minimalne kmitalo, tak nastavim kompenzaci, jako prumernou
												//hodnotu techto nekmitavych vzorku
				kompenzovana2 = 0;              //pokud vzorky minimalne kmitaly, predpokladame, ze neni snimac stisknuty => 0
				stisk2 = 0;
			}

			else//pokud poslednich x vzorku v pameti zakmitavalo vice, provedeme kompenzacni vypocet
			{
				int bigger_than = 0;

				if (copy_hodnota2 < kompenzace2)//pokud je hodnota snimace mensi nez prumerna hodnota, povazuju ji za prum. hodnotu
				{ copy_hodnota2 = kompenzace2; }

				//pokud je hodnota snimace vetsi nez prumerna hodnota a je aktivni stav fall, aktivuje se stav stisk
				if (copy_hodnota2 > (kompenzace2 + 25) && fall2 == 1)
				{ stisk2 = 1; }

				for (i = 0; i < 8; i++)
				{
					if (mem2[memlen - 2 - i] > (kompenzace2) && abs(copy_hodnota2_minula - kompenzace2) < 8)
					{
						bigger_than++;
					}
				}

				if (bigger_than >= 5)
				{ fall2 = 1; }
				//pokud je 5 vzorku z 8 poslednich zkoumanych vetsi nez prumer a soucasne se aktualni hodnota pohybuje kolem prumeru,
				//aktivuje se stav fall2

				kompenzovana2 = copy_hodnota2_minula - kompenzace2;//vypocet kompenzovane hodnoty rozdilem hodnoty snimace a kompenzace

			}

			if (kompenzovana1 < 0) { kompenzovana1 = 0; }//zapornou hodnotu neuvazujeme
			if (kompenzovana2 < 0) { kompenzovana2 = 0; }//zapornou hodnotu neuvazujeme
			hodnota1 = kompenzovana1;//do promenne pro levy snimac ulozim vykompenzovanou hodnotu
			hodnota2 = kompenzovana2;//do promenne pro levy snimac ulozim vykompenzovanou hodnotu


			if (fall1 == 1)//pokud je aktivni stav fall - tedy v poslednich 5 vzorcich byla hodnota snimace vyssi nez prumerna(kompenzace)
			{
				fall1_counter++;
				if (fall1_counter == 40 || stisk1 == 1)//stav fall je aktivni po dobu 15 vzorku, pokud nedojde k jeho ukonceni aktivnim stavem "stisk"
				{
					fall1 = 0;
					fall1_counter = 0;
				}
				else
				{
					hodnota1 = 0;               //zobrazeni nulove nekmitave hodnoty
					copy_hodnota1 = kompenzace1;//pri aktivnim stavu fall beru misto hodnoty ze snimace hodnotu posledniho prumeru,
				}                               //to slouzi k vyfiltrovani podkmitu, ktery je zpusoben kontaktem ruky se snimacem
			}

			if (fall2 == 1)//pokud je aktivni stav fall - tedy v poslednich 5 vzorcich byla hodnota snimace vyssi nez prumerna(kompenzace)
			{
				fall2_counter++;
				if (fall2_counter == 15 || stisk2 == 1)//stav fall je aktivni po dobu 15 vzorku, pokud nedojde k jeho ukonceni aktivnim stavem "stisk"
				{
					fall2 = 0;
					fall2_counter = 0;
				}
				else
				{
					hodnota2 = 0;               //zobrazeni nulove nekmitave hodnoty
					copy_hodnota2 = kompenzace2;//pri aktivnim stavu fall beru misto hodnoty ze snimace hodnotu posledniho prumeru,
				}                               //to slouzi k vyfiltrovani podkmitu, ktery je zpusoben kontaktem ruky se snimacem
			}

			copy_hodnota1_minula = copy_hodnota1;
			copy_hodnota2_minula = copy_hodnota2;   //zpracovani hodnoty snimace je zpozdeno o jeden krok, aby bylo mozne vyfiltrovat podkmit
													//do pole pameti poslednich x vzorku ulozim upravenou hodnotu snimace, aby bylo mozne
													//pocitat prumer pro kompenzaci z relevantnejsich hodnot (bez podkmitu)
	   ////////////////////////////////////////////////////////////////////////////////////////////////

			ey[1] = (int)hodnota2 * 2;
			if(ey[1] < 0){ey[1] = 0;}
			ey[0] = (int)(hodnota1 * 1.2);
			if(ey[0] < 0){ey[0] = 0;}
}
//////////////////////////////////////////////////////////////////////////////////////////
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
}

void TIM4_IRQHandler(void)//kazdou pulsekundu tickne
{
	switch(SECONDS_TIMER_STATE)
	{
		case 0:
			count_seconds = 0;				//je nutne, aby se neintegrovalo po castech!!!
		break;

		case 1:
			count_seconds++;
			if(count_seconds >= 20)
			{
				TEN_SECONDS = 1;			//nastavim stav uplynuti 10 sekund
				SECONDS_TIMER_STATE = 0;	//prepnu na stav, kdy se nic nedeje
				count_seconds = 0;			//vynuluju citac
			}
		break;

		case 2:
			count_seconds++;
			if(count_seconds >= 1)
			{
				ONE_SECOND = 1;
				count_seconds = 0;			//vynuluju citac
			}
		break;

	}


TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}


void TIM3_IRQHandler(void)//obstarava pohyb micku
{
if(pong_game_active == 1)
{
	pong_move_ball(pong_ball, pong_step, plate_height, plate_width);

}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}



void TIM2_IRQHandler(void)//obstarava pohyb platu, score, mody her
{
	if(PROGRAM_STATE == 0)//zobrazeni uvodni obrazovky menu, pro volbu hernich modu
	{
		if (LAST_PROGRAM_STATE != PROGRAM_STATE)
		{
			//tady se provede vykresleni obrazovky, pokud se PROGRAM_STATE nerovna LAST_PROGRAME_STATE
			fill_rectangle( 0 , 0 ,MAX_X, MAX_Y ,GREEN);
			fill_rectangle( 1 , 1 ,MAX_X-1, MAX_Y-1 ,BLACK);
			zoom_x = zoom_y = 2;
			write_string( "Vyzkousej svoji" , (uint16_t)((MAX_X / 2)-(8 * 15 * zoom_x) / 2), 10 ,GREEN);//15 je pocet znaku
			write_string( "silu" , (uint16_t)((MAX_X / 2)-(8 * 4 * zoom_x) / 2), (5 + 16 * zoom_y + 10),GREEN);
			zoom_x = zoom_y = 1;
			fill_rectangle(15,(5 + (16 * 2 + 5 + 16 * 2 + 10)),304,(5 + (16 * 2 + 5 + 16 * 2 + 10) + 2),RED);
			zoom_x = zoom_y = 1;
			write_string( "Stiskni vlevo" , 15, ((5 + (16 * 2 + 5 + 16 * 2 + 10) + 2) + 30) ,GREEN);
			write_string( "a zkus svoji" , 15, (((5 + (16 * 2 + 5 + 16 * 2 + 10) + 2) + 30) + 16 * zoom_y + 5) ,GREEN);
			zoom_x = 3; zoom_y = 5;
			write_string( "SILU" , 15, (1 * 16 + (((5 + (16 * 2 + 5 + 16 * 2 + 10) + 2) + 30) + 16 * 1 + 5) + 5) ,YELLOW);
			zoom_x = zoom_y = 1;
			write_string( "Stiskni vpravo" , 195, ((5 + (16 * 2 + 5 + 16 * 2 + 10) + 2) + 30) ,GREEN);
			write_string( "a hrej" , 195, (((5 + (16 * 2 + 5 + 16 * 2 + 10) + 2) + 30) + 16 * zoom_y + 5) ,GREEN);
			zoom_x = 3; zoom_y = 5;
			write_string( "PONG" , 195, (1 * 16 + (((5 + (16 * 2 + 5 + 16 * 2 + 10) + 2) + 30) + 16 * 1 + 5) + 5) ,YELLOW);

			for(tmp = 0; tmp <memlen; tmp++)
			{mem1[tmp] = 0;  mem2[tmp] = 0;}

			for(tmp = 0; tmp < cnt_ln; tmp++)
			{
				ey[tmp] = 0;
				ey_last[tmp] = 0;
			}

			LAST_PROGRAM_STATE = PROGRAM_STATE;
		}

		if(ey[0] >= menu_press)
		{
			press_counter++;
			if(press_counter >= 10)
			{
				press_counter = 0;
				PROGRAM_STATE= 1;     //prepnu na Mereni
			}
		}
		if(ey[1] >= menu_press)
		{
			press_counter++;
			if(press_counter >= 10)
			{
				press_counter = 0;
				PROGRAM_STATE= 2;     //Prepnu na Pong
			}
		}

	}



	if(PROGRAM_STATE == 1)//mod mereni sily
	{
		if(LAST_PROGRAM_STATE!= PROGRAM_STATE)
	    {
			fill_rectangle( 1 , 1 ,MAX_X-1, MAX_Y-1 ,BLACK);
			zoom_x = zoom_y = 1;
			write_string( "Max Force:" , 20, 40 , GREEN);
			zoom_x = zoom_y = 1;
			write_string( "Max Force:" , 218, 40 , YELLOW);

			measure_game = 1;

			LAST_PROGRAM_STATE = PROGRAM_STATE;
			SECONDS_TIMER_STATE = 0;
			bar1 = 0;
			bar2 = 0;
			bar_start = 0;
			l_bar1 = 20;//hodnota musi byt vetsi nez nula, aby se na zacatku neprekreslil ramecek
			l_bar2 = 20;//hodnota musi byt vetsi nez nula, aby se na zacatku neprekreslil ramecek
			actual_force_cnt = 0;
			press_counter = 0;
			Timer7Init();
	    }

		if(TEN_SECONDS == 1)
		{
			TIM_Cmd(TIM7, DISABLE);
			TIM_SetCounter(TIM7, 0);
			measure_game = 0;
			l_bar1 = 20;//hodnota musi byt vetsi nez nula, aby se na zacatku neprekreslil ramecek
			l_bar2 = 20;//hodnota musi byt vetsi nez nula, aby se na zacatku neprekreslil ramecek
			actual_force_cnt = 0;

			SECONDS_TIMER_STATE = 0;//-------
			PROGRAM_STATE = 0;
			TEN_SECONDS = 0;
			press_counter = 0;
		}

		if((ey[0] >= 30 || ey[1] >= 30) || (ey[0] >= 30 && ey[1] >= 30) || (ey[0] >= 30 && ey[1] < 30) || (ey[0] < 30 && ey[1] >= 30))
		{
			SECONDS_TIMER_STATE = 0;
		}
		if(ey[0] < 30 || ey[1] < 30)
		{
			press_counter++;
			if(press_counter >= 3)
			{
				press_counter = 0;
				SECONDS_TIMER_STATE = 1;
			}
		}

	}//end of if(PROGRAM_STATE == 1)




	if(PROGRAM_STATE == 2)//mod hra Pong
	{
		if(LAST_PROGRAM_STATE != PROGRAM_STATE)
		{
			Timer3Init();//obstarava pohyb micku
			pong_score[0] = pong_score[1] = 0;
			fill_rectangle( 0 , 0 ,MAX_X, MAX_Y ,BLACK);//This erase the text "game over"
			fill_rectangle( 0 , pong_size_y-1 ,MAX_X, MAX_Y ,GREEN);
			fill_rectangle( 1 , pong_size_y ,MAX_X-1, MAX_Y-1 ,BLACK);
			SECONDS_TIMER_STATE = 2;
			count_seconds = 0;

			zoom_x = zoom_y = 1;
			write_string( "--SCORE--" , 120, 2 ,YELLOWISH_GREEN);
			pong_move_plates(1, 1, plate_height, plate_width);//zobrazeni plejtu, aby se hrac pred startem zorientoval
			write_uint((uint8_t)pong_score[0], 50, 2, YELLOWISH_GREEN);
			write_uint((uint8_t)pong_score[1], 230, 2, YELLOWISH_GREEN);

			LAST_PROGRAM_STATE = PROGRAM_STATE;

		}

		if(ONE_SECOND == 1)//odpocitavani pred startem hry
		{
			ONE_SECOND = 0;
			counter_to_start--;
			switch(counter_to_start)
			{
				case 4:
					zoom_x = zoom_y = 2;
					write_string( "3" , (uint16_t)((MAX_X / 2)-(8 * 1 * zoom_x) / 2), 100 ,YELLOW);//1 je pocet znaku
				break;

				case 3:
					zoom_x = zoom_y = 2;
					write_string( "2" , (uint16_t)((MAX_X / 2)-(8 * 1 * zoom_x) / 2), 100 ,YELLOW);//1 je pocet znaku
				break;

				case 2:
					zoom_x = zoom_y = 2;
					write_string( "1" , (uint16_t)((MAX_X / 2)-(8 * 1 * zoom_x) / 2), 100 ,YELLOW);//1 je pocet znaku
				break;

				case 1:
					zoom_x = zoom_y = 2;
					write_string( "START" , (uint16_t)((MAX_X / 2)-(8 * 5 * zoom_x) / 2), 100 ,YELLOW);//5 je pocet znaku
				break;

				case 0:
					pong_game_active = 1;
					zoom_x = zoom_y = 2;
					write_string( "     " , (uint16_t)((MAX_X / 2)-(8 * 5 * zoom_x) / 2), 100 ,YELLOW);//smaze hlasku START
					counter_to_start = 5;
					SECONDS_TIMER_STATE = 0;
				break;

			}
								//nastaveni promenne, ktera spusti casovac, ktery hybe ballem
		}

		if(pong_game_active == 1)//if 1, the timer4 starts move ball
		{
			pong_move_plates(ey[0], ey[1], plate_height, plate_width);
		}


	}//end of if(PROGRAM_STATE == 2)


	if(PROGRAM_STATE == 3)//pong - game over, moznost nove hry pongu
		{
			if(LAST_PROGRAM_STATE != PROGRAM_STATE)
			{
				if(pong_score[0] == 3 && pong_score[1] == 0 || pong_score[0] == 0 && pong_score[1] == 3)
				{
					zoom_x = zoom_y = 3;
					write_string( "KONEC HRY" , (uint16_t)((MAX_X / 2)-(8 * 9 * zoom_x) / 2), 100 ,YELLOW);//9 je pocet znaku
				}

				if(pong_score[0] == 10)
				{
					zoom_x = zoom_y = 2;
					write_string( "Hrac vlevo vyhral!" , (uint16_t)((MAX_X / 2)-(8 * 18 * zoom_x) / 2), 100 ,YELLOW);//20 je pocet znaku
				}
				if(pong_score[1] == 10)
				{
					zoom_x = zoom_y = 2;
					write_string( "Hrac vpravo vyhral!" , (uint16_t)((MAX_X / 2)-(8 * 19 * zoom_x) / 2), 100 ,YELLOW);//21 je pocet znaku
				}

				zoom_x = zoom_y = 1;
				write_string( "Pro novou hru STISKNI" , (uint16_t)((MAX_X / 2)-(8 * 21 * zoom_x) / 2), ((100 + 16 * 2) + 10) ,GREEN);//21 je pocet znaku

				SECONDS_TIMER_STATE = 1;//zacatek pocitani 10 sekund do prepnuti do hlavniho menu

				LAST_PROGRAM_STATE = PROGRAM_STATE;
			}



			if(TEN_SECONDS == 1)
			{
				PROGRAM_STATE = 0;
				TEN_SECONDS = 0;
				press_counter = 0;
			}

			if(ey[0] >= menu_press || ey[1] >= menu_press)
			{
				press_counter++;
				if(press_counter >= 10)
				{
					press_counter = 0;
					PROGRAM_STATE= 2;     //prepnu na Pong
					pong_score[0] = pong_score[1] = 0;
					SECONDS_TIMER_STATE = 0;
				}
			}


		}//end of if(PROGRAM_STATE == 3)

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
