Inbetween state. Nothing is working

This commit is contained in:
Anne de Jong 2020-10-14 09:42:19 +02:00
parent 29662c82e3
commit bc9639f10c
12 changed files with 311 additions and 303 deletions

View File

@ -5,7 +5,7 @@ cmake_policy(SET CMP0079 NEW)
# This is used for code completion in vim # This is used for code completion in vim
set(CMAKE_EXPORT_COMPILE_COMMANDS=ON) set(CMAKE_EXPORT_COMPILE_COMMANDS=ON)
project(LASP) project(LASP LANGUAGES C CXX)
# Whether we want to use blas yes or no # Whether we want to use blas yes or no
set(LASP_USE_BLAS TRUE) set(LASP_USE_BLAS TRUE)
@ -14,28 +14,44 @@ set(LASP_USE_BLAS TRUE)
set(LASP_FLOAT double) set(LASP_FLOAT double)
# set(LASP_FLOAT float) # set(LASP_FLOAT float)
add_definitions(-DLASP_PARALLEL) option(LASP_PARALLEL "Parallel processing" ON)
option(LASP_RTAUDIO "Compile with RtAudio Daq backend" ON)
option(LASP_ULDAQ "Compile with UlDaq backend" ON)
option(LASP_DEBUG "Compile in debug mode" ON)
option(LASP_FFTW_BACKEND "Compile with FFTW fft backend" ON)
option(LAS_FFTPACK_BACKEND "Compile with Fftpack fft backend" OFF)
if(LASP_PARALLEL)
add_definitions(-DLASP_MAX_NUM_THREADS=30) add_definitions(-DLASP_MAX_NUM_THREADS=30)
add_definitions(-D_REENTRANT)
endif()
if(LASP_RTAUDIO)
add_definitions(-DHAS_RTAUDIO_API)
endif()
if(LASP_ULDAQ)
add_definitions(-DHAS_ULDAQ_API)
endif()
add_definitions(-DLASP_MAX_NUM_CHANNELS=80) add_definitions(-DLASP_MAX_NUM_CHANNELS=80)
# Reasonable maximum to the nfft size, at 48kHz this is 700s of data.. # Reasonable maximum to the nfft size, at 48kHz this is 700s of data...
add_definitions(-DLASP_MAX_NFFT=33554432) # 2**25 add_definitions(-DLASP_MAX_NFFT=33554432) # 2**25
# ####################################### End of user-adjustable variables section # ####################################### End of user-adjustable variables section
add_definitions(-D_REENTRANT)
# ############### Choose an fft backend here # ############### Choose an fft backend here
set(LASP_FFT_BACKEND fftpack) if(LASP_FFTW_BACKEND AND LASP_FFTPACK_BACKEND)
#set(LASP_FFT_BACKEND "fftw") message(FATAL_ERROR "Either FFTW or Fftpack backend should be chosen. Please disable one of them")
endif()
if(LASP_FFT_BACKEND STREQUAL "fftw") if(LASP_FFTW_BACKEND)
find_library(FFTW_LIBRARY NAMES fftw3 fftw) find_library(FFTW_LIBRARY NAMES fftw3 fftw)
set(FFTW_LIBRARIES "${FFTW_LIBRARY}") set(FFTW_LIBRARIES "${FFTW_LIBRARY}")
set(LASP_FFT_LIBRARY "${FFTW_LIBRARIES}") set(LASP_FFT_LIBRARY "${FFTW_LIBRARIES}")
add_definitions(-DLASP_FFT_BACKEND_FFTW) add_definitions(-DLASP_FFT_BACKEND_FFTW)
elseif(LASP_FFT_BACKEND STREQUAL "fftpack") elseif(LASP_FFTPACK_BACKEND)
add_definitions(-DLASP_FFT_BACKEND_FFTPACK) add_definitions(-DLASP_FFT_BACKEND_FFTPACK)
set(LASP_FFT_LIBRARY "fftpack") set(LASP_FFT_LIBRARY "fftpack")
endif() endif()
@ -49,10 +65,6 @@ else()
add_definitions(-DLASP_SINGLE_PRECISION) add_definitions(-DLASP_SINGLE_PRECISION)
endif(LASP_FLOAT STREQUAL "double") endif(LASP_FLOAT STREQUAL "double")
if(NOT DEFINED LASP_DEBUG)
message(FATAL_ERROR "LASP_DEBUG flag not defined. Please set -DLASP_DEBUG=TRUE
or -DLASP_DEBUG=FALSE")
endif(NOT DEFINED LASP_DEBUG)
# ##################### END Cmake variables converted to a macro # ##################### END Cmake variables converted to a macro
set(Python_ADDITIONAL_VERSIONS "3.8") set(Python_ADDITIONAL_VERSIONS "3.8")
@ -83,14 +95,8 @@ else()
include_directories(/usr/local/include/rtaudio) include_directories(/usr/local/include/rtaudio)
link_directories(/usr/local/lib) link_directories(/usr/local/lib)
add_definitions(-DHAS_RTAUDIO)
add_definitions(-DHAS_RTAUDIO_PULSEAUDIO_API)
add_definitions(-DHAS_RTAUDIO_ALSA_API)
# This should become optional later on, and be added to the windows list as # This should become optional later on, and be added to the windows list as
# well. # well.
add_definitions(-DHAS_ULDAQ)
add_definitions(-DHAS_ULDAQ_LINUX_API)
endif(CMAKE_SYSTEM_NAME STREQUAL "Windows") endif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
@ -152,12 +158,18 @@ endif(LASP_USE_BLAS)
find_package(PythonLibs REQUIRED ) find_package(PythonLibs REQUIRED )
find_package(PythonInterp REQUIRED) find_package(PythonInterp REQUIRED)
if(LASP_FFTPACK_BACKEND)
add_subdirectory(fftpack) add_subdirectory(fftpack)
include_directories( include_directories(
fftpack fftpack
)
endif()
include_directories(
lasp/c lasp/c
) )
set(cpp_daq_linklibs pthread)
add_subdirectory(lasp) add_subdirectory(lasp)
add_subdirectory(test) add_subdirectory(test)

View File

@ -1,31 +1,34 @@
include_directories(/usr/include/rtaudio) set(cpp_daq_files lasp_cppdaq.cpp)
# set(cpp_daq_linklibs pthread)
# set(cpp_daq_linklibs PARENT_SCOPE)
# add_library(cpp_daq lasp_cppdaq.cpp lasp_cppuldaq.cpp lasp_cpprtaudio.cpp) if(LASP_RTAUDIO)
add_library(cpp_daq lasp_cppdaq.cpp lasp_cppuldaq.cpp ) include_directories(/usr/include/rtaudio)
list(APPEND cpp_daq_files lasp_cpprtaudio.cpp)
set_source_files_properties(lasp_daq.pyx PROPERTIES CYTHON_IS_CXX TRUE) list(PREPEND cpp_daq_linklibs rtaudio)
set_source_files_properties(lasp_deviceinfo.pyx PROPERTIES CYTHON_IS_CXX TRUE) endif()
set_source_files_properties(lasp_daqconfig.pyx PROPERTIES CYTHON_IS_CXX TRUE) if(LASP_ULDAQ)
list(APPEND cpp_daq_files lasp_cppuldaq.cpp)
set_source_files_properties(lasp_daq.cxx PROPERTIES COMPILE_FLAGS list(PREPEND cpp_daq_linklibs uldaq)
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}") endif()
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) if(win32)
target_link_libraries(lasp_daq python37) list(APPEND cpp_daq_linklibs python)
target_link_libraries(lasp_deviceinfo python37)
target_link_libraries(lasp_daqconfig python37)
endif(win32) endif(win32)
message("Linklibs: ${cpp_daq_linklibs}")
add_library(cpp_daq ${cpp_daq_files})
foreach(cython_file lasp_daq lasp_deviceinfo lasp_daqconfig)
set_source_files_properties(${cython_file}.pyx PROPERTIES
CYTHON_IS_CXX TRUE)
set_source_files_properties(${cython_file}.cxx PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
cython_add_module(${cython_file} ${cython_file}.pyx)
target_link_libraries(${cython_file} ${cpp_daq_linklibs})
endforeach()

View File

@ -1,105 +1,26 @@
#include "lasp_cppdaq.h" #include "lasp_cppdaq.h"
#include "lasp_cppuldaq.h"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <iostream>
#include <strstream>
using std::cout;
using std::endl;
#define MAX_DEV_COUNT_PER_API 20 #define MAX_DEV_COUNT_PER_API 20
#ifdef HAS_ULDAQ_LINUX_API #ifdef HAS_ULDAQ_API
void fillUlDaqDeviceInfo(vector<DeviceInfo> &devinfolist) { #include "lasp_cppuldaq.h"
#endif
UlError err; #ifdef HAS_RTAUDIO_API
unsigned int numdevs = MAX_DEV_COUNT_PER_API; #include "lasp_cpprtaudio.h"
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 #endif
vector<DeviceInfo> Daq::getDeviceInfo() { vector<DeviceInfo> Daq::getDeviceInfo() {
vector<DeviceInfo> devs; vector<DeviceInfo> devs;
#ifdef HAS_ULDAQ_LINUX_API #ifdef HAS_ULDAQ_API
fillUlDaqDeviceInfo(devs); fillUlDaqDeviceInfo(devs);
#endif #endif
#ifdef HAS_RTAUDIO_ALSA_API #ifdef HAS_RTAUDIO_API
fillRtAudioDeviceInfo(devs);
#endif #endif
#ifdef HAS_RTAUDIO_PULSEAUDIO_API
#endif
#ifdef HAS_RTAUDIO_WIN_WASAPI_API
#endif
return devs; return devs;
} }
@ -113,13 +34,13 @@ DaqConfiguration::DaqConfiguration(const DeviceInfo &device) {
inchannel_sensitivities.resize(device.ninchannels, 1.0); inchannel_sensitivities.resize(device.ninchannels, 1.0);
for (us i = 0; i < eninchannels.size(); i++) { for (us i = 0; i < eninchannels.size(); i++) {
std::strstream chname; std::stringstream chname;
chname << "Unnamed input channel " << i; chname << "Unnamed input channel " << i;
inchannel_names.push_back(chname.str()); inchannel_names.push_back(chname.str());
} }
for (us i = 0; i < enoutchannels.size(); i++) { for (us i = 0; i < enoutchannels.size(); i++) {
std::strstream chname; std::stringstream chname;
chname << "Unnamed output channel " << i; chname << "Unnamed output channel " << i;
outchannel_names.push_back(chname.str()); outchannel_names.push_back(chname.str());
} }
@ -187,7 +108,7 @@ Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config)
if (enoutchannels.size() != 1) { if (enoutchannels.size() != 1) {
throw runtime_error("Invalid length of enabled outChannels vector"); throw runtime_error("Invalid length of enabled outChannels vector");
} }
} }
double Daq::samplerate() const { double Daq::samplerate() const {
@ -201,6 +122,8 @@ DataType Daq::dataType() const {
assert((us)dataTypeIndex < availableDataTypes.size()); assert((us)dataTypeIndex < availableDataTypes.size());
return availableDataTypes[dataTypeIndex]; return availableDataTypes[dataTypeIndex];
} }
double Daq::inputRangeForChannel(us ch) const { double Daq::inputRangeForChannel(us ch) const {
if (!(ch < ninchannels)) { if (!(ch < ninchannels)) {
throw runtime_error("Invalid channel number"); throw runtime_error("Invalid channel number");
@ -208,6 +131,8 @@ double Daq::inputRangeForChannel(us ch) const {
assert(inputRangeIndices.size() == eninchannels.size()); assert(inputRangeIndices.size() == eninchannels.size());
return availableInputRanges[inputRangeIndices[ch]]; return availableInputRanges[inputRangeIndices[ch]];
} }
us Daq::neninchannels() const { us Daq::neninchannels() const {
mutexlock lock(mutex); mutexlock lock(mutex);
us inch = std::count(eninchannels.begin(), eninchannels.end(), true); us inch = std::count(eninchannels.begin(), eninchannels.end(), true);
@ -215,6 +140,8 @@ us Daq::neninchannels() const {
inch++; inch++;
return inch; return inch;
} }
us Daq::nenoutchannels() const { us Daq::nenoutchannels() const {
mutexlock lock(mutex); mutexlock lock(mutex);
return std::count(enoutchannels.begin(), enoutchannels.end(), true); return std::count(enoutchannels.begin(), enoutchannels.end(), true);

View File

@ -1,11 +1,11 @@
#ifndef LASP_CPPDAQ_H #ifndef LASP_CPPDAQ_H
#define LASP_CPPDAQ_H #define LASP_CPPDAQ_H
#ifdef HAS_RTAUDIO #ifdef HAS_RTAUDIO_API
#include <RtAudio.h> #include <RtAudio.h>
#endif #endif
#ifdef HAS_ULDAQ #ifdef HAS_ULDAQ_API
#include <uldaq.h> #include <uldaq.h>
#endif #endif
@ -13,6 +13,9 @@
#include "string" #include "string"
#include "vector" #include "vector"
#include <mutex> #include <mutex>
#include <iostream>
#include <sstream>
using std::cerr; using std::cerr;
using std::cout; using std::cout;
using std::endl; using std::endl;
@ -38,7 +41,8 @@ class DataType {
}; };
const DataType dtype_invalid; const DataType dtype_invalid;
const DataType dtype_fl64("64-bits floating point", 4, true); const DataType dtype_fl32("32-bits floating point", 4, true);
const DataType dtype_fl64("64-bits floating point", 8, true);
const DataType dtype_int8("8-bits integers", 1, false); const DataType dtype_int8("8-bits integers", 1, false);
const DataType dtype_int16("16-bits integers", 2, false); const DataType dtype_int16("16-bits integers", 2, false);
const DataType dtype_int32("32-bits integers", 4, false); const DataType dtype_int32("32-bits integers", 4, false);
@ -47,6 +51,7 @@ const std::vector<DataType> dataTypes = {
dtype_int8, dtype_int8,
dtype_int16, dtype_int16,
dtype_int32, dtype_int32,
dtype_fl32,
dtype_fl64, dtype_fl64,
}; };
@ -66,28 +71,17 @@ class DaqApi {
} }
}; };
#ifdef HAS_ULDAQ_LINUX_API #ifdef HAS_ULDAQ_API
const DaqApi uldaqapi("UlDaq", 0); const DaqApi uldaqapi("UlDaq", 0);
#endif #endif
#ifdef HAS_RTAUDIO_ALSA_API #ifdef HAS_RTAUDIO_API
const DaqApi rtaudioalsaapi("RtAudio Linux ALSA", 1, RtAudio::Api::LINUX_ALSA); const DaqApi rtaudioAlsaApi("RtAudio Linux ALSA", 1, RtAudio::Api::LINUX_ALSA);
const DaqApi rtaudioPulseaudioApi("RtAudio Linux Pulseaudio", 2, RtAudio::Api::LINUX_PULSE);
const DaqApi rtaudioWasapiApi("RtAudio Windows Wasapi", 3, RtAudio::Api::WINDOWS_WASAPI);
const DaqApi rtaudioDsApi("RtAudio Windows DirectSound", 4, RtAudio::Api::WINDOWS_DS);
const DaqApi rtaudioAsioApi("RtAudio Windows ASIO", 4, RtAudio::Api::WINDOWS_ASIO);
#endif #endif
const vector<DaqApi> compiledApis = {
#ifdef HAS_ULDAQ_LINUX_API
uldaqapi,
#endif
#ifdef HAS_RTAUDIO_ALSA_API
rtaudioalsaapi,
#endif
#ifdef HAS_RTAUDIO_PULSEAUDIO_API
DaqApi("RtAudio Linux Pulseaudio", 2, RtAudio::Api::LINUX_PULSE),
#endif
#ifdef HAS_RTAUDIO_WIN_WASAPI_API
DaqApi("RtAudio Windows Wasapi", 3, RtAudio::Api::WINDOWS_WASAPI),
#endif
};
// Structure containing device info parameters // Structure containing device info parameters
class DeviceInfo { class DeviceInfo {

View File

@ -0,0 +1,97 @@
#include "lasp_cpprtaudio.h"
#include <RtAudio.h>
#include <atomic>
#include <thread>
using std::atomic;
void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist) {
vector<RtAudio::Api> apis;
RtAudio::getCompiledApi(apis);
for(auto api: apis) {
RtAudio rtaudio(api);
us count = rtaudio.getDeviceCount();
for(us devno = 0; devno< count;devno++) {
RtAudio::DeviceInfo devinfo = rtaudio.getDeviceInfo(devno);
DeviceInfo d;
switch(api){
case RtAudio::LINUX_ALSA:
d.api = rtaudioAlsaApi;
break;
case RtAudio::LINUX_PULSE:
d.api = rtaudioPulseaudioApi;
break;
case RtAudio::WINDOWS_WASAPI:
d.api = rtaudioWasapiApi;
break;
case RtAudio::WINDOWS_DS:
d.api = rtaudioDsApi;
break;
case RtAudio::WINDOWS_ASIO:
d.api = rtaudioAsioApi;
break;
default:
cerr << "Not implemented RtAudio API, skipping." << endl;
continue;
break;
}
d.device_name = devinfo.name;
d.api_specific_devindex = devno;
for(us j=0; j<devinfo.sampleRates.size();j++){
us rate = devinfo.sampleRates[j];
d.availableSampleRates.push_back((double) rate);
if(devinfo.preferredSampleRate == rate) {
d.prefSampleRateIndex = j;
}
}
d.noutchannels = devinfo.outputChannels;
d.ninchannels = devinfo.inputChannels;
d.availableInputRanges = {1.0};
RtAudioFormat formats = devinfo.nativeFormats;
if(formats & RTAUDIO_SINT8) {
d.availableDataTypes.push_back(dtype_int8);
}
if(formats & RTAUDIO_SINT16) {
d.availableDataTypes.push_back(dtype_int16);
}
if(formats & RTAUDIO_SINT32) {
d.availableDataTypes.push_back(dtype_fl32);
}
if(formats & RTAUDIO_FLOAT64) {
d.availableDataTypes.push_back(dtype_fl64);
}
d.prefDataTypeIndex = d.availableDataTypes.size() - 1;
devinfolist.push_back(d);
}
}
}
class AudioDaq: public Daq {
atomic<bool> stopThread;
std::thread* thread = NULL;
SafeQueue<void*> *inqueue = NULL;
SafeQueue<void*> *outqueue = NULL;
void* inbuffer = NULL;
void* outbuffer = NULL;
public:
friend void threadfcn(AudioDaq*);
};

View File

@ -1,72 +1,11 @@
#ifndef RTAUDIO_H #ifndef RTAUDIO_H
#define RTAUDIO_H #define RTAUDIO_H
#include "lasp_cppqueue.h"
#include "lasp_cppdaq.h" #include "lasp_cppdaq.h"
#include <algorithm>
#include <vector>
#include <mutex>
#include <atomic>
#include <thread>
using std::vector; Daq* createRtAudioDevice(const DeviceInfo& devinfo,
using std::atomic; const DaqConfiguration& config);
typedef vector<bool> boolvec;
typedef unsigned int us; void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist);
class RtA: public Daq {h
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<double*> *inqueue = NULL;
SafeQueue<double*> *outqueue = NULL;
double* inbuffer = NULL;
double* outbuffer = NULL;
public:
double samplerate() const {return this->_samplerate;}
DT9837A(
us samplesPerBlock,
boolvec& inChannels,
boolvec& outChannels,
double samplerate,
bool monitorOutput,
us device_no = 0
);
DT9837A(const DT9837A&) = delete;
~DT9837A();
void setIEPEEnabled(boolvec& config);
// Coupling_ac: true, means AC coupling, false means DC coupling
void setACCouplingMode(boolvec& coupling_ac);
void setInputRange(boolvec& high_range);
us neninchannels() const;
us nenoutchannels() const;
bool isRunning() const { return bool(thread); }
virtual void start(
SafeQueue<double*> *inqueue,
SafeQueue<double*> *outqueue) final;
virtual void stop() final;
friend void threadfcn(DT9837A*);
};
#endif // RTAUDIO_H #endif // RTAUDIO_H

View File

@ -10,7 +10,7 @@
using std::atomic; using std::atomic;
/* using std::this_thread; */ /* using std::this_thread; */
const us MAX_DEF_COUNT = 100; const us MAX_DEV_COUNT_PER_API = 100;
const us UL_ERR_MSG_LEN = 512; const us UL_ERR_MSG_LEN = 512;
inline void showErr(UlError err) { inline void showErr(UlError err) {
@ -54,13 +54,13 @@ public:
throw runtime_error("Invalid sample rate"); throw runtime_error("Invalid sample rate");
} }
DaqDeviceDescriptor devdescriptors[MAX_DEF_COUNT]; DaqDeviceDescriptor devdescriptors[MAX_DEV_COUNT_PER_API];
DaqDeviceDescriptor descriptor; DaqDeviceDescriptor descriptor;
DaqDeviceInterface interfaceType = ANY_IFC; DaqDeviceInterface interfaceType = ANY_IFC;
UlError err; UlError err;
us numdevs = MAX_DEF_COUNT; us numdevs = MAX_DEV_COUNT_PER_API;
err = ulGetDaqDeviceInventory(interfaceType, devdescriptors, &numdevs); err = ulGetDaqDeviceInventory(interfaceType, devdescriptors, &numdevs);
if (err != ERR_NO_ERROR) { if (err != ERR_NO_ERROR) {
throw runtime_error("Device inventarization failed"); throw runtime_error("Device inventarization failed");
@ -515,3 +515,78 @@ Daq *createUlDaqDevice(const DeviceInfo &devinfo,
} }
return daq; return daq;
} }
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);
}
}
}

View File

@ -6,6 +6,8 @@
Daq* createUlDaqDevice(const DeviceInfo& devinfo, Daq* createUlDaqDevice(const DeviceInfo& devinfo,
const DaqConfiguration& config); const DaqConfiguration& config);
void fillUlDaqDeviceInfo(vector<DeviceInfo> &devinfolist);
#endif // ULDAQ_H #endif // ULDAQ_H

View File

@ -1,4 +1,6 @@
cimport cython cimport cython
from .lasp_deviceinfo cimport DeviceInfo
from cpython.ref cimport PyObject,Py_INCREF, Py_DECREF from cpython.ref cimport PyObject,Py_INCREF, Py_DECREF
from .lasp_device_common import AvType from .lasp_device_common import AvType
@ -138,6 +140,18 @@ cdef class Daq:
def isRunning(self): def isRunning(self):
return self.sd is not NULL return self.sd is not NULL
@staticmethod
def getDeviceInfo():
cdef:
vector[cppDeviceInfo] devinfos = cppDaq.getDeviceInfo()
pydevinfo = []
for i in range(devinfos.size()):
d = DeviceInfo()
d.devinfo = <cppDeviceInfo> devinfos[i]
pydevinfo.append(d)
return pydevinfo
# @cython.nonecheck(True) # @cython.nonecheck(True)
# def start(self, avstream): # def start(self, avstream):
# """ # """

View File

@ -10,28 +10,21 @@ Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves
""" """
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import List from typing import List
from dataclasses_json import dataclass_json from dataclasses_json import dataclass_json
from ..lasp_common import Qty, SIQtys, lasp_shelve from ..lasp_common import lasp_shelve, SIQtys, Qty
# class InputMode:
# differential = 'Differential'
# single_ended = 'Single-ended'
# pseudo_differential = 'Pseudo-differential'
# undefined = 'Undefined'
class CouplingMode: class CouplingMode:
ac = 'AC' ac = 'AC'
dc = 'DC' dc = 'DC'
undefined = 'Undefined' undefined = 'Undefined'
class Range: class Range:
oneV = '+/- 1 V' oneV = '+/- 1 V'
tenV = '+/- 10 V' tenV = '+/- 10 V'
undefined = 'Undefined' undefined = 'Undefined'
@dataclass_json @dataclass_json
@dataclass @dataclass
class DAQChannel: class DAQChannel:
@ -40,60 +33,16 @@ class DAQChannel:
sensitivity: float = 1.0 sensitivity: float = 1.0
qty: Qty = SIQtys.default qty: Qty = SIQtys.default
range_: str = 'Undefined' range_: str = 'Undefined'
ACCoupling_enabled: bool = False
IEPE_enabled: bool = False IEPE_enabled: bool = False
@dataclass_json
@dataclass cdef class DAQConfiguration:
class DAQConfiguration:
""" """
Initialize a device descriptor Initialize a device descriptor
Args:
duplex_mode: Set device to duplex mode, if possible
monitor_gen: If set to true, add monitor channel to recording.
outputDelayBlocks: number of blocks to delay output stream when added
to input for monitoring the output synchronously with input.
input_device_name: ASCII name with which to open the device when connected
outut_device_name: ASCII name with which to open the device when connected
==============================
en_format: index of the format in the list of sample formats
en_input_rate: index of enabled input sampling frequency [Hz]
in the list of frequencies.
input_channel_configs: list of channel indices which are used to
acquire data from.
input_sensitivity: List of sensitivity values, in units of [Pa^-1]
input_gain_settings: If a DAQ supports it, list of indices which
corresponds to a position in the possible input
gains for each channel. Should only be not equal
to None when the hardware supports changing the
input gain.
en_output_rate: index in the list of possible output sampling
frequencies.
en_output_channels: list of enabled output channels
===============================
""" """
api: int # DaqConfiguration config
duplex_mode: bool
input_device_name: str
output_device_name: str
en_input_sample_format: str
en_output_sample_format: str
en_input_rate: int
en_output_rate: int
input_channel_configs: List[DAQChannel] = field(default_factory=list)
output_channel_configs: List[DAQChannel] = field(default_factory=list)
monitor_gen: bool = False
outputDelayBlocks: int = 0
nFramesPerBlock: int = 1024
def getInputChannels(self): def getInputChannels(self):
return self.input_channel_configs return self.input_channel_configs
@ -101,15 +50,6 @@ class DAQConfiguration:
def getOutputChannels(self): def getOutputChannels(self):
return self.output_channel_configs return self.output_channel_configs
def firstEnabledInputChannelNumber(self):
"""
Returns the channel number of the first enabled channel. Returns -1 if
no channels are enabled.
"""
for i, ch in enumerate(self.input_channel_configs):
if ch.channel_enabled:
return i
return -1
def firstEnabledOutputChannelNumber(self): def firstEnabledOutputChannelNumber(self):
""" """

View File

@ -1,5 +1,6 @@
__all__ = ['DeviceInfo'] __all__ = ['DeviceInfo']
cdef class DeviceInfo: cdef class DeviceInfo:
def __cinit__(self): def __cinit__(self):
pass pass
@ -10,6 +11,9 @@ cdef class DeviceInfo:
@property @property
def name(self): return self.devinfo.device_name.decode('utf-8') def name(self): return self.devinfo.device_name.decode('utf-8')
def __repr__(self):
return self.api + ': ' + self.name
@property @property
def ninchannels(self): return self.devinfo.ninchannels def ninchannels(self): return self.devinfo.ninchannels

View File

@ -1,5 +1,6 @@
include_directories(${CMAKE_SOURCE_DIR}/lasp/c) include_directories(${CMAKE_SOURCE_DIR}/lasp/c)
include_directories(${CMAKE_SOURCE_DIR}/lasp/device) include_directories(${CMAKE_SOURCE_DIR}/lasp/device)
add_executable(test_bf test_bf.c) add_executable(test_bf test_bf.c)
add_executable(test_workers test_workers.c) add_executable(test_workers test_workers.c)
add_executable(test_fft test_fft.c) add_executable(test_fft test_fft.c)
@ -11,4 +12,4 @@ target_link_libraries(test_workers lasp_lib pthread)
target_link_libraries(test_math lasp_lib pthread) target_link_libraries(test_math lasp_lib pthread)
add_executable(test_uldaq test_uldaq.cpp) add_executable(test_uldaq test_uldaq.cpp)
target_link_libraries(test_uldaq cpp_daq uldaq pthread) target_link_libraries(test_uldaq cpp_daq ${cpp_daq_linklibs})