2022-10-06 19:13:21 +00:00
|
|
|
/* #define DEBUGTRACE_ENABLED */
|
2022-05-23 15:26:29 +00:00
|
|
|
#include "debugtrace.hpp"
|
2022-07-29 07:32:26 +00:00
|
|
|
#include "lasp_daqconfig.h"
|
2022-05-23 15:26:29 +00:00
|
|
|
|
2023-06-14 19:23:53 +00:00
|
|
|
#include "lasp_config.h"
|
2022-05-23 15:26:29 +00:00
|
|
|
#include "lasp_daq.h"
|
|
|
|
#if LASP_HAS_ULDAQ == 1
|
|
|
|
#include "lasp_uldaq.h"
|
|
|
|
#endif
|
|
|
|
#if LASP_HAS_RTAUDIO == 1
|
|
|
|
#include "lasp_rtaudiodaq.h"
|
|
|
|
#endif
|
2023-06-14 19:23:53 +00:00
|
|
|
#if LASP_HAS_PORTAUDIO == 1
|
|
|
|
#include "lasp_portaudiodaq.h"
|
|
|
|
#endif
|
2022-10-11 08:05:28 +00:00
|
|
|
using rte = std::runtime_error;
|
2022-05-23 15:26:29 +00:00
|
|
|
|
2022-07-29 07:32:26 +00:00
|
|
|
Daq::~Daq() { DEBUGTRACE_ENTER; }
|
2022-07-20 12:58:48 +00:00
|
|
|
|
2022-05-23 15:26:29 +00:00
|
|
|
std::unique_ptr<Daq> Daq::createDaq(const DeviceInfo &devinfo,
|
2022-10-10 17:17:38 +00:00
|
|
|
const DaqConfiguration &config) {
|
2022-05-23 15:26:29 +00:00
|
|
|
DEBUGTRACE_ENTER;
|
|
|
|
|
|
|
|
#if LASP_HAS_ULDAQ == 1
|
2022-07-29 07:32:26 +00:00
|
|
|
if (devinfo.api.apicode == LASP_ULDAQ_APICODE) {
|
2022-05-23 15:26:29 +00:00
|
|
|
return createUlDaqDevice(devinfo, config);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if LASP_HAS_RTAUDIO == 1
|
2022-10-10 17:17:38 +00:00
|
|
|
// See lasp_daqconfig.h:114 ALSA, up to
|
2022-07-29 07:32:26 +00:00
|
|
|
if (devinfo.api.apicode == LASP_RTAUDIO_APICODE) {
|
2022-05-23 15:26:29 +00:00
|
|
|
return createRtAudioDevice(devinfo, config);
|
|
|
|
}
|
2023-06-14 19:23:53 +00:00
|
|
|
#endif
|
|
|
|
#if LASP_HAS_PORTAUDIO == 1
|
|
|
|
if (devinfo.api.apicode == LASP_PORTAUDIO_APICODE) {
|
|
|
|
return createPortAudioDevice(devinfo, config);
|
|
|
|
}
|
2022-05-23 15:26:29 +00:00
|
|
|
#endif
|
2022-10-11 08:05:28 +00:00
|
|
|
throw rte(string("Unable to match Device API: ") + devinfo.api.apiname);
|
2022-05-23 15:26:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config)
|
2022-10-10 17:17:38 +00:00
|
|
|
: DaqConfiguration(config), DeviceInfo(devinfo) {
|
|
|
|
DEBUGTRACE_ENTER;
|
2022-07-20 12:58:48 +00:00
|
|
|
|
2022-10-11 08:05:28 +00:00
|
|
|
if (duplexMode()) {
|
|
|
|
if (neninchannels() == 0) {
|
|
|
|
throw rte("Duplex mode enabled, but no input channels enabled");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nenoutchannels() == 0) {
|
|
|
|
throw rte("Duplex mode enabled, but no output channels enabled");
|
|
|
|
}
|
|
|
|
}
|
2023-03-10 14:44:19 +00:00
|
|
|
if(!duplexMode() && monitorOutput) {
|
|
|
|
throw rte("Output monitoring only allowed when running in duplex mode");
|
|
|
|
}
|
2022-10-11 08:05:28 +00:00
|
|
|
|
2022-10-10 17:17:38 +00:00
|
|
|
if (!hasInternalOutputMonitor && monitorOutput) {
|
2022-10-11 08:05:28 +00:00
|
|
|
throw rte(
|
2022-10-10 17:17:38 +00:00
|
|
|
"Output monitor flag set, but device does not have output monitor");
|
|
|
|
}
|
2022-05-23 15:26:29 +00:00
|
|
|
|
2022-10-10 17:17:38 +00:00
|
|
|
if (!config.match(devinfo)) {
|
2022-10-11 08:05:28 +00:00
|
|
|
throw rte("DaqConfiguration does not match device info");
|
2022-10-10 17:17:38 +00:00
|
|
|
}
|
2022-10-11 12:50:44 +00:00
|
|
|
if (neninchannels(false) > devinfo.ninchannels) {
|
2022-10-11 08:05:28 +00:00
|
|
|
throw rte(
|
2022-10-10 17:17:38 +00:00
|
|
|
"Number of enabled input channels is higher than device capability");
|
2022-07-20 12:58:48 +00:00
|
|
|
}
|
2022-10-11 12:50:44 +00:00
|
|
|
if (nenoutchannels() > devinfo.noutchannels) {
|
2022-10-11 08:05:28 +00:00
|
|
|
throw rte(
|
2022-10-10 17:17:38 +00:00
|
|
|
"Number of enabled output channels is higher than device capability");
|
|
|
|
}
|
|
|
|
}
|
2022-05-23 15:26:29 +00:00
|
|
|
|
|
|
|
double Daq::samplerate() const {
|
2022-09-27 15:20:45 +00:00
|
|
|
DEBUGTRACE_ENTER;
|
2022-05-23 15:26:29 +00:00
|
|
|
return availableSampleRates.at(sampleRateIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
DataTypeDescriptor::DataType Daq::dataType() const {
|
|
|
|
return availableDataTypes.at(dataTypeIndex);
|
|
|
|
}
|
2022-10-10 17:17:38 +00:00
|
|
|
const DataTypeDescriptor &Daq::dtypeDescr() const {
|
|
|
|
return dtype_map.at(dataType());
|
|
|
|
}
|
2022-05-23 15:26:29 +00:00
|
|
|
|
2022-10-17 17:37:31 +00:00
|
|
|
dvec Daq::inputRangeForEnabledChannels(const bool include_monitor) const {
|
|
|
|
dvec res;
|
|
|
|
auto chs = enabledInChannels(include_monitor);
|
|
|
|
for(auto& ch : chs) {
|
|
|
|
res.push_back(availableInputRanges.at(ch.rangeIndex));
|
2022-05-23 15:26:29 +00:00
|
|
|
}
|
2022-10-17 17:37:31 +00:00
|
|
|
return res;
|
2022-05-23 15:26:29 +00:00
|
|
|
}
|
|
|
|
|
2022-10-17 17:37:31 +00:00
|
|
|
us Daq::neninchannels(const bool include_monitorchannel) const {
|
2022-07-20 12:58:48 +00:00
|
|
|
boolvec eninchannels = this->eninchannels(include_monitorchannel);
|
|
|
|
return std::count(eninchannels.cbegin(), eninchannels.cend(), true);
|
2022-05-23 15:26:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
us Daq::nenoutchannels() const {
|
2022-07-20 12:58:48 +00:00
|
|
|
boolvec enchannels = this->enoutchannels();
|
|
|
|
return std::count(enchannels.cbegin(), enchannels.cend(), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
boolvec Daq::eninchannels(bool include_monitor) const {
|
|
|
|
boolvec res;
|
|
|
|
if (hasInternalOutputMonitor && include_monitor) {
|
|
|
|
res.push_back(monitorOutput);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto &ch : inchannel_config) {
|
|
|
|
res.push_back(ch.enabled);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
boolvec Daq::enoutchannels() const {
|
|
|
|
boolvec res;
|
|
|
|
for (auto &ch : outchannel_config) {
|
|
|
|
res.push_back(ch.enabled);
|
|
|
|
}
|
|
|
|
return res;
|
2022-05-23 15:26:29 +00:00
|
|
|
}
|