Esempio n. 1
0
int microStep(int in)
{
	uInt8 MS1Sig[2];
	uInt8 MS2Sig[2];

	// Pull to zero for active in current controller mode
	switch (in){
	case 1 : // no mirostep
		MS1Sig[0] = 0;	MS1Sig[1] = 0;
		MS2Sig[0] = 0;	MS2Sig[1] = 0;
		break;
	case 2 : // half step
		MS1Sig[0] = 1;	MS1Sig[1] = 1;
		MS2Sig[0] = 0;	MS2Sig[1] = 0;
		break;
	case 4: // quarter step
		MS1Sig[0] = 0;	MS1Sig[1] = 0;
		MS2Sig[0] = 1;	MS2Sig[1] = 1;
		break;
	case 8: // eighth step
		MS1Sig[0] = 1;	MS1Sig[1] = 1;
		MS2Sig[0] = 1;	MS2Sig[1] = 1;
		break;
	default :
		return -1;
	}

	TaskHandle microStep = 0;

	DAQmxCreateTask("MS1", &microStep);
	DAQmxCreateDOChan(microStep, "Dev1/port0/line6", "MS1", DAQmx_Val_ChanForAllLines); // MS1
	DAQmxCfgSampClkTiming(microStep, NULL, 3000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 2); // Ext. Trig
	DAQmxWriteDigitalLines(microStep, 2, 0, 1000.0, DAQmx_Val_GroupByChannel, MS1Sig, NULL, NULL); // MS1 out 
	DAQmxStartTask(microStep);
	DAQmxWaitUntilTaskDone(microStep, 1.0); // Wait for action to be completed
	DAQmxStopTask(microStep);
	DAQmxClearTask(microStep);

	microStep = 0;

	DAQmxCreateTask("MS2", &microStep);
	DAQmxCreateDOChan(microStep, "Dev1/port0/line7", "MS2", DAQmx_Val_ChanForAllLines); // MS1
	DAQmxCfgSampClkTiming(microStep, NULL, 3000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 2); // Ext. Trig
	DAQmxWriteDigitalLines(microStep, 2, 0, 1000.0, DAQmx_Val_GroupByChannel, MS2Sig, NULL, NULL); // MS1 out 
	DAQmxStartTask(microStep);
	DAQmxWaitUntilTaskDone(microStep, 1.0); // Wait for action to be completed
	DAQmxStopTask(microStep);
	DAQmxClearTask(microStep);
	
	return 0;
}
Esempio n. 2
0
int32 Tweezers::CurrentRun(float64* curr, float64* indata, void* lpParam)
{
	threadinfo* t = (threadinfo*)lpParam;

	// config and start analog tast
	DAQmxErrRtn(DAQmxCfgSampClkTiming(AOtaskHandle,"",10*float64(1/(*t->delta*1E-3)),DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,(*t->cycles*10*t->nofFrames)));
	DAQmxErrRtn(DAQmxCfgOutputBuffer(AOtaskHandle, t->nofFrames*10));
	DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(AOtaskHandle, "PFI0", DAQmx_Val_Rising));
	DAQmxErrRtn(DAQmxWriteAnalogF64(AOtaskHandle,t->nofFrames*10,0,10.0,DAQmx_Val_GroupByChannel,curr,&written,NULL));
	DAQmxErrRtn(DAQmxStartTask(AOtaskHandle));

	cerr << "\nTrying to allocate buffer for " << (*t->cycles * t->nofFrames) << " frames\n";
	// config and start pulse channel with parameters set by user
	//DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_FiniteSamps,*t->cycles * t->nofFrames));
	DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_ContSamps,1));
	DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(DOtaskHandle, "PFI0", DAQmx_Val_Rising));
	DAQmxErrRtn(DAQmxStartTask(DOtaskHandle));

	// config analog in task
	DAQmxErrRtn(DAQmxCfgSampClkTiming(AItaskHandle,"Ctr0Out",100,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,*t->cycles * t->nofFrames));
	DAQmxErrRtn(DAQmxStartTask(AItaskHandle));

	// set trigger line to 1 - GO!
	DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[1],&written,NULL);
	
	// wait until cam trigger task is done
	DAQmxWaitUntilTaskDone(AOtaskHandle,-1);
	
	// reset trigger line
	DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[0],&written,NULL);

    // read protocol samples
	DAQmxReadAnalogF64(AItaskHandle,*t->cycles * t->nofFrames,5.0,DAQmx_Val_GroupByChannel,indata,*t->cycles * t->nofFrames*2,&read,NULL);

	//read indeed current
	ofstream strom;
	strom.open("newcurrent.txt", ofstream::app);
	for(int i=0;i<t->nofFrames;i++)
		strom<<i*(*t->delta*1E-3)<<"\t"<<indata[i]<<endl;
		strom.close();
	
	// stop tasks, disable trigger
	DAQmxStopTask(AOtaskHandle);
	DAQmxStopTask(DOtaskHandle);
	DAQmxStopTask(AItaskHandle);
	DAQmxDisableStartTrig(AOtaskHandle);
	DAQmxDisableStartTrig(DOtaskHandle);
}
Esempio n. 3
0
// constructor
Tweezers::Tweezers(double iF0,double id0,double ic1,double ic2,double ic3,double Anti_Voltage, void* lpParam)
{

	threadinfo* t = (threadinfo*)lpParam;

	// set calibration parameters
	F0 = iF0;
	d0 = id0;
	c1 = ic1;
	c2 = ic2;
	c3 = ic3;
	AV = Anti_Voltage;

	x4 = *t->x4;
	x3 = *t->x3;
	x2 = *t->x2;
	x1 = *t->x1;
	x0 = *t->x0;

	done = false;
	islate = false;

	residual = AV;
	tmp_residual = AV;

	trigdata[0][0] = 0;
	trigdata[1][0] = 1;

	// initialize device
	DAQmxResetDevice("Dev1");

	// create and setup analog task
	DAQmxCreateTask("AO",&AOtaskHandle);
	DAQmxCreateAOVoltageChan(AOtaskHandle,"Dev1/ao0","",-10.0,10.0,DAQmx_Val_Volts,NULL);

	DAQmxGetExtendedErrorInfo(errBuff,2048);
	cerr<<errBuff;

	// create and reset start trigger
	// implicit timing => no start task... (?)

	DAQmxCreateTask("TR",&TRtaskHandle);
	DAQmxCreateDOChan(TRtaskHandle,"Dev1/port0/line7","TR",DAQmx_Val_ChanForAllLines);
	DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[0],&written,NULL);

	// create pulse channel for trigger
	DAQmxCreateTask("DO",&DOtaskHandle);
	DAQmxCreateCOPulseChanTime(DOtaskHandle,"Dev1/Ctr0","",DAQmx_Val_Seconds,DAQmx_Val_Low,1E-3*(*t->wait),1E-3*(*t->delta)/2.0,1E-3*(*t->delta/2.0));

	DAQmxCreateTask("AI",&AItaskHandle);
	DAQmxCreateAIVoltageChan(AItaskHandle,"Dev1/ai0,Dev1/ai2","",DAQmx_Val_RSE,-10,+10,DAQmx_Val_Volts,NULL);

	DAQmxGetExtendedErrorInfo(errBuff,2048);
	cerr<<errBuff;

	// set to zero force
	Reset();
}
Esempio n. 4
0
void YON(int in)
{
	TaskHandle YOn = 0;	
	uInt8 onSig[2] = { in, in };

	DAQmxCreateTask("YON", &YOn);
	DAQmxCreateDOChan(YOn, "Dev1/port0/line5", "YON", DAQmx_Val_ChanForAllLines); // Yon	
	DAQmxCfgSampClkTiming(YOn, NULL, 3000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 2); // Ext. Trig
	DAQmxWriteDigitalLines(YOn, 2, 0, 1000.0, DAQmx_Val_GroupByChannel, onSig, NULL, NULL); // turn Off 
	DAQmxStartTask(YOn);
	DAQmxWaitUntilTaskDone(YOn, 1.0); // Wait for action to be completed
	DAQmxStopTask(YOn);
	DAQmxClearTask(YOn);
}
Esempio n. 5
0
void YDIR(int in)
{
	TaskHandle YDir = 0;
	uInt8 dirSig[2] = { in, in };

	DAQmxCreateTask("YDir", &YDir);
	DAQmxCreateDOChan(YDir, "Dev1/port0/line3", "YDir", DAQmx_Val_ChanForAllLines); // Ydirection
	DAQmxCfgSampClkTiming(YDir, NULL, 3000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 2); // Int. Trig
	DAQmxWriteDigitalLines(YDir, 2, 0, 1000.0, DAQmx_Val_GroupByChannel, dirSig, NULL, NULL); // turn Off 
	DAQmxStartTask(YDir);
	DAQmxWaitUntilTaskDone(YDir, 1.0); // Wait for action to be completed
	DAQmxStopTask(YDir);
	DAQmxClearTask(YDir);
}
Esempio n. 6
0
int32 Tweezers::RecoverFromError()
{
	// stop running tasks
	DAQmxErrRtn(DAQmxStopTask(DOtaskHandle));
	DAQmxErrRtn(DAQmxStopTask(AOtaskHandle));
	DAQmxErrRtn(DAQmxStopTask(AItaskHandle));

	// disable start triggers
	DAQmxErrRtn(DAQmxDisableStartTrig(DOtaskHandle));
	DAQmxErrRtn(DAQmxDisableStartTrig(AOtaskHandle));
	
	// reset trigger line
	DAQmxErrRtn(DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[0],&written,NULL));

	// reset to zero
	DAQmxErrRtn(SetCurrent(AV));
}
Esempio n. 7
0
void moveXStage(int steps, uInt8 clockSig[])
{
	int bits = steps * 2;

	TaskHandle	XClockOut = 0;
	uInt8 *signal = new uInt8[bits];
	for (int i = 0; i < bits; i += 2) {
		signal[i] = clockSig[0];
		signal[i + 1] = clockSig[1];
	}

	DAQmxCreateTask("X", &XClockOut);
	DAQmxCreateDOChan(XClockOut, "Dev1/port0/line0", "X", DAQmx_Val_ChanForAllLines); // Xmotor
	DAQmxCfgSampClkTiming(XClockOut, NULL, motorSpeed, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, bits); // Ext. Trig
	DAQmxWriteDigitalLines(XClockOut, bits, 0, 1000.0, DAQmx_Val_GroupByChannel, signal, NULL, NULL); // X Motor signal	
	DAQmxStartTask(XClockOut); // Pulse motor
	DAQmxWaitUntilTaskDone(XClockOut, 1000.0); // Wait for action to be completed
	DAQmxStopTask(XClockOut);
	DAQmxClearTask(XClockOut);

	delete signal;
}
Esempio n. 8
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);
}
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//General vars
	char errMsg[512];

	//Read input arguments
	float64 timeout;
	bool writeDigitalLines;
	uInt32 bytesPerChan;
	int numSampsPerChan;
	bool32 autoStart;
	int32 status;
	TaskHandle taskID, *taskIDPtr;

	//Get TaskHandle
	taskIDPtr = (TaskHandle*)mxGetData(mxGetProperty(prhs[0],0, "taskID"));
	taskID = *taskIDPtr;

	mxClassID writeDataClassID = mxGetClassID(prhs[1]);

	if ((writeDataClassID == mxLOGICAL_CLASS) || (writeDataClassID == mxDOUBLE_CLASS))
		writeDigitalLines = true;
	else
		writeDigitalLines = false;

	if (writeDigitalLines)
	{
		status = DAQmxGetWriteDigitalLinesBytesPerChan(taskID,&bytesPerChan); //This actually returns the number of bytes required to represent one sample of Channel data
		if (status)
			handleDAQmxError(status,"DAQmxGetWriteDigitalLinesBytesPerChan");
	}
	
	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
		timeout = DAQmx_Val_WaitInfinitely;
	else
	{
		timeout = (float64) mxGetScalar(prhs[2]);
		if (mxIsInf(timeout) || (timeout < 0))
			timeout = DAQmx_Val_WaitInfinitely;
	}		

	if ((nrhs < 4) || mxIsEmpty(prhs[3]))
	{
		if (writeDigitalLines)
			autoStart = true;
		else
			autoStart = false;
	}
	else
		autoStart = (bool32) mxGetScalar(prhs[3]);


	mwSize numRows = mxGetM(prhs[1]);
	if ((nrhs < 5) || mxIsEmpty(prhs[4]))
		if (writeDigitalLines)
		{
			numSampsPerChan = numRows / bytesPerChan;
		}
		else 
			numSampsPerChan = numRows;
	else
		numSampsPerChan = (int) mxGetScalar(prhs[4]);


	//Verify correct input length

	//Write data
	int32 sampsWritten;


	switch (writeDataClassID)
	{	
		case mxUINT32_CLASS:
			status = DAQmxWriteDigitalU32(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt32*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxUINT16_CLASS:
			status = DAQmxWriteDigitalU16(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt16*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxUINT8_CLASS:
			status = DAQmxWriteDigitalU8(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &sampsWritten, NULL);
		break;

		case mxDOUBLE_CLASS:
		case mxLOGICAL_CLASS:
			{
				if (numRows < (numSampsPerChan * bytesPerChan))
					mexErrMsgTxt("Supplied writeData argument must have at least (numSampsPerChan x numBytesPerChannel) rows.");
				else if (writeDataClassID == mxLOGICAL_CLASS)
					status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &sampsWritten, NULL);
				else //mxDOUBLE_CLASS
				{
					//Convert DOUBLE data to LOGICAL values
					double *writeDataRaw = mxGetPr(prhs[1]);
					mwSize numElements = mxGetNumberOfElements(prhs[1]);

					uInt8 *writeData = (uInt8 *)mxCalloc(numElements,sizeof(uInt8));					

					for (unsigned int i=0;i<numElements;i++)
					{
						if (writeDataRaw[i] != 0)
							writeData[i] = 1;
					}
					status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, writeData, &sampsWritten, NULL);

					mxFree(writeData);
				}
			}

		break;

		default:
			sprintf_s(errMsg,"Class of supplied writeData argument (%s) is not valid", mxGetClassName(prhs[1]));
			mexErrMsgTxt(errMsg);
	}

	//Handle output arguments
	if (nlhs > 0) {
		plhs[0] = mxCreateDoubleScalar(0);	
		double *sampsPerChanWritten = mxGetPr(plhs[0]);

		if (!status)
		{
			//mexPrintf("Successfully wrote %d samples of data\n", sampsWritten);		
			*sampsPerChanWritten = (double)sampsWritten;
		}
		else //Write failed
			handleDAQmxError(status, mexFunctionName());
	}

}
Esempio n. 10
0
int32 Tweezers::Run(float64* force, float64* indata, void* lpParam)
{
	threadinfo* t = (threadinfo*)lpParam;

	// init output data array
	float64 out_data[1];
	out_data[0] = 0.0;

	register int i = 0,j = 0;

	// # of samples to be generated per cycle
	register int nofSamples = (int)(t->nofFrames/(*t->cycles)) * (*t->delta)*1E-3 * Srate_HTSP;
	//cerr<<nofSamples<<" samples\n";

	// setup HTSP timing and deactivate onboard memory
	DAQmxErrRtn(DAQmxCfgSampClkTiming(AOtaskHandle,"OnboardClock",Srate_HTSP,DAQmx_Val_Rising,DAQmx_Val_HWTimedSinglePoint,nofSamples));
	DAQmxSetRealTimeConvLateErrorsToWarnings(AOtaskHandle, TRUE);

	// setup start trigger
	DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(AOtaskHandle, "PFI0", DAQmx_Val_Rising));

	// setup counter task and start trigger
	// maybe change trigger to digital line? need to use ContSamps, otherwise limited frame #
	//DAQmxErrRtn(DAQmxCreateCOPulseChanTime(DOtaskHandle,"Dev1/Ctr0","",DAQmx_Val_Seconds,DAQmx_Val_Low,0,1E-3*(*t->delta)/2,1E-3*(*t->delta/2)));
	DAQmxErrRtn(DAQmxCfgImplicitTiming(DOtaskHandle, DAQmx_Val_ContSamps, 1));

	// setup start trigger
	DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(DOtaskHandle, "PFI0", DAQmx_Val_Rising));

	// setup analog in task
	DAQmxErrRtn(DAQmxCfgSampClkTiming(AItaskHandle,"Ctr0Out",100,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,*t->cycles * t->nofFrames));
	//DAQmxErrRtn(DAQmxCfgDigEdgeStartTrig(AItaskHandle, "PFI0", DAQmx_Val_Rising));

	// start tasks (still waiting for edge trigger from TRtask)
	DAQmxErrRtn(DAQmxStartTask(DOtaskHandle));
	DAQmxErrRtn(DAQmxStartTask(AOtaskHandle));
	DAQmxErrRtn(DAQmxStartTask(AItaskHandle));

	// precalulate number of loop runs to speed up loop
	int samps = (nofSamples * (*t->cycles) - 1);
	
	// write first sample outside loop, so there is enough time to send the TR start trigger
	out_data[0] = current(force[0],t->dist);

	DAQmxErrRtn(DAQmxWriteAnalogF64(AOtaskHandle,1,true,-1,DAQmx_Val_GroupByChannel,out_data,&written,NULL));

	// GO!
	DAQmxErrRtn(DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[1],&written,NULL));

	// 1 kHz sample generation loop
	while(!(*t->bead_lost &&
			// [email protected]: 05/10/2012 16:16 - dont stop recording if bead is lost in Creep-noint protocol
			*t->protocol != "Creep-noint"
			// end of change
		) && i < samps)
	{
		j = (++i % nofSamples);
		//cerr<<j<<"\r";
		out_data[0] = current(force[j],t->dist);
		DAQmxErrRtn(DAQmxWaitForNextSampleClock(AOtaskHandle, 1.0, &islate));
		DAQmxErrRtn(DAQmxWriteAnalogF64(AOtaskHandle,1,true,-1,DAQmx_Val_GroupByChannel,out_data,&written,NULL));
		if(islate)
		{
			cerr<<i++<<"\n****** late write - out of sync! *******\n";
			*t->bead_lost = TRUE;
			t->syncerror = TRUE;
		}
	}

	printf("DEBUG: bead_lost(%d) protocol(%s) i(%d) samps(%d)\n",
		*t->bead_lost, *t->protocol, i, samps);

	// wait for last sample to be generated
	DAQmxErrRtn(DAQmxWaitForNextSampleClock(AOtaskHandle, 1.0, &islate));

	// make sure enough trigger pulses are generated
	Sleep(*t->delta * 5);

	// stop tasks
	DAQmxErrRtn(DAQmxStopTask(DOtaskHandle));
	DAQmxErrRtn(DAQmxStopTask(AOtaskHandle));

	// number of frames actually taken
	t->FramesTaken = 1 + floor(t->nofFrames * (double)i/(double)(nofSamples * (*t->cycles)));

	// read protocol samples
	DAQmxReadAnalogF64(AItaskHandle,t->FramesTaken,5.0,DAQmx_Val_GroupByChannel,indata,t->FramesTaken*2,&read,NULL);

	DAQmxErrRtn(DAQmxStopTask(AItaskHandle));
	
	// disable start triggers
	DAQmxErrRtn(DAQmxDisableStartTrig(DOtaskHandle));
	DAQmxErrRtn(DAQmxDisableStartTrig(AOtaskHandle));
	
	// reset trigger line
	DAQmxErrRtn(DAQmxWriteDigitalLines(TRtaskHandle,1,1,10,DAQmx_Val_GroupByChannel,trigdata[0],&written,NULL));

}
Esempio n. 11
0
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//General vars
	char errMsg[512];

	//Read input arguments
	float64 timeout;
	//bool dataIsLogicalOrDouble;  
	    // For unsigned int data (8, 16, or 32-bit) we call DAQmxWriteDigitalU<whatever>() to 
	    // write the data to the buffer.  For logical or double data, we call DAQmxWriteDigitalLines().
	    // For the first, the several channel settings have to be "packed" into a single unsigned int.
	    // For the second, each channel is set individually.
        // Note that a "channel" in this context is a thing you set up with a single call to the 
	    // DAQmxCreateDOChan() function.
	    // That is, a channel can consist of more than one TTL line.  
	    // This var is set to true iff the data is logical or double.
	uInt32 maxLinesPerChannel;
	int32 numSampsPerChan;  // The number of time points to output, aka the number of "scans"
	bool32 autoStart;
	int32 status;
	TaskHandle taskID, *taskIDPtr;

	//Get TaskHandle
	taskIDPtr = (TaskHandle*)mxGetData(mxGetProperty(prhs[0],0, "taskID"));
	taskID = *taskIDPtr;

	// Get type and dimensions of data array
	mxClassID writeDataClassID = mxGetClassID(prhs[1]);
    bool dataIsLogicalOrDouble = ((writeDataClassID == mxLOGICAL_CLASS) || (writeDataClassID == mxDOUBLE_CLASS)) ;
	mwSize numRows = mxGetM(prhs[1]);
	mwSize numCols = mxGetN(prhs[1]);

	// Determine the timeout
	if ((nrhs < 3) || mxIsEmpty(prhs[2]))
		timeout = DAQmx_Val_WaitInfinitely;
	else
	{
		timeout = (float64) mxGetScalar(prhs[2]);
		if (mxIsInf(timeout) || (timeout < 0))
			timeout = DAQmx_Val_WaitInfinitely;
	}		

	// Determine whether to start automatically or not
	if ((nrhs < 4) || mxIsEmpty(prhs[3]))
	{
		int32 sampleTimingType;
		status = DAQmxGetSampTimingType(taskID, &sampleTimingType) ;
		if (status)
			handleDAQmxError(status,"DAQmxSetSampTimingType");
		if ( sampleTimingType == DAQmx_Val_OnDemand )
		{
			// The task is using on-demand timing, so we want the 
			// new values to be immediately output.  (And trying to call 
			// DAQmxWriteDigitalLines() for an on-demand task, with autoStart set to false, 
			// will error anyway.
			autoStart = (bool32) true;
		}
		else
		{
			autoStart = (bool32) false;
		}
	}
	else
	{
		autoStart = (bool32) mxGetScalar(prhs[3]);
	}

	// Determine the number of scans (time points) to write out
	if ((nrhs < 5) || mxIsEmpty(prhs[4]))
	{
		if (dataIsLogicalOrDouble)
		{
			status = DAQmxGetWriteDigitalLinesBytesPerChan(taskID,&maxLinesPerChannel); 
				// maxLinesPerChannel is maximum number of lines per channel.
				// Each DO "channel" can consist of multiple DO lines.  (A channel is the thing created with 
				// a call to DAQmxCreateDOChan().)  So this returns the maximum number of lines per channel, 
				// across all the channels in the task.  When you call DAQmxWriteDigitalLines(), the data must consist
				// of (number of scans) x (number of channels) x maxLinesPerChannel uint8 elements.  If a particular channel has fewer lines
				// than the max number, the extra ones are ignored.
			if (status)
				handleDAQmxError(status,"DAQmxGetWriteDigitalLinesBytesPerChan");
			numSampsPerChan = (int32) (numRows/maxLinesPerChannel);  // this will do an implicit floor
		}
		else
			numSampsPerChan = (int32) numRows;
	}
	else
	{
		numSampsPerChan = (int32) mxGetScalar(prhs[4]);
	}

	// Verify that the data contains the right number of columns
	uInt32 numberOfChannels;
	status = DAQmxGetTaskNumChans(taskID, &numberOfChannels) ;
	if (status)
		handleDAQmxError(status,"DAQmxGetTaskNumChans");
	if (numCols != numberOfChannels )
	{
		mexErrMsgTxt("Supplied writeData argument must have as many columns as there are channels in the task.");
	}

	// Verify that the data contains enough rows that we won't read off the end of it.
	// Note that for logical or double data, the different lines for each channel must be stored in the *rows*.
	// So for each time point, there's a maxLinesPerChannel x nChannels submatrix for that time point.
	int numberOfRowsNeededPerScan = (dataIsLogicalOrDouble ? maxLinesPerChannel : 1) ;
	int minNumberOfRowsNeeded = numberOfRowsNeededPerScan * numSampsPerChan ;
	if (numRows < minNumberOfRowsNeeded )
	{
		mexErrMsgTxt("Supplied writeData argument does not have enough rows.");
	}

	//Write data
	int32 scansWritten;

	switch (writeDataClassID)
	{	
		case mxUINT32_CLASS:
			status = DAQmxWriteDigitalU32(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt32*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxUINT16_CLASS:
			status = DAQmxWriteDigitalU16(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt16*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxUINT8_CLASS:
			status = DAQmxWriteDigitalU8(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxLOGICAL_CLASS:
			status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, (uInt8*) mxGetData(prhs[1]), &scansWritten, NULL);
		break;

		case mxDOUBLE_CLASS:
			{
				//Convert DOUBLE data to LOGICAL values
				double *writeDataRaw = mxGetPr(prhs[1]);
				mwSize numElements = mxGetNumberOfElements(prhs[1]);

				uInt8 *writeData = (uInt8 *)mxCalloc(numElements,sizeof(uInt8));					

				for (unsigned int i=0;i<numElements;i++)
				{
					if (writeDataRaw[i] != 0)
						writeData[i] = 1;
				}
				status = DAQmxWriteDigitalLines(taskID, numSampsPerChan, autoStart, timeout, dataLayout, writeData, &scansWritten, NULL);

				mxFree(writeData);
			}
		break;

		default:
			sprintf_s(errMsg,"Class of supplied writeData argument (%s) is not valid", mxGetClassName(prhs[1]));
			mexErrMsgTxt(errMsg);
	}

	// If an error occured at some point during writing, deal with that
	if (status)
		handleDAQmxError(status, mexFunctionName());

	// Handle output arguments, if needed
	if (nlhs > 0) 
	{
		plhs[0] = mxCreateDoubleScalar(0);	
		double * sampsPerChanWritten = mxGetPr(plhs[0]);
		*sampsPerChanWritten = (double)scansWritten ; 
	}
}