#include "stdafx.h"
#include "acquisition.h"
#include "piezo.h"


CAPTURE data; // raw captured data
FWFFT fwdata; // vysledek transformace;
output odata; // vystup bwfft
initial inidata; //konfigurace
outputdata recdata; //rekonstuovana data

#define timeout 30000

volatile BOOL	bRun;
volatile BOOL	bGain,bExposure; // nastavovani zisku a  expoizice za behu programu
volatile BOOL	bShowAcq; // zobrazeni snimku z kamery
static	volatile BOOL	bHalted;
HANDLE hCaptureThread, hFFTThread;
CRITICAL_SECTION cs_copyRawdata,cs_showRawdata;
HANDLE hSemAcq,hSemAcqReady,hSemShowAcq,hSemShowAcqReady;

volatile BOOL	bRunFwFFT;
static	volatile BOOL	bHaltedFwFFT;
HANDLE hFwFFTThread;
CRITICAL_SECTION cs_copyFwFFTdata;
HANDLE hSemFwFFT,hSemFwFFTReady;

volatile BOOL	bRunBwFFT;
static	volatile BOOL	bHaltedBwFFT;
HANDLE hBwFFTThread;
CRITICAL_SECTION cs_copyBwFFTdata;
HANDLE hSemBwFFT,hSemBwFFTReady;

volatile BOOL	bRunShowRec; 
static	volatile BOOL	bHaltedShowRec;
volatile BOOL	bShowAmp; // prubeh amplitudy
volatile BOOL	bSaveImag = FALSE; // ulozeni obrazku
volatile BOOL	bRegulace = FALSE; // zapnuti regulace pomoci pieza
volatile BOOL	bMaximumA = FALSE; // zapnuti nalezeni maxima pomoci pieza
volatile BOOL	bShow3D = FALSE; // zobrazeni 3D rekonstrukce
SPid regulator; // regulacni struktura
SMax maximumA; // struktura pro hledani maxima
volatile BOOL bStopShowAcq = FALSE; // zastaveni zobrazovani snimku z kamery
HANDLE hShowRecThread;
CRITICAL_SECTION cs_show;
//HANDLE hSemBwFFT,hSemBwFFTReady;


void setting(){
	FILE *fr;
	
//	fr = fopen("c://windows//winkamera.ini","r");
	fopen_s(&fr,".//winkamera.ini","r");
	fscanf_s(fr,"expozice=%d\n",&inidata.expozice);
	fscanf_s(fr,"gain=%d\n",&inidata.gain);
	fscanf_s(fr,"offset=%d\n",&inidata.offset);
	fscanf_s(fr,"separacex=%d\n",&inidata.separxy.cx);
	fscanf_s(fr,"separacey=%d\n",&inidata.separxy.cy);
	fscanf_s(fr,"expanze=%d\n",&inidata.expanz);
	fscanf_s(fr,"koefapod=%lf\n",&inidata.apod);
	fscanf_s(fr,"threads=%d\n",&inidata.threads);
	fscanf_s(fr,"fpsref=%d\n",&inidata.fpsrefr);
	fscanf_s(fr,"nosnanonstop=%d\n",&inidata.detekcenosne);
	fscanf_s(fr,"showacq=%d\n",&inidata.showacq);
	fscanf_s(fr,"showacqx=%d\n",&inidata.showacqxy.cx);
	fscanf_s(fr,"showacqy=%d\n",&inidata.showacqxy.cy);
	fscanf_s(fr,"showamp=%d\n",&inidata.showamp);
	fscanf_s(fr,"showampx=%d\n",&inidata.showampxy.cx);
	fscanf_s(fr,"showampy=%d\n",&inidata.showampxy.cy);
	fscanf_s(fr,"regiGain=%lf\n",&regulator.iGain);
	fscanf_s(fr,"regpGain=%lf\n",&regulator.pGain);
	fscanf_s(fr,"regdGain=%lf\n",&regulator.dGain);
	fscanf_s(fr,"posAx=%d\n",&inidata.posrecA.cx);
	fscanf_s(fr,"posAy=%d\n",&inidata.posrecA.cy);
	fscanf_s(fr,"posFx=%d\n",&inidata.posrecF.cx);
	fscanf_s(fr,"posFy=%d\n",&inidata.posrecF.cy);
	fscanf_s(fr,"posAmpx=%d\n",&inidata.posampl.cx);
	fscanf_s(fr,"posAmpy=%d\n",&inidata.posampl.cy);
	fscanf_s(fr,"posCamx=%d\n",&inidata.poscam.cx);
	fscanf_s(fr,"posCamy=%d\n",&inidata.poscam.cy);
	fscanf_s(fr,"regulace=%d\n",&inidata.regulace);
	fscanf_s(fr,"Scpx=%d\n",&inidata.Scpx);
	fscanf_s(fr,"SimAF=%d\n",&inidata.SimAF);
	fscanf_s(fr,"stabPha=%lf\n",&regulator.stabPha);
	fscanf_s(fr,"posavFx=%d\n",&inidata.posavF.cx);
	fscanf_s(fr,"posavFy=%d\n",&inidata.posavF.cy);
	fscanf_s(fr,"posavAx=%d\n",&inidata.posavA.cx);
	fscanf_s(fr,"posavAy=%d\n",&inidata.posavA.cy);
	fscanf_s(fr,"pos3dx=%d\n",&inidata.posrec3D.cx);
	fscanf_s(fr,"pos3dy=%d\n",&inidata.posrec3D.cy);
	fscanf_s(fr,"pos3d=%d\n",&inidata.rec3d);
	fclose(fr);
}

void savesetting(){
	FILE *fw;
	
//	fr = fopen("c://windows//winkamera.ini","r");
	fopen_s(&fw,".//winkamera.ini","w");
	fprintf_s(fw,"expozice=%d\n",inidata.expozice);
	fprintf_s(fw,"gain=%d\n",inidata.gain);
	fprintf_s(fw,"offset=%d\n",inidata.offset);
	fprintf_s(fw,"separacex=%d\n",inidata.separxy.cx);
	fprintf_s(fw,"separacey=%d\n",inidata.separxy.cy);
	fprintf_s(fw,"expanze=%d\n",inidata.expanz);
	fprintf_s(fw,"koefapod=%lf\n",inidata.apod);
	fprintf_s(fw,"threads=%d\n",inidata.threads);
	fprintf_s(fw,"fpsref=%d\n",inidata.fpsrefr);
	fprintf_s(fw,"nosnanonstop=%d\n",inidata.detekcenosne);
	fprintf_s(fw,"showacq=%d\n",inidata.showacq);
	fprintf_s(fw,"showacqx=%d\n",inidata.showacqxy.cx);
	fprintf_s(fw,"showacqy=%d\n",inidata.showacqxy.cy);
	fprintf_s(fw,"showamp=%d\n",inidata.showamp);
	fprintf_s(fw,"showampx=%d\n",inidata.showampxy.cx);
	fprintf_s(fw,"showampy=%d\n",inidata.showampxy.cy);
	fprintf_s(fw,"regiGain=%lf\n",regulator.iGain);
	fprintf_s(fw,"regpGain=%lf\n",regulator.pGain);
	fprintf_s(fw,"regdGain=%lf\n",regulator.dGain);
	fprintf_s(fw,"posAx=%d\n",inidata.posrecA.cx);
	fprintf_s(fw,"posAy=%d\n",inidata.posrecA.cy);
	fprintf_s(fw,"posFx=%d\n",inidata.posrecF.cx);
	fprintf_s(fw,"posFy=%d\n",inidata.posrecF.cy);
	fprintf_s(fw,"posAmpx=%d\n",inidata.posampl.cx);
	fprintf_s(fw,"posAmpy=%d\n",inidata.posampl.cy);
	fprintf_s(fw,"posCamx=%d\n",inidata.poscam.cx);
	fprintf_s(fw,"posCamy=%d\n",inidata.poscam.cy);
	fprintf_s(fw,"regulace=%d\n",inidata.regulace);
	fprintf_s(fw,"Scpx=%d\n",inidata.Scpx);
	fprintf_s(fw,"SimAF=%d\n",inidata.SimAF);
	fprintf_s(fw,"stabPha=%lf\n",regulator.stabPha);
	fprintf_s(fw,"posavFx=%d\n",inidata.posavF.cx);
	fprintf_s(fw,"posavFy=%d\n",inidata.posavF.cy);
	fprintf_s(fw,"posavAx=%d\n",inidata.posavA.cx);
	fprintf_s(fw,"posavAy=%d\n",inidata.posavA.cy);
	fprintf_s(fw,"pos3dx=%d\n",inidata.posrec3D.cx);
	fprintf_s(fw,"pos3dy=%d\n",inidata.posrec3D.cy);
	fprintf_s(fw,"pos3d=%d\n",inidata.rec3d);
	fclose(fw);
}


void wtoc(CHAR* Dest, const WCHAR* Source)
{
int i = 0;

while(Source[i] != '\0')
{
Dest[i] = (CHAR)Source[i];
++i;
}
}

void ctow(WCHAR* Dest, const CHAR* Source)
{
int i = 0;

while(Source[i] != '\0')
{
Dest[i] = (WCHAR)Source[i];
++i;
}
}

void m12_16(LPWORD ip, LPWORD op, int n)
{
LPWORD	ep = op+n;
	_asm{
		mov		esi,	[ip]
		mov		edi,	[op]
t10:

		mov		eax,	[esi]
		mov		ecx,	eax
		mov		ebx,	[esi+4]
	
		shrd	edx,	eax,	4

		shrd	eax,	ebx,	16
		shrd	edx,	eax,	4
		and		eax,	0FFF0FFF0h
		shr		eax,	4
		shrd	edx,	ebx,	4
		shrd	edx,	ecx,	16
		and		edx,	0FFF0FFF0h
		shr		edx,	4
		mov		[edi],	edx
		mov		[edi+4],eax

		mov		eax,	[esi+8]
		mov		edx,	ebx
		and		ebx,	0FFF00000h
		shr		edx,	12
		mov		ecx,	eax
		and		edx,	00F0h
		shl		ecx,	8
		or		ebx,	edx
		mov		edx,	eax
		and		ecx,	0F00h
		shr		edx,	4
		or		ebx,	ecx
		and		edx,	0F000h
		and		eax,	0FFF0FFF0h
		shr		eax,	4
		or		ebx,	edx
		mov		[edi+12],eax
		and		ebx,	0FFF0FFF0h
		shr		ebx,	4
		add		esi,	12
		mov		[edi+8],ebx
		add		edi,	16
		cmp		edi,	[ep]
		jc		t10
	}
}

void mv40Unpack12( LPWORD pwDst, double *pDst, LPWORD pwSrc, DWORD dwBuffWidth, DWORD dwHeight, DWORD dwPixSize, DWORD dwField1, DWORD dwWidth)
{
DWORD	y, t;
LPWORD	op, ip;

	for(op = pwDst, y=0; y<dwHeight; y++, op+=dwWidth) {

		ip = pwSrc + dwBuffWidth * (y/2);
//		printf("%d\n", y);
		m12_16(ip, op, dwWidth);
		for(t = 0;t < dwWidth;t++){
			*(pDst + (y * dwWidth) + t) = *(op + t);
		}
	}
} 



//<****** fft shifting ***** ///

void shiftdata(complex *out, SIZE s_out, SHIFT *init){

	///complex *out vystup komplexni cislo na souradnicich s_out 
	// complex *inp vstupni pole s velikosti s_inp , typ shiftovani int type_shift

	int tx,ty;
	int zero = 0;

	switch(init->type_shift){
		case 0 :{ // no shift 
			//puts("no shift");
			break;
				}

          // shiftovani realne transformace
		case 1 :{ // r2c shift
			if((s_out.cx >= init->out_resolution.cx / 2)){ 
				tx = s_out.cx - init->out_resolution.cx / 2;
				if((s_out.cy >= init->out_resolution.cy / 2))	
					if(s_out.cy != init->out_resolution.cy - 1)
						ty = s_out.cy - init->out_resolution.cy / 2;				
					else 
						zero = 1;				
				else
					ty = s_out.cy + init->out_resolution.cy / 2;
			}
			else {
				tx = - s_out.cx + init->out_resolution.cx / 2;
				if((s_out.cy > init->out_resolution.cy / 2))
					ty = - s_out.cy + 3 * (init->out_resolution.cy / 2);
				else
					if(s_out.cy != 0)
						ty = - s_out.cy + init->out_resolution.cy / 2; 
					else 
						zero = 1;
			}

			if (zero) {				
				(*out).im = 0;
				(*out).re = 0;
				zero = 0;
 			} else  
				*out = *(init->inp + (ty * init->inp_resolution.cx + tx));		

			break;
				}
		
			// shiftovani komplexni transformace
		case 2:{ // c2c shift
			if((s_out.cx >= init->out_resolution.cx / 2) && (s_out.cx <= init->out_resolution.cx - 1))
				tx = s_out.cx - init->out_resolution.cx / 2;
			else
				tx = s_out.cx + init->out_resolution.cx / 2;

			if((s_out.cy >= init->out_resolution.cy / 2) && (s_out.cy <= init->out_resolution.cy - 1))
				ty = s_out.cy - init->out_resolution.cy / 2;
			else
				ty = s_out.cy + init->out_resolution.cy / 2;

				*out = *(init->inp + (ty * init->inp_resolution.cx + tx));		
			break;
			   }
	}
}


void get_shift_res(SHIFT *init){

	switch(init->type_shift){
		case 0 :{ // no shift 
			init->out_resolution = init->inp_resolution;
			//puts("no shift");
			break;
				}
		case 1 :{ // shift r2c
			init->out_resolution.cx = init->inp_resolution.cx * 2 - 1;
			init->out_resolution.cy = init->inp_resolution.cy - 1;
			//puts("r2c shift");
			break;
				}
		case 2 :{ //shift c2c
			init->out_resolution.cx = init->inp_resolution.cx;
			init->out_resolution.cy = init->inp_resolution.cy;
			//puts("c2c shift");
			break;
				}

	}
}

void hledejNosnou(SHIFT *init){
	SIZE souradnice;
	int x,y;
	double amp,max = 0;
	complex pom;

	for(y = 0; y < init->inp_resolution.cy; y++)
		for(x = init->offset; x < init->inp_resolution.cx; x++){
			pom = *(init->inp + y * init->inp_resolution.cx + x);
			amp = sqrt(pow(pom.im,2) + pow(pom.re,2));
			if(amp > max){
				max = amp;
				souradnice.cx = x + init->inp_resolution.cx - 1;
				if(y < init->inp_resolution.cy / 2) 
					souradnice.cy = y + init->inp_resolution.cy / 2;
				else
					souradnice.cy = y;
			}
		}
	init->nosna = souradnice;
}

double hledejIntenzituZdroje(SHIFT *init){ // zajistuje nezavislost na intenzite osvetleni, hleda max intenzitu v oblasti kolem stredu spektra
	int x,y;
	double amp,max = 0;
	complex pom;
	SIZE dxy;

//	for(y = 0; y < 20; y++)
	for(y = init->inp_resolution.cy / 2 - 20; y < init->inp_resolution.cy / 2 + 20; y++)
		for(x = init->inp_resolution.cx / 2 - 20; x < init->inp_resolution.cx / 2 + 20; x++){
//		for(x = 0; x < 20; x++){
			dxy.cx = y; // ted si nejsem jist proc je to prehozene ale funguje to lepe, asi to ma neco spolecneho s oznacenim souradnic v wfft
			dxy.cy = x;
			shiftdata(&pom,dxy,init);
//			pom = *(init->inp + y * init->inp_resolution.cx + x);
			amp = sqrt(pow(pom.im,2) + pow(pom.re,2));
			if(amp > max)
				max = amp;
		}
	init->intenzitazdroje = max;
	return max;
}

void hanningovo_okno(SHIFT *init){
	
	double val,vx,vy;
	const double PI = 3.141592654;
	
	init->apodizace = (double *)malloc(init->velsepar.cx*init->velsepar.cy*sizeof(double));

	for(int y = 0; y < init->velsepar.cy; y++){
		vy = init->apod_koef * PI * (2 * (y + 1) / (double)init->velsepar.cy - 1);
		for(int x = 0;x < init->velsepar.cx; x++){
			vx = init->apod_koef * PI * (2 * (x + 1) / (double)init->velsepar.cx - 1);
			val = sqrt(pow(vx,2) + pow(vy,2));
			if(val < PI)
				*(init->apodizace + y * init->velsepar.cx + x) = 0.5 * (1 + cos(val));
			else
				*(init->apodizace + y * init->velsepar.cx + x) = 0;
		}
	}
}



void separace(SHIFT *init){

	SIZE dxy;
	complex K;

	for(int y = 0; y < init->velsepexp.cy; y++)
		for(int x = 0; x < init->velsepexp.cx; x++){
			if((x > init->expanze - 1)&&(x < init->expanze + init->velsepar.cx)
			&&(y > init->expanze - 1)&&(y < init->expanze + init->velsepar.cy)){
				dxy.cx = init->nosna.cx - init->velsepar.cx / 2 + x - init->expanze;
				dxy.cy = init->nosna.cy - init->velsepar.cy / 2 + y - init->expanze;

				// pokud je vyrez mimo obrazek je chybejici cast doplnena nulou
				if((dxy.cx >= init->out_resolution.cx)||(dxy.cy >= init->out_resolution.cy)){
					K.re = 0;
					K.im = 0;
				}
				else {
					shiftdata(&K,dxy,init);
					K.re = *(init->apodizace + (y - init->expanze) * init->velsepar.cx + (x - init->expanze))  * K.re;
					K.im = *(init->apodizace + (y - init->expanze) * init->velsepar.cx + (x - init->expanze))  * K.im;
				}
				//*(init->separovana + y * (2 * init->expanze + init->velsepar.cx) + x) = K;
			}
			else{
				K.im = 0; 
				K.re = 0;
			}
			*(init->separovana + y * init->velsepexp.cx + x) = K;
		}
}


void get_expandet_res(SHIFT *init){

	init->velsepexp.cx = init->velsepar.cx + 2 * init->expanze;
	init->velsepexp.cy = init->velsepar.cy + 2 * init->expanze;
}

void kopie(SHIFT *init){

	SIZE dxy;
	complex K;

	// kopirovani c2c

	for(dxy.cy = 0; dxy.cy < init->inp_resolution.cy; dxy.cy++)
		for(dxy.cx = 0; dxy.cx < init->inp_resolution.cx; dxy.cx++){
			shiftdata(&K,dxy,init);
			*(init->separovana + dxy.cy * init->inp_resolution.cx + dxy.cx) = K;
		}


}


//****** fft shifting ***** >///


DWORD WINAPI AcquisitionProc( LPVOID )
{
HANDLE	hMVlocal = INVALID_HANDLE_VALUE;
LPWORD	pRawData;
LPWORD image = NULL;
double *dimage = NULL;
DWORD	dwSerNum;
U32	devices = 0;
SIZE resolution;
DWORD bytesperline, foffset, bpp;
int mvret = 0; //chybova hlaseni
int count =0;

//clock_t start;

bRun = TRUE; 

while (bRun) {
		if (hMVlocal == INVALID_HANDLE_VALUE) {
			mvret = mm40GetNumberDevices( szMM40_Name, &devices );
			if (devices) {
				mm40GetDevice( 0 , &dwSerNum ); // nastaveni zarizeni 0 na firewire pri vice zarizenich
				mm40Initialize( szMM40_Name, dwSerNum, &hMVlocal );
				if (mvret = mm40StartImageAcquisition( hMVlocal ) != MM40_OK ) {
					bRun = FALSE;
					break;
				}

				mm40GetResolution( hMVlocal, &resolution, &bytesperline, &foffset, &bpp);

				image = (LPWORD)calloc(resolution.cx*resolution.cy,sizeof(image[0]));
				dimage = (double *)malloc(resolution.cx*resolution.cy*sizeof(double));

				EnterCriticalSection(&cs_copyRawdata);
					mm40SetGain( hMVlocal, data.gain);
					mm40SetExposure( hMVlocal, data.exposure );
					data.resolution = resolution;
					data.image = image;
					data.dimage = dimage;
				LeaveCriticalSection(&cs_copyRawdata);


			}
		}

		pRawData=NULL;
		if ( hMVlocal != INVALID_HANDLE_VALUE ) {
			while ( 1 ) {
				//start = clock();
				if (!bRun) break;
				mvret = mm40WaitForImage( hMVlocal, 60000);	//$$$

				/*if(FILE *f = fopen("log.txt","a")){
				  fprintf(f,"%ld\n",clock()-start);
 				  fclose(f);
				}*/

				if ( mvret == MM40_INVALID_HANDLE ) {
					mmStopAcquisition( hMVlocal );
					hMVlocal = INVALID_HANDLE_VALUE;
					break;
				}
				if ( mvret == MM40_NO_IMAGE ) continue;
				if ( mvret == MM40_OK ) {

					if (mm40AcquireImage( hMVlocal, (PVOID*)&pRawData ) != MM40_OK) {
				   		//Beep(1000, 50);
						continue;
					}

					if (pRawData==NULL) continue;


					if(WaitForSingleObject(hSemAcq, timeout) == WAIT_TIMEOUT)
						MessageBox(NULL, TEXT("timeout snímání kamery") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);;

					EnterCriticalSection(&cs_copyRawdata);
					if(bGain){ 
						mm40SetGain( hMVlocal, data.gain);
						bGain = FALSE;
					}
					if(bExposure){
						mm40SetExposure( hMVlocal, data.exposure );
						bExposure = FALSE;
					}
					mv40Unpack12( image, dimage, pRawData, bytesperline, resolution.cy, bpp, 0, resolution.cx);	
					LeaveCriticalSection(&cs_copyRawdata);
					ReleaseSemaphore(hSemAcqReady, 1, NULL); 
					
					if(bShowAcq){
						ReleaseSemaphore(hSemShowAcqReady, 1, NULL); 
						if(WaitForSingleObject(hSemShowAcq, timeout) == WAIT_TIMEOUT)
							MessageBox(NULL, TEXT("timeout zobrazení náhledu") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
					}
				}
			}
		}

		if (!bRun) break;

		if ( hMVlocal == INVALID_HANDLE_VALUE )
			continue;

		if (!bRun) break;
}

	if (hMVlocal != INVALID_HANDLE_VALUE) {
		mm40StopImageAcquisition( hMVlocal );
		mm40Uninitialize( hMVlocal );
	}
	Sleep(100);

	//free(pRawData);
    free(image);
	free(dimage);

	bHalted = TRUE;
	hCaptureThread = NULL;
	return mvret;
}


void shStopAcq()
{
	if (!bRun || hCaptureThread==NULL) return;

	bRun = FALSE;
	ReleaseSemaphore(hSemAcq,1,NULL); // ukonceni nacitani  

	WaitForSingleObject( hCaptureThread, 1000 ); // cekani na ukonceni vlakna

	CloseHandle(hCaptureThread);
	CloseHandle(hSemAcq);
	CloseHandle(hSemAcqReady);
	return;
}

BOOL shStartAcq()
{

BOOL	ret = FALSE;
DWORD	ThreadId;

	if (bRun) goto ex;
	
	bGain = bExposure = FALSE;

	data.exposure = inidata.expozice;
	data.gain = inidata.gain;
	bShowAcq = inidata.showacq;

	hSemAcq = CreateSemaphore (NULL, 0, 1, NULL);
	hSemAcqReady = CreateSemaphore (NULL, 0, 1, NULL);

	InitializeCriticalSection(&cs_copyRawdata);

	bHalted = FALSE;
	hCaptureThread = CreateThread( NULL, 0, AcquisitionProc, NULL, 0, &ThreadId);
	
	if (hCaptureThread==NULL) goto ex;

	while(!bRun && !bHalted) 
 		Sleep(5);

	ReleaseSemaphore(hSemAcq, 1, NULL); // nacteni prvniho obrazku a priprava druheho do rawdata

	ret = bRun; 
ex:
	return ret;
}

void Gain(int input)
{
	EnterCriticalSection(&cs_copyRawdata);
	data.gain = input;
	bGain = TRUE;
	LeaveCriticalSection(&cs_copyRawdata);
	inidata.gain = input;
	//Sleep(500);
}

int gGain() // spoustet pouze jednou na zacatku 
{
	return inidata.gain;
}


void Exposure(int input)
{
	EnterCriticalSection(&cs_copyRawdata);
	data.exposure = input;
	bExposure = TRUE;
	LeaveCriticalSection(&cs_copyRawdata);
	//Sleep(500);
	inidata.expozice = input;
}

int gExposure() // spoustet pouze jednou na zacatku 
{
	return inidata.expozice;
}

void nosna(int input)
{
	if(bRunFwFFT) EnterCriticalSection(&cs_copyFwFFTdata);
	inidata.detekcenosne = input;
	if(bRunFwFFT) LeaveCriticalSection(&cs_copyFwFFTdata);
}

int gnosna()
{
	if(bRunFwFFT) EnterCriticalSection(&cs_copyFwFFTdata);
	BOOL pom = inidata.detekcenosne;
	if(bRunFwFFT) LeaveCriticalSection(&cs_copyFwFFTdata);
	return pom;
}

// FFT vypocty
DWORD WINAPI FwFFTProc( LPVOID )
{
fftw_plan plan_f = NULL;
fftw_plan plan_s = NULL;
fftw_complex *spec_f = NULL;
fftw_complex *spec_s = NULL;
SIZE resolution;
BOOL FirstFFT = TRUE;
BOOL FirstCycle = TRUE;
int ret = 0;

	bRunFwFFT = TRUE;

//	fftw_init_threads();  //inicializace probehne pri spusteni v hlavnim vlaknu
//	fftw_plan_with_nthreads(2);

	//clock_t start;
	while(bRunFwFFT){
		//start = clock(); 
		if(WaitForSingleObject(hSemAcqReady, timeout)== WAIT_TIMEOUT)
			MessageBox(NULL, TEXT("timeout příjmu dat pro FFT") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
			//puts("timeout in fft"); // cekame az budou dostupna data z AcquireProc()
			if(FirstCycle){
				EnterCriticalSection(&cs_copyRawdata); 
				resolution = data.resolution;
	 			spec_f = (fftw_complex *)fftw_malloc(resolution.cy * ((int)resolution.cx/2 + 1) * sizeof(fftw_complex));
	 			spec_s = (fftw_complex *)fftw_malloc(resolution.cy * ((int)resolution.cx/2 + 1) * sizeof(fftw_complex));
				plan_f = fftw_plan_dft_r2c_2d(resolution.cy,resolution.cx,data.dimage,spec_f,FFTW_FORWARD * FFTW_ESTIMATE);
				plan_s = fftw_plan_dft_r2c_2d(resolution.cy,resolution.cx,data.dimage,spec_s,FFTW_FORWARD * FFTW_ESTIMATE);
				FirstCycle = FALSE;
				fwdata.FwFFTresolution.cy = resolution.cy;
				fwdata.FwFFTresolution.cx = (int)resolution.cx/2 + 1;
				LeaveCriticalSection(&cs_copyRawdata);
				if(spec_f == NULL || spec_s == NULL || plan_f == NULL || plan_s == NULL){
					bRunFwFFT = FALSE;
					break;
				}
			}
			//printf("wait=%ld ",clock()-start);
			if(FirstFFT){
				EnterCriticalSection(&cs_copyRawdata); 
				fftw_execute(plan_f);
				LeaveCriticalSection(&cs_copyRawdata);
				FirstFFT = FALSE;
				if(WaitForSingleObject(hSemFwFFT, timeout)== WAIT_TIMEOUT)
					MessageBox(NULL, TEXT("timeout odeslání dat z FFT") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
					//puts("timeout fft"); // cekame az bude mozno predat data 
				EnterCriticalSection(&cs_copyFwFFTdata); 
				fwdata.pFwFFTData = spec_f;
				LeaveCriticalSection(&cs_copyFwFFTdata);
				ReleaseSemaphore(hSemFwFFTReady, 1, NULL);// data jsou predana
			} else{				
				EnterCriticalSection(&cs_copyRawdata); 
				fftw_execute(plan_s);
				LeaveCriticalSection(&cs_copyRawdata);
				FirstFFT = TRUE;
				if(WaitForSingleObject(hSemFwFFT, timeout)== WAIT_TIMEOUT)
					MessageBox(NULL, TEXT("timeout odeslání dat FFT") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
					//puts("timeout fft"); // cekame az bude mozno predat data 
				EnterCriticalSection(&cs_copyFwFFTdata); 
				fwdata.pFwFFTData = spec_s;
				LeaveCriticalSection(&cs_copyFwFFTdata);
				ReleaseSemaphore(hSemFwFFTReady, 1, NULL);// data jsou predana
			}
			//printf("fft=%ld ",clock()-start);
			//printf("%d\n",count);
		ReleaseSemaphore(hSemAcq, 1, NULL); // povolujeme AcquireProc() predani dalsich dat
		//printf("celk=%ld \n",clock()-start);
	
	

	}
	Sleep(100);
	fftw_destroy_plan(plan_f);
	fftw_destroy_plan(plan_s);
	//free(spec_f);
	//free(spec_s);

	bHaltedFwFFT = TRUE;
	hFwFFTThread = NULL;
	return ret;

}


BOOL shStartFwFFT()
{

BOOL	ret = FALSE;
DWORD	ThreadId;

	if (bRunFwFFT) goto ex;
	
	hSemFwFFT = CreateSemaphore (NULL, 0, 1, NULL);
	hSemFwFFTReady = CreateSemaphore (NULL, 0, 1, NULL);

	InitializeCriticalSection(&cs_copyFwFFTdata);

	bHaltedFwFFT = FALSE;
	hFwFFTThread = CreateThread( NULL, 0, FwFFTProc, NULL, 0, &ThreadId);
	
	if (hFwFFTThread==NULL) goto ex;

	while(!bRunFwFFT && !bHaltedFwFFT) 
 		Sleep(5);

	ReleaseSemaphore(hSemFwFFT, 1, NULL); // zpracovani prvni FwFFT

	ret = bRunFwFFT; 
ex:
	return ret;
}

void shStopFwFFT()
{
	if (!bRunFwFFT || hFwFFTThread==NULL) return;

	bRunFwFFT = FALSE;
	ReleaseSemaphore(hSemFwFFT,1,NULL); // ukonceni nacitani  

	WaitForSingleObject( hFwFFTThread, 1000 ); // cekani na ukonceni vlakna

	CloseHandle(hFwFFTThread);
	CloseHandle(hSemFwFFT);
	CloseHandle(hSemFwFFTReady);
	return;
}

// FTT vypocty konec


/* void saveimage(){
	unsigned char *p_intensity;
	BOOL FirstCycle = TRUE;
	SHIFT shdata,redata;

	//clock_t start;

//	fftw_init_threads();
//	fftw_plan_with_nthreads(2);

	fftw_plan plan = NULL;
	complex *spec;


	for(int count = 0;count < 20;count++ ){
/*		char fn[256];
		sprintf(fn,"c:\\images\\0%d.pgm",count);
       		  
		if ( !(f=fopen(fn,"wb")) ) {
			fprintf(stderr,"Error creating output file!\n");
			return;
		}
*/
		
/*		if(WaitForSingleObject(hSemFwFFTReady, timeout)== WAIT_TIMEOUT)
			puts("timeout in refft");
		EnterCriticalSection(&cs_copyRawdata);

		shdata.inp = (complex *)fwdata.pFwFFTData; // ukazatel na pole ,meni se pri kazdem prubehu

		//start = clock();
		
		if(FirstCycle){
			// inicializace
			shdata.inp_resolution = data.FwFFTresolution;
			shdata.type_shift = 1;
			shdata.expanze = 40;
			shdata.offset = 0; // pro hledani nosne 0 = hleda se od stredu => za nosnou se zvoli nulta frekvence
			shdata.velsepar.cx = 200;
			shdata.velsepar.cy = 160;

			get_shift_res(&shdata);
			get_expandet_res(&shdata);

			shdata.apod_koef = 0.8;
			hanningovo_okno(&shdata);

			shdata.separovana = (complex *)malloc(shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(complex));


			hledejNosnou(&shdata); // pri prvnim cyklu najdu nosnou
			FirstCycle = FALSE;
			
			redata.inp_resolution = shdata.velsepexp;
			redata.inp = shdata.separovana;
			redata.type_shift = 2;
			redata.separovana = (complex *)malloc(shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(complex));
			get_shift_res(&redata);

			spec = (complex *)fftw_malloc(redata.out_resolution.cx * redata.out_resolution.cy * sizeof(complex));
			plan = fftw_plan_dft_2d(redata.out_resolution.cy,redata.out_resolution.cx,(fftw_complex *)redata.separovana,(fftw_complex *)spec,FFTW_BACKWARD,FFTW_ESTIMATE);

			p_intensity = (unsigned char *)malloc(shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(char));; // alokace pro zobrazeni

		}
		LeaveCriticalSection(&cs_copyRawdata);
		
//		start = clock();
		separace(&shdata); // separce + apodizace
//		printf("separace %ldms\n",clock()-start);
		kopie(&redata); // kopie a siftovani pro zpetnou fft
//		start = clock();
		fftw_execute(plan);
		

//		printf("fft %ldms\n",clock()-start);
		
		complex T;
		//printf("nosna xy = %d %d \n", shdata.nosna.cx , shdata.nosna.cy);

	//	printf("data M  %f %f\n",(*(shdata.separovana+10)).re,(*(shdata.separovana+10)).im); 

		double pom,max = 0;  
		for(int x = 0; x < shdata.velsepexp.cx*shdata.velsepexp.cy; x++){
			T = *(spec + x);
			pom = pow(pow(T.re,2) + pow(T.im,2),0.5);
			if(max < pom) 
				max = pom;
		}
		printf("max=%f nosna xy = %d %d %f\n",max, shdata.nosna.cx , shdata.nosna.cy, max);

	

		for(int x = 0; x < shdata.velsepexp.cx*shdata.velsepexp.cy; x++){
			T = *(spec + x);
			pom = pow(pow(T.re,2) + pow(T.im,2),0.5);
			*(p_intensity + x) = (pom / max) * 255;
		}


/*		double pom,max = 0;  
		for(int x = 0; x < shdata.velsepar.cx*shdata.velsepar.cy; x++){
			pom = *(shdata.apodizace+ x);
			if(max < pom) 
				max = pom;
		}
		printf("max=%f nosna xy = %d %d %f\n",max, shdata.nosna.cx , shdata.nosna.cy, max);

	

		for(int x = 0; x < shdata.velsepar.cx*shdata.velsepar.cy; x++){
			pom = *(shdata.apodizace + x);
			*(p_intensity + x) = (pom / max) * 255;
		}


		fprintf(f,"P5\n%u %u\n%u\n", shdata.velsepexp.cx,shdata.velsepexp.cy, 255);
		fwrite(p_intensity, 1, shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(unsigned char), f);

		ReleaseSemaphore(hSemFwFFT, 1, NULL); // zpracovani dalsiho obrazku;
//		fclose(f); 


	}
}
*/


DWORD WINAPI BwFFTProc(LPVOID)
{
	SHIFT shdata,redata;
	fftw_plan plan = NULL;
	complex *spec;
	BOOL FirstFFT = TRUE;
	BOOL FirstCycle = TRUE;
	int ret = 0;

	bRunBwFFT = TRUE;

	//clock_t start;
	while(bRunBwFFT){

		if(WaitForSingleObject(hSemFwFFTReady, timeout)== WAIT_TIMEOUT)
			MessageBox(NULL, TEXT("timeout příjmu dat pro výpočet BFFT") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
			//puts("timeout in refft"); // ceka se na vysledek dopredne fft

		EnterCriticalSection(&cs_copyFwFFTdata);
		shdata.inp = (complex *)fwdata.pFwFFTData; // ukazatel na pole ,meni se pri kazdem prubehu

		if(FirstCycle){
			// inicializace
			shdata.inp_resolution = fwdata.FwFFTresolution;
			shdata.type_shift = 1;
			shdata.expanze = inidata.expanz;
			shdata.offset = inidata.offset; // pro hledani nosne 0 = hleda se od stredu => za nosnou se zvoli nulta frekvence
			shdata.velsepar = inidata.separxy;

			get_shift_res(&shdata);
			get_expandet_res(&shdata);

			shdata.apod_koef = inidata.apod;
			hanningovo_okno(&shdata);

			shdata.separovana = (complex *)malloc(shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(complex));


			hledejNosnou(&shdata); // pri prvnim cyklu najdu nosnou
			FirstCycle = FALSE;

			//printf("nosna %d %d \n",shdata.nosna.cx,shdata.nosna.cy);
			
			redata.inp_resolution = shdata.velsepexp;
			redata.inp = shdata.separovana;
			redata.type_shift = 2;
			redata.separovana = (complex *)malloc(shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(complex));
			get_shift_res(&redata); 

			spec = (complex *)fftw_malloc(redata.out_resolution.cx * redata.out_resolution.cy * sizeof(complex));
			plan = fftw_plan_dft_2d(redata.out_resolution.cy,redata.out_resolution.cx,(fftw_complex *)redata.separovana,(fftw_complex *)spec,FFTW_BACKWARD,FFTW_ESTIMATE);

			EnterCriticalSection(&cs_copyBwFFTdata);
			odata.data = (complex *)malloc(redata.out_resolution.cy*redata.out_resolution.cx*sizeof(complex));
			odata.resolution = redata.out_resolution;
			LeaveCriticalSection(&cs_copyBwFFTdata);

			//p_intensity = (unsigned char *)malloc(shdata.velsepexp.cx*shdata.velsepexp.cy*sizeof(char));; // alokace pro zobrazeni

		}
		if(inidata.detekcenosne)
			hledejNosnou(&shdata); // nonstop detekce
		redata.intenzitazdroje = hledejIntenzituZdroje(&shdata);
		separace(&shdata); // separce + apodizace
		LeaveCriticalSection(&cs_copyFwFFTdata);
		kopie(&redata); // kopie a siftovani pro zpetnou fft

		ReleaseSemaphore(hSemFwFFT, 1, NULL); // zpracovani dalsiho obrazku - lze spustit jiz po kopii separovaneho obrazku;

		fftw_execute(plan); // vypocet zpetne fft

		if(WaitForSingleObject(hSemBwFFT, timeout)== WAIT_TIMEOUT)
			MessageBox(NULL, TEXT("timeout odeslání dat po BFFT") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
			//puts("timeout out refft"); // cekame az bude mozno predat data 
		EnterCriticalSection(&cs_copyBwFFTdata);
		memcpy(odata.data,spec,redata.out_resolution.cy*redata.out_resolution.cx*sizeof(complex)); // kopirovani dat rekonstrukce
		odata.intenzitaZdroje = redata.intenzitazdroje;
		LeaveCriticalSection(&cs_copyBwFFTdata);
		ReleaseSemaphore(hSemBwFFTReady, 1, NULL);// data jsou predana

	}
	Sleep(100);
	fftw_destroy_plan(plan);
	bHaltedBwFFT = TRUE;
	hBwFFTThread = NULL;
	return ret;

}

BOOL shStartBwFFT()
{

BOOL	ret = FALSE;
DWORD	ThreadId;

	if (bRunBwFFT) goto ex;
	
	hSemBwFFT = CreateSemaphore (NULL, 0, 1, NULL);
	hSemBwFFTReady = CreateSemaphore (NULL, 0, 1, NULL);

	InitializeCriticalSection(&cs_copyBwFFTdata);

	bHaltedBwFFT = FALSE;
	hBwFFTThread = CreateThread( NULL, 0, BwFFTProc, NULL, 0, &ThreadId);
	
	if (hFwFFTThread==NULL) goto ex;

	while(!bRunBwFFT && !bHaltedBwFFT) 
 		Sleep(5);

	ReleaseSemaphore(hSemBwFFT, 1, NULL); // zpracovani prvni FwFFT

	ret = bRunBwFFT; 
ex:
	return ret;
}

void shStopBwFFT()
{
	if (!bRunBwFFT || hBwFFTThread==NULL) return;

	bRunBwFFT = FALSE;
	ReleaseSemaphore(hSemBwFFT,1,NULL); // ukonceni nacitani  

	WaitForSingleObject( hBwFFTThread, 1000 ); // cekani na ukonceni vlakna

	CloseHandle(hBwFFTThread);
	CloseHandle(hSemBwFFT);
	CloseHandle(hSemBwFFTReady);
	return;
}


// ulozeni obrazku ve formatu tiff
BOOL TiffWrite ( BOOL bRaw16,SIZE resolution, void *image, char *filename)
{
ULONG	stripBytes, numStrips, imageWidth, imageHeight;
USHORT	bitsPerSample;
USHORT	samplesPerPixel;
USHORT	photometric;
struct	tiff * m_tiff;


if ((m_tiff = TIFFOpen(filename, "w" )) == NULL )
		return FALSE;

if (bRaw16) {
	bitsPerSample = 16;
	imageHeight = numStrips = resolution.cy;
	stripBytes = resolution.cx * 2;
	imageWidth = resolution.cx;
}else
{
	bitsPerSample = 8;
	imageHeight = numStrips = resolution.cy;
	imageWidth = stripBytes = resolution.cx;
}
samplesPerPixel = 1;
photometric = 1;

	// All required fields for RGB and grayscale, except Xres, Yres, and res-unit.
	TIFFSetField( m_tiff, TIFFTAG_ROWSPERSTRIP, (ULONG) 1 );
	TIFFSetField( m_tiff, TIFFTAG_BITSPERSAMPLE, bitsPerSample );
	TIFFSetField( m_tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel );
	TIFFSetField( m_tiff, TIFFTAG_IMAGEWIDTH,  imageWidth );
	TIFFSetField( m_tiff, TIFFTAG_IMAGELENGTH, imageHeight );
	TIFFSetField( m_tiff, TIFFTAG_PHOTOMETRIC, photometric );
	TIFFSetField( m_tiff, TIFFTAG_PLANARCONFIG, (USHORT) 1 );	// RGBRGB
	TIFFSetField( m_tiff, TIFFTAG_COMPRESSION,  (USHORT) 1 );	// None


if (bRaw16) {
	// Grayscale 16 bit

	USHORT * srcPtr = static_cast< USHORT * >(image);
	ULONG	stripWords;			// unsigned short per strip
	stripWords = stripBytes >> 1;
	for ( ULONG strip = 0; strip < numStrips; strip++ ) {
		TIFFWriteEncodedStrip( m_tiff, strip, srcPtr, stripBytes );
		srcPtr += resolution.cx;
	}
}else
{
	UCHAR * srcPtr = static_cast< UCHAR * >(image);
	for ( ULONG strip = 0; strip < numStrips; strip++ ) {
		TIFFWriteEncodedStrip( m_tiff, strip, srcPtr, stripBytes );
		srcPtr += resolution.cx;
	}
}

TIFFClose( m_tiff );

return TRUE;

}

// zapis dat raw
BOOL RawWrite (SIZE resolution, complex *image, char *filename)
{
	FILE *fw;
	if(fopen_s(&fw,filename,"wb"))
		return FALSE;
	fwrite(image, sizeof(complex), resolution.cx*resolution.cy, fw);
	fclose(fw);
	return TRUE;
}
// vlakno zobrazeni


 WNDCLASS wc;
 HWND hWndA,hWndF,hWndW,hWndAA,hWnd3D;
 HDC hDCA,hDCF,hDCW,hDCAA,hDC3D;
 HGLRC hRCA,hRCF,hRCW,hRCAA,hRC3D;        
 MSG msg;
 BOOL bQuit = FALSE;
 TCHAR szAppName[255];
 TCHAR szWinName[] = TEXT("OknoZobrazeniikv");  
 //TCHAR szAppNameW[] = TEXT("náhled");  

 SIZE resolution; // rozliseni rekonstrukce
 SIZE resolutionW; // rozliseni kamery por zobrazeni snimaneho obrazu
 SIZE resolutionSW; // rozliseni pro zobrazeni kamery
 SIZE resolutionAA; // zobrazovani prumerne amplitudy
 unsigned char *bufferF, // buffer pro zobrazeni  faze
				*buffer3d, // buffer pro 3d podobne jako faze bez vyrezu
				*bufferA, // zobrazeni amplitudy
				*bufferW, // zobrazeni nahledu
				*bufferAA; // zobrazeni prubehu prumerne amplitudy
 LPWORD buffer;
 double *bufferAAd, // buffer pro vypocet prubehu prumerne amplitudy
		*bufferAFd; // buffer pro vypocet prubehu prumerne faze

 complex *bufferAF; // buffer rekonstruovane complexni amplitudy
 static int vyr = 10; // velikost vyrezu
 clock_t tstart,aver;
 double average = 0, amplitude = 0, ampl = 0,akoef = 1;
 int count = 0, picture = 0;
 //3D rekonstrukce
 double *X, *Y, *Z, *barva;
 int px = 45,py = 45,pz = 0;
 double zoom = 0.8;


/********************
 * Window Procedure
 *
 ********************/

LRESULT CALLBACK WndProc (HWND hWnd, UINT message,
                          WPARAM wParam, LPARAM lParam)
{

    switch (message)
    {
    case WM_CREATE:
        return 0;
    case WM_CLOSE:
        PostQuitMessage (0);
        return 0;

    case WM_DESTROY:
        return 0;

    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_ESCAPE:
            PostQuitMessage(0);
            return 0;
        }
        return 0;

    default:
        return DefWindowProc (hWnd, message, wParam, lParam);
    }
}


/*******************
 * Enable OpenGL
 *
 *******************/

void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC)
{
    PIXELFORMATDESCRIPTOR pfd;
    int iFormat;
	RECT WindowRect;
	int width;// Šířka
	int height;// Výška

    /* get the device context (DC) */
    *hDC = GetDC (hWnd);

    /* set the pixel format for the DC */
    ZeroMemory (&pfd, sizeof (pfd));
    pfd.nSize = sizeof (pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | 
      PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE;
    iFormat = ChoosePixelFormat (*hDC, &pfd);
    SetPixelFormat (*hDC, iFormat, &pfd);

    /* create and enable the render context (RC) */
    *hRC = wglCreateContext( *hDC );
    wglMakeCurrent( *hDC, *hRC );

	GetClientRect(hWnd, &WindowRect);// Získá velikost okna
	width = WindowRect.right - WindowRect.left;// Šířka okna
	height = WindowRect.bottom - WindowRect.top;// Výška okna
	//printf(" rozmery okna %d %d",width,height);
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION); 
	glLoadIdentity();
	glOrtho(0, width,height,0, -1, 1);
	//glFrustum(0, width,height,0, -1, 1);


}


/******************
 * Disable OpenGL
 *
 ******************/

void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC)
{
    wglMakeCurrent (NULL, NULL);
    wglDeleteContext (hRC);
    ReleaseDC (hWnd, hDC);
}


void ShowImages(){  
	int x,y;
	int pos = 0; // poloha pieza
	int nob; // pocet ignorovanych bodu prinevhodnem vyrezu
	SIZE positF,positA; // misto kliknuti mysi pro urceni vyrezu faze
	double	pom = 0,Apom = 0,
			amax = 0,fmax = 0, // promene pro normovani obrazu na 256 odstinu sedi 
			amin = 1e308 , fmin = 1e308,
			amp = 0, // prumerovani amplitudy prez cely obraz
			faze = 0,  // prumerovani a faze prez vyrez
			ampv = 0, // prumerovani amplitudy prez vyrez pro detekci maximalni amplitudy
			intenzitaZdroje; 
			
	tstart = clock();
 	if(WaitForSingleObject(hSemBwFFTReady, 30000)== WAIT_TIMEOUT)
		MessageBox(NULL, TEXT("timeout zobrazení rekonstrukce") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
					//puts("timeout wiev");
	EnterCriticalSection(&cs_copyBwFFTdata);
	memcpy(bufferAF,odata.data,resolution.cx*resolution.cy*sizeof(bufferAF[0]));
	intenzitaZdroje = odata.intenzitaZdroje;
	LeaveCriticalSection(&cs_copyBwFFTdata);
	ReleaseSemaphore(hSemBwFFT, 1, NULL);

	complex T;
	for(x = 0; x < resolution.cx*resolution.cy; x++){
		T = (*(bufferAF + x));
		pom = pow(pow(T.re,2) + pow(T.im,2),0.5) / intenzitaZdroje;
		if(amax < pom) amax = pom;
		if(amin > pom) amin = pom;
		pom = 3.5 + atan2(T.im,T.re); // je nutne dostat fazi do kladných hodnot + 3.5
		if(fmax < pom) fmax = pom;
		if(fmin > pom) fmin = pom;
	}

	EnterCriticalSection(&cs_show);
	pos = recdata.posit; // poloha pieza
	positF = recdata.positionF;
	positA = recdata.positionA;
	LeaveCriticalSection(&cs_show);

	// prumerovani amplitudy prez cely obrazek
	for(y = 0; y <  resolution.cy; y++)
		for(x = 0; x < resolution.cx; x++){
			T = (*(bufferAF + y * resolution.cx + x));
			Apom += pom = pow(pow(T.re,2) + pow(T.im,2),0.5) / intenzitaZdroje;
			*(bufferA + y * resolution.cx + x) = (unsigned char)(((pom - amin)*255) /(amax - amin));
			pom = 3.5 + atan2(T.im,T.re); // je nutne dostat fazi do kladných hodnot + 3.5
			*(bufferF + y * resolution.cx + x) = (unsigned char)(((pom - fmin)*255) /(fmax - fmin));
			if(bShow3D) *(buffer3d + y * resolution.cx + x) = (unsigned char)(((pom - fmin)*255) /(fmax - fmin));
		}
	ampl += amp = Apom; // ampl - prumerovani amplitudy pres vice snimku, amp prumerna amplituda jednoho snimku
 
	// prumerovani faze prez vyrez
	pom = 0;
	nob = 0; // pocet bodu ktere budou ignorovany pokud vyjde zvoleny vyrez mimo obrazovku
	for(y = positF.cy - vyr; y <  positF.cy + vyr; y++)
		for(x = positF.cx - vyr; x < positF.cx + vyr; x++){
			if(x > resolution.cx || y > resolution.cy || x < 0 || y < 0 ) 
				nob++;
			else{  
				if((y == positF.cy - vyr) || (y == positF.cy + vyr - 1) || (x == positF.cx - vyr) || (x == positF.cx + vyr - 1))			
					*(bufferF + y * resolution.cx + x) = 255;
				T = (*(bufferAF + y * resolution.cx + x));
				pom += atan2(T.im,T.re);
			}
		} 
	faze = pom / (4 * vyr * vyr - nob); // prumerna faze z vyrezu jednoho obrazku
	
	// prumerovani amplitudy pres vyrez , pro hledani maxima intenzity
	pom = 0;
	nob = 0; // pocet bodu ktere budou ignorovany pokud vyjde zvoleny vyrez mimo obrazovku
	for(y = positA.cy - vyr; y <  positA.cy + vyr; y++)
		for(x = positA.cx - vyr; x < positA.cx + vyr; x++){
			if(x > resolution.cx || y > resolution.cy || x < 0 || y < 0) 
				nob++;
			else{  
				if((y == positA.cy - vyr) || (y == positA.cy + vyr - 1) || (x == positA.cx - vyr) || (x == positA.cx + vyr - 1))			
					*(bufferA + y * resolution.cx + x) = 255;
				T = (*(bufferAF + y * resolution.cx + x));
				pom += (pow(pow(T.im,2) + pow(T.re,2),0.5) / intenzitaZdroje);
			}
		} 
	ampv = pom / (4 * vyr * vyr - nob); // prumerna amplituda z vyrezu jednoho obrazku


/*	{ if(FILE *f = fopen("zdroj.txt","a")){
		fprintf(f,"%lf;%lf;%lf\n",intenzitaZdroje,amp,ampv);
		fclose(f);
	}
	} */


	// zobrazeni amplitudy
    wglMakeCurrent(hDCA,hRCA);

	glPixelZoom(1,-1);
	glClear(GL_COLOR_BUFFER_BIT);               // vymazani vsech bitovych rovin barvoveho bufferu
	glDrawBuffer(GL_BACK);                     // pixmapa se bude kreslit do zadniho barvoveho bufferu
	glRasterPos2i(0,0);                        // nastaveni souradnic leveho spodniho rohu pixmapy
	glDrawPixels(                               // vykresleni pixmapy
		resolution.cx, resolution.cy,        // sirka a vyska pixmapy
        GL_LUMINANCE,                             // format dat pixelu
        GL_UNSIGNED_BYTE,                   // datovy typ kazde barevne slozky
        bufferA);                               // ukazatel na pamet s barvami pixelu
		  
    SwapBuffers (hDCA);

	//zobrazeni faze
    wglMakeCurrent(hDCF,hRCF);
	glPixelZoom(1,-1);
    glClear(GL_COLOR_BUFFER_BIT);               // vymazani vsech bitovych rovin barvoveho bufferu
    glDrawBuffer(GL_BACK);                     // pixmapa se bude kreslit do zadniho barvoveho bufferu
	glRasterPos2i(0,0);                        // nastaveni souradnic leveho spodniho rohu pixmapy
	glDrawPixels(                               // vykresleni pixmapy
		resolution.cx, resolution.cy,        // sirka a vyska pixmapy
        GL_LUMINANCE,                             // format dat pixelu
        GL_UNSIGNED_BYTE,                   // datovy typ kazde barevne slozky
        bufferF);                               // ukazatel na pamet s barvami pixelu

    SwapBuffers (hDCF);


	if(bShowAcq){ // zobrazeni nahledu kamery
		if(WaitForSingleObject(hSemShowAcqReady, timeout) == WAIT_TIMEOUT)
			MessageBox(NULL, TEXT("timeout zobrazení náhledu kamery") , TEXT("chyba"), MB_OK | MB_ICONINFORMATION);
						//puts("timeout show-acq");
		memcpy(buffer,data.image,resolutionW.cx*resolutionW.cy*sizeof(buffer[0]));
		if(bStopShowAcq) bShowAcq = FALSE;
		ReleaseSemaphore(hSemShowAcq, 1, NULL); 

		amax = 0, amin = 1e308;
		for(x = 0; x < resolutionW.cx*resolutionW.cy; x++){
			pom = (*(buffer + x));
			if(amax < pom) amax = pom;
			if(amin > pom) amin = pom;
		}

		for(y = 0; y <  resolutionW.cy; y++)
			for(x = 0; x < resolutionW.cx; x++){
				pom = (*(data.image + y * resolutionW.cx + x));
				*(bufferW + y * resolutionW.cx + x) = (unsigned char)(((pom - amin)*255) /(amax - amin));
		}
	

		wglMakeCurrent(hDCW,hRCW);
		glPixelZoom((GLfloat)(resolutionSW.cx/(double)resolutionW.cx), (GLfloat)(-resolutionSW.cy/(double)resolutionW.cy));

		glClear(GL_COLOR_BUFFER_BIT);               // vymazani vsech bitovych rovin barvoveho bufferu
		glDrawBuffer(GL_BACK);                     // pixmapa se bude kreslit do zadniho barvoveho bufferu
		glRasterPos2i(0,0);                        // nastaveni souradnic leveho spodniho rohu pixmapy
		glDrawPixels(                               // vykresleni pixmapy
			resolutionW.cx, resolutionW.cy,        // sirka a vyska pixmapy
			GL_LUMINANCE,                             // format dat pixelu
			GL_UNSIGNED_BYTE,                   // datovy typ kazde barevne slozky
			bufferW);                               // ukazatel na pamet s barvami pixelu

		SwapBuffers (hDCW);
	}

	if(bShowAmp){ // zobrazeni prubehu amplitudy
		if((ampv * akoef > resolutionAA.cy) || ((ampv * akoef < 50) && (ampv != 0))){ 
			// prepocet prumerne amplitudy podle posledniho mereni tak aby se do grafu vesla maximalni hodnota
			double tmp = akoef;
			akoef =  (0.5 * resolutionAA.cy) / ampv;
			for(x = 0; x < resolutionAA.cx; x++ ){
			 *(bufferAAd + x) = *(bufferAAd + x) * akoef / tmp;
			}
		}
		*(bufferAAd + resolutionAA.cx - 1) = ampv * akoef;
		*(bufferAFd + resolutionAA.cx - 1) = ((faze + 3.5)/(3.5 + 3.14))* resolutionAA.cy;
		for(x = 0; x < resolutionAA.cx - 1; x++ ){
			*(bufferAAd + x) = *(bufferAAd + x + 1);
			*(bufferAFd + x) = *(bufferAFd + x + 1);
			for(y = 0; y < resolutionAA.cy; y++ ){
				*(bufferAA + y * 3 * resolutionAA.cx + 3 * x + 1 - 1) = 0;		// smazani bodu amplitudy
				*(bufferAA + y * 3 * resolutionAA.cx + 3 * x + 0 - 1) = 0;		// smazani bodu faze
			}
			// pro amplitudu
			if(*(bufferAAd + x) > resolutionAA.cy) 
				*(bufferAA + 3 * x) = 255;
			else
				*(bufferAA + (resolutionAA.cy - 1 - (unsigned char)*(bufferAAd + x))* 3 * resolutionAA.cx + 3 * x + 1 - 1 ) = 255;
			//pro fazi
			*(bufferAA + (resolutionAA.cy - 1 - (unsigned char)*(bufferAFd + x))* 3 * resolutionAA.cx + 3 * x + 0 - 1 ) = 255;
		}
		wglMakeCurrent(hDCAA,hRCAA);
		glPixelZoom(1,-1);
		glClear(GL_COLOR_BUFFER_BIT);               // vymazani vsech bitovych rovin barvoveho bufferu
		glDrawBuffer(GL_BACK);                     // pixmapa se bude kreslit do zadniho barvoveho bufferu
		glRasterPos2i(0,0);                        // nastaveni souradnic leveho spodniho rohu pixmapy
		glDrawPixels(                               // vykresleni pixmapy
			resolutionAA.cx, resolutionAA.cy,        // sirka a vyska pixmapy
			GL_RGB,//GL_LUMINANCE,                             // format dat pixelu
			GL_UNSIGNED_BYTE,                   // datovy typ kazde barevne slozky
			bufferAA);                               // ukazatel na pamet s barvami pixelu

		SwapBuffers (hDCAA);
	}

	//zobrazeni 3D nahledu
	if(bShow3D){
		//naplnit pole pro zobrazeni
		for(y = 0; y < resolution.cy; y++)
			for(x = 0; x < resolution.cx; x++){
				*(X + y * resolution.cx + x) = 1.5 * (double)x / resolution.cx - 0.75;
				*(Y + y * resolution.cx + x) = *(buffer3d + y * resolution.cx + x) / 255. - 0.5;
				*(Z + y * resolution.cx + x) = 1.5 * (double)y / resolution.cy - 0.75;
				*(barva + y * resolution.cx + x) = *(buffer3d + y * resolution.cx + x) / 255.;
			}
		wglMakeCurrent(hDC3D,hRC3D);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glDrawBuffer(GL_BACK);
		//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
		//glEnable(GL_BLEND);// Zapne blending
		//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// Typ blendingu
		glLoadIdentity();
		glFrustum(0, resolution.cx,resolution.cy,0, -1, 1);
		//glPixelZoom(-1,-1);
		//glTranslatef(py*0.01,pz*0.01,.0f);
		//glCullFace(GL_FRONT);   
		//glEnable(GL_CULL_FACE);  
		glRotatef(px,1.0f,0.0f,0.0f); // rotace kolem osy ktera je 1.0
		glRotatef(py,0.0f,1.0f,0.0f); // rotace kolem osy ktera je 1.0
		glRotatef(pz,0.0f,0.0f,1.0f); // rotace kolem osy ktera je 1.0
		//glEnable(GL_LINE_SMOOTH);
		glScalef(zoom,zoom,zoom);
			double a = 0.75;
			//spodni
			glBegin(GL_LINE_LOOP);
				glColor3f(255,0,0);
			    //glNormal3f(0.0,-1.0,0.0);   
			    glVertex3f(-a,-a,-a);   
				glVertex3f(a,-a,-a);   
				glVertex3f(a,-a,a);   
				glVertex3f(-a,-a,a); 
			glEnd();
			//zadni
			glBegin(GL_LINE_LOOP);
				glColor3f(0,255,0);
			    //glNormal3f(0.0,0.0,-1.0);   
				glVertex3f(-a,a,-a);   
				glVertex3f(a,a,-a);   
				glVertex3f(a,-a,-a);   
				glVertex3f(-a,-a,-a);   
			glEnd();   
			//prava
			glBegin(GL_LINE_LOOP);   
				glColor3f(0,0,255);
			    //glNormal3f(1.0,0.0,0.0);   
				glVertex3f(a,a,a);   
				glVertex3f(a,-a,a);   
				glVertex3f(a,-a,-a);   
				glVertex3f(a,a,-a);   
			glEnd();   

		for(y = 0; y < resolution.cy-1; y++)
			for(x=0; x < resolution.cx-1; x++){
				glBegin(GL_QUADS);//GL_LINE_LOOP);
					glColor3f(*(barva + y * resolution.cx + x),0,1-*(barva + y * resolution.cx + x));
					glVertex3f(*(X + y * resolution.cx + x),*(Y + y * resolution.cx + x),*(Z + y * resolution.cx + x));
      				//glColor3f(0.0f,1.0f,0.0f);
					glVertex3f(*(X + (y+1) * resolution.cx + x),*(Y + (y+1) * resolution.cx + x),*(Z + (y+1) * resolution.cx + x));
       				//glColor3f(0.0f,0.0f,1.0f);
					glVertex3f(*(X + (y+1) * resolution.cx + x + 1),*(Y + (y+1) * resolution.cx + x + 1),*(Z + (y+1) * resolution.cx + x + 1));
       				//glColor3f(0.0f,1.0f,1.0f);
					glVertex3f(*(X + y * resolution.cx + x + 1),*(Y + y * resolution.cx + x + 1),*(Z + y * resolution.cx + x + 1));
				glEnd();
			}
			glBegin(GL_LINES);
				glColor3f(0,0,255);
				glVertex3f(0.0,0.0,0.0);
				glVertex3f(0.2,0.0,0.0);
				glColor3f(255,0,0);
				glVertex3f(0.0,0.0,0.0);
				glVertex3f(0.0,0.2,0.0);
				glColor3f(0,255,0);
				glVertex3f(0.0,0.0,0.0);
				glVertex3f(0.0,0.0,0.2);
			glEnd();

		SwapBuffers(hDC3D);
	}

	if(bSaveImag){ // ukladani obrazku
		bSaveImag = FALSE;
		char fn[255];
		if(inidata.SimAF){
			sprintf_s(fn,255,".\\amplituda\\%04d.tif",picture);
			TiffWrite ( FALSE,resolution,(void *)bufferA,fn);
			sprintf_s(fn,255,".\\faze\\%04d.tif",picture);
			TiffWrite ( FALSE,resolution,(void *)bufferF,fn);
		}
		if(bShowAcq){
			sprintf_s(fn,255,".\\zdroj\\%04d.tif",picture);
			TiffWrite ( TRUE,resolutionW,(void *)buffer,fn);
		}
		if(inidata.Scpx){
			sprintf_s(fn,255,".\\komplexni\\%04d.cpx",picture);
			RawWrite(resolution,bufferAF,fn);
			{	
			sprintf_s(fn,255,".\\komplexni\\%04d.cpd",picture);
			FILE *fw = NULL;
			char timebuf[50];
			if(fw = fopen(fn,"w")){
				time_t cas;
				time(&cas);
				ctime_s(timebuf, 50, &cas);
				int cc=0;
				while(timebuf[cc]!=0)
					cc++;
				timebuf[cc-1]=0;
				fprintf(fw,"cas;intenzita_Zdroje;prumerna_amplituda_ve_vyrezu;prumerna_amplituda;max_amplituda;min_amplituda;prumerna_faze_ve_vyrezu;pozice_vyrezu_faze_x;y;pozice_vyrezu_amplitudy_x;y,piezo\n");
				fprintf(fw,"%s;%lf;%lf;%lf;%lf;%lf;%lf;%d;%d;%d;%d;%d",timebuf,intenzitaZdroje,ampv,amp,amax,amin,faze,positF.cx,positF.cy,positA.cx,positA.cy,pos);
				fclose(fw);
				}
			}

		}
		picture++;
	}
	
	// regulace+
	if(bRegulace) {
			pos = maximumA.offset - (int)(50 * UpdatePID(&regulator,regulator.stabPha - faze,faze));
/*			if(FILE *f = fopen("log.txt","a")){
			fprintf(f,"%d\n",maximumA.offset);
			fclose(f);}*/
			if(pos < -32768 || pos > 32768)
				bRegulace = FALSE;
			else
				outCom(pos,pos);
	}

	//detekce maximalni amplitudy
	if(bMaximumA) {
		if(int prvek = UpdateAmax(&maximumA,ampv,faze)){
			bMaximumA = FALSE;
			regulator.stabPha = faze;
			bRegulace = TRUE;
			//MessageBox(NULL, TEXT("dosazeno maximum amplitudy") , TEXT("info"), MB_OK | MB_ICONINFORMATION);
		} else {
			pos = maximumA.offset = maximumA.offset + (50 * maximumA.koef);
			outCom(pos,pos);
		}
	} 

	count++;
	aver += (clock() - tstart);
	if(count == inidata.fpsrefr){
		average = count/(aver*1e-3);
		amplitude = ampl/(resolution.cx*resolution.cy*count); 
		count = 0;
		aver = 0;
		ampl = 0;
		EnterCriticalSection(&cs_show);
		recdata.fps = average;  // snimky za sec
		recdata.avampl = amplitude; // prumerna amplituda
		recdata.phase = faze; // prumerna faze z vyrezu
		recdata.posit = pos; // poloha pieza
		LeaveCriticalSection(&cs_show);
	}
 }  

//(2*3.14*maximumA.cntFF+faze)/(2*3.14/547*(1+cos(asin(0.25))));

void setpiezo(int data)
{
	//if(data > 32768) data = 65535 - data; // docasna uprava protoze tu nemam borland c++
	if(data > -1 && data < 65536) {
		bRegulace = bMaximumA = FALSE;
		EnterCriticalSection(&cs_show);
		recdata.posit = maximumA.offset = data - 32768; // poloha pieza
		LeaveCriticalSection(&cs_show);
		outCom(data - 32768,data - 32768);
	}
	return;
}

double getfps()
{	
	double fps = 0;
	if(bRunShowRec) {
		EnterCriticalSection(&cs_show);
		fps = recdata.fps;
		LeaveCriticalSection(&cs_show);
	};
	return fps;
}

double getavampl() // vraci prumernou amplitudu
{	
	double ampl = 0;  
	if(bRunShowRec) {
		EnterCriticalSection(&cs_show);
		ampl = recdata.avampl;
		LeaveCriticalSection(&cs_show);
	};
	return ampl;
}

double getavpha() // vraci prumernou fazi
{	
	double pha = 0;
	if(bRunShowRec) {
		EnterCriticalSection(&cs_show);
		pha = recdata.phase;
		LeaveCriticalSection(&cs_show);
	};
	return pha;
}

int getavpos()
{	
	int pos = 0;
	if(bRunShowRec) {
		EnterCriticalSection(&cs_show);
		pos = recdata.posit + 32768;
		LeaveCriticalSection(&cs_show);
	};
	return pos;
}


int SetClientRect(HWND hWnd, int width,int height){

	RECT rcWindow, rcClient;
	int difWidth, difHeight;

	GetWindowRect(hWnd, &rcWindow);
	GetClientRect(hWnd, &rcClient);

	difWidth = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
	difHeight = (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);

	return MoveWindow(hWnd, rcWindow.left, rcWindow.top, width + difWidth, height + difHeight, TRUE);
}

SIZE GetWindowPos(HWND hWnd){
	RECT rect;
	SIZE pos;
	//long dwWindowPos;
	GetWindowRect(hWnd, &rect);
	//dwWindowPos = MAKELONG(rect.left, rect.top);
	//MessageBox(NULL, TEXT("test") , TEXT("test"), MB_OK | MB_ICONINFORMATION);
	pos.cx = rect.left;
	pos.cy = rect.top;
	return pos;
}
 
DWORD WINAPI ShowRecProc(LPVOID)
{
    /* register window class */
    wc.style = CS_OWNDC;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = szWinName;
    RegisterClass (&wc);



	//BOOL FirstCycle = TRUE;
	int ret = 0;

	bRunShowRec = TRUE;

	WaitForSingleObject(hSemBwFFTReady, 30000); // nastaveni velikosti okna + alokace pole pro zobrazovana data
	EnterCriticalSection(&cs_copyBwFFTdata);
	resolution = odata.resolution;
	LeaveCriticalSection(&cs_copyBwFFTdata);
	ReleaseSemaphore(hSemBwFFT, 1, NULL);

	EnterCriticalSection(&cs_copyRawdata);
	resolutionW = data.resolution; // nastaveni rozliseni nahledu kamery
	LeaveCriticalSection(&cs_copyRawdata);
	resolutionSW = inidata.showacqxy;
	resolutionAA = inidata.showampxy;

	bufferAF = (complex *)malloc(resolution.cx*resolution.cy * sizeof(complex)); 	// bufer rekonstruovane faze a amplitudy
	bufferF = (unsigned char *)calloc(resolution.cx*resolution.cy,sizeof(char)); 	// zobrazeni rekonstrukce faze
	buffer3d = (unsigned char *)calloc(resolution.cx*resolution.cy,sizeof(char)); 	// zobrazeni rekonstrukce 3d
	bufferA = (unsigned char *)calloc(resolution.cx*resolution.cy,sizeof(char)); 	// zobrazeni rekonstrukce amplitudy
	bufferW = (unsigned char *)calloc(resolutionW.cx*resolutionW.cy,sizeof(char)); 	// online zobrazeni poledu kamery
	bufferAA = (unsigned char *)calloc(3*resolutionAA.cx*resolutionAA.cy,sizeof(char)); 	// bufer pro zobrazovani grafu amplitudy
	bufferAAd = (double *)calloc(resolutionAA.cx,sizeof(double)); 	// bufer dat pro vypocet obrazku v bufferu AA
	bufferAFd = (double *)calloc(resolutionAA.cx,sizeof(double)); 	// bufer dat pro vypocet obrazku v bufferu AF
	buffer = (LPWORD)calloc(resolutionW.cx*resolutionW.cy,sizeof(buffer[0])); 	
	//3D rekonstrukce
	X = (double *)malloc(resolution.cx*resolution.cy*sizeof(double));
    Y = (double *)malloc(resolution.cx*resolution.cy*sizeof(double));
    Z = (double *)malloc(resolution.cx*resolution.cy*sizeof(double));
    barva = (double *)malloc(resolution.cx*resolution.cy*sizeof(double));



	    /* create windows */
	
	swprintf(szAppName,255,L"rekonstrukce amplituda - rozměr x = %d, y = %d",resolution.cx,resolution.cy);
    hWndA = CreateWindow (
      szWinName,szAppName, 
      WS_CAPTION | WS_VISIBLE,
	  inidata.posrecA.cx, inidata.posrecA.cy, resolution.cx, resolution.cy,
      NULL, NULL, hInstance, NULL);

	SetClientRect(hWndA,resolution.cx,resolution.cy);

	swprintf(szAppName,255,L"rekonstrukce fáze - rozměr x = %d, y = %d",resolution.cx,resolution.cy);
	hWndF = CreateWindow (
      szWinName,szAppName, 
      WS_CAPTION | WS_VISIBLE,
	  inidata.posrecF.cx, inidata.posrecF.cy, resolution.cx, resolution.cy,
      NULL, NULL, hInstance, NULL);

	SetClientRect(hWndF,resolution.cx,resolution.cy);

	swprintf(szAppName,255,L"kamera - rozměr zobrazení x = %d, y = %d - rozměr snímání x = %d, y = %d",resolutionSW.cx,resolutionSW.cy,resolutionW.cx,resolutionW.cy);
	hWndW = CreateWindow (
      szWinName,szAppName, 
      WS_CAPTION, //| WS_POPUPWINDOW, //| WS_VISIBLE,
	  inidata.poscam.cx, inidata.poscam.cy, resolutionSW.cx, resolutionSW.cy,
      NULL, NULL, hInstance, NULL);

	SetClientRect(hWndW,resolutionSW.cx,resolutionSW.cy);

	swprintf(szAppName,255,L"pruběh průměrné amplitudy(č) a fáze(m)");
	hWndAA = CreateWindow (
      szWinName,szAppName, 
      WS_CAPTION, //| WS_POPUPWINDOW, //| WS_VISIBLE,
	  inidata.posampl.cx, inidata.posampl.cy, resolutionAA.cx, resolutionAA.cy,
      NULL, NULL, hInstance, NULL);

	SetClientRect(hWndAA,resolutionAA.cx,resolutionAA.cy);

	swprintf(szAppName,255,L"3D náhled bez navázání fáze");
	hWnd3D = CreateWindow (
      szWinName,szAppName, 
      WS_CAPTION, //| WS_POPUPWINDOW, //| WS_VISIBLE,
	  inidata.posrec3D.cx, inidata.posrec3D.cy, 100, 100,
      NULL, NULL, hInstance, NULL);

	SetClientRect(hWnd3D,resolution.cx,resolution.cy);


	if(bShowAcq) ShowWindow(hWndW, SW_RESTORE); // zobrazeni okna kamery pokud je treba 
	if(bShowAmp) ShowWindow(hWndAA, SW_RESTORE); // zobrazeni okna prumerne amplitudy
	if(bShow3D) ShowWindow(hWnd3D, SW_RESTORE); // zobrazeni okna 3D

	EnterCriticalSection(&cs_show);
	recdata.positionF = inidata.posavF;
	recdata.positionA = inidata.posavA;
	LeaveCriticalSection(&cs_show);
	

	maximumA.pocethodnot = 0;
	maximumA.koef = 1;
	maximumA.offset = 0;
	maximumA.tmpA = 0;
	maximumA.cntFF = 0;

	initComport(TEXT("COM1")); // otevreni portu com


	//skryti oken v taskbaru

	//ShowWindow(FindWindow(TEXT("Shell_TrayWnd"), NULL), SW_SHOW);

	/* enable OpenGL for the window */
	EnableOpenGL (hWndA, &hDCA, &hRCA);

	EnableOpenGL (hWndF, &hDCF, &hRCF);

	EnableOpenGL (hWndW, &hDCW, &hRCW);

	EnableOpenGL (hWndAA, &hDCAA, &hRCAA);

	EnableOpenGL (hWnd3D, &hDC3D, &hRC3D);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);       // barva pozadi
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);      // mod ulozeni pixelu

	while (!bQuit)
    {
		/* check for messages */
        if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        {
            /* handle or dispatch messages */
				if(msg.message == WM_QUIT)
					bQuit = TRUE;

				if(msg.hwnd == hWndF) {		// obsluha udalosti okna faze
								switch(msg.message){

									case WM_LBUTTONDOWN: 
										POINTS ptMouse;
										ptMouse = MAKEPOINTS(msg.lParam);
										EnterCriticalSection(&cs_show);
										recdata.positionF.cx = ptMouse.x;
										recdata.positionF.cy = ptMouse.y;
										inidata.posavF = recdata.positionF;
										LeaveCriticalSection(&cs_show);
										break;

									case WM_RBUTTONDOWN: 
										regulator.stabPha = 0;
										break;

									case WM_MBUTTONDOWN:
										EnterCriticalSection(&cs_show);
										recdata.positionF.cx = resolution.cx / 2;
										recdata.positionF.cy = resolution.cy / 2;
										inidata.posavF = recdata.positionF;
										LeaveCriticalSection(&cs_show);
										break;
																							 
									default:
										TranslateMessage (&msg);
										DispatchMessage (&msg);
									
								}							
				} else

				if(msg.hwnd == hWndA) {		// obsluha udalosti okna amplitudy
								switch(msg.message){

									case WM_LBUTTONDOWN: 
										POINTS ptMouse;
										ptMouse = MAKEPOINTS(msg.lParam);
										EnterCriticalSection(&cs_show);
										recdata.positionA.cx = ptMouse.x;
										recdata.positionA.cy = ptMouse.y;
										inidata.posavA = recdata.positionA;
										LeaveCriticalSection(&cs_show);
										break;

									case WM_RBUTTONDOWN: 
										bRegulace = FALSE; // zastaveni regulace
										maximumA.pocethodnot = 0;
										maximumA.cntFF = 0;
										maximumA.koef = 1;
										maximumA.offset = recdata.posit;
										recdata.positionF = recdata.positionA;
										maximumA.tmpA = 0;
										bMaximumA = TRUE; // spusteni hledani maxima amlitudy
										break;

									//case WM_MOUSEHWHEEL:

									default:
										TranslateMessage (&msg);
										DispatchMessage (&msg);
									
								}	
				} else

				if(msg.hwnd == hWnd3D) {		// obsluha udalosti okna 3D
								switch(msg.message){

									case WM_KEYDOWN: 
										switch(msg.wParam){
											case 49 :
												pz = pz + 5;
												break;
											case 50 :
												pz = pz - 5;
												break;
											case 51 :
												py = py + 5;
												break;
											case 52 :
												py = py - 5;
												break;
											case 53 :
												px = px + 5;
												break;
											case 54 :
												px = px - 5;
												break;
											case 55 :
												zoom = zoom + 0.1;
												break;
											case 56 :
												zoom = zoom - 0.1;
												break;
										}
										//break;

									default:
										TranslateMessage (&msg);
										DispatchMessage (&msg);
									
								}						
				}else
					{
					TranslateMessage (&msg);
					DispatchMessage (&msg);
					}

		}
        else
        {
		  ShowImages(); // zpracovani obrazu vysledku
		}
    }

	// ulozeni polohy oken

	/* shutdown OpenGL */
    DisableOpenGL (hWndA, hDCA, hRCA);
    DisableOpenGL (hWndF, hDCF, hRCF);
    DisableOpenGL (hWndW, hDCW, hRCW);
    DisableOpenGL (hWndAA, hDCAA, hRCAA);
    DisableOpenGL (hWnd3D, hDC3D, hRC3D);

	inidata.posrecA = GetWindowPos(hWndA);
	inidata.posrecF = GetWindowPos(hWndF);
	inidata.poscam = GetWindowPos(hWndW);
	inidata.posampl = GetWindowPos(hWndAA);
	inidata.posrec3D = GetWindowPos(hWnd3D);

	/* destroy the window explicitly */
    DestroyWindow (hWndA);
    DestroyWindow (hWndF);
    DestroyWindow (hWndW);
    DestroyWindow (hWndAA);
    DestroyWindow (hWnd3D);

	free(bufferAF);
	free(bufferA);
	free(bufferF);
	free(buffer3d);
	free(bufferW);
	free(bufferAA);
	free(bufferAAd);
	free(bufferAFd);
	free(buffer);
	closeComport();	 // uzavreni portu com pokud byl pouzit
	bHaltedShowRec = TRUE;
	hShowRecThread = NULL;

	return ret;

}

BOOL shStartShowRec()
{

BOOL	ret = FALSE;
DWORD	ThreadId;

	if (bRunShowRec) goto ex;
	
	//hSemBwFFT = CreateSemaphore (NULL, 0, 1, NULL);
	//hSemBwFFTReady = CreateSemaphore (NULL, 0, 1, NULL);

	InitializeCriticalSection(&cs_show);

	bShowAmp = inidata.showamp;
	bRegulace = inidata.regulace;
	bShow3D = inidata.rec3d;

	bHaltedShowRec = FALSE;
	hShowRecThread = CreateThread( NULL, 0, ShowRecProc, NULL, 0, &ThreadId);
	
	if (hShowRecThread==NULL) goto ex;

	while(!bRunShowRec && !bHaltedShowRec) 
 		Sleep(5);

	//ReleaseSemaphore(hSemBwFFT, 1, NULL); // zpracovani prvni FwFFT

	ret = bRunShowRec; 
ex:
	return ret;
}

void shStopShowRec()
{
	if (!bRunShowRec || hShowRecThread==NULL) return;

	bRunShowRec = FALSE;
	bQuit = TRUE;
	//ReleaseSemaphore(hSemBwFFT,1,NULL); // ukonceni nacitani  

	WaitForSingleObject( hShowRecThread, 1000 ); // cekani na ukonceni vlakna

	CloseHandle(hShowRecThread);
	//CloseHandle(hSemBwFFT);
	//CloseHandle(hSemBwFFTReady);

	return;
}


void ShowCam(int input) // spusteni zobrazovani primo z kamery
{ 
	inidata.showacq = input;
	switch(input){
	case 0: if(bShowAcq){
				bStopShowAcq = TRUE;
				ShowWindow(hWndW, SW_HIDE); // skryti okna
				break;
			}
	case 1: if(!bShowAcq){
				bStopShowAcq = FALSE;
				bShowAcq = TRUE;
				ShowWindow(hWndW, SW_RESTORE); // zobrazeni okna
				break;
			}
	}
	return;
}

int gShowCam()
{
	return bShowAcq;
}

void ShowAmpl(int input)
{
	if(input != bShowAmp){
		inidata.showamp = input;
		if(input) 
			ShowWindow(hWndAA, SW_RESTORE);
		else
			ShowWindow(hWndAA, SW_HIDE);
		bShowAmp = input;
	}
	return;
}


int gShowAmpl()
{
	return bShowAmp;
}

void SaveData()
{
	bSaveImag = TRUE;
}

int gShow3D()
{
	return bShow3D;
}

void Show3D(int input)
{
	if(input != bShow3D){
		inidata.rec3d = input;
		if(input) 
			ShowWindow(hWnd3D, SW_RESTORE);
		else
			ShowWindow(hWnd3D, SW_HIDE);
		bShow3D = input;
		}
	return;
}


void DoRegulace(int input)
{
	if(input != bRegulace){
		inidata.regulace = input;
		bRegulace = input;
	}
	return;
}
int gRegulace()
{
	return bRegulace;
}



void initialize(){
	setting();

	fftw_init_threads();  //inicializace fft
	fftw_plan_with_nthreads(inidata.threads);
}

void start(){	
	if(shStartAcq()){
		if(shStartFwFFT()){
			if(shStartBwFFT()){
				shStartShowRec();
			}
		}
	}
 }

void deinitialize(){
	savesetting();
}

void stop(){
	shStopShowRec();
	shStopBwFFT();
	shStopFwFFT();
	shStopAcq();
 }
