Exemple #1
0
int main(int argc, char **argv)
{
	int	status;
	int	bitdepth;
	int	width, height;
	int	min, max;
	int	i, j, numgains;
	float	gain;
	int	num_ad;
	int	num_vspeeds;
	int	num_hspeeds;
	float	speed;
	AndorCapabilities caps;
	at_32 lNumCameras;
	at_32 lCameraHandle;
	int	start_n, stop_n;
	int	npix;

	/* Check command line */

	npix = 90;

	if (argc > 1) sscanf(argv[1], "%d", &npix);
	
	/* FIRST, FIND OUT WHAT WE NEED TO KNOW ABOUT THIS CAMERA. */

	printf("Initializing Andor Camera.\n");

	/* How many cameras are connected */

	printf("GetAvailableCameras = %d\n", GetAvailableCameras(&lNumCameras));
	if (lNumCameras == 1)
		printf("There is %d camera connected.\n", lNumCameras);
	else
		printf("There are %d cameras connected.\n", lNumCameras);

	if (lNumCameras <= 0) exit(0);

	/* Get the camera we are working with. */

	printf("GetCameraHandle = %d\n", GetCameraHandle(0, &lCameraHandle));

	printf("SetCurrentCamera = %d\n", SetCurrentCamera(lCameraHandle));

	/* Initialize the CCD */

	printf("Initialize = %d\n", Initialize("/usr/local/etc/andor"));

	/* Wait for this to happen */

	sleep(2);

	/* What Capabilities do we have? */

	caps.ulSize = sizeof(caps);
	printf("GetCapabilities = %d\n", GetCapabilities(&caps));

	if (caps.ulCameraType & AC_CAMERATYPE_IXON)
		printf("Camera is an iXon.\n");
	else
		printf("Camera is not an iXon.\n");

	if (caps.ulAcqModes & AC_ACQMODE_FRAMETRANSFER)
		printf("Frame transfer is available.\n");
	else
		printf("Frame transfer is not available.\n");

	if (caps.ulSetFunctions & AC_SETFUNCTION_CROPMODE)
		printf("Crop mode is available.\n");
	else
		printf("Crop mode is not available.\n");

	/* Find out what the width and height are */

	printf("GetDetector = %d\n", GetDetector(&width, &height));
	printf("Andor full size %dx%d.\n", width, height);

	/* What is the allowable temperature range? */

	printf("GetTemperatureRange = %d\n", GetTemperatureRange(&min, &max));
	printf("Andor temperature range is %d to %d C.\n", min, max);
	
	/* How many preamp gains do we have? */

	printf("GetNumberPreAmpGains = %d\n", GetNumberPreAmpGains(&numgains));
	printf("Andor number of preamp gains is %d.\n", numgains);

	/* Let's find out what these gains are */

	for (i=0; i<numgains; i++)
	{
		printf("GetPreAmpGain = %d\n", GetPreAmpGain(i, &gain));
		printf("Andor Preamp Gain %d is %f.\n", i, gain);
	}

	/* How many vertical speeds do we have? */

	printf("GetNumberVSSpeeds = %d\n", GetNumberVSSpeeds(&num_vspeeds));
	printf("Andor number of Vertical Speeds is %d.\n", num_vspeeds);

	/* Let's find out what these VSpeeds are */

	for (i=0; i<num_vspeeds; i++)
	{
		printf("GetVSSpeed = %d\n", GetVSSpeed(i, &speed));
		printf("Andor Vertical Speed %d is %.2f uS.\n",
				i, speed);
	}

	for(j = 0; j < 1; j++)
	{
	    if (j == 0)
		    printf("For EMCCD output:\n");
	    else
		    printf("For CCD output:\n");

	    /* How many horizontal speeds do we have? */

	    printf("GetNumberHSSpeeds = %d\n",
		GetNumberHSSpeeds(0, j, &num_hspeeds));
	    printf("Andor number of Horizontal Speeds is %d.\n", num_hspeeds);

	    /* Let's find out what these speeds are */

	    for (i=0; i<num_hspeeds; i++)
	    {
		printf("GetHSSpeed = %d\n", GetHSSpeed(0, j, i, &speed));
		printf("Andor Horizontal Speed %d is %.2f MHz.\n", i, speed);
	    }

	}

	/* What is the range of gain settings - This is always wrong  */

	printf("GetEMGainRange = %d\n", GetEMGainRange(&min, &max));
	printf("Andor EM Gain range is %d to %d.\n", min, max);

	/* How many AD channels are there? */

	printf("GetNumberADChannels = %d\n", GetNumberADChannels(&num_ad));
	printf("Number of AD channels = %d\n", num_ad);

	/* What are the bit depths? */

	for(i=0; i < num_ad; i++)
	{
	    printf("GetBitDepth = %d\n", GetBitDepth(i, &bitdepth));
	    printf("AD channel %d has bit depth %d\n", i, bitdepth);
	}

	/* NOW WE START TO SET THINGS UP THE WAY WE WANT THEM */

	/* Turn on Cameralink mode */

	printf("SetCameraLinkMode = %d\n", SetCameraLinkMode(1));

	/* Put us in Frame Transfer Mode */

	printf( "Turning on Frame Transfer Mode.\n");
	printf("SetFrameTransferMode = %d\n", SetFrameTransferMode(1));

        /* Set output amplifier to EMCCD */

	printf("SetOutputAmplifier = %d\n", SetOutputAmplifier(0));

	/* Turn on advanced EM settings */

	printf("SetEMAdvanced = %d\n", SetEMAdvanced(1));

	/* Let's see if that worked... we should get 1000 as maximum */

	printf("GetEMGainRange = %d\n", GetEMGainRange(&min, &max));
	printf("Andor EM Gain range is %d to %d.\n", min, max);

	/* Set EM gain */

	printf("SetEMCCDGain = %d\n", SetEMCCDGain(300));

	/* Set our horizontal speed to the desired one. */

        printf("SetHSSpeed = %d\n", SetHSSpeed(0, 0));

	/* Set our vertical speed to the desired one. */

        printf("SetVSSpeed = %d\n", SetVSSpeed(0));

	/* Set our gain to the desired one. */

	printf("SetPreAmpGain = %d\n", SetPreAmpGain(2));

        /* Setup the read mode. I suspect this is the problem */

        printf("SetReadMode = %d\n", SetReadMode(4));

	/* Try to get frames like this */

        printf("SetAcquisitionMode = %d\n", SetAcquisitionMode(5));
	printf("PrepareAcquisition = %d\n", PrepareAcquisition());
	printf("StartAcquisition %d\n", StartAcquisition());
	sleep(1);
	printf("AbortAcquisition %d\n", AbortAcquisition());

	/* This sequence seemed to work with the server */

        //printf("SetHSSpeed = %d\n", SetHSSpeed(0, 1));

	/* DO we get the right gain range now? */

	printf("GetEMGainRange = %d\n", GetEMGainRange(&min, &max));
	printf("Andor EM Gain range is %d to %d.\n", min, max);

        /* We wish to use Cropped mode */

        printf("SetIsolatedCropMode = %d\n",
		SetIsolatedCropMode(1,npix,npix,1,1));

        /* Set the image to read the full area of cropped region */

        printf("SetImage = %d\n", SetImage(1, 1, 1, npix, 1, npix));

        /* Set exposure time to 1mS */

        printf("SetExposureTime = %d\n", SetExposureTime(0.001));

	/* Set Kinetic Cycle time to the smallest possible value */

	printf("SetKineticCycleTime = %d\n",SetKineticCycleTime(0.0));

	/* OK, let's see what the frame rate is */

        printf("SetAcquisitionMode = %d\n", SetAcquisitionMode(5));
	printf("StartAcquisition %d\n", StartAcquisition());
	sleep(1);
	printf("GetTotalNumberImagesAcquired = %d\n",
			GetTotalNumberImagesAcquired(&start_n));
	sleep(5);
	printf("GetTotalNumberImagesAcquired = %d\n",
			GetTotalNumberImagesAcquired(&stop_n));
	printf("Frame rate seems to be %.2f Hz\n",
			(double)(stop_n - start_n)/5.0);
	printf("AbortAcquisition = %d\n",AbortAcquisition());


	/* Get one frame... it seems things work better after this */

	GetStatus(&status);
	while(status==DRV_ACQUIRING) GetStatus(&status);
	printf("SaveAsFITS %d\n", SaveAsFITS("./image.fit", 4));

	/* That is all */

	printf("ShutDown = %d\n", ShutDown());

	exit(0);
}
//------------------------------------------------------------------------------
//	FUNCTION NAME:	InitializeCamera()
//
//  RETURNS:				If the function terminates before entering the message loop,
//      						return FALSE.
//    							Otherwise, return the WPARAM value sent by the WM_QUIT
//									message.
//
//  LAST MODIFIED:	PMcK	11/11/98
//
//  DESCRIPTION:		calls initialization function, processes message loop
//
//                  Windows recognizes this function by name as the initial
//									entry point for the program.  This function calls the
//									application initialization routine, if no other instance of
//									the program is running, and always calls the instance
//									initialization routine.  It then executes a	message
//									retrieval and dispatch loop that is the top-level control
//    							structure for the remainder of execution.  The loop is
//									terminated when a WM_QUIT  message is received, at which
//									time this function exits the application instance by
//									returning the value passed by PostQuitMessage().
//
//    							If the function must abort before entering the message loop,
//									it returns the conventional value NULL.
//
//
//	ARGUMENTS: 			hInstance - The handle to the instance of this application
//									that is currently being executed.
//
//    							hPrevInstance - The handle to the instance of this
//									application that was last executed.  If this is the only
//									instance of this application executing, hPrevInstance is
//									NULL. In Win32 applications, this parameter is always NULL.
//
//    							lpCmdLine - A pointer to a null terminated string specifying
//									the command line of the application.
//
//    							nCmdShow - Specifies how the main window is to be diplayed.
//------------------------------------------------------------------------------
bool ANDOR885_Camera::InitializeCamera()
{
	AndorCapabilities	caps;
	char 				aBuffer[256];
	int					errorValue;
	bool				errorFlag = false;
//	int 				test,test2; //need to pause while camera initializes

	float				speed, STemp, gain;
	int					iSpeed, nAD, nAmp, nPreAmp, index, IsPreAmpAvailable;

	int i;


	caps.ulSize = sizeof(AndorCapabilities);

	long numCameras;
	GetAvailableCameras(&numCameras);

    GetCurrentDirectoryA(256,aBuffer);// Look in current working directory
                                    // for driver files. Note: had to override usual mapping of GetCurrentDirectory to
									// GetCurrentDirectoryW because of mismatch of argument types.

    errorValue=Initialize(aBuffer);  // Initialize driver in current directory
	printError(errorValue, "Initialize error", &errorFlag, ANDOR_ERROR);
	if (errorFlag)
		return true;

    // Get camera capabilities
    errorValue=GetCapabilities(&caps);
	printError(errorValue, "Get Andor Capabilities information Error", &errorFlag, ANDOR_ERROR);

    // Get Head Model
    errorValue=GetHeadModel(model);
	printError(errorValue, "Get Head Model information Error", &errorFlag, ANDOR_ERROR);

    // Get detector information
    errorValue=GetDetector(&imageWidth,&imageHeight);
	printError(errorValue, "Get Detector information Error", &errorFlag, ANDOR_ERROR);

	// Set frame transfer mode
	errorValue=SetFrameTransferMode((frameTransfer == ANDOR_ON) ? 1 : 0);
	printError(errorValue, "Set Frame Transfer Mode Error", &errorFlag, ANDOR_ERROR);

    // Set acquisition mode to required setting specified in xxxxWndw.c
    errorValue=SetAcquisitionMode(acquisitionMode);
	printError(errorValue, "Set Acquisition Mode Error", &errorFlag, ANDOR_ERROR);

	
	if(caps.ulGetFunctions > 32)
	{
		GetEMCCDGain(&EMCCDGain);
	}

	if(readMode == READMODE_IMAGE) {
    	// This function only needs to be called when acquiring an image. It sets
		// the horizontal and vertical binning and the area of the image to be
		// captured. In this example it is set to 1x1 binning and is acquiring the
		// whole image
  		SetImage(1,1,1,imageWidth,1,imageHeight);
	}

    // Set read mode to required setting specified in xxxxWndw.c
    errorValue=SetReadMode(readMode);
	printError(errorValue, "Set Read Mode Error", &errorFlag, ANDOR_ERROR);

    // Set Vertical speed to max
/*    STemp = 0;
    VSnumber = 0;
    GetNumberVSSpeeds(&index);
    for(iSpeed=0; iSpeed<index; iSpeed++){
      GetVSSpeed(iSpeed, &speed);
      if(speed > STemp){
        STemp = speed;
        VSnumber = iSpeed;
      }
    }
    errorValue=SetVSSpeed(VSnumber);
	printError(errorValue, "Set Vertical Speed Error", &errorFlag, ANDOR_ERROR);
*/
	
	if (!notDestructed){
		STemp = 0;
		GetNumberVSSpeeds(&index);
		for(iSpeed=0; iSpeed < index; iSpeed++){
			GetVSSpeed(iSpeed, &speed);
			verticalShiftSpeed_t.choices[iSpeed] = STI::Utils::valueToString(speed);
			if(speed > STemp){
				STemp = speed;
				verticalShiftSpeed = iSpeed;
			}
		}
		verticalShiftSpeed_t.initial = (--verticalShiftSpeed_t.choices.end())->second;
	}
    errorValue = SetVSSpeed(verticalShiftSpeed);
	printError(errorValue, "Set Vertical Speed Error", &errorFlag, ANDOR_ERROR);

	/* Set Vertical Clock Voltage; 
		note: only the fastest vertical shift speeds will benefit from the higher clock voltage;
			  increasing clock voltage adds noise.
	*/
	if (!notDestructed) {
		index = 0;
		errorValue = GetNumberVSAmplitudes(&index);
		if (errorValue == DRV_SUCCESS) {
			for (i = 0; i < index; i++){
				if (i == 0){
					verticalClockVoltage_t.choices[i] = "Normal";
				} else {
					verticalClockVoltage_t.choices[i] = STI::Utils::valueToString(i);
				}
			}
			verticalClockVoltage_t.initial = (verticalClockVoltage_t.choices.begin())->second;
		}
	}
	errorValue = SetVSAmplitude(0);
	printError(errorValue, "Set Vertical Clock Voltage Error", &errorFlag, ANDOR_ERROR);

    // Set Horizontal Speed to max and check bit depth
	//(scan over all possible AD channels; although, the 885 has only one 14-bit channel)
		STemp = 0;
	//    HSnumber = 0;
		ADnumber = 0;
	if (!notDestructed) {
		errorValue = GetNumberADChannels(&nAD);
		if (errorValue != DRV_SUCCESS){
		  std::cerr << "Get number AD Channel Error\n";
		  errorFlag = true;
		}
		else if (nAD != 1) {
			std::cerr << "Expect 1 AD channel for this camera. The following code will miss channels\n";
			errorFlag = true;
		}
		else {
			errorValue = GetNumberHSSpeeds(0, 0, &index);
			if(errorValue == DRV_SUCCESS){
				for (iSpeed = 0; iSpeed < index; iSpeed++) {
				  GetHSSpeed(0, 0, iSpeed, &speed);
				  horizontalShiftSpeed_t.choices[iSpeed] = STI::Utils::valueToString(speed);
				  if(speed < STemp){
					STemp = speed;
					horizontalShiftSpeed = iSpeed;
				  }
				}
				horizontalShiftSpeed_t.initial = horizontalShiftSpeed_t.choices.find(horizontalShiftSpeed)->second;
			}
			//getBitDepth
			if (DRV_SUCCESS != GetBitDepth(0, &bitDepth))
				return true;
		}

		errorValue = GetNumberAmp(&nAmp);
		printError(errorValue, "Get Number Amplifiers Error", &errorFlag, ANDOR_ERROR);

		errorValue = GetNumberPreAmpGains(&nPreAmp);
		printError(errorValue, "Get Number Preamplifiers Error", &errorFlag, ANDOR_ERROR);

		if (nAmp == 1 && nAD == 1) {
			for (i = 0; i < nPreAmp; i++) {
				errorValue = GetPreAmpGain(i, &gain);
				errorValue = IsPreAmpGainAvailable(0,0,horizontalShiftSpeed,i,&IsPreAmpAvailable);
				if (IsPreAmpAvailable == 1) {
					preAmpGain_t.choices[i] = STI::Utils::valueToString(gain);
				}
			}
			if (!preAmpGain_t.choices.empty()) {
				preAmpGain = preAmpGain_t.choices.begin()->first;
				//preAmpGainPos = 0;
				preAmpGain_t.initial = (preAmpGain_t.choices.begin())->second; // set the initial condition for the preamplifier gain
				errorValue = SetPreAmpGain(preAmpGain);
				printError(errorValue, "Set AD Channel Error", &errorFlag, ANDOR_ERROR);
			} else {
				std::cerr << "No gains available at this speed. Weird.";
				errorFlag = true;
			}
		} else {
			std::cerr << "Unexpected number of A/D's or output amps" << std::endl;
			std::cerr << "Expected A/D's:       1 \t Measured: " << nAD << std::endl;
			std::cerr << "Expected output Amps: 1 \t Measured: " << nAmp << std::endl;
			errorFlag = true;
		}
	}
	else {
		errorValue = SetPreAmpGain(preAmpGain);
		printError(errorValue, "Set AD Channel Error", &errorFlag, ANDOR_ERROR);
	}
	

    errorValue=SetADChannel(ADnumber);
	printError(errorValue, "Set AD Channel Error", &errorFlag, ANDOR_ERROR);


    errorValue=SetHSSpeed(0,horizontalShiftSpeed);
	printError(errorValue, "Set Horizontal Speed Error", &errorFlag, ANDOR_ERROR);

    if(errorFlag)
    	//MessageBox(GetActiveWindow(),aBuffer,"Error!",MB_OK); SMD
	    std::cerr<<aBuffer<<std::endl;


  // Wait for 2 seconds to allow MCD to calibrate fully before allowing an
  // acquisition to begin
//  test=GetTickCount();
//  do{
//  	test2=GetTickCount()-test;
//  }while(test2<2000);

	Sleep(2000);

	errorValue = SetExposureTime(exposureTime);
	printError(errorValue, "Exposure time error", &errorFlag, ANDOR_ERROR);

	// It is necessary to get the actual times as the system will calculate the
	// nearest possible time. eg if you set exposure time to be 0, the system
	// will use the closest value (around 0.01s)
	  GetAcquisitionTimings(&exposureTime,&accumulateTime,&kineticTime);
	  std::cerr << "Actual Exposure Time is " << exposureTime << " s.\n";

  // Set Shutter is made up of ttl level, shutter and open close time

  //Check Get open close time
	if(openTime==0)
		openTime=1;
	if(closeTime==0)
		closeTime=1;

	// Set shutter
	errorValue=SetShutter(ttl,shutterMode,closeTime,openTime);
	if(errorValue!=DRV_SUCCESS){
		std::cerr << "Shutter error\n";
		errorFlag = true;  
	}
	else
		std::cerr << "Shutter set to specifications\n";

	/*// Determine availability of trigger option and set trigger selection
	std::map<int,std::string>::iterator it;
	std::vector<int> triggerKeys;
	for (it = triggerMode_t.choices.begin(); it != triggerMode_t.choices.end(); it++)
	{
		errorValue = SetTriggerMode(it->first);
		if (errorValue != DRV_SUCCESS)
			triggerKeys.push_back(it->first);
	}
	for (int i = 0; i < triggerKeys.size(); i++)
		triggerMode_t.choices.erase(triggerKeys.at(i));

	if (triggerMode_t.choices.empty()) {
		std::cerr << "No triggerModes found" << std::endl;
		return true;
	}
	else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL_EXPOSURE) != 
		triggerMode_t.choices.end()) 
		triggerMode = TRIGGERMODE_EXTERNAL_EXPOSURE;
	else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL) != 
		triggerMode_t.choices.end())
		triggerMode = TRIGGERMODE_EXTERNAL;
	else
		triggerMode = triggerMode_t.choices.begin()->first;

	errorValue=SetTriggerMode(triggerMode);
	printError(errorValue, "Set Trigger Mode Error", &errorFlag, ANDOR_ERROR);
	triggerMode_t.initial = triggerMode_t.choices.find(triggerMode)->second;
*/

	// Determine availability of trigger option and set trigger selection
	std::map<int,std::string>::iterator it;
	std::vector<int> triggerKeys;
	for (it = triggerMode_t.choices.begin(); it != triggerMode_t.choices.end(); it++)
	{
		errorValue = SetTriggerMode(it->first);
		if (errorValue != DRV_SUCCESS)
			triggerKeys.push_back(it->first);
	}
	for (int i = 0; i < triggerKeys.size(); i++)
		triggerMode_t.choices.erase(triggerKeys.at(i));

	if (triggerMode_t.choices.empty()) {
		std::cerr << "No triggerModes found" << std::endl;
		return true;
	}
	else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL_EXPOSURE) != 
		triggerMode_t.choices.end()) 
		triggerMode = TRIGGERMODE_EXTERNAL_EXPOSURE;
	else if (triggerMode_t.choices.find(TRIGGERMODE_EXTERNAL) != 
		triggerMode_t.choices.end())
		triggerMode = TRIGGERMODE_EXTERNAL;
	else
		triggerMode = triggerMode_t.choices.begin()->first;

	errorValue=SetTriggerMode(triggerMode);
	printError(errorValue, "Set Trigger Mode Error", &errorFlag, ANDOR_ERROR);
	triggerMode_t.initial = triggerMode_t.choices.find(triggerMode)->second;


	errorValue = GetTemperatureRange(&minTemp, &maxTemp);
	if (errorValue != DRV_SUCCESS){
		std::cerr << "Error finding temperature range or camera is not on" << std::endl;
		errorFlag = true;
	}
	else {
		std::cerr << "Temperature must be between " << minTemp << " and " << maxTemp << std::endl;
		std::cerr << "Warning: Water cooling is required for temperatures < -58 deg C" << std::endl;

		//Set temperature
		if (coolerSetpt > maxTemp || coolerSetpt < minTemp) {
			std::cerr << "Chosen temperature out of range." << std::endl;
			if (coolerSetpt > maxTemp)
				coolerSetpt = maxTemp;
			else
				coolerSetpt = minTemp;
			std::cerr << "Resetting temp to nearest acceptable value " << std::endl;
		} 

		errorValue = SetTemperature(coolerSetpt);
		printError(errorValue, "Error setting cooler temperature", &errorFlag, ANDOR_ERROR);

		int i;
		errorValue = IsCoolerOn(&i);
		if (i == 0) {
			// if it's off and it's supposed to be on, turn it on
			if (coolerStat == ANDOR_ON) {
				std::cerr << "Turning on cooler." << std::endl;
				errorValue = CoolerON();
				printError(errorValue, "Error turning on cooler", &errorFlag, ANDOR_ERROR);
			}
			
		} else if (i == 1) {
			std::cerr << "Cooler is on." << std::endl;
			//if it's on and it's supposed to be off, turn it off
			if (coolerStat == ANDOR_OFF)
			{
				errorValue = CoolerOFF();
				printError(errorValue, "Error turning off cooler", &errorFlag, ANDOR_ERROR);
			} else {
				errorValue = GetTemperature(&i);
				switch(errorValue){
					case DRV_TEMP_STABILIZED:
						std::cerr << "Cooler temp has stabilized at " << i << " deg C" << std::endl;
						break;
					case DRV_TEMP_NOT_REACHED:
						std::cerr << "Cooler temp is " << i << " deg C" << std::endl;
						std::cerr << "Cooler setpoint has not been reached." << std::endl;
						std::cerr << "This may be because water cooling is required for setpoints < -58 deg C" << std::endl;
						std::cerr << "Either wait or try resetting cooler setpoint" << std::endl;
						break;
					case DRV_TEMP_DRIFT:
						std::cerr << "Cooler temp is " << i << " deg C" << std::endl;
						std::cerr << "Cooler temperature has drifted. Try resetting setpoint" << std::endl;
						break;
					case DRV_TEMP_NOT_STABILIZED:
						std::cerr << "Cooler temp is " << i << " deg C" << std::endl;
						std::cerr << "Temperature has been reached, but cooler has not stabilized" << std::endl;
						std::cerr << "Either wait or try resetting cooler setpoint" << std::endl;
						break;
					default:
						std::cerr << "Unrecognized error sequence. Camera may be off or acquiring" << std::endl;
						break;
				}
			}
		}
		
		
		if(!errorFlag){
			std::cerr << "Cooler temperature set to: " << coolerSetpt << std::endl;
		}
	
	}




	errorValue = SetSpool(0,0,NULL,10);  //Disable spooling
	printError(errorValue, "Spool mode error", &errorFlag, ANDOR_ERROR);

	// Returns the value from PostQuitMessage
	return errorFlag;
}