222 lines
6.1 KiB
C++
222 lines
6.1 KiB
C++
#include "lasp_cppdaq.h"
|
|
#include "lasp_cppuldaq.h"
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <strstream>
|
|
using std::cout;
|
|
using std::endl;
|
|
|
|
#define MAX_DEV_COUNT_PER_API 20
|
|
|
|
#ifdef HAS_ULDAQ_LINUX_API
|
|
void fillUlDaqDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
|
|
|
UlError err;
|
|
unsigned int numdevs = MAX_DEV_COUNT_PER_API;
|
|
|
|
DaqDeviceDescriptor devdescriptors[MAX_DEV_COUNT_PER_API];
|
|
DaqDeviceDescriptor descriptor;
|
|
DaqDeviceInterface interfaceType = ANY_IFC;
|
|
|
|
err = ulGetDaqDeviceInventory(interfaceType, devdescriptors, &numdevs);
|
|
|
|
if (err != ERR_NO_ERROR)
|
|
throw std::runtime_error("UlDaq device inventarization failed");
|
|
|
|
for (unsigned i = 0; i < numdevs; i++) {
|
|
|
|
descriptor = devdescriptors[i];
|
|
|
|
DeviceInfo devinfo;
|
|
devinfo.api = uldaqapi;
|
|
string name, interface;
|
|
|
|
if (string(descriptor.productName) == "DT9837A") {
|
|
if (descriptor.devInterface == USB_IFC) {
|
|
name = "USB - ";
|
|
} else if (descriptor.devInterface == BLUETOOTH_IFC) {
|
|
/* devinfo. */
|
|
name = "Bluetooth - ";
|
|
} else if (descriptor.devInterface == ETHERNET_IFC) {
|
|
/* devinfo. */
|
|
name = "Ethernet - ";
|
|
}
|
|
|
|
name += string(descriptor.productName) + " ";
|
|
name += string(descriptor.uniqueId);
|
|
devinfo.device_name = name;
|
|
|
|
devinfo.api_specific_devindex = i;
|
|
devinfo.availableDataTypes.push_back(dtype_fl64);
|
|
devinfo.prefDataTypeIndex = 0;
|
|
|
|
devinfo.availableSampleRates.push_back(10000);
|
|
devinfo.availableSampleRates.push_back(12000);
|
|
devinfo.availableSampleRates.push_back(20000);
|
|
devinfo.availableSampleRates.push_back(24000);
|
|
devinfo.availableSampleRates.push_back(32000);
|
|
devinfo.availableSampleRates.push_back(48000);
|
|
devinfo.availableSampleRates.push_back(51000);
|
|
|
|
devinfo.prefSampleRateIndex = 5;
|
|
|
|
devinfo.availableFramesPerBlock.push_back(512);
|
|
devinfo.availableFramesPerBlock.push_back(1024);
|
|
devinfo.availableFramesPerBlock.push_back(2048);
|
|
devinfo.availableFramesPerBlock.push_back(4096);
|
|
devinfo.availableFramesPerBlock.push_back(8192);
|
|
devinfo.prefFramesPerBlockIndex = 1;
|
|
|
|
devinfo.availableInputRanges = {1.0, 10.0};
|
|
devinfo.prefInputRangeIndex = 0;
|
|
|
|
devinfo.ninchannels = 4;
|
|
devinfo.noutchannels = 1;
|
|
|
|
devinfo.hasInputIEPE = true;
|
|
devinfo.hasInputACCouplingSwitch = true;
|
|
devinfo.hasInputTrigger = true;
|
|
|
|
// Finally, this devinfo is pushed back in list
|
|
devinfolist.push_back(devinfo);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
vector<DeviceInfo> Daq::getDeviceInfo() {
|
|
vector<DeviceInfo> devs;
|
|
#ifdef HAS_ULDAQ_LINUX_API
|
|
fillUlDaqDeviceInfo(devs);
|
|
#endif
|
|
|
|
#ifdef HAS_RTAUDIO_ALSA_API
|
|
|
|
#endif
|
|
|
|
#ifdef HAS_RTAUDIO_PULSEAUDIO_API
|
|
#endif
|
|
|
|
#ifdef HAS_RTAUDIO_WIN_WASAPI_API
|
|
#endif
|
|
return devs;
|
|
}
|
|
|
|
DaqConfiguration::DaqConfiguration(const DeviceInfo &device) {
|
|
|
|
api = device.api;
|
|
device_name = device.device_name;
|
|
|
|
eninchannels.resize(device.ninchannels, false);
|
|
enoutchannels.resize(device.noutchannels, false);
|
|
|
|
inchannel_sensitivities.resize(device.ninchannels, 1.0);
|
|
for (us i = 0; i < eninchannels.size(); i++) {
|
|
std::strstream chname;
|
|
chname << "Unnamed input channel " << i;
|
|
inchannel_names.push_back(chname.str());
|
|
}
|
|
|
|
for (us i = 0; i < enoutchannels.size(); i++) {
|
|
std::strstream chname;
|
|
chname << "Unnamed output channel " << i;
|
|
outchannel_names.push_back(chname.str());
|
|
}
|
|
sampleRateIndex = device.prefSampleRateIndex;
|
|
dataTypeIndex = device.prefDataTypeIndex;
|
|
framesPerBlockIndex = device.prefFramesPerBlockIndex;
|
|
|
|
monitorOutput = false;
|
|
|
|
inputIEPEEnabled.resize(device.ninchannels, false);
|
|
inputACCouplingMode.resize(device.ninchannels, false);
|
|
inputRangeIndices.resize(device.ninchannels, device.prefInputRangeIndex);
|
|
|
|
assert(match(device));
|
|
}
|
|
|
|
bool DaqConfiguration::match(const DeviceInfo& dev) const {
|
|
return (dev.device_name == device_name && dev.api == api);
|
|
}
|
|
|
|
Daq *Daq::createDevice(const DaqConfiguration &config,
|
|
const vector<DeviceInfo> &devinfos) {
|
|
|
|
bool match;
|
|
DeviceInfo devinfo;
|
|
for (auto cur_devinfo : devinfos) {
|
|
if ((match = config.match(cur_devinfo))) {
|
|
devinfo = cur_devinfo;
|
|
break;
|
|
}
|
|
}
|
|
if (!match) {
|
|
return NULL;
|
|
}
|
|
|
|
// Some basic sanity checks
|
|
if ((devinfo.ninchannels != config.eninchannels.size())) {
|
|
throw runtime_error("Invalid length of enabled input channels specified");
|
|
}
|
|
if ((devinfo.noutchannels != config.enoutchannels.size())) {
|
|
throw runtime_error("outvalid length of enabled output channels specified");
|
|
}
|
|
|
|
if (devinfo.api == uldaqapi) {
|
|
return createUlDaqDevice(devinfo, config);
|
|
} else {
|
|
throw std::runtime_error(string("Unable to match API: ") +
|
|
devinfo.api.apiname);
|
|
}
|
|
}
|
|
|
|
|
|
Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config)
|
|
: DaqConfiguration(config), DeviceInfo(devinfo) {
|
|
|
|
if (monitorOutput && !(nenoutchannels() > 0)) {
|
|
throw runtime_error(
|
|
"Output monitoring only possible when output is enabled");
|
|
}
|
|
// Some sanity checks
|
|
if (eninchannels.size() != 4) {
|
|
throw runtime_error("Invalid length of enabled inChannels vector");
|
|
}
|
|
|
|
if (enoutchannels.size() != 1) {
|
|
throw runtime_error("Invalid length of enabled outChannels vector");
|
|
}
|
|
}
|
|
|
|
|
|
double Daq::samplerate() const {
|
|
assert(sampleRateIndex < availableSampleRates.size());
|
|
return availableSampleRates[sampleRateIndex];
|
|
}
|
|
|
|
|
|
DataType Daq::dataType() const {
|
|
|
|
assert((us)dataTypeIndex < availableDataTypes.size());
|
|
return availableDataTypes[dataTypeIndex];
|
|
}
|
|
double Daq::inputRangeForChannel(us ch) const {
|
|
if (!(ch < ninchannels)) {
|
|
throw runtime_error("Invalid channel number");
|
|
}
|
|
assert(inputRangeIndices.size() == eninchannels.size());
|
|
return availableInputRanges[inputRangeIndices[ch]];
|
|
}
|
|
us Daq::neninchannels() const {
|
|
mutexlock lock(mutex);
|
|
us inch = std::count(eninchannels.begin(), eninchannels.end(), true);
|
|
if (monitorOutput)
|
|
inch++;
|
|
return inch;
|
|
}
|
|
us Daq::nenoutchannels() const {
|
|
mutexlock lock(mutex);
|
|
return std::count(enoutchannels.begin(), enoutchannels.end(), true);
|
|
}
|