Skip to content
PcoCameraSdk.cpp 116 KiB
Newer Older
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed
/**************************************************************************
###########################################################################
 This file is part of LImA, a Library for Image Acquisition

 Copyright (C) : 2009-2011
 European Synchrotron Radiation Facility
 BP 220, Grenoble 38043
 FRANCE

 This is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.

 This software is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, see <http://www.gnu.org/licenses/>.
###########################################################################
**************************************************************************/
#include <cstdlib>

#ifndef __linux__
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed
#include <process.h>
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed
#include <sys/stat.h>
#include <sys/timeb.h>
#include <time.h>

#include "lima/Exceptions.h"
#include "lima/HwSyncCtrlObj.h"

#include "PcoCamera.h"
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed
#include "PcoCameraSdk.h"
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed
#include "PcoSyncCtrlObj.h"

using namespace lima;
using namespace lima::Pco;


//=================================================================================================
//=================================================================================================

// 4294967295.0 = double(DWORD(0xFFFFFFFF)) 
#define DWORD_MAX_FLOAT 4294967295.0

#define	MAX_DWORD_MS (double(4294967295.0e-3))
#define	MAX_DWORD_US (double(4294967295.0e-6))
#define	MAX_DWORD_NS (double(4294967295.0e-9))

void _pco_time2dwbase(double exp_time, DWORD &dwExp, WORD &wBase) {
	// conversion time(s) to PCO standard DWORD + UNIT(ms, us, ns)
		// exp & lat time is saved in seconds (LIMA). 
		// PCO requires them expressed in DWORD as ms(base=2), us(base=1) or ns(base=0)
		// max DWORD 0xFFFFFFFF = 4294967295.0
		// find the lowest unit (ns -> us -> ms) which does not overflow DWORD
    
	if(exp_time <= MAX_DWORD_NS) {   
		dwExp = DWORD(exp_time * 1.0e9); wBase = 0; // ns
	} else 	if(exp_time <= MAX_DWORD_US) {  
		dwExp = DWORD(exp_time * 1.0e6); wBase = 1; // us
	} else {  
		dwExp = DWORD(exp_time * 1.0e3); wBase = 2; // ms
	}

	DWORD mask = 0x7;
	DWORD min = 0x1000;

	if(dwExp > min){
		dwExp |= mask;
		dwExp ^= mask;
	}
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed

//=================================================================================================
//=================================================================================================
void Camera::_pco_GetAcqEnblSignalStatus(WORD &wAcquEnableState, int &error)
{
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	WORD _wAcquEnableState;



#ifdef __linux__
    error = camera->PCO_GetAcqEnblSignalStatus(&_wAcquEnableState);   
    PCO_CHECK_ERROR(error, "PCO_GetAcqEnblSignalStatus");
#else
	error = PcoCheckError(__LINE__, __FILE__, PCO_GetAcqEnblSignalStatus(m_handle, &_wAcquEnableState));
#endif

    if(error) return;
    
    wAcquEnableState = _wAcquEnableState;
}

//=================================================================================================
//=================================================================================================
double Camera::pcoGetCocRunTime()
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
    return m_pcoData->cocRunTime;
}
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed

double Camera::pcoGetFrameRate()
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	return m_pcoData->frameRate;
//=================================================================================================
//=================================================================================================
void Camera::_pco_GetCOCRuntime(int &error){
		
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	const char *msg;

	//====================================== get the coc runtime 
    //---- only valid if it was used PCO_SetDelayExposureTime
	//---- and AFTER armed the cam

	// Get and split the 'camera operation code' runtime into two DWORD. One will hold the longer
	// part, in seconds, and the other will hold the shorter part, in nanoseconds. This function can be
	// used to calculate the FPS. The sum of dwTime_s and dwTime_ns covers the delay, exposure and
	// readout time. If external exposure is active, it returns only the readout time.

	DWORD dwTime_s, dwTime_ns;
    double runTime;

#ifndef __linux__
	PCO_FN3(error, msg,PCO_GetCOCRuntime, m_handle, &dwTime_s, &dwTime_ns);
    PCO_PRINT_ERR(error, msg); 	if(error) return;
#else

    error=camera->PCO_GetCOCRuntime(&dwTime_s, &dwTime_ns);
    msg = "PCO_GetCOCRuntime" ; PCO_CHECK_ERROR(error, msg);
    if(error) return;
#endif


    m_pcoData->cocRunTime = runTime = ((double) dwTime_ns * NANO) + (double) dwTime_s;
    m_pcoData->frameRate = (dwTime_ns | dwTime_s) ? 1.0 / runTime : 0.0;

	
	
	DEB_TRACE() << DEB_VAR2(m_pcoData->frameRate, m_pcoData->cocRunTime);

	return;

}




//=================================================================================================
//=================================================================================================
void Camera::_pco_SetTimestampMode(WORD mode, int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;

    WORD modeNew, modeOld;


#ifndef __linux__
	char *msg;
	int error;
	err = error = 0;

    WORD modeMax;
    
	DWORD capsDesc1; 
	_pco_GetGeneralCapsDESC(capsDesc1, error);

	if(capsDesc1 & BIT8)
	{
	    DEB_ALWAYS() << "\n   timestampmode not allowed" ;
		err = -1;
		return;
	}
	modeMax = (capsDesc1 & BIT3) ? 3 : 2;
	if(mode > modeMax)
	{
	    DEB_ALWAYS() << "\n  invalid value" << DEB_VAR2(mode, modeMax);
		err = -1;
		return;
	}

	_pco_GetTimestampMode(modeOld, err);
	if(err) return;

	if(mode == modeOld)
	{
	    DEB_TRACE()<< "\n   no change " << DEB_VAR2(mode, modeOld); 
		return;
	}

	PCO_FN2(error, msg,PCO_SetTimestampMode,m_handle, mode);
	PCO_PRINT_ERR(error, msg); 	
	err |= error;
	if(err) return;

	_pco_GetTimestampMode(modeNew, err);
	if(err) return;

#else

    err=camera->PCO_GetTimestampMode(&modeOld);
    PCO_CHECK_ERROR(err, "PCO_GetTimestampMode"); 

    err=camera->PCO_SetTimestampMode(mode);
    PCO_CHECK_ERROR(err, "PCO_SetTimestampMode"); 

    err=camera->PCO_GetTimestampMode(&modeNew);
    PCO_CHECK_ERROR(err, "PCO_GetTimestampMode"); 

#endif

	DEB_TRACE() 
        << "\n   " << DEB_VAR3(mode, modeOld, modeNew) 
        ;

    return;
}

//=================================================================================================
//=================================================================================================
void Camera::_pco_GetTimestampMode(WORD &mode, int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;

#ifndef __linux__
	char *msg;
	int error;
	err = error = 0;
    
	PCO_FN2(error, msg,PCO_GetTimestampMode,m_handle, &mode);
	PCO_PRINT_ERR(error, msg); 	
	err |= error;
	if(err) return;
#else

    err=camera->PCO_GetTimestampMode(&mode);
    PCO_CHECK_ERROR(err, "PCO_GetTimestampMode"); 

#endif

	DEB_TRACE() 
        << "\n   " << DEB_VAR1(mode) 
        ;
    return;
}
//=================================================================================================
//=================================================================================================
WORD Camera::_pco_GetRecordingState(int &err){
	DEB_MEMBER_FUNCT();
	DEF_FNID;
    WORD wRecState_actual;
    

#ifndef __linux__	
	char *msg;
	int error;
	msg = _PcoCheckError(__LINE__, __FILE__, 
		PCO_GetRecordingState(m_handle, &wRecState_actual), error);
	
	err = error;

	if(error) {
		printf("=== %s [%d]> ERROR %s\n", fnId, __LINE__, msg);
		throw LIMA_HW_EXC(Error, "PCO_GetRecordingState");
	}
#else
	err=camera->PCO_GetRecordingState(&wRecState_actual);
    PCO_CHECK_ERROR(err, "PCO_GetRecordingState");
#endif


	return wRecState_actual;

}
//=================================================================================================
//=================================================================================================

/**************************************************************************************************
	If a set recording status = [stop] command is sent and the current status is already
	[stop]’ped, nothing will happen (only warning, error message). 
	
	If the camera is in
	[run]’ing state, it will last some time (system delay + last image readout), until the
	camera is stopped. The system delay depends on the PC and the image readout
	depends on the image size transferred. The SetRecordingState = [stop] checks for a
	stable stop state by calling GetRecordingState.  --- 165 ms 
	
	Please call PCO_CancelImages to remove pending buffers from the driver.   --- 1.5 s
**************************************************************************************************/

const char * Camera::_pco_SetRecordingState(int state, int &err){
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	long long usStart;


	WORD wRecState_new, wRecState_actual;

	wRecState_new = state ? 0x0001 : 0x0000 ; // 0x0001 => START acquisition

	usElapsedTimeSet(usStart);

    wRecState_actual = _pco_GetRecordingState(err);

#ifndef __linux__
	char *msg;
	

	_setCameraState(CAMSTATE_RECORD_STATE, !!(wRecState_actual));

	m_pcoData->traceAcq.usTicks[8].value = usElapsedTime(usStart);
	m_pcoData->traceAcq.usTicks[8].desc = "PCO_GetRecordingState execTime";
	usElapsedTimeSet(usStart);
#else
	//_setCameraState(CAMSTATE_RECORD_STATE, !!(wRecState_actual));

	m_pcoData->traceAcq.usTicks[traceAcq_GetRecordingState].value = usElapsedTime(usStart);
	m_pcoData->traceAcq.usTicks[traceAcq_GetRecordingState].desc = "PCO_GetRecordingState execTime";
	usElapsedTimeSet(usStart);
#endif

	//if(wRecState_new == wRecState_actual) {error = 0; return fnId; }

	// ------------------------------------------ cancel images 
	if(wRecState_new == 0) {
		int count = 1;

		_setCameraState(CAMSTATE_RECORD_STATE, false);


#if 0
		PCO_FN2(error, msg,PCO_GetPendingBuffer, m_handle, &count);
		PCO_PRINT_ERR(error, msg); 	if(error) return msg;
#endif

#ifndef __linux__
		if(count) {
			DEB_TRACE() << ":  PCO_CancelImages() - CALLING";
			PCO_FN1(err, msg,PCO_CancelImages, m_handle);
			PCO_PRINT_ERR(err, msg); 	if(err) return msg;
		} else {
			DEB_TRACE() << ":  PCO_CancelImages() - BYPASSED";
		}
	}

	if(wRecState_new != wRecState_actual) 
	{
		DEB_TRACE() << fnId << ": PCO_SetRecordingState " << DEB_VAR1(wRecState_new);
		PCO_FN2(err, msg,PCO_SetRecordingState, m_handle, wRecState_new);
		PCO_PRINT_ERR(err, msg); 	if(err) return msg;

		if(_getDebug(DBG_TRACE_FIFO))
		{
			printf("---TRACE - PCO_SetRecordingState[%d]\n", wRecState_new);
		}
	}

	if(wRecState_new) 
		m_sync->setExposing(pcoAcqRecordStart);

#else
if(count && !_isCameraType(Edge)) 
		{
			DEB_TRACE() << fnId << ": PCO_CancelImages";

            err=camera->PCO_CancelImage();
            PCO_CHECK_ERROR(err, "PCO_CancelImage");

            err=camera->PCO_CancelImageTransfer();
            PCO_CHECK_ERROR(err, "PCO_CancelImageTransfer");
		}
	}

    err=camera->PCO_SetRecordingState(wRecState_new);
    PCO_CHECK_ERROR(err, "PCO_SetRecordingState");
#endif

    wRecState_actual = _pco_GetRecordingState(err);
	_setCameraState(CAMSTATE_RECORD_STATE, !!(wRecState_actual));

#ifndef __linux__
	m_pcoData->traceAcq.usTicks[9].value = usElapsedTime(usStart);
	m_pcoData->traceAcq.usTicks[9].desc = "PCO_SetRecordingState execTime";
	usElapsedTimeSet(usStart);
#else
	m_pcoData->traceAcq.usTicks[traceAcq_SetRecordingState].value = usElapsedTime(usStart);
	m_pcoData->traceAcq.usTicks[traceAcq_SetRecordingState].desc = "PCO_SetRecordingState execTime";
	usElapsedTimeSet(usStart);
#endif

	_armRequired(true);

#ifndef __linux__
	m_pcoData->traceAcq.usTicks[10].value = usElapsedTime(usStart);
	m_pcoData->traceAcq.usTicks[10].desc = "PCO_CancelImages execTime";
	usElapsedTimeSet(usStart);
#else
	m_pcoData->traceAcq.usTicks[traceAcq_CancelImages].value = usElapsedTime(usStart);
	m_pcoData->traceAcq.usTicks[traceAcq_CancelImages].desc = "PCO_CancelImages execTime";
	usElapsedTimeSet(usStart);
#endif



	//DEB_TRACE() << fnId << ": " << DEB_VAR4(error, state, wRecState_actual, wRecState_new);
	return fnId;

}
//=================================================================================================
//=================================================================================================

//=================================================================================================
//=================================================================================================
int Camera::_pco_GetBitAlignment(int &alignment){
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	int error = 0;
	WORD wBitAlignment;

#ifndef __linux__
	error = PCO_GetBitAlignment(m_handle, &wBitAlignment);
	error = PCO_CHECK_ERROR(error, "PCO_GetBitAlignment");
#else
    error=camera->PCO_GetBitAlignment(&wBitAlignment);
    PCO_CHECK_ERROR(error, "PCO_GetBitAlignment");
    PCO_THROW_OR_TRACE(error, "PCO_GetBitAlignment") ;
#endif
	
	if(error) return error;

	alignment = m_pcoData->wBitAlignment = wBitAlignment;

	return error;
}

//=================================================================================================
//=================================================================================================

// wBitAlignment:
// - 0x0000 = [MSB aligned]; all raw image data will be aligned to the MSB. This is thedefault setting.
// - 0x0001 = [LSB aligned]; all raw image data will be aligned to the LSB.


int Camera::_pco_SetBitAlignment(int alignment){
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	int error = 0;
	WORD wBitAlignment;

	if((alignment <0) ||(alignment >1)){
		DEB_ALWAYS() << "ERROR - invalid value " << DEB_VAR1(alignment);
		return -1;
	}

	wBitAlignment = int(alignment);

#ifndef __linux__
	error = PCO_SetBitAlignment(m_handle, wBitAlignment);
	error = PCO_CHECK_ERROR(error, "PCO_SetBitAlignment");
#else
    error=camera->PCO_SetBitAlignment(wBitAlignment);
    const char *msg = "PCO_SetBitAlignment" ; PCO_CHECK_ERROR(error, msg);
    PCO_THROW_OR_TRACE(error, msg) ;
#endif

	return error;
}





//=================================================================================================
//=================================================================================================
	//-------------------------------------------------------------------------------------------------
	// PCO_SetADCOperation
    // Set analog-digital-converter (ADC) operation for reading the image sensor data. Pixel data can be
    // read out using one ADC (better linearity) or in parallel using two ADCs (faster). This option is
    // only available for some camera models. If the user sets 2ADCs he must center and adapt the ROI
    // to symmetrical values, e.g. pco.1600: x1,y1,x2,y2=701,1,900,500 (100,1,200,500 is not possible).
    //
	// DIMAX -> 1 adc
	//-------------------------------------------------------------------------------------------------
int Camera::_pco_GetADCOperation(int &adc_working, int &adc_max)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;

	int error;
	WORD wADCOperation;

	adc_max = m_pcoData->stcPcoDescription.wNumADCsDESC; // nr of ADC in the system

	if(adc_max == 2) {

#ifndef __linux__
		const char *msg;
		PCO_FN2(error, msg,PCO_GetADCOperation, m_handle, &wADCOperation);
#else
		error=camera->PCO_GetADCOperation(&wADCOperation);
		PCO_CHECK_ERROR(error, "PCO_GetADCOperation");
#endif

		if(error) wADCOperation = (WORD) 1;
	} else {
		adc_max = 1;
		wADCOperation = (WORD) 1;
	}

	adc_working = wADCOperation;
	m_pcoData->wNowADC= wADCOperation;

	return error;
}

//=================================================================================================
//=================================================================================================

int Camera::_pco_SetADCOperation(int adc_new, int &adc_working)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;

	int error, adc_max;

	error = _pco_GetADCOperation(adc_working, adc_max);

	DEB_TRACE() << fnId << ": " DEB_VAR2(adc_max, adc_working);

	if(error) return error;

	if((adc_new >=1) && (adc_new <= adc_max) && (adc_new != adc_working) ){

#ifndef __linux__
		const char *msg;
		PCO_FN2(error, msg,PCO_SetADCOperation, m_handle, (WORD) adc_new);
#else
        error=camera->PCO_SetADCOperation((WORD) adc_new);
        PCO_CHECK_ERROR(error, "PCO_SetADCOperation");
#endif
		_pco_GetADCOperation(adc_working, adc_max);
	}
	m_pcoData->wNowADC = adc_working;
	return error;
}
//=================================================================================================
//=================================================================================================

bool Camera::_isCapsDesc(int caps)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;

	DWORD _dwCaps1;

#ifndef __linux__
	int error;
	_pco_GetGeneralCapsDESC(_dwCaps1, error);
	if(error)
	{
		DEB_ALWAYS() << "ERROR - _pco_GetGeneralCapsDESC";
		return FALSE;
	}
#else
	_dwCaps1 = m_pcoData->stcPcoDescription.dwGeneralCaps1;
#endif


	switch(caps)
	{
		case capsCDI:
			return !!(_dwCaps1 & GENERALCAPS1_CDI_MODE);

		case capsDoubleImage:
			return !!(m_pcoData->stcPcoDescription.wDoubleImageDESC);
	
		case capsRollingShutter:
			return _isCameraType(Edge);

		case capsGlobalShutter:
			//#define GENERALCAPS1_NO_GLOBAL_SHUTTER                 0x00080000 // Camera does not support global shutter
			return _isCameraType(Edge) && !(_dwCaps1 & GENERALCAPS1_NO_GLOBAL_SHUTTER);

		case capsGlobalResetShutter:
			//#define GENERALCAPS1_GLOBAL_RESET_MODE                 0x00100000 // Camera supports global reset rolling readout
			return _isCameraType(Edge) && !!(_dwCaps1 & GENERALCAPS1_GLOBAL_RESET_MODE);

		case capsHWIO:
			return !!(_dwCaps1 & GENERALCAPS1_HW_IO_SIGNAL_DESCRIPTOR);

		case capsCamRam:
			return ( (_dwCaps1 & GENERALCAPS1_NO_RECORDER) == 0) ;

		case capsMetadata:
			return !!(_dwCaps1 & GENERALCAPS1_METADATA);


		//----------------------------------------------------------------------------------------------------------
		// dwGeneralCapsDESC1;      // General capabilities:
        //		Bit 3: Timestamp ASCII only available (Timestamp mode 3 enabled)
		//		Bit 8: Timestamp not available
		// m_pcoData->stcPcoDescription.dwGeneralCapsDESC1 & BIT3 / BIT8

		case capsTimestamp3:
			return (!(_dwCaps1 & BIT8)) && (_dwCaps1 & BIT3);

		case capsTimestamp:
			return !(_dwCaps1 & BIT8);

		default:
			return FALSE;
	}

}


//=================================================================================================
//=================================================================================================
//SC2_SDK_FUNC int WINAPI PCO_GetCDIMode(HANDLE ph, WORD *wCDIMode); 
// Gets the correlated double image mode of the camera, if available.
// Only available with a dimax
// In: HANDLE ph -> Handle to a previously opened camera.
//     WORD *wCDIMode -> Pointer to a WORD variable to receive the correlated double image mode.
// Out: int -> Error message.

//SC2_SDK_FUNC int WINAPI PCO_SetCDIMode(HANDLE ph,  WORD wCDIMode); 
// Sets the correlated double image mode of the camera, if available.
// Only available with a dimax
// In: HANDLE ph -> Handle to a previously opened camera.
//     WORD wCDIMode -> WORD variable to set the correlated double image mode.
// Out: int -> Error message.
// CDI mode is available if in the camera descriptor the flag

//Mode parameter is simple: 0 is off (default), 1 is on.
// CDI mode is available if in the camera descriptor the flag
// #define GENERALCAPS1_CDI_MODE                          0x00010000 // Camera has Correlated Double Image Mode
// in GENERALCAPS1 is set.


void Camera::_pco_GetCDIMode(WORD &wCDIMode, int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	//char *pcoFn;
	int pcoErr;
	err = 0;

	if(!_isCapsDesc(capsCDI))
	{
		wCDIMode = 0;
		err = 1;
		DEB_TRACE() <<  "WARNING / CDI mode is NOT ALLOWED!";
		return;
	
	err = 0;

#ifndef __linux__
	pcoErr = PCO_GetCDIMode(m_handle, &wCDIMode);
#else
	wCDIMode = 0;
	DEB_ALWAYS() <<  "ERROR / TODO / NOT IMPLEMENTED YET";
    pcoErr = -1;
#endif

	err |= PCO_CHECK_ERROR(pcoErr, "PCO_GetCDIMode");
//=================================================================================================
//=================================================================================================
void Camera::_pco_SetCDIMode(WORD wCDIMode, int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	//char *pcoFn;
	int pcoErr;
	err = 0;

	if(!_isCapsDesc(capsCDI))
	{
		err = 1;
		DEB_TRACE() <<  "WARNING / CDI mode is NOT ALLOWED!";
		return;
	}
	
	if(wCDIMode) 
	{
		wCDIMode = 1;
		_pco_SetDoubleImageMode(0, err); 		// cdi and double image are exclusive
	}
#ifndef __linux__
	pcoErr = PCO_SetCDIMode(m_handle, wCDIMode);
#else
	DEB_ALWAYS() <<  "ERROR / TODO / NOT IMPLEMENTED YET";
    pcoErr = -1;
#endif
Roberto Arturo Homs-Regojo's avatar
Roberto Arturo Homs-Regojo committed

	err |= PCO_CHECK_ERROR(pcoErr, "PCO_SetCDIMode");
	
	return;
}
//=================================================================================================
//=================================================================================================
void Camera::_pco_GetDoubleImageMode(WORD &wDoubleImage, int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	//char *pcoFn;
	int pcoErr;
	err = 0;

	if(!_isCapsDesc(capsDoubleImage))
	{
		wDoubleImage = 0;
		err = 1;
		DEB_TRACE() <<  "WARNING / DoubleImage mode is NOT ALLOWED!";
		return;
	}
	
	err = 0;

#ifndef __linux__
	pcoErr = PCO_GetDoubleImageMode(m_handle, &wDoubleImage);
#else
	wDoubleImage = 0;
	DEB_ALWAYS() <<  "ERROR / TODO / NOT IMPLEMENTED YET";
    pcoErr = -1;
#endif

	err |= PCO_CHECK_ERROR(pcoErr, "PCO_GetDoubleImageMode");

	return;
}

//=================================================================================================
//=================================================================================================
void Camera::_pco_SetDoubleImageMode(WORD wDoubleImage, int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	//char *pcoFn;
	int pcoErr;
	err = 0;

	if(!_isCapsDesc(capsDoubleImage))
	{
		err = 1;
		DEB_TRACE() <<  "WARNING / DoubleImage mode is NOT ALLOWED!";
		return;
	}
	
	if(wDoubleImage) 
	{
		wDoubleImage = 1;
		_pco_SetCDIMode(0, err);		// cdi and double image are exclusive
	}

	err = 0;

#ifndef __linux__
	pcoErr = PCO_SetDoubleImageMode(m_handle, wDoubleImage);
#else
	DEB_ALWAYS() <<  "ERROR / TODO / NOT IMPLEMENTED YET";
    pcoErr = -1;
#endif

	err |= PCO_CHECK_ERROR(pcoErr, "PCO_SetDoubleImageMode");

	return;
}

//=================================================================================================
//=================================================================================================
void Camera::_pco_GetGeneralCapsDESC(DWORD &capsDesc1, int &err)
{
	err = 0;
#ifndef __linux__
	capsDesc1 = m_pcoData->stcPcoDescription.dwGeneralCapsDESC1;
#else
	capsDesc1 = m_pcoData->stcPcoDescription.dwGeneralCaps1;
#endif
	
	
	return;
}


//=================================================================================================
//=================================================================================================

//SC2_SDK_FUNC int WINAPI PCO_GetSegmentImageSettings(HANDLE ph, WORD wSegment,
//                                                    WORD* wXRes,
//                                                    WORD* wYRes,
//                                                    WORD* wBinHorz,
//                                                    WORD* wBinVert,
//                                                    WORD* wRoiX0,
//                                                    WORD* wRoiY0,
//                                                    WORD* wRoiX1,
//                                                    WORD* wRoiY1);
// Gets the sizes information for one segment. X0, Y0 start at 1. X1, Y1 end with max. sensor size.
// In: HANDLE ph -> Handle to a previously opened camera.
//     WORD *wXRes -> Pointer to a WORD variable to receive the x resolution of the image in segment
//     WORD *wYRes -> Pointer to a WORD variable to receive the y resolution of the image in segment
//     WORD *wBinHorz -> Pointer to a WORD variable to receive the horizontal binning of the image in segment
//     WORD *wBinVert -> Pointer to a WORD variable to receive the vertical binning of the image in segment
//     WORD *wRoiX0 -> Pointer to a WORD variable to receive the left x offset of the image in segment
//     WORD *wRoiY0 -> Pointer to a WORD variable to receive the upper y offset of the image in segment
//     WORD *wRoiX1 -> Pointer to a WORD variable to receive the right x offset of the image in segment
//     WORD *wRoiY1 -> Pointer to a WORD variable to receive the lower y offset of the image in segment
//      x0,y0----------|
//      |     ROI      |
//      ---------------x1,y1
// Out: int -> Error message.
//SC2_SDK_FUNC int WINAPI PCO_GetNumberOfImagesInSegment(HANDLE ph, 
//                                             WORD wSegment,
//                                             DWORD* dwValidImageCnt,
//                                             DWORD* dwMaxImageCnt);
// Gets the number of images in the addressed segment.
// In: HANDLE ph -> Handle to a previously opened camera.
//     DWORD *dwValidImageCnt -> Pointer to a DWORD varibale to receive the valid image count.
//     DWORD *dwMaxImageCnt -> Pointer to a DWORD varibale to receive the max image count.
// Out: int -> Error message.


void Camera::_pco_GetSegmentInfo(int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	//char *pcoFn;
	int pcoErr;
	err = 0;

	err = 0;
	if(!_isCameraType(Dimax | Pco2k | Pco4k))
	{
		err = 1;
		return;
	}

#ifndef __linux__
	struct stcSegmentInfo *_stc;

	for(int iseg = 0; iseg <  PCO_MAXSEGMENTS; iseg++)
	{

		_stc = &m_pcoData->m_stcSegmentInfo[iseg];
		
		_stc->iSegId = iseg+1;
		_stc->wXRes = _stc->wYRes = 
			_stc->wBinHorz = _stc->wBinVert = 
			_stc->wRoiX0 = _stc->wRoiY0  = 
			_stc->wRoiX1 = _stc->wRoiY1 = 0;
			_stc->dwValidImageCnt = _stc->dwMaxImageCnt = 0;
			_stc->iErr = 0;

		pcoErr = PCO_GetSegmentImageSettings(m_handle, iseg,
			&_stc->wXRes, &_stc->wYRes,
			&_stc->wBinHorz, &_stc->wBinVert,
			&_stc->wRoiX0, &_stc->wRoiY0,
			&_stc->wRoiX1, &_stc->wRoiY1);

			_stc->iErr |= pcoErr;
			err |= pcoErr;

		pcoErr = PCO_GetNumberOfImagesInSegment(m_handle, iseg,
			&_stc->dwValidImageCnt, &_stc->dwMaxImageCnt);
	
			_stc->iErr |= pcoErr;
			err |= pcoErr;

	}
#else
	DEB_ALWAYS() <<  "ERROR / TODO / NOT IMPLEMENTED YET";
    pcoErr = -1;
	err |= pcoErr;
#endif
	return;
}


//=================================================================================================
//=================================================================================================
void Camera::_pco_CloseCamera(int &err)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;
	
#ifndef __linux__
	int pcoErr;
	
	//PCO_PRINT_ERR(error, msg); 

	err = 0;
	pcoErr = PCO_CloseCamera(m_handle);
	err |= PCO_CHECK_ERROR(pcoErr, "PCO_CloseCamera");

	m_handle = NULL;
#else
    err = 0;
    
    if(grabber)
    {
        delete grabber;
        grabber = NULL;
    }

    if(camera)
    {
        err = camera->Close_Cam();
        PCO_CHECK_ERROR(err, "Close_Cam");

        delete camera;
        camera = NULL;
    }
#endif
	return;
}
//=================================================================================================
//=================================================================================================

bool Camera::_isCooledCamera()
{

	return !((m_pcoData->stcPcoDescription.sMinCoolSetDESC == 0) && (m_pcoData->stcPcoDescription.sMaxCoolSetDESC == 0));


}








//=================================================================================================
//=================================================================================================
void Camera::_pco_GetCoolingSetpointTemperature(int &val, int &error)
{
	DEB_MEMBER_FUNCT();
	DEF_FNID;

#ifndef __linux__
	char *pcoFn;
	SHORT _sSetpoint;


	if(!_isCooledCamera())
	{
		error = -1;
		val = 0;
		return;
	}

	PCO_FN2(error, pcoFn,PCO_GetCoolingSetpointTemperature, m_handle, &_sSetpoint);
	if(error)
	{
		val = 0;
		return;
	}

	val = _sSetpoint;


#else
	error = -1;

	DEB_ALWAYS() <<  "ERROR / TODO / NOT IMPLEMENTED YET";

	val = 0;