int DllExport _nidaq_read (int id) { int32 samplesRead; sTask *pTask; sDataChain *pData, *pNext; pTask = tasks.item + id; if (pTask->type != DAQmx_Val_OnDemand) return 0; pData = pTask->current; /* if the data is full, make another chain */ if (pData->num == NBUF) { pNext = malloc(sizeof(sDataChain)); pNext->data = malloc(NBUF * pTask->numChannels * sizeof(short)); pNext->num = 0; pNext->next = 0; pData->next = pNext; pTask->current = pNext; pTask->num++; pData = pNext; } DAQmxReadBinaryI16 (pTask->handle, DAQmx_Val_Auto, 10.0, DAQmx_Val_GroupByScanNumber, pData->data + pData->num * pTask->numChannels, (NBUF - pData->num) * pTask->numChannels, &samplesRead, NULL); pData->num += samplesRead; return pTask->num; }
// [outputData, sampsPerChanRead] = readAnalogData(task, numSampsPerChan, outputFormat, timeout, outputVarSizeOrName) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { //Read input arguments // Get the task handle mxArray *mxTaskID = mxGetProperty(prhs[0],0,"taskID"); mxClassID clsID = mxGetClassID(mxTaskID); localAssert(clsID==TASKHANDLE_MXCLASS); TaskHandle *taskIDPtr = (TaskHandle*)mxGetData(mxTaskID); TaskHandle taskID = *taskIDPtr; //Determine if this is a buffered read operation uInt32 bufSize = 0; int32 status = DAQmxGetBufInputBufSize(taskID,&bufSize); if (status) { handleDAQmxError(status,"DAQmxGetBufInputBufSize"); } // Handle input arguments int32 numSampsPerChan = 0; // this does take negative vals in the case of DAQmx_Val_Auto if ((nrhs < 2) || mxIsEmpty(prhs[1]) || mxIsInf(mxGetScalar(prhs[1]))) { if (bufSize==0) numSampsPerChan = 1; else numSampsPerChan = DAQmx_Val_Auto; } else { numSampsPerChan = (int) mxGetScalar(prhs[1]); } char outputFormat[10]; if ((nrhs < 3) || mxIsEmpty(prhs[2])) strcpy_s(outputFormat,"scaled"); else mxGetString(prhs[2], outputFormat, 10); double timeout; if ((nrhs < 4) || mxIsEmpty(prhs[3]) || mxIsInf(mxGetScalar(prhs[3]))) timeout = DAQmx_Val_WaitInfinitely; else timeout = mxGetScalar(prhs[3]); bool outputData; //Indicates whether to return an outputData argument int outputVarSampsPerChan = 0; // this CAN take negative values in case of DAQmx_Val_Auto char outputVarName[MAXVARNAMESIZE]; if ((nrhs < 5) || mxIsEmpty(prhs[4])) { outputData = true; outputVarSampsPerChan = numSampsPerChan; //If value is DAQmx_Val_Auto, then the # of samples available will be queried before allocting array } else { outputData = mxIsNumeric(prhs[4]); if (outputData) { if (nlhs < 2) { mexErrMsgTxt("There must be two output arguments specified if a preallocated MATLAB variable is not specified"); } outputVarSampsPerChan = (int) mxGetScalar(prhs[4]); } else { mxGetString(prhs[4],outputVarName,MAXVARNAMESIZE); } } //Determine output data type mxClassID outputDataClass; mxArray *mxRawDataArrayAI = mxGetProperty(prhs[0],0,"rawDataArrayAI"); //Stored in MCOS Task object as an empty array of the desired class! mxClassID rawDataClass = mxGetClassID(mxRawDataArrayAI); char errorMessage[30]; if (!_strcmpi(outputFormat,"scaled")) outputDataClass = mxDOUBLE_CLASS; else if (!_strcmpi(outputFormat,"native")) outputDataClass = rawDataClass; else { sprintf_s(errorMessage,"Unrecognized output format: %s\n",outputFormat); mexErrMsgTxt(errorMessage); } //Determine # of output channels uInt32 numChannels; DAQmxGetReadNumChans(taskID,&numChannels); //Reflects number of channels in Task, or the number of channels specified by 'ReadChannelsToRead' property //Determine output buffer/size (creating if needed) mxArray *mxOutputDataBuf = NULL; if (outputData) { if (outputVarSampsPerChan == DAQmx_Val_Auto) { uInt32 buf = 0; status = DAQmxGetReadAvailSampPerChan(taskID,&buf); if (status) { handleDAQmxError(status, mexFunctionName()); } outputVarSampsPerChan = buf; } //localAssert(outputVarSampsPerChan >= 0); localAssert(outputVarSampsPerChan > 0); mxOutputDataBuf = mxCreateNumericMatrix(outputVarSampsPerChan,numChannels,outputDataClass,mxREAL); } else { localAssert(false); ////I don't believe this is working //mxOutputDataBuf = mexGetVariable("caller", outputVarName); //outputVarSampsPerChan = mxGetM(mxOutputDataBuf); ////TODO: Add check to ensure WS variable is of correct class } void* outputDataPtr = mxGetData(mxOutputDataBuf); localAssert(outputDataPtr!=NULL); uInt32 arraySizeInSamps = outputVarSampsPerChan * numChannels; localAssert(mxGetNumberOfElements(mxOutputDataBuf)==(size_t)arraySizeInSamps); int32 numSampsPerChanRead; if (outputDataClass == mxDOUBLE_CLASS) //'scaled' // float64 should be double status = DAQmxReadAnalogF64(taskID,numSampsPerChan,timeout,fillMode, (float64*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL); else { //'raw' switch (outputDataClass) { case mxINT16_CLASS: status = DAQmxReadBinaryI16(taskID, numSampsPerChan, timeout, fillMode, (int16*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL); break; case mxINT32_CLASS: status = DAQmxReadBinaryI32(taskID, numSampsPerChan, timeout, fillMode, (int32*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL); break; case mxUINT16_CLASS: status = DAQmxReadBinaryU16(taskID, numSampsPerChan, timeout, fillMode, (uInt16*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL); break; case mxUINT32_CLASS: status = DAQmxReadBinaryU32(taskID, numSampsPerChan, timeout, fillMode, (uInt32*) outputDataPtr, arraySizeInSamps, &numSampsPerChanRead, NULL); break; } } //Return output data if (!status) { //mexPrintf("Successfully read %d samples of data\n", numSampsRead); if (outputData) { if (nlhs > 0) plhs[0] = mxOutputDataBuf; else mxDestroyArray(mxOutputDataBuf); //If you don't read out, all the reading was done for naught } else { //I don't believe this is working localAssert(false); //mexPutVariable("caller", outputVarName, mxOutputDataBuf); // //if (nlhs >= 0) //Return empty value for output data // plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL); } if (nlhs>1) { //Return number of samples actually read plhs[1] = mxCreateDoubleScalar(0.0); double *sampsReadOutput = mxGetPr(plhs[1]); *sampsReadOutput = (double)numSampsPerChanRead; } } else { //Read failed handleDAQmxError(status, mexFunctionName()); } }
int DllExport _nidaq_store (int id, char *nodeName, int simultaneous) { char channelName[256], pathName[256]; int16 *data; int32 stats, samplesRead, idesc, idesc1, idesc2, idesc3, idesc4, idesc5, idesc6, dtype, null = 0; uInt32 i, arraySize, nPacket, packetSize; uInt64 numSamples; float64 convRate, dt, range, resolution, period; sTask *pTask; sDataChain *pData, *pNext; pTask = tasks.item + id; if (simultaneous) { dt = 0.0; } else { DAQmxGetTimingAttribute (pTask->handle, DAQmx_AIConv_Rate, &convRate); dt = 1.0/convRate; } if (pTask->type== DAQmx_Val_OnDemand) { pData = pTask->current; samplesRead = pTask->num * NBUF + pData->num; arraySize = pTask->numChannels * samplesRead; data = (int16 *)malloc(arraySize * sizeof (int16)); nPacket = NBUF * pTask->numChannels; packetSize = nPacket * sizeof (int16); pNext = pTask->start; for (i=0; i<pTask->num; i++) { pData = pNext; memcpy (data + i * nPacket, pData->data, packetSize); pNext = pData->next; free (pData->data); free (pData); } memcpy (data + i * nPacket, pNext->data, pNext->num * pTask->numChannels * sizeof (int16)); free (pNext->data); free (pNext); } else { /* # of samples */ DAQmxGetTimingAttribute (pTask->handle, DAQmx_SampQuant_SampPerChan, &numSamples); arraySize = pTask->numChannels * numSamples; data = (int16 *)malloc(arraySize * sizeof (int16)); DAQmxReadBinaryI16 (pTask->handle, DAQmx_Val_Auto, 10.0, DAQmx_Val_GroupByScanNumber, data, arraySize, &samplesRead, NULL); } /* Get the ADC resolution 12bits=NI6071,NI6115, 16bits=NI6143, 14bits but packed from bit 15=NI6133 */ DAQmxGetChanAttribute (pTask->handle, NULL, DAQmx_AI_Resolution, &resolution); if (resolution == 14.) resolution = 16.; resolution = ldexp (1.0, (int) resolution-1); /* Sampling time */ DAQmxGetTimingAttribute (pTask->handle, DAQmx_SampClk_Rate, &period); period = 1.0/period; //Rate -> Time dtype = DTYPE_SHORT; idesc1 = descr(&dtype, data, &arraySize, &null); dtype = DTYPE_ULONG; idesc2 = descr(&dtype, &i, &null); idesc3 = descr(&dtype, &pTask->numChannels, &null); dtype = DTYPE_ULONGLONG; numSamples = samplesRead - 1; idesc4 = descr(&dtype, &numSamples, &null); dtype = DTYPE_DOUBLE; idesc = descr(&dtype, &range, &null); idesc5 = descr(&dtype, &convRate, &null); idesc6 = descr(&dtype, &period, &null); for (i=0; i<pTask->numChannels; i++) { /* Translate a channel name to a node name */ DAQmxGetNthTaskChannel (pTask->handle, i+1, channelName, 256); sprintf (pathName, "%s:%s:FOO", nodeName, channelName); DAQmxGetChanAttribute (pTask->handle, channelName, DAQmx_AI_Max, &range); range /= resolution; convRate = i * dt; stats = MdsPut(pathName,"BUILD_SIGNAL(BUILD_WITH_UNITS($*$VALUE,'V'),(`$[$:*:($)]),MAKE_DIM(MAKE_WINDOW(0,$,$),MAKE_SLOPE(MAKE_WITH_UNITS($,'s'))))", &idesc, &idesc1, &idesc2, &idesc3, &idesc4, &idesc5, &idesc6, &null); } free (data); DAQmxStopTask (pTask->handle); return 1; }