354 lines
9.8 KiB
C
354 lines
9.8 KiB
C
![]() |
/*
|
||
|
UL call demonstrated: ulDaqOutScan()
|
||
|
|
||
|
Purpose: Continuously output user generated data
|
||
|
on available D/A, and DIO output channels
|
||
|
|
||
|
Demonstration: Outputs user generated data on available
|
||
|
output channels
|
||
|
|
||
|
Steps:
|
||
|
1. Call ulGetDaqDeviceInventory() to get the list of available DAQ devices
|
||
|
2. Call ulCreateDaqDevice() to to get a handle for the first DAQ device
|
||
|
3. Verify the DAQ device has a DAQ output subsystem
|
||
|
4. Get the channel types supported by the DAQ output subsystem
|
||
|
5. Call ulConnectDaqDevice() to establish a UL connection to the DAQ device
|
||
|
6. Configure the analog and digital channels
|
||
|
7. Call ulDaqOutScan() to start the scan
|
||
|
8. Call ulDaqOutScanStatus to check the status of the background operation
|
||
|
9. Display the data for each channel
|
||
|
10. Call ulDaqOutScanStop() to stop the background operation
|
||
|
11. Call ulDisconnectDaqDevice and ulReleaseDaqDevice() before exiting the process
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <math.h>
|
||
|
#include "uldaq.h"
|
||
|
#include "utility.h"
|
||
|
|
||
|
|
||
|
// prototypes
|
||
|
UlError ConfigureAnalogOutputChannels(int numberOfChannels, Range range, DaqOutChanDescriptor* descriptors, int* scanDesriptorIndex);
|
||
|
UlError ConfigureDigitalOutputChannels(DaqDeviceHandle daqDeviceHandle, DaqOutChanDescriptor* descriptors, int* scanDesriptorIndex);
|
||
|
void CreateOutputData(int numberOfChannels, DaqOutChanDescriptor* descriptors, int numberOfSamplesPerChannel, Range range, long long bitsPerPort, double* buffer);
|
||
|
|
||
|
#define MAX_DEV_COUNT 100
|
||
|
#define MAX_STR_LENGTH 64
|
||
|
#define MAX_SCAN_OPTIONS_LENGTH 256
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
int descriptorIndex = 0;
|
||
|
DaqDeviceDescriptor devDescriptors[MAX_DEV_COUNT];
|
||
|
DaqDeviceInterface interfaceType = ANY_IFC;
|
||
|
DaqDeviceHandle daqDeviceHandle = 0;
|
||
|
unsigned int numDevs = MAX_DEV_COUNT;
|
||
|
|
||
|
int samplesPerChannel = 1000;
|
||
|
double rate = 1000;
|
||
|
Range range = BIP10VOLTS;
|
||
|
ScanOption scanOptions = (ScanOption) (SO_DEFAULTIO | SO_CONTINUOUS);
|
||
|
DaqOutScanFlag flags = DAQOUTSCAN_FF_DEFAULT;
|
||
|
|
||
|
int numberOfScanChannels = 2;
|
||
|
int hasDAQO = 0;
|
||
|
int index = 0;
|
||
|
int chanTypesMask = 0;
|
||
|
int bitsPerPort = 0;
|
||
|
|
||
|
char scanOptionsStr[MAX_SCAN_OPTIONS_LENGTH];
|
||
|
char daqoChannelTypeStr[MAX_SCAN_OPTIONS_LENGTH];
|
||
|
char rangeStr[MAX_SCAN_OPTIONS_LENGTH];
|
||
|
|
||
|
DaqOutChanDescriptor scanDescriptors[numberOfScanChannels];
|
||
|
|
||
|
int scanDescriptorIndex = 0;
|
||
|
|
||
|
double* buffer = NULL;
|
||
|
UlError err = ERR_NO_ERROR;
|
||
|
|
||
|
int i = 0;
|
||
|
int __attribute__((unused)) ret;
|
||
|
char c;
|
||
|
|
||
|
// Get descriptors for all of the available DAQ devices
|
||
|
err = ulGetDaqDeviceInventory(interfaceType, devDescriptors, &numDevs);
|
||
|
|
||
|
if (err != ERR_NO_ERROR)
|
||
|
goto end;
|
||
|
|
||
|
// verify at least one DAQ device is detected
|
||
|
if (numDevs == 0)
|
||
|
{
|
||
|
printf("No DAQ device is detected\n");
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
printf("Found %d DAQ device(s)\n", numDevs);
|
||
|
for (i = 0; i < (int) numDevs; i++)
|
||
|
printf(" %s: (%s)\n", devDescriptors[i].productName, devDescriptors[i].uniqueId);
|
||
|
|
||
|
// get a handle to the DAQ device associated with the first descriptor
|
||
|
daqDeviceHandle = ulCreateDaqDevice(devDescriptors[descriptorIndex]);
|
||
|
|
||
|
if (daqDeviceHandle == 0)
|
||
|
{
|
||
|
printf ("\nUnable to create a handle to the specified DAQ device\n");
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
// verify the specified device supports analog output
|
||
|
err = getDevInfoHasDaqo(daqDeviceHandle, &hasDAQO);
|
||
|
if (!hasDAQO)
|
||
|
{
|
||
|
printf("\nThe specified DAQ device does not support DAQ output\n");
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
printf("\nConnecting to device %s - please wait ...\n", devDescriptors[descriptorIndex].devString);
|
||
|
|
||
|
// establish a connection to the DAQ device
|
||
|
err = ulConnectDaqDevice(daqDeviceHandle);
|
||
|
|
||
|
if (err != ERR_NO_ERROR)
|
||
|
goto end;
|
||
|
|
||
|
// get the channel types supported by the DAQ output subsystem
|
||
|
err = getDaqoChannelTypes(daqDeviceHandle, &chanTypesMask);
|
||
|
|
||
|
if (chanTypesMask == 0)
|
||
|
{
|
||
|
printf("\nDaqOutScan is not supported by the specified DAQ device\n");
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
// configure the analog channels
|
||
|
if (chanTypesMask & DAQO_ANALOG)
|
||
|
{
|
||
|
// get the first supported output range
|
||
|
getAoInfoFirstSupportedRange(daqDeviceHandle, &range, rangeStr);
|
||
|
|
||
|
err = ConfigureAnalogOutputChannels(1, range, scanDescriptors, &scanDescriptorIndex);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// no analog channels so decrement the count
|
||
|
numberOfScanChannels--;
|
||
|
}
|
||
|
|
||
|
// configure the digital channels
|
||
|
if ((chanTypesMask & DAQO_DIGITAL) && err == ERR_NO_ERROR)
|
||
|
{
|
||
|
err = ConfigureDigitalOutputChannels(daqDeviceHandle, scanDescriptors, &scanDescriptorIndex);
|
||
|
|
||
|
// get the number of bits in the port
|
||
|
err = getDioInfoNumberOfBitsForFirstPort(daqDeviceHandle, &bitsPerPort);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// no digital channels so decrement the count
|
||
|
numberOfScanChannels--;
|
||
|
}
|
||
|
|
||
|
// allocate a buffer for the output data
|
||
|
buffer = (double*) malloc(numberOfScanChannels * samplesPerChannel * sizeof(double));
|
||
|
|
||
|
if(buffer == 0)
|
||
|
{
|
||
|
printf("\nOut of memory, unable to create scan buffer\n");
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
// fill the buffer with data
|
||
|
CreateOutputData(numberOfScanChannels, scanDescriptors, samplesPerChannel, range, bitsPerPort, buffer);
|
||
|
|
||
|
ConvertScanOptionsToString(scanOptions, scanOptionsStr);
|
||
|
|
||
|
printf("\n%s ready\n", devDescriptors[descriptorIndex].devString);
|
||
|
printf(" Function demonstrated: ulDaqOutScan()\n");
|
||
|
printf(" Number of scan channels: %d\n", numberOfScanChannels);
|
||
|
for (i = 0; i < numberOfScanChannels; i++)
|
||
|
{
|
||
|
ConvertDaqOChanTypeToString(scanDescriptors[i].type, daqoChannelTypeStr);
|
||
|
if (scanDescriptors[i].type == DAQO_ANALOG)
|
||
|
{
|
||
|
ConvertRangeToString(scanDescriptors[i].range, rangeStr);
|
||
|
printf(" ScanChannel %d: type = %s, channel = %d, range = %s\n", i, daqoChannelTypeStr, scanDescriptors[i].channel, rangeStr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf(" ScanChannel %d: type = %s, channel = %d\n", i, daqoChannelTypeStr, scanDescriptors[i].channel);
|
||
|
}
|
||
|
}
|
||
|
printf(" Samples per channel: %d\n", samplesPerChannel);
|
||
|
printf(" Rate: %f\n", rate);
|
||
|
printf(" Scan options: %s\n", scanOptionsStr);
|
||
|
printf("\nHit ENTER to continue\n");
|
||
|
|
||
|
ret = scanf("%c", &c);
|
||
|
|
||
|
ret = system("clear");
|
||
|
|
||
|
// start the output
|
||
|
err = ulDaqOutScan(daqDeviceHandle, scanDescriptors, numberOfScanChannels, samplesPerChannel, &rate, scanOptions, flags, buffer);
|
||
|
|
||
|
if(err == ERR_NO_ERROR)
|
||
|
{
|
||
|
ScanStatus status;
|
||
|
TransferStatus transferStatus;
|
||
|
|
||
|
// get the initial status of the background operation
|
||
|
ulDaqOutScanStatus(daqDeviceHandle, &status, &transferStatus);
|
||
|
|
||
|
while(status == SS_RUNNING && err == ERR_NO_ERROR && !enter_press())
|
||
|
{
|
||
|
// get the current status of the background operation
|
||
|
err = ulDaqOutScanStatus(daqDeviceHandle, &status, &transferStatus);
|
||
|
|
||
|
if(err == ERR_NO_ERROR)
|
||
|
{
|
||
|
// reset the cursor to the top of the display and
|
||
|
// show the termination message
|
||
|
resetCursor();
|
||
|
printf("Hit 'Enter' to terminate the process\n\n");
|
||
|
|
||
|
printf("actual scan rate = %f\n\n", rate);
|
||
|
|
||
|
index = transferStatus.currentIndex;
|
||
|
printf("currentScanCount = %10llu \n", transferStatus.currentScanCount);
|
||
|
printf("currentTotalCount = %10llu \n", transferStatus.currentTotalCount);
|
||
|
printf("currentIndex = %10d \n\n", index);
|
||
|
|
||
|
usleep(100000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ulDaqOutScanStop(daqDeviceHandle);
|
||
|
}
|
||
|
|
||
|
// before leaving, configure the digital port for input
|
||
|
for (i = 0; i < numberOfScanChannels; i++)
|
||
|
{
|
||
|
if (scanDescriptors[i].type == DAQO_DIGITAL)
|
||
|
{
|
||
|
err = ulDConfigPort(daqDeviceHandle, (DigitalPortType) scanDescriptors[i].channel, DD_INPUT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// disconnect from the DAQ device
|
||
|
ulDisconnectDaqDevice(daqDeviceHandle);
|
||
|
|
||
|
end:
|
||
|
|
||
|
// release the handle to the DAQ device
|
||
|
ulReleaseDaqDevice(daqDeviceHandle);
|
||
|
|
||
|
// release the scan buffer
|
||
|
if(buffer)
|
||
|
free(buffer);
|
||
|
|
||
|
if(err != ERR_NO_ERROR)
|
||
|
{
|
||
|
char errMsg[ERR_MSG_LEN];
|
||
|
ulGetErrMsg(err, errMsg);
|
||
|
printf("Error Code: %d \n", err);
|
||
|
printf("Error Message: %s \n", errMsg);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
UlError ConfigureAnalogOutputChannels(int numberOfChannels, Range range, DaqOutChanDescriptor* descriptors, int* scanDesriptorIndex)
|
||
|
{
|
||
|
UlError err = ERR_NO_ERROR;
|
||
|
int numbeOfAnalogChans = 0;
|
||
|
int i;
|
||
|
int index = *scanDesriptorIndex;
|
||
|
|
||
|
// fill a descriptor for each channel
|
||
|
for (i = 0; i< numberOfChannels; i++)
|
||
|
{
|
||
|
descriptors[index].channel = i;
|
||
|
descriptors[index].type = DAQO_ANALOG;
|
||
|
descriptors[index].range = range;
|
||
|
index++;
|
||
|
|
||
|
numbeOfAnalogChans++;
|
||
|
|
||
|
if (numbeOfAnalogChans == numberOfChannels)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*scanDesriptorIndex = index;
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
UlError ConfigureDigitalOutputChannels(DaqDeviceHandle daqDeviceHandle, DaqOutChanDescriptor* descriptors, int* scanDesriptorIndex)
|
||
|
{
|
||
|
UlError err = ERR_NO_ERROR;
|
||
|
DigitalPortType portType;
|
||
|
char portTypeStr[MAX_STR_LENGTH];
|
||
|
int index = *scanDesriptorIndex;
|
||
|
|
||
|
err = getDioInfoFirstSupportedPortType(daqDeviceHandle, &portType, portTypeStr);
|
||
|
|
||
|
// configure the port for output
|
||
|
err = ulDConfigPort(daqDeviceHandle, portType, DD_OUTPUT);
|
||
|
|
||
|
descriptors[index].channel = portType;
|
||
|
descriptors[index].type = DAQO_DIGITAL;
|
||
|
index++;
|
||
|
|
||
|
*scanDesriptorIndex = index;
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
void CreateOutputData(int numberOfChannels, DaqOutChanDescriptor* descriptors, int numberOfSamplesPerChannel, Range range, long long bitsPerPort, double* buffer)
|
||
|
{
|
||
|
const double twoPI = 2 * M_PI;
|
||
|
int sample, channel;
|
||
|
|
||
|
double min = 0.0;
|
||
|
double max = 0.0;
|
||
|
ConvertRangeToMinMax(range, &min, &max);
|
||
|
|
||
|
double f = twoPI / numberOfSamplesPerChannel;
|
||
|
double analogAmplitude = max - min ;
|
||
|
double digitalAmplitude = pow((double)2.0, bitsPerPort) - 1;;
|
||
|
double phase = 0.0;
|
||
|
|
||
|
int index = 0;
|
||
|
|
||
|
for (sample = 0; sample < numberOfSamplesPerChannel; sample++)
|
||
|
{
|
||
|
for (channel = 0; channel < numberOfChannels; channel++)
|
||
|
{
|
||
|
if (descriptors[channel].type == DAQO_ANALOG)
|
||
|
{
|
||
|
double value = (double) (sin(phase) * analogAmplitude/2);
|
||
|
|
||
|
if (channel== 0)
|
||
|
{
|
||
|
buffer[index++] = value;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
buffer[index++] = value/2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
buffer[index++] = (sin(phase) * digitalAmplitude/2 + (digitalAmplitude / 2));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
phase += f;
|
||
|
if( phase > twoPI )
|
||
|
phase = phase - twoPI;
|
||
|
}
|
||
|
}
|
||
|
|