#define ADC_VREF_TYPE 0b00100111
#define F_CPU 8000000UL
#include <stdlib.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "lcd.h"
#include <util/delay.h>
#include "usart.h"
#include <avr/eeprom.h>



unsigned char bank=0;
unsigned int preset=127;
int i=0;
unsigned char k=0; 
char buffer[8];
unsigned int channel=0;
uint8_t  byte_read;

unsigned char relays=0;
int bank_tl=1;
int tl=0;
int stisk_tlac();
int stisk_tlac_podrz();
void send_midi(int cislo_midi);
int read_adc();
void send_continous(int cislo_continous);
int adc_old;
unsigned char tl_old;
void setup_backup();
void setup();
void pc_setup();
void set_standart_map();
void receive_sysex_data();
void led_set(char cislo_led);
 //----------------------------------------------------------------------------- 

 int main(void) 
{ 


DDRD=0b00000000;		//směr toku dat 0 - vstup; 1 - výstup
PORTD=0b00000000;		//je-li výstup ovládá logickou úrověň vývodu, je-li vstup, tak 0je vypnutý pull-up
DDRB=0b00000001;
PORTB=0b00011110;
DDRA=0b01111111;
PORTA=0b00111110;

	USART_Init(MYUBRR);
	
	ADMUX = ADC_VREF_TYPE;
    ADCSRA = 0x87;
     
    lcd_init(LCD_DISP_ON); 
    lcd_clrscr(); 
    lcd_gotoxy(0,0); 
    lcd_puts("BANKA:"); 
    sprintf(buffer,"%2i",bank_tl); 
	lcd_gotoxy(6,0); 	
	lcd_puts(buffer);
	lcd_gotoxy(0,1); 
    lcd_puts("EFEKT:"); 
	lcd_gotoxy(9,0); 
    lcd_puts("EXP:");



//	sprintf(buffer,"%1i",bank); 
//  	lcd_gotoxy(12,1); 
// 	lcd_puts(buffer);

	
	lcd_gotoxy(9,1); 
    lcd_puts("R");

 

	_delay_ms(1000);
	
	PORTA=0b00000000;

	tl=stisk_tlac();

	if(tl==1){setup_backup();}
		

while (1)

      { 
		
		tl=stisk_tlac();

		
		
		if(tl!=0){
			
			if(tl==6){ bank_tl++;				// tlačítko na zvyšování banky registrů
				if(bank_tl==17)bank_tl=1; 
				sprintf(buffer,"%2i",bank_tl); 
	   			lcd_gotoxy(6,0); 	
	   			lcd_puts(buffer);
				tl=1;
				
				}
			
			if(tl==7){ bank_tl--; 
				
				if(bank_tl==0)bank_tl=16;		// tlačítko na snižování banky registrů
				sprintf(buffer,"%2i",bank_tl); 
	   			lcd_gotoxy(6,0); 
	   			lcd_puts(buffer);
				tl=1;
				
				}
		
			sprintf(buffer,"%1i",tl); 
   			lcd_gotoxy(7,1); 
   			lcd_puts(buffer);
			tl_old=tl;
			tl=(tl+(bank_tl-1)*5)-1;			//přičte k číslu tlačítka správné číslo presetu v dané bance
			send_midi(tl);					//vyslání midi zprávy
			led_set(tl_old);
			byte_read = eeprom_read_byte((uint8_t*)(tl+80));
			sprintf(buffer,"%1i",byte_read); 
		   	lcd_gotoxy(10,1);
		   	lcd_puts(buffer);

			if(byte_read==1){PORTA |= 0x01; PORTB &=~ 0x01;}
			if(byte_read==2){PORTB |= 0x01;	PORTA &=~ 0x01;}
			if(byte_read==0){PORTA &=~ 0x01; PORTB &=~ 0x01;}

			_delay_ms(200);
			}
		
		k++;
		
		if(k==2) { 
					int adc_vysledek = read_adc();			// zjištujě stav ADC
        			if(adc_vysledek!=adc_old)				//checkuje jestli byla změna na pedálu
					send_continous(adc_vysledek);			//vyšle zprávu pruběžného kontroleru
					adc_old=adc_vysledek;
					k=0;}


		}

}


int stisk_tlac(){

	tl=0;

	if ((PIND & 0b10000000)==0) {tl=1;}	// test tlacitek dokola
    if ((PIND & 0b01000000)==0) {tl=2;}
    if ((PIND & 0b00100000)==0) {tl=3;}                
    if ((PIND & 0b00010000)==0) {tl=4;} 
    if ((PIND & 0b00001000)==0) {tl=5;}
	if ((PINB & 0b00000010)==0) {tl=6;} 
    if ((PINB & 0b00000100)==0) {tl=7;}  

	if(tl==0)return tl;
	tl_old=tl;


	tl=0;

	if ((PIND & 0b10000000)==0) {tl=1;} 	// overeni stisku
    if ((PIND & 0b01000000)==0) {tl=2;}
    if ((PIND & 0b00100000)==0) {tl=3;}                
    if ((PIND & 0b00010000)==0) {tl=4;} 
    if ((PIND & 0b00001000)==0) {tl=5;}
	if ((PINB & 0b00000010)==0) {tl=6;} 
    if ((PINB & 0b00000100)==0) {tl=7;} 

	if(tl==0)return tl;

	if(tl==tl_old){

		while(
		((PIND & 0b10000000)==0)|| 
	    ((PIND & 0b01000000)==0)||
	    ((PIND & 0b00100000)==0)||
	    ((PIND & 0b00010000)==0)||
	    ((PIND & 0b00001000)==0)||
		((PINB & 0b00000010)==0)||
	    ((PINB & 0b00000100)==0)
	)	{ _delay_ms(1);}

	while(
		((PIND & 0b10000000)==0)|| 
	    ((PIND & 0b01000000)==0)||
	    ((PIND & 0b00100000)==0)||
	    ((PIND & 0b00010000)==0)||
	    ((PIND & 0b00001000)==0)||
		((PINB & 0b00000010)==0)||
	    ((PINB & 0b00000100)==0)
	) {	_delay_ms(1); }

	return tl;

	}

	else return 0; 		

}



int stisk_tlac_podrz(){

	tl=0;

	if ((PIND & 0b10000000)==0) {tl=1;}	// test tlacitek dokola
    if ((PIND & 0b01000000)==0) {tl=2;}
    if ((PIND & 0b00100000)==0) {tl=3;}                
    if ((PIND & 0b00010000)==0) {tl=4;} 
    if ((PIND & 0b00001000)==0) {tl=5;}
	if ((PINB & 0b00000010)==0) {tl=6;} 
    if ((PINB & 0b00000100)==0) {tl=7;}  

	if(tl==0)return tl;
	tl_old=tl;

	_delay_ms(1);

	tl=0;

	if ((PIND & 0b10000000)==0) {tl=1;} 	// overeni stisku
    if ((PIND & 0b01000000)==0) {tl=2;}
    if ((PIND & 0b00100000)==0) {tl=3;}                
    if ((PIND & 0b00010000)==0) {tl=4;} 
    if ((PIND & 0b00001000)==0) {tl=5;}
	if ((PINB & 0b00000010)==0) {tl=6;} 
    if ((PINB & 0b00000100)==0) {tl=7;} 

	return tl;
 		

}


void send_midi(int cislo_midi){
	
	byte_read = eeprom_read_byte((uint8_t*)cislo_midi);	
	int control_change_channel = 0b10110000 + channel;		

/*	USART_Transmit(control_change_channel);			// (1011cccc) - cccc = číslo kanálu
	USART_Transmit(0);						// (0nnnnnnn) - nnnnnnn = číslo kontroleru
	USART_Transmit(bank);							// (0vvvvvvv) - vvvvvvv = hodnota

	USART_Transmit(control_change_channel);			// (1011cccc) - cccc = číslo kanálu
	USART_Transmit(32);						// (0nnnnnnn) - nnnnnnn = číslo kontroleru
	USART_Transmit(0);
*/
	int program_change_channel = 0b11000000 + channel;	

	USART_Transmit(program_change_channel);			// (1100cccc) - cccc = číslo kanálu
	USART_Transmit(byte_read);					// (0ppppppp) - ppppppp = číslo presetu
	
	sprintf(buffer,"%3i",byte_read); 
   	lcd_gotoxy(13,1); 
   	lcd_puts(buffer);

}


void send_continous(int cislo_continous){

	int control_change_channel = 0b10110000 + channel;		

	USART_Transmit(control_change_channel);			// (1011cccc) - cccc = číslo kanálu
	USART_Transmit(7);						// (0nnnnnnn) - nnnnnnn = číslo kontroleru
	USART_Transmit(cislo_continous);							// (0vvvvvvv) - vvvvvvv = hodnota
/*
	USART_Transmit(control_change_channel);			// (1011cccc) - cccc = číslo kanálu
	USART_Transmit(39);						// (0nnnnnnn) - nnnnnnn = číslo kontroleru
	USART_Transmit(0);
*/
}



int read_adc()							//čtení ADC převodníku a zobrazení aktuální hodnoty
{
    ADCSRA |= 0x40;
    while ((ADCSRA & 0x10)==0);
    ADCSRA |= 0x10;
	int hodnota = ADCH;
	hodnota = hodnota/2;
    sprintf(buffer,"%3i",hodnota);
	lcd_gotoxy(13,0); 
    lcd_puts(buffer);
	return hodnota;
}


void led_set(char cislo_led){

switch(cislo_led){
	case 1: PORTA=0b00000010;	break;
	case 2: PORTA=0b00000100;	break;
	case 3: PORTA=0b00001000;	break;
	case 4: PORTA=0b00010000;	break;
	case 5: PORTA=0b00100000;	break;
	}
}

void setup_backup()
{
	lcd_clrscr();
	lcd_gotoxy(0,0); 
    lcd_puts("Nastaveni - tl.1");
	lcd_gotoxy(0,1); 
    lcd_puts("PC setup  - tl.2");
	_delay_ms(200);
	do {tl=stisk_tlac();}	while((tl!=1)&&(tl!=2));	//cekani na prepnuti mezi zalohou(tl==2) a nastavenim(tl==1)
	if(tl==1) setup();	
	if(tl==2) pc_setup();

	lcd_clrscr(); 
    lcd_gotoxy(0,0); 
    lcd_puts("BANKA:"); 
    sprintf(buffer,"%2i",bank_tl); 
	lcd_gotoxy(6,0); 	
	lcd_puts(buffer);
	lcd_gotoxy(0,1); 
    lcd_puts("EFEKT:"); 
	lcd_gotoxy(9,0); 
    lcd_puts("EXP:");
	
//	sprintf(buffer,"%1i",bank); 
//  	lcd_gotoxy(12,1); 
// 	lcd_puts(buffer);
	sprintf(buffer,"%3i",preset); 
   	lcd_gotoxy(13,1); 
   	lcd_puts(buffer);
	
	lcd_gotoxy(9,1); 
    lcd_puts("R");

	

}

void setup(){


	lcd_clrscr();
	lcd_gotoxy(0,0); 
    lcd_puts("Vychozi 0-79 - 1");
	lcd_gotoxy(0,1); 
    lcd_puts("Vlastni nast - 2");
	_delay_ms(200);
	do {tl=stisk_tlac();}	while((tl!=1)&&(tl!=2));	//cekani na prepnuti mezi zalohou(tl==2) a nastavenim(tl==1)

	
	if(tl==1) {
		lcd_clrscr();
	   	lcd_puts("Nastaveni");
		set_standart_map();
		lcd_clrscr();
	   	lcd_puts("Nastaveni - OK");
		_delay_ms(2000);

		main();
		}

	if(tl==2) {

			    lcd_init(LCD_DISP_ON_CURSOR_BLINK);		
	while(1){
			PORTA=0b00000000;
			
			lcd_clrscr(); 
		    lcd_gotoxy(0,0); 
		    lcd_puts("BANKA:"); 
		    sprintf(buffer,"%2i",bank_tl); 
			lcd_gotoxy(6,0); 	
			lcd_puts(buffer);
			lcd_gotoxy(0,1); 
		    lcd_puts("EFEKT:"); 
			lcd_gotoxy(9,0); 
		    lcd_puts("EXP:");
	
//			sprintf(buffer,"%1i",bank); 
//		  	lcd_gotoxy(12,1); 
//		 	lcd_puts(buffer);
	
			lcd_gotoxy(9,1); 
		    lcd_puts("R");
			lcd_gotoxy(7,1);
			do {tl=stisk_tlac();   

			lcd_gotoxy(7,1);
						
	
				if(tl==6){ bank_tl++;				// tlačítko na zvyšování banky registrů
					if(bank_tl==17)bank_tl=1; 
					sprintf(buffer,"%2i",bank_tl); 
		   			lcd_gotoxy(6,0); 	
		   			lcd_puts(buffer);
					tl=0;
		
					}
	
				if(tl==7){ bank_tl--; 
		
					if(bank_tl==0)bank_tl=16;		// tlačítko na snižování banky registrů
					sprintf(buffer,"%2i",bank_tl); 
		   			lcd_gotoxy(6,0); 
		   			lcd_puts(buffer);
					tl=0;
		
					}
			}	while((tl==0)||(tl==6)||(tl==7));
			
			led_set(tl);
			
			sprintf(buffer,"%1i",tl); 
			lcd_gotoxy(7,1); 
			lcd_puts(buffer);
		
			tl=((tl+(bank_tl-1)*5)-1);			//přičte k číslu tlačítka správné číslo presetu v dané bance
		
			byte_read = eeprom_read_byte((uint8_t*)tl);
			preset=byte_read;
//			sprintf(buffer,"%1i",bank); 
//		  	lcd_gotoxy(12,1); 
//		 	lcd_puts(buffer);
			sprintf(buffer,"%3i",byte_read); 
		   	lcd_gotoxy(13,1); 
		   	lcd_puts(buffer);

			byte_read = eeprom_read_byte((uint8_t*)(tl+80));
			sprintf(buffer,"%1i",byte_read); 
		   	lcd_gotoxy(10,1); 
		   	lcd_puts(buffer);		
			relays=byte_read;



			_delay_ms(500);

			do {tl=stisk_tlac_podrz();   
					lcd_gotoxy(15,1);
						
	
				if(tl==6){ preset++;				// tlačítko na zvyšování presetu
					if(preset==128)preset=0; 
					sprintf(buffer,"%3i",preset); 
		   			lcd_gotoxy(13,1); 	
		   			lcd_puts(buffer);
					tl=0;
		
					}
	
				if(tl==7){ preset--; 
		
					if(preset==-1)preset=127;		// tlačítko na snižování presetu
					sprintf(buffer,"%3i",preset); 
		   			lcd_gotoxy(13,1); 
		   			lcd_puts(buffer);
					tl=0;
					}
					_delay_ms(100);		

			}	while((tl==0)||(tl==6)||(tl==7));

			_delay_ms(500);

			do {tl=stisk_tlac();
			lcd_gotoxy(10,1);				
				if(tl==7){
					if(relays==1){
						relays=0;
						sprintf(buffer,"%1i",relays); 
					   	lcd_gotoxy(10,1); 
			   			lcd_puts(buffer);	
						tl=0;
						}
					else{
					relays=1;
					sprintf(buffer,"%1i",relays); 
				   	lcd_gotoxy(10,1); 
		   			lcd_puts(buffer);	
					tl=0;}
				}
	
				if(tl==6){
					if(relays==2){
						relays=0;
						sprintf(buffer,"%1i",relays); 
					   	lcd_gotoxy(10,1); 
			   			lcd_puts(buffer);	
						tl=0;
						}
					else{
					relays=2;
					sprintf(buffer,"%1i",relays); 
				   	lcd_gotoxy(10,1); 
		   			lcd_puts(buffer);	
					tl=0;}
				}
				
			}while(tl==0);

			tl=((tl+(bank_tl-1)*5)-1);
			eeprom_write_byte ((uint8_t*)tl ,preset);
			eeprom_write_byte ((uint8_t*)(tl+80) ,relays);			
			lcd_clrscr();
		   	lcd_puts("Nastaveni - OK");
			_delay_ms(2000);
	
	

	}

	
	}
}


void set_standart_map(){

	for(i=0; i<=79; i++){
		
		eeprom_write_byte ((uint8_t*)i ,i );		

		}
	for(i=80; i<=159; i++){
		
		eeprom_write_byte ((uint8_t*)i ,0 );		

		}

	i=0;

}



void pc_setup(){

	lcd_clrscr();
	lcd_gotoxy(0,0); 
    lcd_puts("Odeslani  - tl.1");
	lcd_gotoxy(0,1); 
    lcd_puts("Prijmuti  - tl.2");

	do {tl=stisk_tlac();}	while((tl!=1)&&(tl!=2));	//cekani na prepnuti mezi zalohou(tl==2) a nastavenim(tl==1)
	
	if(tl==2) receive_sysex_data();

	USART_Transmit(0xF0);	//start
	USART_Transmit(0x7D);	//id výrobce
	USART_Transmit(0x7F);	//id zařízení
	USART_Transmit(0x1);

	for(i=0; i<=159; i++){
		
			byte_read = eeprom_read_byte((uint8_t*)i);		
			USART_Transmit(byte_read);
			_delay_ms(1);
		}

	USART_Transmit(0xF7);
}

void receive_sysex_data(){
	
	unsigned char pole_sysex[160];

	lcd_clrscr();
	lcd_gotoxy(0,0); 
    lcd_puts("Ocekavam prijem");
	lcd_gotoxy(0,1); 
    lcd_puts("SysEx dat");

	byte_read = USART_Receive();	byte_read=0;
	byte_read = USART_Receive();	byte_read=0;
	byte_read = USART_Receive();	byte_read=0;
	byte_read = USART_Receive();	byte_read=0;

	for(i=0; i<=159; i++){
	
		pole_sysex[i] = USART_Receive();		

		}

	byte_read = USART_Receive();

	for(i=0; i<=159; i++){

		eeprom_write_byte ((uint8_t*)i ,pole_sysex[i] );

		}



	if(byte_read==0xF7){
		lcd_clrscr();
		lcd_gotoxy(0,0); 
	    lcd_puts("Prijem dat");
		lcd_gotoxy(0,1); 
	    lcd_puts("probehl uspesne");
			_delay_ms(2000);
	}
	else{
		lcd_clrscr();
		lcd_gotoxy(0,0); 
	    lcd_puts("Prijem dat");
		lcd_gotoxy(0,1); 
	    lcd_puts("se nezdaril");
			_delay_ms(2000);	




	}

}



/*

#define F_CPU 8000000UL 

 #include <avr/eeprom.h>; 
 #include <util/delay.h> 
 #include "lcd.h" 


 unsigned char i; 

 //store initial byte to eeprom 

 uint8_t EEMEM eeprombyte=0x10; 

 //store initial word to eeprom 

 uint16_t EEMEM eepromword=0x5555; 

 //store string to eeprom 

 uint8_t EEMEM eepromstring[5]={"Test\0"}; 

 int main(void) 

 { 

 //RAM byte variable 

 uint8_t RAMbyte; 

 //RAM word variable 

 uint16_t RAMword; 

 //RAM array of bytes 

 uint8_t RAMstring[5]; 

 //read byte from EEPROm and store to RAM 

 RAMbyte = eeprom_read_byte(&eeprombyte); 

 //read word from EEPROM and store to RAM 

 RAMword = eeprom_read_word(&eepromword); 

 //copy string fro mEEPROM to RAM 

 eeprom_read_block ((void *)&RAMstring, (const void *)&eepromstring,5); 
    char buffer[8]; 
    lcd_init(LCD_DISP_ON); // initialize display, cursor off 
    lcd_clrscr(); 
    lcd_gotoxy(0,0); 
    lcd_puts("RoBoProG"); 
    lcd_gotoxy(0,1); 
    lcd_puts("Run:"); 
    for (i=3;i>0;i--) 
    { 
       sprintf(buffer,"%2i",i); 
       lcd_gotoxy(4,1); 
       lcd_puts(buffer); 
       _delay_ms(1000); 
    } 
    lcd_clrscr(); 

    lcd_puts(RAMstring); 
    sprintf(buffer,"%i",RAMbyte); 
    lcd_gotoxy(5,0); 
    lcd_puts(buffer); 
    sprintf(buffer,"%i",RAMword); 
    lcd_gotoxy(0,1); 
    lcd_puts(buffer); 


 return (0); 

 }


*/


/*
#include <stdio.h>
#define ENTER 0x1E
#define ESC 0x1C
void main()
{ int Klavesa;
switch (Klavesa)
{ case ENTER: doEnter(); //příkaz pro stisknutí Enter
break;
case ESC: doESC();
break;
} }
*/

/*     for (i=111;i>0;i--) 
    { 
  sprintf(buffer,"%3i",i); 
       lcd_gotoxy(13,1); 
       lcd_puts(buffer); 
       _delay_ms(500);
    
	if ((PINC & 0b10000000) == 0) i=i+50; 
	 
*/

/*
#include <mega16.h>

unsigned int cek1 = 0;

void main (void)
{

PORTC=0x01;
DDRC=0x01;
PORTD=0x40;
DDRD=0x00;

while (1)
      {         
         if ((PIND & 0x40) == 0)
          PORTC |= 0x01;
         else PORTC &=0xFE; 
      };
}

*/
