/*		Acquisition Program for IPM Princeton CCDs - MASTER PC

		Author: Emanuele Ceracchi

		INFO berrilli@roma2.infn.it - cantarano@roma2.infn.it

		Version 1.2  C/C++ MS DS 97 v5.0
		Last Modification 09/17/2000


		history

		v1.0 implemented in Rome "Tor Vergata" University during the laboratory test phase.

		v1.1 connection with the HP9000 Series 700i IPM server.
			 
		v1.2 running test in observational configuration.

*/
		
extern "C" {
#define PIXCM 1 
#include "platform.h" //Contains the Declarations & Enumerators for the different platforms.(i.e. SUN,Mac,Win98,Win NT)
#include "pigendef.h" //Contains the Declarations & Enumerators for the simple dll
#include "pigenfcn.h" //Contains the Declarations for the simple dll
#include "piimgdef.h" //ROI definition
#include "piimgfcn.h" //ROI functions
#include "pishtdef.h" //PI controller DLLs external defintion and define file shutter operations
#include "pishtfcn.h" //PI controller DLLs external defintion shutter operations.
#include "pivardef.h" //Contains the Declarations for PI variables functions
#include "pivarfcn.h" //Contains the Declarations for variable functions
#include "pividdef.h" //PI controller Video routines (RS170)
#include "pimltfcn.h" //Multiple frame collection
#include "pitimdef.h" //Timing mode definition
#include "pitimfcn.h" //Timing mode function
#include "pifcsfcn.h" //Contains the Declarations for the simple dll skipping operations
#include "pifcsdef.h" //Contains the Declarations & Enumerators for the simple dll
}

#include "stdio.h"
#include "stdlib.h"
#include "time.h"     
#include "fstream.h" 
#include "string.h" 
#include "conio.h"
#include "direct.h"
#include "dos.h"
#include "math.h"
#include "io.h"
#include "share.h"

#include <Windows.h>
#include <Wininet.h>

#define LGMSG 0x100			// 256 : socket message max dimension
#define NPIX 262144			//512X512
#define DIMX 512			//Pixel image dimension
#define DIMY 512			//Pixel image dimension


void short_initccd(void);
void initccd(void);
void buio(void);
void saveimm(void);
void word(void);
void foto(void);
void fast(void);
void statistica(void);
void time(void);
void acqlog(void);
void err(void);
void fine(void);
void ritardo(int);
void risposta(void);
int  iniz_socket(void);
void InitFtp(void);
void saveimm2ftp(void);

long shbuffer_size;		  //Imaage buffer dimension
int shcontroller_ok;	  //Status code for the PI initialization routine
int DONE_FLAG;            //Flag for data collection
int TEXP=0;               //exposure time (ms)
int TESTWR;				  //fflush flag
int S;					  //Delay counter 
unsigned short port = 3002; //Socket port number
unsigned int STATUS;      //Used for status of PICM_ChkData
unsigned int ERROR_CODE;  //If status is false, this holds error
short IMM0[NPIX];         //Image buffer
short huge *LPVBUFFER=0;  //Image pointer to the memory 
short MIN_IMA,MAX_IMA;    //Image minimum & maximum
double TEXPSEC=0;		  //exposure time (s)
double AVG,RMS;           //Image average & rms
char PATH[59]={0};		  //Image disk path
char ERRORSTRING[60]={0}; //Error string
char RECORD[120]={0};     //"acq.log" record (path,data,texp,avg....) 
char DATIME[30]={0};      //Date & time
char PIERROR[6]={0};      //PI functions error code
char c;                   //For DEBUG and GETCH
char *arcetri  = "192.168.2.102"; // IPM Server IP number
char msg[LGMSG];          //Message from/to HP 9000

FILE *ALOG;               //Pointer to the "acq.log" file
FILE *FileList;

SOCKET sock;

static HANDLE shglb;	  //

HINTERNET InetSession, FtpSession;
char FileName[59]={0};
char FTPPATH[30]={0};


//*********************************************************************
//*********************************************************************
//		Main program
//*********************************************************************
//*********************************************************************	

void main(void)

{
	   
   cout<<"                      THEMIS-IPM CCD 2 WL acquisition program"<<endl;
   cout<<"                Dep. of Physics - University of Rome 'Tor Vergata'"<<endl;
   ALOG=fopen("c:\\test\\pc2_wl_acq.log","atc");         //apre l'acq.log 
   if (ALOG==0)
     {
       strcpy(ERRORSTRING,"@@@ ERROR @@@ Can't open Log file @@@"); //torna un errore se non riesce ad aprire il file
	   cout<<ERRORSTRING<<endl;
	   strcpy(ERRORSTRING,"");
	   fine();
     }		
   fputs("\n\n**************** S T A R T  P R O G R A M *************** \n\t\t      ",ALOG);
   time();
   fputs(DATIME,ALOG); //salva nell'Acq.log data e ora dell'inizio del programma
   fputs("\n********************************************************* \n\n",ALOG);
   cout<<"                            "<<DATIME<<endl<<endl;
   initccd();    /* PentaMax initialisation  */
   sock = iniz_socket();  /* socket initialisation  */

   InitFtp();
   if (!(FileList = fopen("c:\\test\\files_on_disk.lis","atc")))
	   printf("Errore in apertura file lista\n");
   sprintf(FTPPATH,"%s","/data/themis/test_ftp/");

   word();

}																								

//*********************************************************************
//*********************************************************************
//          PentaMax CCD Initialization Procedure
//*********************************************************************
//*********************************************************************	

void initccd(void)  
{	
	
   void ccderror(void);
	
   int controller_ok;		//ritorno delle funzioni Princeton
   long buffer_size;		//dimensioni del buffer dell'immagine
   static HANDLE hglb;		//
   
   cout<<"                              * I N I T   W L   C C D *"<<endl;

	//Create and Initialize controller object
   controller_ok=PICM_CreateController(DC131,KDK_1035x1317,ROM_FULL,APP_NORMAL_IMAGING,&ERROR_CODE);
   if (controller_ok!=1)
	 {
		strcpy(ERRORSTRING,"@@@ CCD ERROR @@@ Create contoller    error ");
        ccderror();
		fine();
	 }

	//Set type of PC PI-interface card used. This will also set the ADC defaults     
   controller_ok=PICM_SetInterfaceCard(PCI_COMPLEX_PC_Interface,0x0d00,CHANNEL_10,&ERROR_CODE);
   if (controller_ok!=1)
	 {
		strcpy(ERRORSTRING,"@@@ CCD ERROR @@@ Set interface card    error ");
        ccderror();
	    fine();
	 }
   
   //This function will set the fast ADC avaiable in controller.
   PICM_Set_Fast_ADC();
   
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@	
   //In modalita' MASTER commentare la funzione 
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   //PICM_Set_acqmode(CTRL_EXTSYNC_NORMAL);  //Configura la camera ad acquisire mediante un trigger esterno
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	
   //Set ROI for image, If this function is not called full image is default. 
   //this allows a sub-region and/or a grouped/binned image to be collected.  
   controller_ok=PICM_SetROI(146,5,1169,1028,2,2,&ERROR_CODE);
   if (controller_ok!=1)
	 {
		strcpy(ERRORSTRING,"@@@ CCD ERROR @@@ Set ROI    error ");
        ccderror();
	    fine();
	 }
   
   //This function returns the amount of memory the user should allocate to 
   //hold all of his data.
   buffer_size=PICM_SizeNeedToAllocate();
   hglb=GlobalAlloc(GPTR, buffer_size);
   LPVBUFFER=(short huge*) GlobalLock(hglb);
   
//   PICM_Set_shuttermode(SHUTTER_CLOSE);   //Configura lo shutter in modalita' non "manuale"
   PICM_Set_shuttermode(SHUTTER_NORMAL);  //Physically open or close shutter: condition may be OPEN or CLOSE
   PICM_Set_controller_version(5);        //Configura la versione del controller
   PICM_Set_RS170_enable(TRUE);           //Abilita la modalita' RS170
   PICM_CMSetLongParam(CMP_VIDEO_TYPE, 2);//Abilita' la visualizzazione sul monitor

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@	
   //In modalita' SLAVE commentare la funzione 
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   PICM_CMSetLongParam(CMP_LOGIC_OUTPUT,SHUTTER); //Configura il Logic Out a generare un gradino all'apertura dello shutter
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   
   //This function downloads all information to controller It sets up the    
   //dma buffers, ring buffer, and the users buffer. It also hooks in the     
   //interrupt routine used by data collection.
   controller_ok=PICM_Initialize_System(LPVBUFFER,&ERROR_CODE);
   if (controller_ok!=1)
	 {
		strcpy(ERRORSTRING,"@@@ CCD ERROR @@@ Initialize System    error ");
        ccderror();
		fine();
	 }
   PICM_Set_shuttermode(SHUTTER_NORMAL);  //Physically open or close shutter: condition may be OPEN or CLOSE

   cout<<"                  * I N I T   W L  C C D  2  S U C C E S S F U L *"<<endl<<endl;
}

//*********************************************************************
//*********************************************************************
//          Fast PentaMax CCD initialization procedure
//*********************************************************************
//*********************************************************************	

void short_initccd(void)  //Inizializza la CCD
{	
	
   void ccderror(void);
	
   int controller_ok; //ritorno delle funzioni Princeton
   
   //This function down loads all information to controller It sets up the    
   //dma buffers, ring buffer, and the users buffer. It Also hooks in the     
   //interrupt routine used by data collection.

   controller_ok=PICM_Initialize_System(LPVBUFFER,&ERROR_CODE);
   if (controller_ok!=1)
	 {
		strcpy(ERRORSTRING,"@@@ CCD ERROR @@@ Initialize System    error ");
        ccderror();
		fine();
	 }
}


//*********************************************************************
//*********************************************************************
//          ERROR output procedure
//*********************************************************************
//*********************************************************************	


void ccderror(void)  //Visualizza a video e salva nell'acq.log un errore riscontrato nelle funzioni Princeton
					
{
   sprintf(PIERROR,"%d",ERROR_CODE); 
   strcat(ERRORSTRING,PIERROR);
   strcat(ERRORSTRING,"\n");
   fputs(ERRORSTRING,ALOG); //Salva nel Log file la stringa di errore con il relativo codice
   TESTWR=1;
   while (TESTWR!=0) 
      TESTWR=fflush(ALOG);  //Forza la scrittura dell'Acq.log
   cout<<ERRORSTRING<<endl; //Visualizza a video la stringa di errore
   strcpy(ERRORSTRING,"");
   strcpy(PIERROR,"");
}

//*********************************************************************
//*********************************************************************	 
//          Acquisition mode management procedure
//*********************************************************************
//*********************************************************************	

void word(void)  //Carica l'action word dal foto.ini e identifica l'azione da compiere
{
   int i;            //Flag di errore 1=OK 0=Error
   int n;			// length of string
   int cont1;		 //
   int flag_azione;  //Flag azione=1 ok, =0 wait
   char word[7]={0}; //Contiene l'action word



   while(1) 

   {
   	   //alloca spazio in memoria per l'immagine//
		shbuffer_size=PICM_SizeNeedToAllocate();
		shglb=GlobalAlloc(GPTR, shbuffer_size);
		LPVBUFFER=(short huge*) GlobalLock(shglb);

		shcontroller_ok=PICM_Initialize_System(LPVBUFFER,&ERROR_CODE);
		if (shcontroller_ok!=1)
		{
			strcpy(ERRORSTRING,"@@@ CCD ERROR @@@ Initialize System    error ");
			ccderror();
			fine();
		}
	    i=0;
	    cont1=0;
	    PATH[59]='\0';
		strcpy (word,"");
		word[6]='\0';

        // polling su rete tramite socket
	    n = recv(sock, msg, LGMSG, 0);
	    msg[n] = 0;
        //printf("%s %d\n",msg,n);
        sscanf(msg,"%d%s%d%s\0",&flag_azione,word,&TEXP,PATH);

		strcpy(FileName,PATH);


		//Se il tempo d'esposizione non e' compreso tra 20 e 60000 ms 
		//il programma va in errore e carica in texp un tempo d'esposizione di default di 50 ms 
     
		if ((TEXP>60000)||(TEXP<20))
		{
			strcpy(ERRORSTRING,"@@@ ERROR!!! @@@ Exposition time out of range @@@"); 
			TEXP=50;
			err();
		}
	    TEXPSEC=TEXP*0.001; //Trasforma il tempo d'esposizione in secondi 
	  
		// FOTO - Image acquistition section -------------------------------------
		if (!strcmpi(word,"foto"))
		{
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@	
			//In modalita' SLAVE commentare la funzione - Master action delay 
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  			for (int cont=0; cont<=10000000; cont++)  // delay ~ 0.1 sec 
	  		S=cont;                                    // permette a slave attesa
			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			foto();
			risposta();
			i=1;            
		}
       
		// BUIO - Dark image acquistition section -------------------------------------
		if (!strcmpi(word,"buio"))
		{
           //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@	
           //In modalita' SLAVE commentare la funzione - Master action delay 
           //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			for (int cont=0; cont<=10000000; cont++) // 0.1s delay
			S=cont;
           //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
			buio();
			risposta();
			i=1;			
		}
		 
		// FAST - High rate image acquistition section --------------------------------
		if (!strcmpi(word,"fast"))	 
		{
			fast();
			risposta();
			i=1;			
		}
        if (!strcmpi(word,"fine"))	 
		fine();
		 
		// Loop for word --------------------------------------------------------------
		//Se trova per 10000 volte l'action word nulla restituisce un errore
		if (!strcmpi(word,""))
		{
			i=1;
			cont1++;
			if (cont1==10000)
			{
				i=0;
				cont1=0;
			}
		}
	  
		//Se il flag di errore i e' uguale a 0 il programma restituisce un errore	
		if (i==0)
		{
			strcpy(ERRORSTRING,"@@@ ERROR!!! @@@ Wrong action code @@@"); 
			err();
		}
        // dealloca spazio in memoria per l'immagine
		GlobalUnlock(shglb);
		GlobalFree(shglb);
	}	// End main while


        
}	// End procedure		
			
//*********************************************************************
//*********************************************************************
//       FOTO Procedure - NORMAL image acquisition
//       maximum frame rate in this mode is ~ 2 frames/s
//*********************************************************************
//*********************************************************************


void foto(void)
{  
	 
	PICM_SetExposure(TEXPSEC,&ERROR_CODE);//Set the camera exposure in seconds	

	PICM_Start_controller();//Startup Controller to acquire data

    DONE_FLAG=false;
	
	while(!DONE_FLAG)
		DONE_FLAG=PICM_ChkData(&STATUS);//Checks if data has been collected

	saveimm();  // image storing
	/* saveimm2ftp(); */
	PICM_Stop_controller();  //Stops Controller from collecting data
	statistica();  // Image statistical properties 
	time();  //  time procedure
	acqlog(); // acq.log updating
	
}

//*********************************************************************
//*********************************************************************
//       BUIO Procedure - DARK image acquIsition procedure
//*********************************************************************
//*********************************************************************

void buio(void) //Aquisisce immagini di buio
{

	PICM_Set_shuttermode(SHUTTER_CLOSE);//Physically open or close shutter: condition may be OPEN or CLOSE
	PICM_SetExposure(TEXPSEC,&ERROR_CODE); //Set the camera exposure in seconds
	short_initccd();

	PICM_Start_controller();//Startup Controller to acquire data
	DONE_FLAG=false;
	while(!DONE_FLAG)
		DONE_FLAG=PICM_ChkData(&STATUS);//Checks if data has been collected
	
	saveimm();
	/* saveimm2ftp(); */
	PICM_Stop_controller();//Stops Controller from collecting data
	PICM_Set_shuttermode(SHUTTER_NORMAL);//Physically open or close shutter: condition may be OPEN or CLOSE  
	short_initccd();
	statistica();
	time();
	acqlog();
}

//*********************************************************************
//*********************************************************************
//       Image disk storing procedure
//*********************************************************************
//*********************************************************************

void saveimm(void) //Salva l'immagine, il nome del file e' contenuto in PATH 
{    
	
   int jndx;   //indice di riga                       
   int jndy;   //indice di colonna
   short huge *immbuffer;//Puntatore dell'immagine
   char huge *address; //Punta al primo elemento dell'immagine
   
   FILE *ofsout=0;   //Puntatore del file in cui verra' salvata l'immagine

   immbuffer=LPVBUFFER;
   ofsout=fopen(PATH,"wb");//Open file to save image

   if (ofsout==0)  //Se non riesce ad aprire il file va in errore
   {
      strcpy(ERRORSTRING,"@@@ ERROR @@@ Can't open file to save image @@@"); 
	  err();
	  fine();
   }
   
   address=(char huge*)LPVBUFFER; 
   //Carica in IMM0 l'immagine
   
   for(jndx=0;jndx<DIMX;jndx++)
   {
      fwrite(address,2,DIMX,ofsout);
	  address=address + DIMY * 2;
	  for(jndy=0;jndy<DIMY;jndy++)
	  {
	     IMM0[jndx*DIMY+jndy]=*immbuffer;
         immbuffer++;
	  }
   }
   
   TESTWR=1;
   while (TESTWR!=0) 
		TESTWR=fflush(ofsout);  //Forza la scrittura dell'immagine sul disco  	   

   fclose(ofsout);         //Close file to save image
   PICM_ResetUserBuffer(); //This function resets software counters and address of users buffer for data collection.
}

//*********************************************************************
//*********************************************************************
//       FAST Procedure - Fast image acqusition procedure
//       maximum frame rate in this mode is ~ 5 frames/s
//*********************************************************************
//*********************************************************************

void fast(void)  //Aquisisce immagini alla massima velocita' consentita
				 //La camera e' comandata Hardware (5 immagini al secondo c.a.)	
{

   int nimm=0;  //Numero immagini da acquisire
   int cont;    //Contatore delle immagini
   int jndx;    //indice di riga                      
   int jndy;    //indice di colonna
   int	count_100=100; //contatore delle 100 immagini che trascorrono tra 2 visualizzazioni a video
   int	flag_saturazione=0; // flag=0 no saturazione, flag=1 saturazione possibile
   short huge *immbuffer;
   long il,cont1; //Contatori per la statistica
   long double sum,sum2,app; //Variabili di appoggio per la statistica
   char pathfix[6]; //Stringhe per generare il nome dell'immagine
   char pathfix1[5];//Stringhe per generare il nome dell'immagine
   char numdir[2];  //Stringhe per generare il nome dell'immagine
   char undscore[2];//Stringhe per generare il nome dell'immagine
   char seq[8];		//Stringhe per generare il nome dell'immagine
   char data[8];    //Stringhe per generare il nome dell'immagine
   char ext[4];     //Stringhe per generare il nome dell'immagine
   char stat[60];   //Contiene tempo d'esposizione avg ed rms  dell'immagine
   char huge *address;
   struct tm *date_time;
	
   FILE *ofsout=0; //Puntatore del file in cui verra' salvata l'immagine
   FILE *appoggio=0;//Puntatore di un file di appoggio utilizzato per cambiare directory di salvataggio

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@	
   //In modalita' MASTER commentare la funzione 
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   //PICM_Set_acqmode(CTRL_FREERUN); //Disabilita il trigger esterno 
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@	
	
   PICM_Set_AutoStop(0); //Set hardware to collect that many frames and then automaticly stop
						  //0 - free run, 1 - stops after one frame
   PICM_Initialize_System(LPVBUFFER,&ERROR_CODE);//This function down loads all information to controller

   strcpy(PATH,"");
   strcpy(data,"");
   strcpy(pathfix,"");
   strcpy(pathfix1,"");
   strcpy(numdir,"");

   PATH[59]='\0';
   pathfix[5]='\0';
   pathfix1[4]='\0';
   numdir[1]='\0';
   undscore[1]='\0';
   seq[8]='\0';
   data[8]='\0';
   ext[8]='\0';

   strcpy(undscore,"_");
   strcpy(ext,".imm");
   time_t timer;
   time(&timer);
   strcpy(seq,"");
   strcpy(RECORD,"");
   strcpy(stat,"");
   strcpy(pathfix,"c:\\data_");
   strcpy(pathfix1,"wl");
	
   cout<<"Inserire numero immagini da acquisire: ";
   cin>>nimm;
	
   PICM_SetExposure(TEXPSEC,&ERROR_CODE);//Set the camera exposure in seconds
	
   PICM_Start_controller();//Startup Controller to acquire data
   _chdir("c:\\data_0");   //Cambia la directory principale dove saranno salvate le immagini

   for(cont=0;cont<nimm;cont++)
   {
      DONE_FLAG=false;
      while(!DONE_FLAG)
	     DONE_FLAG=PICM_ChkData(&STATUS);//Checks if data has been collected
      
	  //Ogni 10000 immagini cambia la directory principale
	  if (cont==10000)
	  {
	     PICM_Stop_controller();
	         
         strcat(pathfix,numdir);
         chdir("c:\\data_1");
	     appoggio=fopen("prova.xxx","wb"); //simula fopen con file d'appoggio
	     fclose(appoggio);
         ritardo(5);//Ritardo di 5 secondi 
		 PICM_Start_controller();
	  }
	 
	  if (cont==20000)
	  {
		 PICM_Stop_controller();
	         
         strcat(pathfix,numdir);
         chdir("c:\\data_2");
	     appoggio=fopen("prova.xxx","wb"); //simula fopen con file d'appoggio
	     fclose(appoggio);
         ritardo(5);//Ritardo di 5 secondi 
		 PICM_Start_controller();
	  }
	  
	  //genera il nome del file con cui verra' salvata l'immagine
	  strcat(PATH,pathfix1);
	  strcat(PATH,undscore);
	  date_time=localtime(&timer);
	  strftime(data,60,"%Y%m%d",date_time);
	  strcat(PATH,data);
	  strcat(PATH,undscore);
	  sprintf(seq,"%08d",cont);
	  strcat(PATH,seq);
	  strcat(PATH,ext);
	  
	  ofsout=fopen(PATH,"wb");//Open file to save image
      immbuffer=LPVBUFFER;
	  address=(char huge*)LPVBUFFER; 
      for(jndx=0;jndx<DIMX;jndx++)
	  {
	     fwrite(address,2,DIMX,ofsout);
		 address=address + DIMY * 2;
		 for(jndy=0;jndy<DIMY;jndy++)
		 {
		    IMM0[jndx*DIMY+jndy]=*immbuffer;
            immbuffer++;
		 }
	  }
      fclose(ofsout);//Close file to save image
      PICM_ResetUserBuffer();//This function resets software counters and address of users buffer for data collection.
		  
	  sum=0;
	  sum2=0;
      cont1=0;
	  for(il=51200; il<52224; il++)   //1024 punti
	  {
	     sum=sum+IMM0[il];
		 app=(long double)IMM0[il];
		 sum2=sum2+app*app;
	  }
	  cont1=1024;
      AVG=(double) (sum/cont1);
      RMS=(double)sum2/(double)cont1;
      RMS=RMS-(double)AVG*AVG;
      RMS=sqrt(RMS);
	  if((AVG+3*RMS) >= 4000 )
	     flag_saturazione=1;
	  time();
	  
	  //Genera la stringa da salvare nel Log file
	  strcpy(RECORD,PATH);
	  strcat(RECORD,DATIME);
	  sprintf(stat,"  %3.3f",TEXPSEC);
	  strcat(RECORD,stat);
	  sprintf(stat," %7.2f",AVG);
      strcat(RECORD,stat);
	  sprintf(stat,"  %7.2f",RMS);
	  strcat(RECORD,stat);
      strcat(RECORD,"\n");
	  fputs(RECORD,ALOG);
	  
	  //Ogni 100 acquisizioni visualizza a video PATH AVG e RMS dell'immagine corrente
	  if(count_100 >= 100)
	  {
	  printf("%s   %3.4f   %3.4f \n",PATH,AVG,RMS);
	     if (flag_saturazione == 1)
		 {
		    cout<<"@@@ WARNING @@@ Possible saturation @@@"<<endl;
			flag_saturazione=0;
		 }
			 count_100=0;
	  }
	  count_100++;
	  strcpy(PATH,"");
   }
	
   PICM_Stop_controller(); //Deactives all controller functions and prepares for safe shut down
   PICM_CleanUp();//This function deallocates all data collection buffers and unhooks the data collection interrupt routine.
   AVG=0;
   RMS=0;
   initccd();
}

//*********************************************************************
//*********************************************************************
//       Image statistics procedure
//*********************************************************************
//*********************************************************************

void statistica(void) //Calcola media, valore assoluto, minimo e massimo dell'immagine
{
 
   long il,cont;
   long double sum,sum2,app;
 
   sum=0;
   sum2=0;
   cont=0;
 
   for(il=0; il<NPIX; il++)   //Loop calcolo statistica 512X512
   {
	  sum=sum+IMM0[il];
	  app=(long double)IMM0[il];
	  sum2=sum2+app*app;
   }
   cont=NPIX;
   AVG=(double) (sum/cont);
   RMS=(double)sum2/(double)cont;
   RMS=RMS-(double)AVG*AVG;
   RMS=sqrt(RMS);
   //cerco il massimo e il minimo dell'immagine
   MIN_IMA=4095;
   MAX_IMA=0;
   for (il=0; il<NPIX; il++)
   {
      if(IMM0[il]<MIN_IMA)
	     MIN_IMA=IMM0[il];
	  	  
	  if(IMM0[il]>MAX_IMA)
         MAX_IMA=IMM0[il];
   }
   if(MAX_IMA==MIN_IMA)
   {
	  strcpy(ERRORSTRING,"@@@ ERROR @@@ Image is flat @@@"); 
	  err();
   }
   if(MAX_IMA>=4095)
   {
      strcpy(ERRORSTRING,"@@@ ERROR @@@ A/D converter is saturated @@@"); 
	  err();
   } 
}

//*********************************************************************
//*********************************************************************
//       Time update procedure
//*********************************************************************
//*********************************************************************

void time(void) //Carica in DATIME data e ora correnti
{
   strcpy(DATIME,"");
   time_t timer;
   struct tm *date_time;
   time(&timer);
   date_time=localtime(&timer);
   strftime(DATIME,60,"  %y/%m/%d  %X ",date_time);
}

//*********************************************************************
//*********************************************************************
//       avq.log updating procedure
//*********************************************************************
//*********************************************************************

void acqlog(void) //Salva nell'acq.log percorso,data,ora,tempo d'esposizione
				  //AVG,RMS,minimo e massimo dell'immagine corrente
{
   char stat[60];
    
   strcpy(RECORD,"");
   strcpy(stat,"");
   strcpy(RECORD,PATH);
   strcat(RECORD,DATIME);
   sprintf(stat,"  %3.3f",TEXPSEC);
   strcat(RECORD,stat);
   sprintf(stat," %7.2f",AVG);
   strcat(RECORD,stat);
   sprintf(stat,"  %7.2f",RMS);
   strcat(RECORD,stat);
   strcat(RECORD,"\n");
   fputs(RECORD,ALOG);
   TESTWR=1;
   while (TESTWR!=0) 
      TESTWR=fflush(ALOG);
   printf("%s %2.3f %4.2f %4.2f %4d %4d \n",PATH,TEXPSEC,AVG,RMS,MIN_IMA,MAX_IMA);

   fprintf(FileList,"%s\n",PATH);
   fflush(FileList);

}

//*********************************************************************
//*********************************************************************
//      File for HP 9000 procedure (risposta)
//*********************************************************************
//*********************************************************************

void risposta(void) //Scrittura file con AVG e RMS per ok Arcetri
{
	sprintf(msg,"%d %.2f %.2f",1,AVG,RMS);
	send(sock, msg, strlen(msg), 0);
}

//*********************************************************************
//*********************************************************************
//       Error management procedure
//*********************************************************************
//*********************************************************************

void err(void) //Visualizza a video e salva nell'acq.log l'errore che si e' verificato
{
   time();
   strcat(ERRORSTRING,DATIME);
   strcat(ERRORSTRING,"\n");
   fputs(ERRORSTRING,ALOG);
   TESTWR=1;
   while (TESTWR!=0) 
      TESTWR=fflush(ALOG);
   cout<<endl<<ERRORSTRING<<endl<<endl;
   strcpy(ERRORSTRING,"");
}

//*********************************************************************
//*********************************************************************
//		Delay routine
//*********************************************************************
//*********************************************************************

void ritardo(int t) //Genera un ritardo t in secondi

{
   long initial,final;
   long ltime;
   initial=time(&ltime);
   final=initial+t;
   while (time(&ltime)<final);
   return;
}

//*********************************************************************
//*********************************************************************
//		END routine
//*********************************************************************
//*********************************************************************

void fine(void) //Termina il programma 
{

   cout<<"Program end"<<endl;
   closesocket(sock);
   cout<<"closesocket done"<<endl;

   fclose(ALOG);

   fclose(FileList);
   cout<<"log file closed"<<endl;

   cout<<endl<<"**************** Press any key to exit ****************"<<endl;
   do {c=getch();}
   while (!c);
   exit(0);
}


//*********************************************************************
//*********************************************************************
//		Socket initialization
//*********************************************************************
//*********************************************************************
int iniz_socket()
{
	WSADATA data;
	WORD version;
	int err;  
	
	
	struct sockaddr_in adr;
	version = MAKEWORD(2,2);
	
	err = WSAStartup(version, &data);
	if (err != 0) {
		printf("WSAStartup : %d\n", err); exit(4);
	}

  memset(&adr, 0, sizeof(adr));
  if((sock = socket( AF_INET, SOCK_STREAM, 0)) == -1) {
		printf("creation socket : %d\n", WSAGetLastError()); exit(1);
  }
  adr.sin_family = AF_INET;
  adr.sin_port = htons(port);

  adr.sin_addr.s_addr = inet_addr(arcetri);
  printf("connecting to %s:%d... ", arcetri, port);
  if(connect(sock, (struct sockaddr *)&adr, sizeof(adr)) == -1) {
		printf("connect error : %d\n", WSAGetLastError()); exit(1);
  }
  printf("connected.\n");
  return sock;
}


void	InitFtp(void)

{
	InetSession = InternetOpen("MyProgram/1.0",
		INTERNET_OPEN_TYPE_DIRECT,
		NULL,
		NULL,
		INTERNET_FLAG_ASYNC);

	FtpSession = InternetConnect(InetSession,
		"192.168.2.68",
		INTERNET_DEFAULT_FTP_PORT,
		"themis",
		"98izana",
		INTERNET_SERVICE_FTP,
		INTERNET_FLAG_PASSIVE,
		NULL);

return;

}

void saveimm2ftp(void)

{
	char	tmpFileName[59], FileOut[59];

	sprintf(tmpFileName,"%s",FileName);
	sprintf(FileOut,"%s%s",FTPPATH,&tmpFileName[10]);

	if (!FtpPutFile(FtpSession,PATH,FileOut,FTP_TRANSFER_TYPE_BINARY,NULL))
		printf("Errore nella procedura di trasferimento FTP");
}



