Working C++ multiple API sit
This commit is contained in:
parent
a43857070b
commit
29662c82e3
|
@ -5,6 +5,7 @@ add_library(cpp_daq lasp_cppdaq.cpp lasp_cppuldaq.cpp )
|
|||
|
||||
set_source_files_properties(lasp_daq.pyx PROPERTIES CYTHON_IS_CXX TRUE)
|
||||
set_source_files_properties(lasp_deviceinfo.pyx PROPERTIES CYTHON_IS_CXX TRUE)
|
||||
set_source_files_properties(lasp_daqconfig.pyx PROPERTIES CYTHON_IS_CXX TRUE)
|
||||
|
||||
set_source_files_properties(lasp_daq.cxx PROPERTIES COMPILE_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
|
||||
|
@ -12,12 +13,19 @@ set_source_files_properties(lasp_daq.cxx PROPERTIES COMPILE_FLAGS
|
|||
set_source_files_properties(lasp_deviceinfo.cxx PROPERTIES COMPILE_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
|
||||
|
||||
set_source_files_properties(lasp_daqconfig.cxx PROPERTIES COMPILE_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
|
||||
|
||||
cython_add_module(lasp_daq lasp_daq.pyx)
|
||||
cython_add_module(lasp_deviceinfo lasp_deviceinfo.pyx)
|
||||
cython_add_module(lasp_daqconfig lasp_daqconfig.pyx)
|
||||
|
||||
target_link_libraries(lasp_daq cpp_daq uldaq rtaudio pthread)
|
||||
target_link_libraries(lasp_deviceinfo cpp_daq uldaq rtaudio pthread)
|
||||
target_link_libraries(lasp_daqconfig cpp_daq uldaq rtaudio pthread)
|
||||
if(win32)
|
||||
target_link_libraries(lasp_daq python37)
|
||||
target_link_libraries(lasp_deviceinfo python37)
|
||||
target_link_libraries(lasp_daqconfig python37)
|
||||
endif(win32)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
from .lasp_daqconfig import *
|
||||
from .lasp_avtype import *
|
||||
from .lasp_device_common import *
|
||||
from .lasp_daq import *
|
||||
from .lasp_deviceinfo import *
|
||||
from .lasp_daqconfig import *
|
||||
|
||||
|
|
|
@ -39,16 +39,10 @@ cdef extern from "lasp_pyarray.h":
|
|||
|
||||
ctypedef unsigned us
|
||||
ctypedef vector[bool] boolvec
|
||||
ctypedef vector[double] dvec
|
||||
ctypedef vector[us] usvec
|
||||
|
||||
cdef extern from "lasp_cppdaq.h" nogil:
|
||||
cdef cppclass cppDaq "Daq":
|
||||
void start(SafeQueue[void*] *inQueue,
|
||||
SafeQueue[void*] *outQueue) except +
|
||||
void stop()
|
||||
double samplerate()
|
||||
us neninchannels()
|
||||
us nenoutchannels()
|
||||
DataType getDataType()
|
||||
|
||||
cdef cppclass DaqApi:
|
||||
string apiname
|
||||
|
@ -63,21 +57,27 @@ cdef extern from "lasp_cppdaq.h" nogil:
|
|||
|
||||
cdef cppclass cppDeviceInfo "DeviceInfo":
|
||||
DaqApi api
|
||||
string name
|
||||
string device_name
|
||||
unsigned devindex
|
||||
vector[DataType] availableDataTypes
|
||||
vector[double] availableSampleRates
|
||||
vector[us] availableFramesPerBlock
|
||||
|
||||
int prefSampleRateIndex
|
||||
int prefInputRangeIndex
|
||||
int prefFramesPerBlockIndex
|
||||
unsigned ninchannels
|
||||
unsigned noutchannels
|
||||
bool hasInputIEPE
|
||||
bool hasInputACCouplingSwitch
|
||||
bool hasInputTrigger
|
||||
vector[double] inputRanges
|
||||
vector[double] availableInputRanges
|
||||
|
||||
cdef cppclass DaqConfiguration:
|
||||
boolvec eninchannels
|
||||
boolvec enoutchannels
|
||||
vector[string] channel_names
|
||||
vector[double] channel_sensitivities
|
||||
unsigned sampleRateIndex
|
||||
DataType datatype
|
||||
bool monitorOutput
|
||||
|
@ -85,12 +85,19 @@ cdef extern from "lasp_cppdaq.h" nogil:
|
|||
|
||||
boolvec inputIEPEEnabled;
|
||||
boolvec inputACCouplingMode;
|
||||
boolvec inputHighRange;
|
||||
usvec inputRangeIndices;
|
||||
|
||||
cdef cppclass cppDaq "Daq":
|
||||
void start(SafeQueue[void*] *inQueue,
|
||||
SafeQueue[void*] *outQueue) except +
|
||||
void stop()
|
||||
double samplerate()
|
||||
us neninchannels()
|
||||
us nenoutchannels()
|
||||
DataType getDataType()
|
||||
|
||||
cdef cppclass DaqDevices:
|
||||
@staticmethod
|
||||
cppDaq* createDaqDevice(cppDeviceInfo&, DaqConfiguration&)
|
||||
|
||||
@staticmethod
|
||||
vector[cppDeviceInfo] getDeviceInfo()
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "lasp_cppdaq.h"
|
||||
#include "lasp_cppuldaq.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <strstream>
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
@ -11,7 +14,6 @@ void fillUlDaqDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
|||
|
||||
UlError err;
|
||||
unsigned int numdevs = MAX_DEV_COUNT_PER_API;
|
||||
unsigned deviceno;
|
||||
|
||||
DaqDeviceDescriptor devdescriptors[MAX_DEV_COUNT_PER_API];
|
||||
DaqDeviceDescriptor descriptor;
|
||||
|
@ -43,13 +45,11 @@ void fillUlDaqDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
|||
|
||||
name += string(descriptor.productName) + " ";
|
||||
name += string(descriptor.uniqueId);
|
||||
devinfo.name = name;
|
||||
devinfo.device_name = name;
|
||||
|
||||
devinfo.devindex = i;
|
||||
devinfo.api_specific_devindex = i;
|
||||
devinfo.availableDataTypes.push_back(dtype_fl64);
|
||||
|
||||
devinfo.ninchannels = 4;
|
||||
devinfo.noutchannels = 1;
|
||||
devinfo.prefDataTypeIndex = 0;
|
||||
|
||||
devinfo.availableSampleRates.push_back(10000);
|
||||
devinfo.availableSampleRates.push_back(12000);
|
||||
|
@ -61,17 +61,31 @@ void fillUlDaqDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
|||
|
||||
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> DaqDevices::getDeviceInfo() {
|
||||
vector<DeviceInfo> Daq::getDeviceInfo() {
|
||||
vector<DeviceInfo> devs;
|
||||
#ifdef HAS_ULDAQ_LINUX_API
|
||||
fillUlDaqDeviceInfo(devs);
|
||||
|
@ -89,8 +103,57 @@ vector<DeviceInfo> DaqDevices::getDeviceInfo() {
|
|||
return devs;
|
||||
}
|
||||
|
||||
Daq *DaqDevices::createDevice(const DeviceInfo &devinfo,
|
||||
const DaqConfiguration &config) {
|
||||
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())) {
|
||||
|
@ -107,3 +170,52 @@ Daq *DaqDevices::createDevice(const DeviceInfo &devinfo,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#ifndef LASP_CPPDAQ_H
|
||||
#define LASP_CPPDAQ_H
|
||||
#include <strstream>
|
||||
|
||||
#ifdef HAS_RTAUDIO
|
||||
#include <RtAudio.h>
|
||||
|
@ -13,12 +12,19 @@
|
|||
#include "lasp_cppqueue.h"
|
||||
#include "string"
|
||||
#include "vector"
|
||||
#include <mutex>
|
||||
using std::cerr;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::runtime_error;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::runtime_error;
|
||||
|
||||
typedef unsigned int us;
|
||||
typedef vector<bool> boolvec;
|
||||
typedef vector<double> dvec;
|
||||
typedef vector<us> usvec;
|
||||
typedef std::lock_guard<std::mutex> mutexlock;
|
||||
|
||||
class DataType {
|
||||
public:
|
||||
|
@ -28,10 +34,7 @@ class DataType {
|
|||
|
||||
DataType(const char *name, unsigned sw, bool is_floating)
|
||||
: name(name), sw(sw), is_floating(is_floating) {}
|
||||
DataType():
|
||||
name("invalid data type"),
|
||||
sw(0),
|
||||
is_floating(false) {}
|
||||
DataType() : name("invalid data type"), sw(0), is_floating(false) {}
|
||||
};
|
||||
|
||||
const DataType dtype_invalid;
|
||||
|
@ -90,83 +93,116 @@ const vector<DaqApi> compiledApis = {
|
|||
class DeviceInfo {
|
||||
public:
|
||||
DaqApi api;
|
||||
string name = "";
|
||||
unsigned devindex;
|
||||
string device_name = "";
|
||||
|
||||
int api_specific_devindex = -1;
|
||||
|
||||
vector<DataType> availableDataTypes;
|
||||
vector<double> availableSampleRates;
|
||||
vector<us> availableFramesPerBlock;
|
||||
int prefDataTypeIndex = 0;
|
||||
|
||||
vector<double> availableSampleRates;
|
||||
int prefSampleRateIndex = -1;
|
||||
|
||||
vector<us> availableFramesPerBlock;
|
||||
unsigned prefFramesPerBlockIndex = 0;
|
||||
|
||||
dvec availableInputRanges;
|
||||
int prefInputRangeIndex = 0;
|
||||
|
||||
unsigned ninchannels = 0;
|
||||
unsigned noutchannels = 0;
|
||||
|
||||
bool hasInputIEPE = false;
|
||||
bool hasInputACCouplingSwitch = false;
|
||||
bool hasInputTrigger = false;
|
||||
vector<double> inputRanges;
|
||||
|
||||
/* DeviceInfo(): */
|
||||
/* datatype(dtype_invalid) { } */
|
||||
|
||||
double prefSampleRate() const {
|
||||
if ((prefSampleRateIndex < availableSampleRates.size()) &&
|
||||
if (((us) prefSampleRateIndex < availableSampleRates.size()) &&
|
||||
(prefSampleRateIndex >= 0)) {
|
||||
return availableSampleRates[prefSampleRateIndex];
|
||||
} else {
|
||||
throw std::runtime_error("No prefered sample rate available");
|
||||
}
|
||||
}
|
||||
|
||||
operator string() const {
|
||||
std::stringstream str;
|
||||
str << api.apiname + " " << devindex <<
|
||||
" number of input channels: " << ninchannels <<
|
||||
" number of output channels: " << noutchannels;
|
||||
str << api.apiname + " " << api_specific_devindex
|
||||
<< " number of input channels: " << ninchannels
|
||||
<< " number of output channels: " << noutchannels;
|
||||
return str.str();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Device configuration parameters
|
||||
class DaqConfiguration {
|
||||
public:
|
||||
DaqApi api;
|
||||
string device_name;
|
||||
|
||||
boolvec eninchannels; // Enabled input channels
|
||||
boolvec enoutchannels; // Enabled output channels
|
||||
|
||||
unsigned sampleRateIndex; // Index in list of sample rates
|
||||
DataType
|
||||
datatype = dtype_invalid; // Required datatype for output, should be present in the list
|
||||
bool monitorOutput; // Whether the first output channel should be replicated
|
||||
vector<double> inchannel_sensitivities;
|
||||
vector<string> inchannel_names;
|
||||
|
||||
// This is not necessary at the moment
|
||||
/* vector<double> outchannel_sensitivities; */
|
||||
vector<string> outchannel_names;
|
||||
|
||||
us sampleRateIndex = 0; // Index in list of sample rates
|
||||
|
||||
us dataTypeIndex = 0; // Required datatype for output, should be
|
||||
// present in the list
|
||||
|
||||
us framesPerBlockIndex = 0;
|
||||
|
||||
bool monitorOutput = false; // Whether the first output channel should be replicated
|
||||
// to the input as the first channel
|
||||
|
||||
unsigned nFramesPerBlock;
|
||||
|
||||
boolvec inputIEPEEnabled;
|
||||
boolvec inputACCouplingMode;
|
||||
boolvec inputHighRange;
|
||||
|
||||
usvec inputRangeIndices;
|
||||
|
||||
// Create a default configuration, with all channels disabled on both
|
||||
// input and output, and default channel names
|
||||
DaqConfiguration(const DeviceInfo &device);
|
||||
|
||||
bool match(const DeviceInfo &devinfo) const;
|
||||
};
|
||||
|
||||
class Daq;
|
||||
class DaqDevices {
|
||||
class Daq : public DaqConfiguration,public DeviceInfo {
|
||||
|
||||
mutable std::mutex mutex;
|
||||
|
||||
public:
|
||||
static vector<DeviceInfo> getDeviceInfo();
|
||||
static Daq *createDevice(const DeviceInfo &, const DaqConfiguration &config);
|
||||
};
|
||||
|
||||
class Daq {
|
||||
static Daq *createDevice(const DaqConfiguration &config,
|
||||
const std::vector<DeviceInfo> &devinfos);
|
||||
|
||||
Daq(const DeviceInfo &devinfo, const DaqConfiguration &config);
|
||||
|
||||
public:
|
||||
virtual void start(SafeQueue<void *> *inqueue,
|
||||
SafeQueue<void *> *outqueue) = 0;
|
||||
|
||||
virtual void stop() = 0;
|
||||
virtual double samplerate() const = 0;
|
||||
virtual DataType getDataType() const = 0;
|
||||
|
||||
virtual bool isRunning() const = 0;
|
||||
|
||||
virtual ~Daq(){};
|
||||
virtual us neninchannels() const = 0;
|
||||
virtual us nenoutchannels() const = 0;
|
||||
us neninchannels() const;
|
||||
us nenoutchannels() const;
|
||||
|
||||
double samplerate() const;
|
||||
double inputRangeForChannel(us ch) const;
|
||||
DataType dataType() const;
|
||||
};
|
||||
|
||||
#endif // LASP_CPPDAQ_H
|
||||
|
|
|
@ -1,75 +1,18 @@
|
|||
#include "lasp_cppuldaq.h"
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <uldaq.h>
|
||||
#include <vector>
|
||||
|
||||
using std::cerr;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::runtime_error;
|
||||
typedef std::lock_guard<std::mutex> mutexlock;
|
||||
/* using std::this_thread; */
|
||||
using std::atomic;
|
||||
|
||||
/* using std::this_thread; */
|
||||
const us MAX_DEF_COUNT = 100;
|
||||
const us UL_ERR_MSG_LEN = 512;
|
||||
|
||||
class DT9837A : public Daq {
|
||||
us samplesPerBlock;
|
||||
double _samplerate;
|
||||
boolvec inChannels;
|
||||
boolvec high_range;
|
||||
boolvec outChannels;
|
||||
bool monitorOutput;
|
||||
atomic<bool> stopThread;
|
||||
DaqDeviceHandle handle = 0;
|
||||
|
||||
std::thread *thread = NULL;
|
||||
mutable std::mutex mutex;
|
||||
SafeQueue<void *> *inqueue = NULL;
|
||||
SafeQueue<void *> *outqueue = NULL;
|
||||
|
||||
double *inbuffer = NULL;
|
||||
double *outbuffer = NULL;
|
||||
|
||||
public:
|
||||
double samplerate() const { return this->_samplerate; }
|
||||
|
||||
DT9837A(us samplesPerBlock, const boolvec &inChannels,
|
||||
const boolvec &outChannels, double samplerate, bool monitorOutput,
|
||||
us device_no = 0);
|
||||
DT9837A(const DT9837A &) = delete;
|
||||
|
||||
~DT9837A();
|
||||
|
||||
void setIEPEEnabled(const boolvec &config);
|
||||
|
||||
// Coupling_ac: true, means AC coupling, false means DC coupling
|
||||
void setACCouplingMode(const boolvec &coupling_ac);
|
||||
|
||||
void setInputRange(const boolvec &high_range);
|
||||
|
||||
us neninchannels() const final;
|
||||
us nenoutchannels() const final;
|
||||
|
||||
bool isRunning() const { return bool(thread); }
|
||||
|
||||
virtual void start(SafeQueue<void *> *inqueue,
|
||||
SafeQueue<void *> *outqueue) final;
|
||||
|
||||
virtual void stop() final;
|
||||
DataType getDataType() const final { return dtype_fl64; }
|
||||
|
||||
friend void threadfcn(DT9837A *);
|
||||
};
|
||||
|
||||
inline void showErr(UlError err) {
|
||||
if (err != ERR_NO_ERROR) {
|
||||
char errmsg[UL_ERR_MSG_LEN];
|
||||
|
@ -78,34 +21,36 @@ inline void showErr(UlError err) {
|
|||
}
|
||||
}
|
||||
|
||||
DT9837A::DT9837A(us samplesPerBlock, const boolvec &inChannels,
|
||||
const boolvec &outChannels, double samplerate,
|
||||
bool monitorOutput, us deviceno)
|
||||
: samplesPerBlock(samplesPerBlock), _samplerate(samplerate),
|
||||
inChannels(inChannels), outChannels(outChannels),
|
||||
monitorOutput(monitorOutput) {
|
||||
if (monitorOutput && !(nenoutchannels() > 0)) {
|
||||
throw runtime_error(
|
||||
"Output monitoring only possible when output is enabled");
|
||||
}
|
||||
class DT9837A;
|
||||
void threadfcn(DT9837A *td);
|
||||
|
||||
class DT9837A : public Daq {
|
||||
|
||||
atomic<bool> stopThread;
|
||||
DaqDeviceHandle handle = 0;
|
||||
|
||||
std::thread *thread = NULL;
|
||||
SafeQueue<void *> *inqueue = NULL;
|
||||
SafeQueue<void *> *outqueue = NULL;
|
||||
|
||||
double *inbuffer = NULL;
|
||||
double *outbuffer = NULL;
|
||||
|
||||
us nFramesPerBlock;
|
||||
|
||||
public:
|
||||
DT9837A(const DeviceInfo &devinfo, const DaqConfiguration &config)
|
||||
: Daq(devinfo, config) {
|
||||
|
||||
stopThread = false;
|
||||
high_range = boolvec({false, false, false, false});
|
||||
|
||||
if (samplesPerBlock < 24 || samplesPerBlock > 8192) {
|
||||
nFramesPerBlock = availableFramesPerBlock[framesPerBlockIndex];
|
||||
|
||||
if (nFramesPerBlock < 24 || nFramesPerBlock > 8192) {
|
||||
throw runtime_error("Unsensible number of samples per block chosen");
|
||||
}
|
||||
|
||||
// Some sanity checks
|
||||
if (inChannels.size() != 4) {
|
||||
throw runtime_error("Invalid length of enabled inChannels vector");
|
||||
}
|
||||
|
||||
// Some sanity checks
|
||||
if (outChannels.size() != 1) {
|
||||
throw runtime_error("Invalid length of enabled outChannels vector");
|
||||
}
|
||||
if (samplerate < 10000 || samplerate > 51000) {
|
||||
if (samplerate() < 10000 || samplerate() > 51000) {
|
||||
throw runtime_error("Invalid sample rate");
|
||||
}
|
||||
|
||||
|
@ -121,12 +66,13 @@ DT9837A::DT9837A(us samplesPerBlock, const boolvec &inChannels,
|
|||
throw runtime_error("Device inventarization failed");
|
||||
}
|
||||
|
||||
if (deviceno >= numdevs) {
|
||||
if ((us) api_specific_devindex >= numdevs) {
|
||||
throw runtime_error("Device number {deviceno} too high {err}. This could "
|
||||
"happen when the device is currently not connected");
|
||||
}
|
||||
|
||||
descriptor = devdescriptors[deviceno];
|
||||
descriptor = devdescriptors[api_specific_devindex];
|
||||
|
||||
// get a handle to the DAQ device associated with the first descriptor
|
||||
handle = ulCreateDaqDevice(descriptor);
|
||||
|
||||
|
@ -144,15 +90,32 @@ DT9837A::DT9837A(us samplesPerBlock, const boolvec &inChannels,
|
|||
}
|
||||
|
||||
for (us ch = 0; ch < 4; ch++) {
|
||||
|
||||
err = ulAISetConfigDbl(handle, AI_CFG_CHAN_SENSOR_SENSITIVITY, ch, 1.0);
|
||||
showErr(err);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
throw runtime_error("Fatal: could normalize channel sensitivity");
|
||||
}
|
||||
|
||||
CouplingMode cm = inputACCouplingMode[ch] ? CM_AC : CM_DC;
|
||||
err = ulAISetConfig(handle, AI_CFG_CHAN_COUPLING_MODE, ch, cm);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
showErr(err);
|
||||
throw runtime_error("Fatal: could not set AC/DC coupling mode");
|
||||
}
|
||||
|
||||
IepeMode iepe = inputIEPEEnabled[ch] ? IEPE_ENABLED : IEPE_DISABLED;
|
||||
err = ulAISetConfig(handle, AI_CFG_CHAN_IEPE_MODE, ch, iepe);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
showErr(err);
|
||||
throw runtime_error("Fatal: could not set IEPE mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DT9837A::~DT9837A() {
|
||||
DT9837A(const DT9837A &) = delete;
|
||||
|
||||
~DT9837A() {
|
||||
UlError err;
|
||||
if (isRunning()) {
|
||||
stop();
|
||||
|
@ -166,66 +129,70 @@ DT9837A::~DT9837A() {
|
|||
}
|
||||
}
|
||||
|
||||
void DT9837A::setIEPEEnabled(const boolvec &config) {
|
||||
bool isRunning() const { return bool(thread); }
|
||||
|
||||
void start(SafeQueue<void *> *inqueue, SafeQueue<void *> *outqueue) {
|
||||
if (isRunning()) {
|
||||
throw runtime_error("Cannot change config while sampling is running");
|
||||
throw runtime_error("Thread is already running");
|
||||
}
|
||||
|
||||
// Some sanity checks
|
||||
if (config.size() != 4) {
|
||||
throw runtime_error("Invalid length of enabled IEPE config vector");
|
||||
bool hasinput = neninchannels() > 0;
|
||||
bool hasoutput = nenoutchannels() > 0;
|
||||
|
||||
if (neninchannels() > 0 && !inqueue) {
|
||||
throw runtime_error("Inqueue not given, while input is enabled");
|
||||
}
|
||||
|
||||
IepeMode iepe;
|
||||
UlError err;
|
||||
|
||||
for (us i = 0; i < config.size(); i++) {
|
||||
|
||||
iepe = config[i] ? IEPE_ENABLED : IEPE_DISABLED;
|
||||
err = ulAISetConfig(handle, AI_CFG_CHAN_IEPE_MODE, i, iepe);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
showErr(err);
|
||||
throw runtime_error("Fatal: could not set IEPE mode");
|
||||
}
|
||||
}
|
||||
if (nenoutchannels() > 0 && !outqueue) {
|
||||
throw runtime_error("outqueue not given, while output is enabled");
|
||||
}
|
||||
|
||||
void DT9837A::setACCouplingMode(const boolvec &coupling) {
|
||||
if (isRunning()) {
|
||||
throw runtime_error("Cannot change config while sampling is running");
|
||||
if (hasinput) {
|
||||
assert(!inbuffer);
|
||||
inbuffer =
|
||||
new double[neninchannels() * nFramesPerBlock * 2]; // Watch the 2!
|
||||
}
|
||||
if (hasoutput) {
|
||||
assert(!outbuffer);
|
||||
outbuffer =
|
||||
new double[nenoutchannels() * nFramesPerBlock * 2]; // Watch the 2!
|
||||
}
|
||||
this->inqueue = inqueue;
|
||||
this->outqueue = outqueue;
|
||||
|
||||
/* std::cerr << "************************ WARNING: Forcing coupling mode
|
||||
* to AC
|
||||
* **************************" << endl; */
|
||||
/* boolvec couplingmode = {true, true, true, true}; */
|
||||
/* setACCouplingMode(couplingmode); */
|
||||
|
||||
stopThread = false;
|
||||
thread = new std::thread(threadfcn, this);
|
||||
}
|
||||
|
||||
// Some sanity checks
|
||||
if (coupling.size() != 4) {
|
||||
throw runtime_error("Invalid length of enabled AC coupling mode vector");
|
||||
void stop() {
|
||||
if (!isRunning()) {
|
||||
throw runtime_error("No data acquisition running");
|
||||
}
|
||||
assert(thread);
|
||||
|
||||
stopThread = true;
|
||||
thread->join();
|
||||
delete thread;
|
||||
thread = NULL;
|
||||
|
||||
outqueue = NULL;
|
||||
inqueue = NULL;
|
||||
if (inbuffer)
|
||||
delete inbuffer;
|
||||
if (outbuffer)
|
||||
delete outbuffer;
|
||||
outbuffer = NULL;
|
||||
inbuffer = NULL;
|
||||
}
|
||||
|
||||
CouplingMode cm;
|
||||
UlError err;
|
||||
|
||||
for (us i = 0; i < coupling.size(); i++) {
|
||||
cm = coupling[i] ? CM_AC : CM_DC;
|
||||
|
||||
err = ulAISetConfig(handle, AI_CFG_CHAN_COUPLING_MODE, i, cm);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
showErr(err);
|
||||
throw runtime_error("Fatal: could not set IEPE mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DT9837A::setInputRange(const boolvec &high_range) {
|
||||
if (isRunning()) {
|
||||
throw runtime_error("Cannot change config while sampling is running");
|
||||
}
|
||||
|
||||
// Some sanity checks
|
||||
if (high_range.size() != 4) {
|
||||
throw runtime_error("Invalid length of enabled high range vector");
|
||||
}
|
||||
|
||||
this->high_range = high_range;
|
||||
}
|
||||
friend void threadfcn(DT9837A *);
|
||||
};
|
||||
|
||||
void threadfcn(DT9837A *td) {
|
||||
|
||||
|
@ -233,7 +200,7 @@ void threadfcn(DT9837A *td) {
|
|||
|
||||
const us nenoutchannels = td->nenoutchannels();
|
||||
us neninchannels = td->neninchannels();
|
||||
const us samplesPerBlock = td->samplesPerBlock;
|
||||
const us nFramesPerBlock = td->nFramesPerBlock;
|
||||
|
||||
const bool hasinput = neninchannels > 0;
|
||||
const bool hasoutput = nenoutchannels > 0;
|
||||
|
@ -252,16 +219,16 @@ void threadfcn(DT9837A *td) {
|
|||
|
||||
double samplerate = td->samplerate();
|
||||
|
||||
const double sleeptime = ((double)samplesPerBlock) / (4 * samplerate);
|
||||
const double sleeptime = ((double)nFramesPerBlock) / (4 * samplerate);
|
||||
const us sleeptime_us = (us)(sleeptime * 1e6);
|
||||
/* cerr << "Sleep time in loop: " << sleeptime_us << "us." << endl; */
|
||||
if (sleeptime_us < 10) {
|
||||
cerr << "ERROR: Too small buffer size (samplesPerBlock) chosen!" << endl;
|
||||
cerr << "ERROR: Too small buffer size (nFramesPerBlock) chosen!" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
const us buffer_mid_idx_in = neninchannels * samplesPerBlock;
|
||||
const us buffer_mid_idx_out = nenoutchannels * samplesPerBlock;
|
||||
const us buffer_mid_idx_in = neninchannels * nFramesPerBlock;
|
||||
const us buffer_mid_idx_out = nenoutchannels * nFramesPerBlock;
|
||||
|
||||
DaqDeviceHandle handle = td->handle;
|
||||
assert(handle);
|
||||
|
@ -289,14 +256,14 @@ void threadfcn(DT9837A *td) {
|
|||
assert(outqueue);
|
||||
|
||||
// Initialize the buffer with zeros, before pushing any data.
|
||||
for (us sample = 0; sample < 2 * samplesPerBlock; sample++) {
|
||||
for (us sample = 0; sample < 2 * nFramesPerBlock; sample++) {
|
||||
outbuffer[sample] = 0;
|
||||
}
|
||||
|
||||
cerr << "Starting output DAC" << endl;
|
||||
err = ulAOutScan(handle, 0, 0, BIP10VOLTS,
|
||||
/* BIP60VOLTS, */
|
||||
2 * td->samplesPerBlock, // Watch the 2 here!
|
||||
2 * td->nFramesPerBlock, // Watch the 2 here!
|
||||
&samplerate, scanoptions, outscanflags, outbuffer);
|
||||
|
||||
if (err != ERR_NO_ERROR) {
|
||||
|
@ -307,14 +274,24 @@ void threadfcn(DT9837A *td) {
|
|||
|
||||
// Initialize input, if any
|
||||
if (hasinput) {
|
||||
|
||||
indesc = new DaqInChanDescriptor[neninchannels];
|
||||
us j = 0;
|
||||
for (us chin = 0; chin < 4; chin++) {
|
||||
if (td->inChannels[chin] == true) {
|
||||
if (td->eninchannels[chin] == true) {
|
||||
indesc[j].type = DAQI_ANALOG_SE;
|
||||
indesc[j].channel = chin;
|
||||
indesc[j].range = td->high_range[chin] ? BIP10VOLTS : BIP1VOLTS;
|
||||
|
||||
double rangeval = td->inputRangeForChannel(chin);
|
||||
Range rangenum;
|
||||
if (abs(rangeval - 1.0) < 1e-8) {
|
||||
rangenum = BIP1VOLTS;
|
||||
} else if (abs(rangeval - 10.0) < 1e-8) {
|
||||
rangenum = BIP10VOLTS;
|
||||
} else {
|
||||
std::cerr << "Fatal: input range value is invalid" << endl;
|
||||
goto exit;
|
||||
}
|
||||
indesc[j].range = rangenum;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +306,7 @@ void threadfcn(DT9837A *td) {
|
|||
|
||||
cerr << "Starting input ADC" << endl;
|
||||
err = ulDaqInScan(handle, indesc, neninchannels,
|
||||
2 * td->samplesPerBlock, // Watch the 2 here!
|
||||
2 * td->nFramesPerBlock, // Watch the 2 here!
|
||||
&samplerate, scanoptions, inscanflags, inbuffer);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
showErr(err);
|
||||
|
@ -360,7 +337,7 @@ void threadfcn(DT9837A *td) {
|
|||
}
|
||||
assert(outscanstat == SS_RUNNING);
|
||||
|
||||
if (outxstat.currentScanCount > outTotalCount + 2 * samplesPerBlock) {
|
||||
if (outxstat.currentScanCount > outTotalCount + 2 * nFramesPerBlock) {
|
||||
cerr << "***** WARNING: Missing output sample blocks, DAQ Scan count="
|
||||
<< outxstat.currentScanCount
|
||||
<< " while loop count = " << outTotalCount
|
||||
|
@ -368,7 +345,8 @@ void threadfcn(DT9837A *td) {
|
|||
}
|
||||
outTotalCount = outxstat.currentScanCount;
|
||||
|
||||
/* std::cerr << "Samples scanned: " << outxstat.currentTotalCount << endl;
|
||||
/* std::cerr << "Samples scanned: " << outxstat.currentTotalCount <<
|
||||
* endl;
|
||||
*/
|
||||
if (outxstat.currentIndex < buffer_mid_idx_out) {
|
||||
topoutenqueued = false;
|
||||
|
@ -382,13 +360,13 @@ void threadfcn(DT9837A *td) {
|
|||
"QUEUE WITH ZEROS ***********"
|
||||
<< endl;
|
||||
bufcpy = static_cast<double *>(
|
||||
malloc(sizeof(double) * samplesPerBlock * nenoutchannels));
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
malloc(sizeof(double) * nFramesPerBlock * nenoutchannels));
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
bufcpy[sample] = 0;
|
||||
}
|
||||
}
|
||||
assert(nenoutchannels > 0);
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
outbuffer[buffer_mid_idx_out + sample] = bufcpy[sample];
|
||||
}
|
||||
free(bufcpy);
|
||||
|
@ -406,13 +384,13 @@ void threadfcn(DT9837A *td) {
|
|||
"QUEUE WITH ZEROS ***********"
|
||||
<< endl;
|
||||
bufcpy = static_cast<double *>(
|
||||
malloc(sizeof(double) * samplesPerBlock * nenoutchannels));
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
malloc(sizeof(double) * nFramesPerBlock * nenoutchannels));
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
bufcpy[sample] = 0;
|
||||
}
|
||||
}
|
||||
assert(nenoutchannels > 0);
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
outbuffer[sample] = bufcpy[sample];
|
||||
}
|
||||
free(bufcpy);
|
||||
|
@ -428,10 +406,11 @@ void threadfcn(DT9837A *td) {
|
|||
goto exit;
|
||||
}
|
||||
assert(inscanstat == SS_RUNNING);
|
||||
if (inxstat.currentScanCount > inTotalCount + 2 * samplesPerBlock) {
|
||||
if (inxstat.currentScanCount > inTotalCount + 2 * nFramesPerBlock) {
|
||||
cerr << "***** ERROR: Missing input sample blocks, count="
|
||||
<< inxstat.currentScanCount
|
||||
<< ", probably due to too small buffer size. Exiting thread. *****"
|
||||
<< ", probably due to too small buffer size. Exiting thread. "
|
||||
"*****"
|
||||
<< endl;
|
||||
break;
|
||||
}
|
||||
|
@ -442,13 +421,13 @@ void threadfcn(DT9837A *td) {
|
|||
if (!botinenqueued) {
|
||||
/* cerr << "Copying in buffer bot" << endl; */
|
||||
double *bufcpy = static_cast<double *>(
|
||||
malloc(sizeof(double) * samplesPerBlock * neninchannels));
|
||||
malloc(sizeof(double) * nFramesPerBlock * neninchannels));
|
||||
us monitoroffset = monitorOutput ? 1 : 0;
|
||||
assert(neninchannels > 0);
|
||||
for (us channel = 0; channel < (neninchannels - monitoroffset);
|
||||
channel++) {
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
bufcpy[(monitoroffset + channel) * samplesPerBlock + sample] =
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
bufcpy[(monitoroffset + channel) * nFramesPerBlock + sample] =
|
||||
inbuffer[buffer_mid_idx_in + sample * neninchannels +
|
||||
channel];
|
||||
}
|
||||
|
@ -457,7 +436,7 @@ void threadfcn(DT9837A *td) {
|
|||
// Monitor output goes to first channel, that is
|
||||
// our convention
|
||||
us channel = neninchannels - 1;
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
bufcpy[sample] = inbuffer[buffer_mid_idx_in +
|
||||
sample * neninchannels + channel];
|
||||
}
|
||||
|
@ -469,13 +448,13 @@ void threadfcn(DT9837A *td) {
|
|||
botinenqueued = false;
|
||||
if (!topinenqueued) {
|
||||
double *bufcpy = static_cast<double *>(
|
||||
malloc(sizeof(double) * samplesPerBlock * neninchannels));
|
||||
malloc(sizeof(double) * nFramesPerBlock * neninchannels));
|
||||
us monitoroffset = monitorOutput ? 1 : 0;
|
||||
assert(neninchannels > 0);
|
||||
for (us channel = 0; channel < (neninchannels - monitoroffset);
|
||||
channel++) {
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
bufcpy[(monitoroffset + channel) * samplesPerBlock + sample] =
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
bufcpy[(monitoroffset + channel) * nFramesPerBlock + sample] =
|
||||
inbuffer[sample * neninchannels + channel];
|
||||
}
|
||||
}
|
||||
|
@ -483,7 +462,7 @@ void threadfcn(DT9837A *td) {
|
|||
// Monitor output goes to first channel, that is
|
||||
// our convention
|
||||
us channel = neninchannels - 1;
|
||||
for (us sample = 0; sample < samplesPerBlock; sample++) {
|
||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||
bufcpy[sample] = inbuffer[sample * neninchannels + channel];
|
||||
}
|
||||
}
|
||||
|
@ -521,92 +500,13 @@ exit:
|
|||
std::cerr << "Exit of DAQ thread fcn" << endl;
|
||||
}
|
||||
|
||||
void DT9837A::start(SafeQueue<void *> *inqueue, SafeQueue<void *> *outqueue) {
|
||||
if (isRunning()) {
|
||||
throw runtime_error("Thread is already running");
|
||||
}
|
||||
|
||||
bool hasinput = neninchannels() > 0;
|
||||
bool hasoutput = nenoutchannels() > 0;
|
||||
|
||||
if (neninchannels() > 0 && !inqueue) {
|
||||
throw runtime_error("Inqueue not given, while input is enabled");
|
||||
}
|
||||
|
||||
if (nenoutchannels() > 0 && !outqueue) {
|
||||
throw runtime_error("outqueue not given, while output is enabled");
|
||||
}
|
||||
|
||||
if (hasinput) {
|
||||
assert(!inbuffer);
|
||||
inbuffer =
|
||||
new double[neninchannels() * samplesPerBlock * 2]; // Watch the 2!
|
||||
}
|
||||
if (hasoutput) {
|
||||
assert(!outbuffer);
|
||||
outbuffer =
|
||||
new double[nenoutchannels() * samplesPerBlock * 2]; // Watch the 2!
|
||||
}
|
||||
this->inqueue = inqueue;
|
||||
this->outqueue = outqueue;
|
||||
|
||||
/* std::cerr << "************************ WARNING: Forcing coupling mode to AC
|
||||
* **************************" << endl; */
|
||||
/* boolvec couplingmode = {true, true, true, true}; */
|
||||
/* setACCouplingMode(couplingmode); */
|
||||
|
||||
stopThread = false;
|
||||
thread = new std::thread(threadfcn, this);
|
||||
}
|
||||
|
||||
void DT9837A::stop() {
|
||||
if (!isRunning()) {
|
||||
throw runtime_error("No data acquisition running");
|
||||
}
|
||||
assert(thread);
|
||||
|
||||
stopThread = true;
|
||||
thread->join();
|
||||
delete thread;
|
||||
thread = NULL;
|
||||
|
||||
outqueue = NULL;
|
||||
inqueue = NULL;
|
||||
if (inbuffer)
|
||||
delete inbuffer;
|
||||
if (outbuffer)
|
||||
delete outbuffer;
|
||||
outbuffer = NULL;
|
||||
inbuffer = NULL;
|
||||
}
|
||||
|
||||
us DT9837A::neninchannels() const {
|
||||
mutexlock lock(mutex);
|
||||
us inch = std::count(inChannels.begin(), inChannels.end(), true);
|
||||
if (monitorOutput)
|
||||
inch++;
|
||||
return inch;
|
||||
}
|
||||
|
||||
us DT9837A::nenoutchannels() const {
|
||||
mutexlock lock(mutex);
|
||||
return std::count(outChannels.begin(), outChannels.end(), true);
|
||||
}
|
||||
|
||||
|
||||
Daq *createUlDaqDevice(const DeviceInfo &devinfo,
|
||||
const DaqConfiguration &config) {
|
||||
|
||||
DT9837A *daq = NULL;
|
||||
try {
|
||||
daq = new DT9837A(config.nFramesPerBlock, config.eninchannels,
|
||||
config.enoutchannels,
|
||||
devinfo.availableSampleRates[config.sampleRateIndex],
|
||||
config.monitorOutput, devinfo.devindex);
|
||||
|
||||
daq->setACCouplingMode(config.inputACCouplingMode);
|
||||
daq->setIEPEEnabled(config.inputIEPEEnabled);
|
||||
daq->setInputRange(config.inputHighRange);
|
||||
try {
|
||||
daq = new DT9837A(devinfo, config);
|
||||
|
||||
} catch (runtime_error &e) {
|
||||
if (daq)
|
||||
|
|
|
@ -2,14 +2,6 @@
|
|||
#define ULDAQ_H
|
||||
#include "lasp_cppqueue.h"
|
||||
#include "lasp_cppdaq.h"
|
||||
#include <uldaq.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
using std::atomic;
|
||||
|
||||
Daq* createUlDaqDevice(const DeviceInfo& devinfo,
|
||||
const DaqConfiguration& config);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
cimport cython
|
||||
from cpython.ref cimport PyObject,Py_INCREF, Py_DECREF
|
||||
from .lasp_daqconfig import (Range as pyRange,
|
||||
DAQChannel)
|
||||
from .lasp_avtype import AvType
|
||||
from .lasp_device_common import AvType
|
||||
|
||||
__all__ = ['Daq']
|
||||
|
||||
|
|
|
@ -8,10 +8,7 @@ cdef class DeviceInfo:
|
|||
def api(self): return self.devinfo.api.apiname.decode('utf-8')
|
||||
|
||||
@property
|
||||
def name(self): return self.devinfo.name.decode('utf-8')
|
||||
|
||||
@property
|
||||
def devindex(self): return self.devinfo.devindex
|
||||
def name(self): return self.devinfo.device_name.decode('utf-8')
|
||||
|
||||
@property
|
||||
def ninchannels(self): return self.devinfo.ninchannels
|
||||
|
@ -47,7 +44,7 @@ cdef class DeviceInfo:
|
|||
|
||||
@property
|
||||
def inputRanges(self):
|
||||
return self.devinfo.inputRanges
|
||||
return self.devinfo.availableInputRanges
|
||||
|
||||
@staticmethod
|
||||
def getDeviceInfo():
|
||||
|
@ -60,7 +57,7 @@ cdef class DeviceInfo:
|
|||
us numdevs, devno
|
||||
cppDeviceInfo* devinfo
|
||||
|
||||
devinfos = DaqDevices.getDeviceInfo()
|
||||
devinfos = cppDaq.getDeviceInfo()
|
||||
numdevs = devinfos.size()
|
||||
|
||||
pydevinfos = []
|
||||
|
|
|
@ -8,8 +8,11 @@ from .lasp_atomic import Atomic
|
|||
from threading import Thread, Condition, Lock
|
||||
import numpy as np
|
||||
|
||||
class DAQConfiguration:
|
||||
pass
|
||||
|
||||
import time
|
||||
from .device import (Daq, DeviceInfo, DAQConfiguration,
|
||||
from .device import (Daq, DeviceInfo,
|
||||
# get_numpy_dtype_from_format_string,
|
||||
# get_sampwidth_from_format_string,
|
||||
AvType,
|
||||
|
|
|
@ -11,25 +11,7 @@ using std::endl;
|
|||
int main() {
|
||||
|
||||
/* boolvec inChannels = {true, false, false, false}; */
|
||||
boolvec inChannels = {true, true, false, false};
|
||||
boolvec outChannels = {true};
|
||||
double samplerate = 10000;
|
||||
const us samplesPerBlock = 256;
|
||||
|
||||
DaqConfiguration config;
|
||||
config.eninchannels = inChannels;
|
||||
config.enoutchannels = outChannels;
|
||||
config.inputIEPEEnabled = {false, false, false, false};
|
||||
config.inputACCouplingMode = {false, false, false, false};
|
||||
config.inputHighRange = {false, false, false, false};
|
||||
config.sampleRateIndex = 0;
|
||||
config.datatype = dtype_fl64;
|
||||
config.monitorOutput = true;
|
||||
config.inputIEPEEnabled = {false, false, false, false};
|
||||
config.nFramesPerBlock = samplesPerBlock;
|
||||
cout << "Inchannnels size: " <<config.eninchannels.size() << endl;
|
||||
|
||||
vector<DeviceInfo> devinfos = DaqDevices::getDeviceInfo();
|
||||
auto devinfos = Daq::getDeviceInfo();
|
||||
DeviceInfo devinfo;
|
||||
us i;
|
||||
bool found = false;
|
||||
|
@ -44,7 +26,21 @@ int main() {
|
|||
throw runtime_error("Could not find UlDaq device");
|
||||
}
|
||||
|
||||
Daq* daq = DaqDevices::createDevice(devinfo, config);
|
||||
DaqConfiguration config(devinfos[0]);
|
||||
boolvec inChannels = {true, true, false, false};
|
||||
boolvec outChannels = {true};
|
||||
double samplerate = 10000;
|
||||
const us samplesPerBlock = 256;
|
||||
|
||||
config.eninchannels = inChannels;
|
||||
config.enoutchannels = outChannels;
|
||||
config.sampleRateIndex = 0;
|
||||
config.monitorOutput = true;
|
||||
config.inputIEPEEnabled = {false, false, false, false};
|
||||
cout << "Inchannnels size: " << config.eninchannels.size() << endl;
|
||||
|
||||
|
||||
Daq* daq = Daq::createDevice(config, devinfos);
|
||||
|
||||
SafeQueue<void*> inqueue;
|
||||
SafeQueue<void*> outqueue;
|
||||
|
|
Loading…
Reference in New Issue