示例#1
0
//Gateway routine
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	TaskHandle task;
	int32 numSampsPerChan;
	float64 timeout;

	uInt32 numChannels;
	int32 totalNumSamples;
	uInt32 arraySizeInSamples;
	uInt32 arraySizeInBytes;	
	int32 sampsRead;
	int32 numBytesPerSamp;
	int16 *dataBuffer;
	int32 status;
	int32 errorStringSize;
	char *errorString;

	double *sampsReadOutput;

	//Parse input arguments
	task = (TaskHandle)mxGetScalar(prhs[0]);
	numSampsPerChan = (int32)mxGetScalar(prhs[1]);
	timeout = (float64)mxGetScalar(prhs[2]);
	arraySizeInSamples = (uInt32)mxGetScalar(prhs[3]);
	
	//Determine # of channels and amt. of memory to allocate
	DAQmxGetTaskNumChans(task, &numChannels);
	totalNumSamples = arraySizeInSamples * numChannels;
	arraySizeInBytes = totalNumSamples * sizeof(int16);

	//Create memory for output arguments
	plhs[0] = mxCreateNumericMatrix(totalNumSamples, 1, mxINT16_CLASS, mxREAL); 
	plhs[1] = mxCreateDoubleScalar(0);
	dataBuffer = (int16*)mxGetPr(plhs[0]);
	sampsReadOutput = mxGetPr(plhs[1]);
	
	//Call DAQmx function
	status = (int32) DAQmxReadRaw(task, numSampsPerChan, timeout, dataBuffer, arraySizeInBytes, &sampsRead, &numBytesPerSamp, NULL);

	//Return output buffer
	if (!status)
	{
		mexPrintf("Successfully read %d samples of data\n", sampsRead);		
		*sampsReadOutput = (double)sampsRead;
	}
	else
	{
		//Display error string
		errorStringSize = DAQmxGetErrorString(status,NULL,0); //Gets size of buffer
		errorString = (char *)mxCalloc(errorStringSize,sizeof(char));
		DAQmxGetErrorString(status,errorString,errorStringSize);
		mexPrintf("ERROR in %s: %s\n", mexFunctionName(), errorString);
		mxFree(errorString);

		//Return an empty array insead
		mxDestroyArray(plhs[0]); //I think this is kosher
		plhs[0] = mxCreateNumericMatrix(0, 0, mxINT16_CLASS, mxREAL);
	}

}
示例#2
0
    int NationalInstrumentsDAQ::writeAO(float64 *data)
    {
      int32 written,
            N = _config->ao_samples_per_waveform();

#if 0
      {
        uInt32 nchan;
        char
          buf[1024],
          name[1024];
        memset(buf ,0,sizeof(buf ));
        memset(name,0,sizeof(name));
        DAQWRN( DAQmxGetTaskName(_ao.daqtask,name,sizeof(name)) );
        DAQWRN( DAQmxGetTaskNumChans(_ao.daqtask,&nchan) );
        DAQWRN( DAQmxGetTaskChannels(_ao.daqtask,buf,sizeof(buf)) );
        HERE;
        debug("NI-DAQmx Task (%s) has %d channels"ENDL"\t%s"ENDL,
          name,
          nchan,
          buf);

        while(nchan--)
        { DAQWRN( DAQmxGetNthTaskChannel(_ao.daqtask, 1+nchan, buf, sizeof(buf)) );
          DAQWRN( DAQmxGetPhysicalChanName(_ao.daqtask, buf, buf, sizeof(buf)) );
          debug("\t%d:\t%s"ENDL,nchan,buf);
        }
      }
      {
        FILE *fp = fopen("NationalInstrumentsDAQ_writeAO.f64","wb");
        fwrite(data,sizeof(f64),3*N,fp);
        fclose(fp);
      }
#endif

      DAQJMP( DAQmxWriteAnalogF64(_ao.daqtask,
        N,
        0,                           // autostart?
        1.0,                         // timeout (s) - to write - 0 causes write to fail if blocked at all
        DAQmx_Val_GroupByChannel,
        data,
        &written,
        NULL));
      Guarded_Assert( written == N );
      return 0; // success
Error:
      return 1; // fail
    }
示例#3
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 ; 
	}
}