
/********************************************************************
// menu_xhruby00.c
//-------------------------------------------------------------------
// 
// Knihovna pro praci s menu displejem
//
// Michal Hrubý 2011
// VUTBR
// xhruby00
//
********************************************************************/


#include <avr/io.h>			// hlavičkový soubor pro mikrokontrolér ATmega16
#define F_CPU 8000000UL		// frekvence hodinového signálu (nutné pro delay.h)
#include <util/delay.h>     // hlavičkový soubor pro zpoždění

#include "menu_xhruby00.h" 	// headerfile LCD
#include "motor_xhruby00.h" // headerfile motoru

//-------------------------------------------------------------------
// Globalni promenne
//-------------------------------------------------------------------

	extern char key;		// stisknuta klavesa
	extern char can_exit; 	// umoznuje opustit while pro zacykleni
	extern char skip_wait;	// preskoceni cekani na stiks klavesy - obnov menu
	extern char item_menu;	// postaveni v menu


//-------------------------------------------------------------------
// FUNKCE
//-------------------------------------------------------------------

char menu_forw(char item_menu){
	/***************************************************************
	Provede krok o polozku menu dopredu
	
	Argumenty:
	1)char item_menu : puvodni pozice v menu

	Navratova hodnota:
	char : 	nove pozice v menu

	Pozn:
	menu 30, 40 = jsou konecne, nelze jit dale (31, 41)
	menu 16 = zde maji tlacitka jinou funkci
	menu 0 - menu 5 = dalsi polozka je o 10 vyssi
	****************************************************************/


	if(item_menu==30 || item_menu==40 ){	// nelze udelat krok zpet
		item_menu=item_menu;
	}else{
		if(item_menu==16){				// vyjimka pro 16ku
			item_menu=15;
		}else{

				if((item_menu>0 && item_menu<5)) // krok dopredu se neprovadi v v nekterych obrazovkach
				{
					item_menu=item_menu*10;
				}else {		// specialni rezim, dalsi obrazovka je jenom o +1
					item_menu=item_menu+1;
				}
		}
	}
		
	return item_menu;
}


char menu_back(char item_menu)
{
	/***************************************************************
	Provede krok o polozku menu zpet
	
	Argumenty:
	1)char item_menu : puvodni pozice v menu

	Navratova hodnota:
	char : 	nove pozice v menu

	Pozn: 
	menu 16, 1 = nelze se vratit zpet
	jine nez menu 1 - menu 9 = dalsi polozka je o 10 hodnot zpet
	****************************************************************/


		if(item_menu==16 || item_menu==1){		// vyjimka pro 16ku a 1ku
			item_menu=1;
		}else{
		
			if ((item_menu>1 && item_menu<9) || (item_menu>10 && item_menu<15)){
				item_menu--;
			}else{
				item_menu/=10;
			}
			
		}

	return item_menu;

}



char menu_dec(char item_menu){
	/***************************************************************
	Provede krok o polozku menu dolu
	
	Argumenty:
	1)char item_menu : puvodni pozice v menu

	Navratova hodnota:
	char : 	nove pozice v menu

	Pozn: 
	menu 1 - menu 5 = lze
	menu 11- menu16 = lze
	****************************************************************/

	if((item_menu>1 && item_menu<5)){
  		item_menu--;
	}

	return item_menu;
}


char menu_inc(char item_menu){
	/***************************************************************
	Provede krok o polozku menu nahoru
	
	Argumenty:
	1)char item_menu : puvodni pozice v menu

	Navratova hodnota:
	char : 	nove pozice v menu

	Pozn: 
	menu 1 - menu 3 = lze
	menu 10- menu14 = lze
	****************************************************************/

	if((item_menu>0 && item_menu<4)){
  		item_menu++;
	}
	return item_menu;

}

int new_value_set(int old_set, int position, char value){ 			
	/***************************************************************
	Vlozi hodnotu na urcenou pozici - pro vkladani, upravu hodnot.
	
	Argumenty:
	1)int old_set 	: puvodni hodnota
	2)int position 	: pozice zadavaneho cisla
	3)char value 	: vkladane cislo

	Navratova hodnota:
	int: nova hodnota

	Pozn:
	position prave zadavaneho cisla: 3 = stovky, 2 = desitky, 1 = jednotky.

	****************************************************************/

	int temp3=0; 	// pro stovky
	int temp2=0; 	// pro desitky
	int new_set=0; 	// pro vysledek

	if (position==3)
	{
			temp3 = old_set/100; 						// pocet stovek  ...  435 -> 4
			new_set = old_set-(temp3*100)+(value*100); 	// vynuluje stovky  ... 435 - 400 + value*100
	}

	if (position==2)
	{
			temp3 = old_set/100;						// 435 -> 4
			temp2 = (old_set-(temp3*100))/10; 			// (435 - 400)/10 -> 3
			new_set= old_set-(temp2*10)+(value*10); 	// 435 - 30 + value*10
	}

	if (position==1)
	{
			temp3 = old_set/100;			// 435 -> 4
			temp2 = (old_set-(temp3*100))/10; 			// (435 - 400)/10 -> 3
			new_set = (temp3*100)+(temp2*10)+(value); 	// 4*100 + 3*10 + value
	}
				
  	return new_set;

}



int input_screen(int value, const char *line0, const char *line1, int max_set){
	/***************************************************************
	Vytvori obrazovku pro zadani hodnot
	
	Argumenty:
	1)int value 	: Defaultni hodnota
	2)char *line0	: Text na prvni radek
	3)char *line1	: Text jednotek
	3)int max_set 	: Maximalni mozna hodnota

	Navratova hodnota:
	int: nova hodnota

	****************************************************************/
	char key=0;			//
	char position=3;	// pozice prave zadavaneho cisla: 3 = stovky, 2 = desitky, 1 = jednotky.
	char check=0; 		// umoznuje provadet kontolu zadaneho cisla na max_set po kazdem zadanem znaku.

	
	can_exit=0;				// nastavi nemoznost opusteni zacykleni

	lcd_clear_line(0);				// smaze 1.radek
	lcd_print_s(line0);				// vytiskne 1.radek
	lcd_print_s("[");
	lcd_print_int(max_set,3);
	lcd_print_s("]");
	
	lcd_clear_line(1);				// smaze 2.radek
	lcd_goXY(2, 1);					// odsazeni
	lcd_print_int(value,3);			// vytiskne puvodni hodnotu

	lcd_print_c(' ');				// oddeluje zadana cisla od textu jednotek
	lcd_print_s(line1);				// vytiskne druhy radek (jednotky)

	lcd_goXY(2, 1);					// zapis na pozici STOVKY
	lcd_set_cursor(1);				// zapne kurzor


		while(can_exit==0)
		{
	
			key=keypad_read();
			if(key!=0)
			{
				key=keypad_decode(key);						//DOPLNIT posuny + urychleni pri drzeni

				switch(key)
				{
					case '1':								//vytvorit funkci
					case '2':
					case '3':
					case '4':
					case '5':
					case '6':
					case '7':
					case '8':
					case '9':
					case '0':
						value = new_value_set(value, position, key-48); //key je prevedeno na ascii, proto musime odecist 48
						lcd_print_c(key);
						position--;			// presuneme pozici (ze stovek na desitky)
							
					break;

					case '*':
						item_menu=menu_back(item_menu);	
						can_exit=1;  		// umozni opustit zacykleni cekajici na stisk klavesy
						skip_wait=1;		// umozni preskoceni zacykleni cekai na tlacitko
											// z duvodu potreby znovu prekresleni menu
						break;
							
					case '#':
						if(value<=max_set){	// pokud je hodnota mensi, nez maximalni povolena umozni potvrdit zadanou hodnotu
						item_menu=menu_forw(item_menu);	
						can_exit=1;  			// umozni opustit zacykleni
						skip_wait=1;		// umozni preskoceni zacykleni cekai na tlacitko
											// z duvodu potreby znovu prekresleni menu			
						}


						if(value>max_set){	// prekrocena maximalni hodnota
							lcd_clear_line (0);
							lcd_print_s("PREKROCENO! [max");	//
							lcd_print_int(max_set,3);				// vypise jaka je max povolene hodnota
							lcd_print_s("]");					//
							lcd_goXY(2, 1);	
							position=3;				
						}
				
					break;
								
				}

				

				if (position==0) {		// pokud jsme na pozici 0 presnuneme se na jednotky...
					position=1;
					
					check=1;			//provadet kontrolu po kazdem stiksnuti tlacitka
					
					if(value>max_set){	// prekrocena maximalni hodnota
					lcd_clear_line (0);
					lcd_print_s("PREKROCENO! [max");	//
					lcd_print_int(max_set,3);			// vypise jaka je max povolene hodnota
					lcd_print_s("]");					//
					lcd_goXY(2, 1);	
					position=3;				
					}
				}

				if (check==1){
				  if(value<=max_set){		// prekrocena maximalni hodnota
					lcd_clear_line (0);
					lcd_print_s(line0);		// vytiskne 1.radek
					lcd_goXY(5-position, 1);	
					}
				}

				 
			}   
			_delay_ms(200);			// interval pro opetovny stisk tlacitka
		}
	lcd_set_cursor(0);				// vypne kurzor
	return value;

}


void manual_control(void){
	/***************************************************************
	Obrazovka pro manualni ovladani PanoHeadu

	Pozn:
	Pri posuvu nahoru a dolu lze nastavit zarazky
	klavesou 5 - fotime
		
	****************************************************************/
	char key=0;			//stisknuta klavesa
	can_exit=0;

	while(can_exit==0)
	{
		key=keypad_read();
		if(key!=0)
		{
			key=keypad_decode(key);						
			switch(key)						// Rozhodnuti podle stisknuteho tlacitka
			{
				case '2':
					lcd_goXY(14,1);
					lcd_print_s("NAHORU");
					motor_init();
					motors_ena();
					motor_set_up();
					// kontrola, abychom nepresahli rozsah Y (pohyb nahoru)
					if((get_motor_y_actual()-200)>=MOTOR_Y_MIN){		// v poradku, nejsme na dorazu	
						steps(200, 0, 1);
						minus_motor_y_actual(200);
					}else{												// presahli bychom - zmensime posun na min. velikost Y
						steps((get_motor_y_actual()-MOTOR_Y_MIN), 0, 1);
						minus_motor_y_actual((get_motor_y_actual()-MOTOR_Y_MIN));
					}

					motors_disa();
					lcd_goXY(19, 0);
					lcd_batery_print(batery_check(averageADC(10)));

					break;
				case '4':
					lcd_goXY(14,1);
					lcd_print_s("VLEVO ");
					motor_init();
					motors_ena();
					motor_set_left();
					steps(80, 5, 0);
					motors_disa();
					lcd_goXY(19, 0);
					lcd_batery_print(batery_check(averageADC(10)));
					break;

				case '5':
					lcd_goXY(14,1);
					lcd_print_s("FOTO  ");
					foto_manual();
					lcd_goXY(14,1);
					lcd_print_s("OK   ");
					break;

				case '6':
					lcd_goXY(14,1);
					lcd_print_s("VPRAVO");
					motor_init();
					motors_ena();
					motor_set_right();
					steps(80, 5, 0);
					motors_disa();
					lcd_goXY(19, 0);
					lcd_batery_print(batery_check(averageADC(10)));
					break;

				case '8':
					lcd_goXY(14,1);
					lcd_print_s("DOLU  ");
					motor_init();
					motors_ena();
					motor_set_down();
							
					// kontrola, abychom nepresahli rozsah Y (pohyb dolu)
					if((get_motor_y_actual()+200)<=MOTOR_Y_MAX){		// v poradku, nejsme na dorazu	
						steps(200, 0, 1);
						plus_motor_y_actual(200);
					}else{
						steps((MOTOR_Y_MAX-get_motor_y_actual()), 0, 1);	// presahli bychom - zmensime posun na max. velikost Y
						plus_motor_y_actual((MOTOR_Y_MAX-get_motor_y_actual()));
					}
					motors_disa();
					lcd_goXY(19, 0);
					lcd_batery_print(batery_check(averageADC(10)));
					break;

				case '*':
					item_menu=menu_back(item_menu);	
					can_exit=1;  	// umozni opustit zacykleni
					skip_wait=1;	// umozni preskoceni zacykleni cekai na tlacitko
									// z duvodu potreby znovu prekresleni menu
					break;
				
				}
				 
			}   
			_delay_ms(200);
		}
	item_menu=2; //vrati do hlavniho menu, pozice 2

}
