
/********************************************************************
// panorama_xhruby00.c
//-------------------------------------------------------------------
// 
// Funkce pro vytvareni panoramatu
// 
//
// Michal Hrubý 2011
// VUTBR
// xhruby00
//
********************************************************************/

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




static float angles[3][ANGLES_TABLE_X] PROGMEM={
	/***************************************************************
	Ulozeni tabulky OHNISKO - OsaX - OsaY pro CANON EOS 500D do 
	programove pameti

	Radek 0 - ohniska
	Radek 1 - Velikost stupnu na jednu fotografii - osa X
	Radek 2 - Velikost stupnu na jednu fotografii - osa X

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

	{18  , 24  , 35  , 50  , 65  , 80  , 95  , 115 , 135, 150, 170, 200},
	{55.8, 45.7, 33.7, 24.5, 19.2, 15.7, 13.3, 11.0, 9.4, 8.5, 7.5, 6.4}, 
	{41.7, 32.9, 23.4, 16.7, 13.0, 10.6, 8.9,  7.4,  6.3, 5.7, 5.0, 4.3}

  };


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


float read_angles(unsigned char row, unsigned char col)
{
	/***************************************************************
	vycteni z tabulky OHNISKO - OsaX - OsaY pro CANON EOS 500D 

	Radek 0 - ohniska
	Radek 1 - Velikost stupnu na jednu fotografii - osa X
	Radek 2 - Velikost stupnu na jednu fotografii - osa X

	****************************************************************/
  return pgm_read_float(&angles[col][row]);
}


char fix_focus(char focus){
	/***************************************************************
	Normovani ohniska - prirazeni k hodnote ohniska co je v tabulce
	
	Argumenty:
	1) char focus - vstupni ohnisko

	Navratova hodnota:
	char - normovane ohnisko

	Pozn:
	158 -> 150
	
	****************************************************************/

	char read_table=ANGLES_TABLE_X-1;			//v pripade problemu se pouziej nevyssi ohnisko

	if((char)focus<(char)read_angles(0,0)){				// pokud je nizsi nez v tabulce
		read_table=0;

	}else{
		int i;
		for(i=1;i<ANGLES_TABLE_X;i++)						// projizdi tabulku a porovnava
			{	
				if(focus<(char)read_angles(i,0)){			// pokud je mensi nez dalsi hodnota v tabulce, priradi honotu nizsi
					read_table=i-1;
					break;
				}
			}
	}
	if(focus>(char)read_angles(ANGLES_TABLE_X-1,0)){		//pokud je vyssi, nez maximalni ohnisko
					read_table=ANGLES_TABLE_X-1;
	}

	focus=read_angles(read_table,0);

	return focus;
}



char index_focus(char focus){
	/***************************************************************
	Urceni pozice ohniska v tabulce
	
	Argumenty:
	1) char focus : vstupni ohnisko

	Navratova hodnota:
	char : index v TABULCE

	Pozn:
	18 -> 0
	24 -> 1
	
	****************************************************************/
	int i=0;
	for(i=0; i<ANGLES_TABLE_X; i++){
	 
		  if(focus==read_angles(i,0)){	//pokud jsme narazili na shodu pri pruchodu tabulkou
			break;
		  }
	
	}
	return i;

}


char make_pano_X(char calculate, char focus, char overlap, int osaX){
	/***************************************************************
	Vypocita / vyfoti panorama v ose X
	
	Argumenty:
	1) char calculate	: 1 = pozadujeme pouze vypocet poctu snimku
						  0 = provest foceni
	2) char focus 		: nastavene ohnisko 
	3) char overlap		: procento prekryti snimku
	4) int osaX			: pocet stupnu na osu X

	Navratova hodnota:
	char - pocet fotek na osu X

	Pozn:

	****************************************************************/
	
	
	int actual_position_x = 0;		// aktualni poloha v ramci panaramatu vzlhedem k zacatku panorama - abychom byli schopni se opetovne vratit na stred
	char fotekX=0;					// pocet fotek OsaX


	if(calculate){
		lcd_clear();
		lcd_print_s("Pocitam...");
	}


	focus=fix_focus(focus); 				// prepsani normovym ohniskem
	char read_table_x=index_focus(focus);	// zjisteni indexu


	float viewX = read_angles(read_table_x,1); 	// kolik vidi na 1 snimku

	int CentrOsaX = osaX/2;					// stred panoramatu - zde stojime

	int steps_to_centr_x;					//pocet kroku do stredu panoramatu

	if(viewX>=osaX){						// pozadovany rozsah X se vejde do jedne fotky - netocit
		steps_to_centr_x = 0;
		if(!calculate){						// nepozadujeme pouze vypocet
			motor_ena(0);					// proti vetru
			foto_shot ();					/////////////////////FOCENI///////////////////
			motor_disa(0);
		}
		fotekX=1;


	}else{									// pozadovany rozsah X se vejde do jedne fotky - potreba tocit
		steps_to_centr_x = (CentrOsaX - (viewX/2))*STEPS_FOR_1_X ;
		
	
		if(!calculate){ 					// nepozadujeme pouze vypocet
			motor_init();
			motors_disa();
			motor_set_left();
			steps(steps_to_centr_x, 3, 0);	/////////////////////TOCENI///////////////////
			actual_position_x = 0;			// OKRAJ panoramatu
			motor_set_right();
			foto_shot();					/////////////////////FOCENI///////////////////

		}
	
		fotekX++;							// zvys pocet fotek osa X


		////////////////////////////////////////////////////////////////////////////
	
		float zbytekX = osaX - viewX;

		viewX= (viewX/100)*(100-overlap); 	// zkraceny snimek

		int move =  viewX*STEPS_FOR_1_X ;	// pocet kroku na 1 zkraceny snimek


		while(zbytekX>=0){					// Jeste zbyva cas, kterou jsme nevyfotili
	
			if(!calculate){					// nepozadujeme pouze vypocet	

					// pri potrebe prerusit panorama
					if(keypad_decode(keypad_read())=='*')	
						{
							lcd_lines_print("Koncim panorama","");
							_delay_ms(2500);
							motors_disa();
							goto konec_cyklu;
			
						}

				steps(move, 3, 0); 			/////////////////////TOCENI///////////////////
				actual_position_x += move; 	// aktualni pozice zmenena
				foto_shot ();				/////////////////////FOCENI///////////////////
			}
			fotekX++;						// zvys pocet fotek osy X

			if(zbytekX-viewX>=0){			// zbyva jeste neco na dofoceni?
					zbytekX-=viewX;
			}
			else break;
	
		}
		//zpatky na startovaci pozici
		if(!calculate){						// nepozadujeme pouze vypocet
			motor_set_left(); 
			move = actual_position_x - steps_to_centr_x;
			steps(move, 3, 0);				///////////////////TOCENI ZPET////////////////
			motor_disa(0);
		}
	
	
	}
	konec_cyklu:
	fotekX=	(float)fotekX; //nutnost pretypovat - jinak chybny vystup

	return fotekX;
}




char make_pano_XY(char calculate, char focus, char overlap, int osaY, const int osaX){
	
	/***************************************************************
	Vypocita  pocet rad Y / Vyfoti celkove panorama
	
	Argumenty:
	1) char calculate	: 1 = pozadujeme pouze vypocet poctu snimku
						  0 = provest foceni
	2) char focus 		: nastavene ohnisko 
	3) char overlap		: procento prekryti snimku
	4) int osaY			: pocet stupnu na osu Y
	5) int osaX			: pocet stupnu na osu X

	Navratova hodnota:
	char - pocet radku Y panorama

	Pozn:

	****************************************************************/
	set_shots_actual(1);

	int actual_position_y = 0;		//aktualni poloha v ramci panaramatu vzlhedem k zacatku panorama - abychom byli schopni se opetovne vratit na stred
	char fotekY=0;					//pocet fotek OsaX
	
	
	focus=fix_focus(focus); 		// prepsani normovym ohniskem
	char read_table_y=index_focus(focus);	// zjisteni indexu


	float viewY = read_angles(read_table_y,2); 	// kolik vidi na 1 snimku

	int CentrOsaY = osaY/2;			// stred panoramatu - zde stojime


	int steps_to_centr_y;			//pocet kroku do stredu panoramatu

	if(viewY>=osaY){				// pozadovany rozsah X se vejde do jedne fotky - netocit
		if(!calculate){				// nepozasujeme pouze vypocet
		steps_to_centr_y = 0;
		motor_ena(1);				// proti vetru
		motor_disa(1);
		make_pano_X(0, focus, overlap, osaX);
		}
		fotekY=1;					// pouze jedna rada

	}else{							// je potreba vice snimku

		steps_to_centr_y = (CentrOsaY - (viewY/2))*STEPS_FOR_1_Y ;	//kroku do stredu OSA Y
				
		if(!calculate){ 			// nepozadujeme pouze vypocet
			
			motor_init();
			motors_disa();
			motor_set_up();
			steps(steps_to_centr_y, 3, 1);	/////////////////////TOCENI///////////////////
			actual_position_y = 1;	// OKRAJ panoramatu
			motor_set_down();

			make_pano_X(0, focus, overlap, osaX);	////////////////PANO_X////////////////

		}

		fotekY++;					//	zvys pocet rad Y


		////////////////////////////////////////////////////////////////////////////

	
		float zbytekY = osaY - viewY;


		viewY= (viewY/100)*(100-overlap); // zkraceny snimek


		int move =  viewY*STEPS_FOR_1_Y ;  //pocet kroku na 1 zkraceny snimek

		while(zbytekY>=0){
	
			if(!calculate){			// nepozadujeme pouze vypocet
						
						// pokud je stisknuto opustenu panoramatu
						if(keypad_decode(keypad_read())=='*')	
						{
							lcd_lines_print("Koncim panorama","");
							_delay_ms(1500);
							motors_disa();
							goto konec_cyklu;
			
						}


				motor_set_down();
				steps(move, 3, 1); 			/////////////////////TOCENI///////////////////
				actual_position_y += move; 	// aktualni pozice zmenena

				make_pano_X(0, focus, overlap, osaX);	/////////////PANO_X///////////////
			}
			fotekY++;						//	zvys pocet rad Y


			if(zbytekY-viewY>=0){
					zbytekY-=viewY;

			}
			else break;
	
		}

		//zpatky na startovaci pozici
		
		if(!calculate){						// nepozadujeme pouze vypocet
			motor_set_up(); 
			move = actual_position_y - steps_to_centr_y;
			steps(move, 3, 1);				//////////////////TOCENI ZPET////////////////
			motor_disa(1);
		}
	
	
	}
	konec_cyklu:

	fotekY=	(float)fotekY; 					// Chyba prekladace - nutno pretypovat 

	return fotekY;
}
