Beispiel #1
0
    //************************************
    // Method:    setupCLK
    // FullName:  fetch::device::NationalInstrumentsDAQ::setupCLK
    // Access:    public
    // Returns:   void
    // Qualifier:
    //
    // set up counter for sample clock
    // - A finite pulse sequence is generated by a pair of on-board counters.
    //   In testing, it appears that after the device is reset, initializing
    //   the counter task doesn't work quite right.  First, I have to start the
    //   task with the paired counter once.  Then, I can set things up normally.
    //   After initializing with the paired counter once, things work fine until
    //   the device (or computer) is reset.  My guess is this is a fault of the
    //   board or driver software.
    // - below, we just cycle the counters when config gets called.  This ensures
    //   everything configures correctly the first time, even after a device
    //   reset or cold start.
    //************************************
    void NationalInstrumentsDAQ::setupCLK(float64 nrecords, float64 record_frequency_Hz)
    {
      TaskHandle clk = 0;

      int32      N = _config->ao_samples_per_waveform();
      float64   hz = computeSampleFrequency(nrecords, record_frequency_Hz);
      const char *dev          =_config->name().c_str(),
                 *ctr          =_config->ctr().c_str(),
                 *armstart_in  =_config->armstart().c_str(),
                 *gate_out     =_config->frame_trigger_out().c_str(),
                 *trig         =_config->trigger().c_str();
      float64     lvl          =_config->level_volts();
      char term_ctr[1024]={0},
           term_gate[1024]={0},
           term_arm_out[1024]={0};
      make_terminal_name(term_ctr    ,sizeof(term_ctr)    ,dev,ctr);
      make_terminal_name(term_gate   ,sizeof(term_gate)   ,dev,ctr);
      strcat(term_gate,"Gate");
      make_terminal_name(term_arm_out,sizeof(term_arm_out),dev,gate_out);

      DAQERR( DAQmxClearTask(_clk.daqtask) ); // Once a DAQ task is started, it needs to be cleared before restarting
      DAQERR( DAQmxCreateTask("fetch_CLK",&_clk.daqtask));
      clk = _clk.daqtask;
      DAQERR(DAQmxCreateCOPulseChanFreq     (clk,term_ctr,NULL,DAQmx_Val_Hz,DAQmx_Val_Low,0.0,hz,0.5));
      DAQERR(DAQmxCfgImplicitTiming         (clk,DAQmx_Val_FiniteSamps,N));
      DAQERR(DAQmxCfgDigEdgeStartTrig       (clk,"AnalogComparisonEvent",DAQmx_Val_Rising));
      DAQERR(DAQmxSetArmStartTrigType       (clk,DAQmx_Val_DigEdge));             // Arm trigger has to be through clk
      DAQERR(DAQmxSetDigEdgeArmStartTrigSrc (clk,armstart_in));
      DAQERR(DAQmxSetDigEdgeArmStartTrigEdge(clk,DAQmx_Val_Rising));
      DAQERR(DAQmxSetStartTrigRetriggerable (clk,1));
      DAQERR(DAQmxConnectTerms(term_gate,term_arm_out,DAQmx_Val_DoNotInvertPolarity));
    }
//Function: Run
//Description: Runs acquisition routine in a new thread
//			   This function cannot access gui widgets so all variables are frozen when thread class instance is created
void AcqThread::run()
{
        int             error=0;
        TaskHandle	digTaskHandle=0;
        bool		done;
        int		retVal;
        int		numZSteps;
        int             iZCount;
        int		x1;
        int		x2;
        int		y1;
        int		y2;
        int		numValidXSamps;
        int		numValidYSamps;
        double		debug;

	//set to not be terminated (default)
	terminate = false;

	//scaling coeff has not been calculated for this acq yet
	bScaleCoeffCalc = false;		

	//overscan values have not yet been calculated into the fov
	scanEng->setOverscanCalculated(false);

	done = false;

        do
        {
            //if regular acq (not line scan), call generateWaveForms
            if(!bLinescan)
            {
                scanEng->initScan(true,false);
                retVal = scanEng->generateWaveForms();
                retVal = acqEng->initAcq(true,false);
            }
            else  //Line scan mode
            {
                retVal = scanEng->initScan(true,true);

                if(!NIVisionCurrContourInfo)
                {
                    emit sendMessageForPopup("Error","No data points defined\n");
                    goto Error;
                }
                if (NIVisionCurrContourInfo->type != IMAQ_LINE)
                {
                    emit sendMessageForPopup("Error","Points must be defined with line tool\n");
                    goto Error;
                }

                //grab endpoints from line contour
                x1=NIVisionCurrContourInfo->structure.line->start.x;
                y1=NIVisionCurrContourInfo->structure.line->start.y;
                x2=NIVisionCurrContourInfo->structure.line->end.x;
                y2=NIVisionCurrContourInfo->structure.line->end.y;
		
                //Update data class
                data2P->Header.setLsX1(x1);
                data2P->Header.setLsX2(x2);
                data2P->Header.setLsY1(y1);
                data2P->Header.setLsY2(y2);

                //Calc the voltages that correspond to the x1,y1,x2,y2.  These will define the line scan waveforms.
                double x1V,y1V,x2V,y2V;
                CalcXYVoltsFromPxlVal(x1, y1, x1V, y1V);
                scanEng->setROIPt1XVolts(x1V);
                scanEng->setROIPt1YVolts(y1V);
                CalcXYVoltsFromPxlVal(x2, y2, x2V, y2V);
                scanEng->setROIPt2XVolts(x2V);
                scanEng->setROIPt2YVolts(y2V);

                retVal = scanEng->generateLineScanWaveForms();
                retVal = acqEng->initAcq(true,true);
            }
		
            //_____Setup for 3D Acq if needed_____
            if (acqEng->getB3DAcq())
            {
                numZSteps = this->CalcNumZSteps();
                CalcIntensityScalingCoeff();
            }
            else
                numZSteps = 1;

            //_____DAQmx DigOut Configure Code (Sample clock for Aout and Ain)____________________________________________
            DAQmxErrChk (DAQmxCreateTask("SampleClockTask",&digTaskHandle));
            DAQmxErrChk (DAQmxCreateCOPulseChanFreq (digTaskHandle, "/Dev1/ctr1", "SampleClock", DAQmx_Val_Hz, DAQmx_Val_Low,
                            0.1, scanEng->getSamp_Rate(), 0.5));
            if (bLinescan)
                DAQmxErrChk (DAQmxCfgImplicitTiming(digTaskHandle,DAQmx_Val_ContSamps ,scanEng->getNumSampsPerFrame_LS()))
            else
                DAQmxErrChk (DAQmxCfgImplicitTiming(digTaskHandle,DAQmx_Val_ContSamps ,scanEng->getNumSampsPerFrame()))


            //_____config AOut task for triggered, finite samps_____
            retVal = scanEng->configDAQmxTask(true, false);

            //_____Write samples to daq board_____
            retVal = scanEng->writeDAQmxTask();

            //_____Config AIn task for triggered, finite samps_____
            retVal = acqEng->configDAQmxTask(true, false);

            pDone = 0;
		
            for (iZCount = 0; iZCount < numZSteps; iZCount++)
            {
                //Only if there are Z steps to do
                if(numZSteps>1)
                {
                    //update Z Pos
                    zStep.setDesiredZPos(acqEng->getZStartPos() + (acqEng->getZStepSize() * iZCount));
                    //if (zStep->getDesiredZPos() != acqEng->getZPos())
                    if(numZSteps!=1)
                        zStep.MoveTo(zStep.getDesiredZPos(),zStep.getCurrentStepConvFactor());

                    //Manual zPos Calculations
                    //acqEng->setZPos(acqEng->getZPos()+acqEng->getZStepSize());
                    acqEng->setZPos(zStep.getCurrentZPos());

                    emit sigZPosChange(zStep.getCurrentZPos());

                    //Update pDone for updating gui progress bar
                    pDone = ((double)iZCount)/((double)numZSteps);
                    emit sendProgress(pDone);

                    //update gui field
                    //TwoPhotonGui::doubleSpinBox_zPos->setValue(zStepEng->getCurrentZPos()); NEED IMPLEMENTATION

                    //update acqEng field
                    //acqEng->setZPos(zStep->getCurrentZPos());		NOTE: this isn't working, using manual z-pos calculations
                }

                //if Aom Voltage scaling is selected, update Aom
                if(aomCtrl->getBIntScaling())
                {
                    debug = CalcAomIntVoltage((acqEng->getZStartPos()-acqEng->getZPos()));
                    AomUpdate(debug);		//turns AOM on
                }
                else
                {
                    AomUpdate(aomCtrl->getAomOnVoltage());  //Turns on AOM (no updating for depth)
                }


                //_____Start DAQmx Read._____
                retVal = acqEng->startDAQmxTask();
                //_____Start DAQmx write._____
                retVal = scanEng->startDAQmxTask();

                //_____Start DAQmx Trig._____
                DAQmxErrChk (DAQmxStartTask(digTaskHandle))
                //_____Perform read.  Execution will pause until all samps acquired._____
                retVal = acqEng->readDAQmxTask();

                /*		Added for diagnostics.  I want to write out the acq buffer here before I flip even rows.


                */

                /*
                        NEED IMPLEMENTATION
                //_____Update Histogram._____
                retVal = ProcessDataForHistogram(appState->acqStruct);
                if (appState->acqStruct.bInput1)
                        DeleteGraphPlot (appState->panelHandle, PANEL_HIST1, -1, VAL_IMMEDIATE_DRAW);
                        PlotXY (appState->panelHandle, PANEL_HIST1, appState->binsArray, appState->histArray1, NUM_BINS,
                                VAL_SHORT_INTEGER, VAL_UNSIGNED_INTEGER, VAL_VERTICAL_BAR, VAL_SOLID_SQUARE, VAL_SOLID,
                                1, VAL_BLUE);
                if (appState->acqStruct.bInput2)
                        DeleteGraphPlot (appState->panelHandle, PANEL_HIST2, -1, VAL_DELAYED_DRAW);
                        PlotXY (appState->panelHandle, PANEL_HIST2, appState->binsArray, appState->histArray2, NUM_BINS,
                                VAL_SHORT_INTEGER, VAL_UNSIGNED_INTEGER, VAL_VERTICAL_BAR, VAL_SOLID_SQUARE, VAL_SOLID,
                                1, VAL_BLUE);
                */

                //Update image display
                retVal = ProcessDataForDisplay(bLinescan);
                if(!bLinescan)
                {
                    numValidXSamps = (int)acqEng->getnumValidXSamps();
                    numValidYSamps = (int)acqEng->getnumValidYSamps();
                    if (!bLifetimeFov)
                    {
                        //Had to move imaq.. calls out of this thread.  Wasn't updating when called from this thread.
                        // using signal to notify other thread that new image data are in the image pointers.
                        imaqArrayToImage(*ptrToimage1, *ptrToimageData1, (int)acqEng->getnumValidXSamps(),(int)acqEng->getnumValidYSamps());
                        imaqDisplayImage(*ptrToimage1, displayWinNum1, 1);
                        //emit this->sigUdateVisionWindows(displayWinNum1,numValidXSamps,numValidYSamps);
                    }
                }
                else
                {
                    numValidXSamps = (int)acqEng->getWidth();
                    numValidYSamps = (int)acqEng->getRepeats();
                    if (!bLifetimeFov)
                    {
                        imaqArrayToImage(*ptrToimage2, *ptrToimageData2, (int)acqEng->getWidth(),(int)acqEng->getRepeats());
                        imaqDisplayImage(*ptrToimage2, displayWinNum2, 1);
                        //emit this->sigUdateVisionWindows(displayWinNum2,numValidXSamps,numValidYSamps);
                    }
                }

                //imaqHistogram(image1,65536,0,1,NULL);

                //Update Data2P class instance before writing it to file
                updateDataPtr();

                //Save the data to file if requested
                if (acqEng->getSaveData())
                {
                    if(!bLinescan)
                    {
                            Update2PDataStruct();

                            if (acqEng->getBInput1())
                                    retVal = data2P->WriteTheData(1,acqEng);
                            if (acqEng->getBInput2())
                                    retVal = data2P->WriteTheData(2,acqEng);
                    }
                    else	//If linescan, need to record correct lineLength/lineRate
                    {
                            retVal =scanEng->calcLineLengthStruct(x1,y1,x2,y2);
                            retVal =scanEng->calcLineRate();
                            Update2PDataStruct();
                            data2P->Header.setLineRate(data2P->Header.getLinescanRate());	//ensure linerate recorded is that of linescan

                            if (acqEng->getBInput1())
                                retVal = data2P->WriteTheData(1,acqEng);
                            if (acqEng->getBInput2())
                                retVal = data2P->WriteTheData(2,acqEng);
                    }

                }

                DAQmxStopTask(digTaskHandle);
                retVal = acqEng->stopDAQmxTask();
                retVal = scanEng->stopDAQmxTask();
                //retVal = scanEng->clearDAQmxTask();
                //scanEng->setScanTaskHandle(0);

                if(terminate)
                        goto Kill;

                //turn off Aom until ready to image again (set to 0 volts)
                AomUpdate(0.0);
                aomCtrl->setAomOn(false);
            }
Kill:
            retVal = scanEng->stopDAQmxTask();
            //Cleanup ...
            //	retVal = AcqEngineStopDAQmxTask(acqStruct);
            DAQmxClearTask(scanEng->getScanTaskHandle());
            scanEng->setScanTaskHandle(0);
            //	retVal = ScanEngineStopDAQmxTask(scanStruct);
            DAQmxClearTask(acqEng->getAcqTaskHandle());
            acqEng->setAcqTaskHandle(0);
            DAQmxClearTask(digTaskHandle);

            scanEng->releaseMemory();
            acqEng->releaseMemory();

        }while(bContinuous && (!terminate));

	/*
	SetCtrlVal(appState->panelHandle,PANEL_ledRunning,0);	NEED IMPLEMENTATION
	SetCtrlVal(appState->panelHandle,PANEL_ledAcquiring,0);
	SetCtrlVal(appState->panelHandle,PANEL_cbx3DAcq,0);
	SetCtrlVal(appState->panelHandle,PANEL_cbxSave,0);
	
	
	*/

	//Disable Aom (set to 0 volts)--------------------
	AomUpdate(0.0);
	aomCtrl->setAomOn(false);

	bScaleCoeffCalc = false;

	pDone = 0;

	emit acqFinished();

	quit();
	return;

Error:
	//return;

	if( DAQmxFailed(error) )
            DAQmxGetExtendedErrorInfo(errBuff,2048);

            //DAQmxDisconnectTerms ("/Dev1/PFI12", "/Dev1/PFI1");

	if( digTaskHandle!=0 ) 
	{
            // _____DAQmx Stop Code
            DAQmxStopTask(digTaskHandle);
            DAQmxClearTask(digTaskHandle);
	}
	if( scanEng->getScanTaskHandle() != 0 ) 
	{
            DAQmxStopTask(scanEng->getScanTaskHandle());
            DAQmxClearTask(scanEng->getScanTaskHandle());
            scanEng->setScanTaskHandle(0);

            //SetCtrlVal(appState->panelHandle,PANEL_ledRunning,0);		NEED IMPLEMENTATION
            //SetCtrlVal(appState->panelHandle,PANEL_ledAcquiring,0);
	}
	if( acqEng->getAcqTaskHandle() != 0 ) 
	{
            DAQmxStopTask(acqEng->getAcqTaskHandle());
            DAQmxClearTask(acqEng->getAcqTaskHandle());
            acqEng->setAcqTaskHandle(0);
	}
	
	if (scanEng->getMemIsAllocated())
            scanEng->releaseMemory();
	
	if (acqEng->getMemIsAllocated())
            acqEng->releaseMemory();


//	if( DAQmxFailed(error) )
//		QMessageBox::about(this,"DAQmx Error",errBuff);
        emit sendMessageForPopup("DAQmx Error",errBuff);
	emit acqFinished();
	return;

}
Beispiel #3
0
void ScanThreadLinear::InitializeSyncAndScan(void)
{
//CLEAR TASKS
	DAQmxClearTask(taskClock);
	DAQmxClearTask(taskTrig);
	DAQmxClearTask(taskTrA);
	DAQmxClearTask(taskAnalog);
	
	Samps = globalOptions->IMAGEHEIGHT+NumPtsDw;
	LineRate = Samps*FrameRate;
	
	//CREATE TASKS
	DAQmxCreateTask("",&taskAnalog);
	DAQmxCreateTask("",&taskTrig);
	DAQmxCreateTask("",&taskTrA);
	DAQmxCreateTask("",&taskClock);

	
	/*************************
		   CLOCK SOURCE 
	*************************/
	//CREATE INTERNAL CLOCK SOURCE
	DAQmxCreateCOPulseChanFreq(taskClock, "Dev1/ctr0", "", DAQmx_Val_Hz, 
		DAQmx_Val_Low, __DDELAY, FrameRate, .2);

	
	/*************************
		DIGITAL PULSE TRAIN
	*************************/
	//CREATE DIGITAL LINE
	DAQmxCreateDOChan(taskTrig,"Dev1/port0/line0","",DAQmx_Val_ChanPerLine);

	//SET TIMING AND STATE CLOCK SOURCE
	//Clock source is based off the analog sample clock
	DAQmxCfgSampClkTiming(taskTrig,"ao/SampleClock",FrameRate*Samps,
		DAQmx_Val_Rising,DAQmx_Val_ContSamps,Samps);
	
	/*************************
		ANALOG SAW TOOTH
	*************************/
	//CREATE ANALOG CHANNEL
	DAQmxCreateAOVoltageChan(taskAnalog,"Dev1/ao0",
			   "",-10,10.0,DAQmx_Val_Volts,NULL);
	DAQmxCreateAOVoltageChan(taskAnalog,"Dev1/ao1",
		   "",-10,10.0,DAQmx_Val_Volts,NULL);

	//SET TIMING
	DAQmxCfgSampClkTiming(taskAnalog,"",FrameRate*Samps,
		DAQmx_Val_Rising,DAQmx_Val_ContSamps,Samps);

	//GET TERMINAL NAME OF THE TRIGGER SOURCE
	GetTerminalNameWithDevPrefix(taskTrig, "Ctr0InternalOutput",trigName);
	
	//TRIGGER THE ANALOG DATA BASED OFF INTERNAL TRIGGER (CLOCK SOURCE)
	DAQmxCfgDigEdgeStartTrig(taskAnalog,trigName,DAQmx_Val_Rising);

	if (globalOptions->bVolumeScan == false)
	{
		GenSawTooth(Samps,XScanVolts_mV,XScanOffset_mV,ScanBuff);

		for (int i = 0; i< Samps; i++)
			VolBuff[i] = ScanBuff[i];

		for (int i = Samps; i < 2*Samps; i++)
			VolBuff[i] = YScanOffset_mV/1000;

		DAQmxWriteAnalogF64(taskAnalog, Samps, false ,10 ,DAQmx_Val_GroupByChannel, VolBuff,NULL,NULL);

		//GENERATE PULSE TRAIN TO TRIGGER CAMERA
		GenPulseTrain(Samps,digiBuff);
		DAQmxWriteDigitalLines(taskTrig,Samps,false,10.0,DAQmx_Val_GroupByChannel,digiBuff,NULL,NULL);
	}
	else
	{
		
		int frameCount;

		GenSawTooth(Samps,XScanVolts_mV,XScanOffset_mV,ScanBuff);
		for (frameCount = 0; frameCount < globalOptions->NumFramesPerVol; frameCount++)
		{
			
			for (int i = 0; i< Samps; i++)
				VolumeBuff[i+frameCount*Samps] = ScanBuff[i];
		}

		GenStairCase(Samps,globalOptions->NumFramesPerVol,YScanVolts_mV, YScanOffset_mV, tempBuff);

		for (int i = 0; i < Samps*globalOptions->NumFramesPerVol; i++)
			VolumeBuff[i + Samps*globalOptions->NumFramesPerVol] = tempBuff[i];

		DAQmxWriteAnalogF64(taskAnalog, Samps*globalOptions->NumFramesPerVol, false ,10 ,DAQmx_Val_GroupByChannel, VolumeBuff,NULL,NULL);

		//GENERATE PULSE TRAIN TO TRIGGER CAMERA
		for (int frameCount = 0; frameCount < globalOptions->NumFramesPerVol; frameCount++)
		{
			GenPulseTrain(Samps,digiBuff);
			for (int i = 0; i< Samps; i++)
				digiVolBuff[i+frameCount*Samps] = digiBuff[i];
		}

		DAQmxWriteDigitalLines(taskTrig,Samps*globalOptions->NumFramesPerVol,false,10.0,DAQmx_Val_GroupByChannel,digiVolBuff,NULL,NULL);
	}


	//GENERATE PULSE TRAIN TO TRIGGER CAMERA
	DAQmxCreateCOPulseChanFreq(taskTrA,"Dev1/ctr1","",DAQmx_Val_Hz,DAQmx_Val_Low,0.0,LineRate,0.2);
	DAQmxCfgImplicitTiming(taskTrA,DAQmx_Val_FiniteSamps,globalOptions->IMAGEHEIGHT);
	DAQmxCfgDigEdgeStartTrig(taskTrA,"/Dev1/PFI4",DAQmx_Val_Rising);
	DAQmxSetStartTrigRetriggerable(taskTrA, 1);
	DAQmxConnectTerms ("/Dev1/Ctr1InternalOutput", "/Dev1/RTSI0",  DAQmx_Val_DoNotInvertPolarity);
	
	//START TASKS
	//IMPORTANT - Need to arm analog task first to make sure that the digital and analog waveforms are in sync
	DAQmxStartTask(taskAnalog);
	DAQmxStartTask(taskTrA);
	DAQmxStartTask(taskTrig);
	DAQmxStartTask(taskClock);
}
// from ConfigDAQmxTasks(float xVolts, float yVolts, ScanStructure scanStructure);
int LifetimeAcq::configDAQmxTasks(float xVolts, float yVolts, ScanEngine* scanStruct)
{
	int				error;
	int				retVal;
	char			errBuff[2048];
	double			voltagePair[2];
	//extern Trig_Channel;
	
	voltagePair[0] = (double)xVolts;
	voltagePair[1] = (double)yVolts;
	//_____DAQmx Configure Code________________________________________________________________
	
	
	
	//_____Setup analog output task_____
	DAQmxErrChk (DAQmxCreateTask("AnalogOuput",&aoTaskHandle));
	DAQmxErrChk (DAQmxCreateAOVoltageChan (aoTaskHandle, scanStruct->getXChan(), "xChan", 
						-2.0, 2.0, DAQmx_Val_Volts, NULL));
	DAQmxErrChk (DAQmxCreateAOVoltageChan (aoTaskHandle, scanStruct->getYChan(), "yChan", 
						-2.0, 2.0, DAQmx_Val_Volts, NULL));
	DAQmxErrChk (DAQmxWriteAnalogF64 (aoTaskHandle, 1, 1, 10, DAQmx_Val_GroupByChannel, 
						voltagePair, DAQmx_Val_GroupByChannel, NULL));
	
	
	//_____Setup Analog input task_____
	DAQmxErrChk (DAQmxCreateTask("TrigAcq",&acqTaskHandle));
	
	/*Add analog input channel to acqtask*/
	DAQmxErrChk (DAQmxCreateAIVoltageChan(acqTaskHandle, ACQ_CHANNEL, "PMT", 
						DAQmx_Val_RSE,ACQMIN, ACQMAX, DAQmx_Val_Volts,NULL));

	/*config analog input to use counter output as sample clock and continuous samps*/
	DAQmxErrChk (DAQmxCfgSampClkTiming (acqTaskHandle, SAMPCLK_CHANNEL, SAMP_RATE, 
		DAQmx_Val_Rising, DAQmx_Val_ContSamps, totSamps));

	/*Make buffer size slightly larger than default*/
	DAQmxErrChk (DAQmxSetBufferAttribute (acqTaskHandle, DAQmx_Buf_Input_BufSize, totSamps+1000));
	
	//_____Setup counter task_____
	DAQmxErrChk (DAQmxCreateTask ("couterOutTask", &ctrTaskHandle));
	/*Add counter clock to counter task*/
	DAQmxErrChk (DAQmxCreateCOPulseChanFreq (ctrTaskHandle, COUNTER_CHANNEL, "coChannel", 
					DAQmx_Val_Hz,DAQmx_Val_Low, 0, SAMP_RATE, 0.5));
	
	/*config clock for counter output task to generate correct numSamps*/					
	DAQmxErrChk (DAQmxCfgImplicitTiming (ctrTaskHandle, DAQmx_Val_FiniteSamps, numSamps));

	/*Config triggering of counter task*/
	DAQmxErrChk (DAQmxCfgDigEdgeStartTrig (ctrTaskHandle, TRIG_CHANNEL, DAQmx_Val_Rising));
	DAQmxErrChk (DAQmxSetTrigAttribute (ctrTaskHandle, DAQmx_StartTrig_Retriggerable, TRUE));
	
	

	return 1;

Error:
	if( DAQmxFailed(error) )
		DAQmxGetExtendedErrorInfo(errBuff,2048);

	retVal = this->stopTasks();

	//if( DAQmxFailed(error) )
	//	MessagePopup("DAQmx Error",errBuff);

	return 0;
}