lasp/lasp/device/lasp_cppdaq.cpp

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);
}