extern "C" {
#define PIXCM 1 
#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           0x111000010000000   // 2880*10 : sockUCCI message max dimension
#define NPIX            262144			    //512X512
#define DIMX            512			        //Pixel image dimension
#define DIMY            512			        //Pixel image dimension

#define FILENAME_KEYW   "FILENAME"
#define TIME_EXPO_KEYW  "EXPTIME"
#define PATH            "c:\\"

#define MASTER          1
#define SUCCESS         1
#define FAILLURE        0

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 ERRORSTRING[60]={0}; //Error string
char RECORD[120]={0};     //"acq.log" record (path,data,texp,avg....) 
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 = NULL;        //Pointer to the "acq.log" file
FILE *FileList;

SOCKET sockPc, SockUcci;

static HANDLE shglb;	  //

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

int initccd(void)  
{	
    int controller_ok;		//ritorno delle funzioni Princeton
    long buffer_size;		//dimensioni del buffer dell'immagine
    static HANDLE hglb;		//

    //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,"ERROR:\t\tCCD ERROR @@@ Create contoller error ");
        ccderror();
        return FAILURE;
    }

    //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,"ERROR:\t\tCCD ERROR @@@ Set interface card error ");
        ccderror();
        return FAILURE;
    }

    //This function will set the fast ADC avaiable in controller.
    PICM_Set_Fast_ADC();

    //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,"ERROR:\t\tCCD ERROR @@@ Set ROI error ");
        ccderror();
        return FAILURE;
    }

    //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);

    //Configura lo shutter in modalita' non "manuale"
    PICM_Set_shuttermode(SHUTTER_NORMAL); 
    //Configura la versione del controller
    PICM_Set_controller_version(5);            
    PICM_Set_RS170_enable(TRUE);           //Abilita la modalita' RS170
    //Abilita' la visualizzazione sul monitor
    PICM_CMSetLongParam(CMP_VIDEO_TYPE, 2);

    //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,"ERROR:\tCCD ERROR @@@ Initialize System error ");
        ccderror();
        return FAILURE;
    }

    PICM_Set_shuttermode(SHUTTER_NORMAL);  
    return SUCCESS;
}

//*********************************************************************
//*********************************************************************
//          Fast PentaMax CCD initialization procedure
//*********************************************************************
//*********************************************************************	
int short_initccd(void)  //Inizializza la CCD
{	
    int controller_ok; //ritorno delle funzioni Princeton

    //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,"ERROR:\t\tCCD ERROR @@@ Initialize System error ");
        ccderror();
        return FAILURE;
    }
}

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

int saveimm(FILE *ofsout) 
{    
    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

    immbuffer=LPVBUFFER;

    address=(char huge*)LPVBUFFER; 

    for(jndx=0;jndx<DIMX;jndx++)
    {
        if (fwrite(address,2,DIMX,ofsout) != DIMX)
        {
            printf("ERROR:\t\tA PROBLEM HAS OCCURED WRITING DATA\n");
            PICM_ResetUserBuffer();
            return FAILURE;
        }
        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  	   
    }

    PICM_ResetUserBuffer(); //This function resets software counters and address
    return SUCCESS;
}
//*********************************************************************
//*********************************************************************
//       FOTO Procedure - NORMAL image acquisition
//       maximum frame rate in this mode is ~ 2 frames/s
//*********************************************************************
//*********************************************************************
int 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

    if (saveimm() == FAILURE)  // image storing
    {
        return FAILURE;
    }
    else
    {
        PICM_Stop_controller();  //Stops Controller from collecting data
        return SUCCESS;
    }
}
//*********************************************************************
//*********************************************************************
//       BUIO Procedure - DARK image acquIsition procedure
//*********************************************************************
//*********************************************************************

int buio(void) //Aquisisce immagini di buio
{
    PICM_Set_shuttermode(SHUTTER_CLOSE);//Physically open or close shutter:
    PICM_SetExposure(TEXPSEC,&ERROR_CODE); //Set the camera exposure in seconds
    if (short_initccd() == FAILURE) 
    {
        return FAILURE;
    }

    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

    if (saveimm() == FAILURE)  // image storing
    {
        return FAILURE;
    }
    else
    {
        PICM_Stop_controller();//Stops Controller from collecting data
        PICM_Set_shuttermode(SHUTTER_NORMAL);//Physically open or close shutter
        if (short_initccd() == FAILURE) 
        {
            return FAILURE;
        }
        else
        {
            return SUCCESS;
        }
    }
}

int end_acq(FILE *ofsout)
{
    test=1;
    //Flush disk buffers
    while (test !=0)
    {
        test=fflush(ofsout);    	   
    }

    //Close fits file
    if (fclose(ofsout) == 0)
    {
        return SUCCESS;
    }
    else
    {
        printf("ERROR:\t\tIMPOSSIBLE TO CLOSE THE FITS FILE\n");
        return FAILURE;
    }
}

int CameraAcqCmd(void)  
{
    int answer;
    //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();
        return FAILURE;
    }

    answer =  foto();

    // dealloca spazio in memoria per l'immagine
    GlobalUnlock(shglb);
    GlobalFree(shglb);
    return answer;
}	

int CameraEndAcqCmd(void)  
{
    return end_acq();
}	

int CameraDarkCmd(void)  
{
    int answer;
    //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,"ERROR:\t\tCCD ERROR @@@ Initialize System error ");
        ccderror();
        return FAILURE;
    }

    answer =  buio();

    // dealloca spazio in memoria per l'immagine
    GlobalUnlock(shglb);
    GlobalFree(shglb);
    return answer;
}	

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

void ccderror(void)  
{
    sprintf(PIERROR,"%d",ERROR_CODE); 
    strcat(ERRORSTRING,PIERROR);
    strcat(ERRORSTRING,"\n");
    printf("ERROR:\t\t %s",ERRORSTRING);
    strcpy(ERRORSTRING,"");
    strcpy(PIERROR,"");
}
