From a73ef3d7a89a66e93be2da913a8faaa09ed4b2f1 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Sun, 4 Oct 2020 22:29:54 +0200 Subject: [PATCH] First work on moving RtAudio Api back to C++. --- .gitignore | 4 +- CMakeLists.txt | 12 ++ lasp/device/CMakeLists.txt | 18 +-- lasp/device/__init__.py | 3 +- lasp/device/lasp_cppdaq.cpp | 92 ++++++++++++++ lasp/device/lasp_cppdaq.h | 114 +++++++++++++++++- ...sp_cpprtaudiodaq.h => lasp_cpprtaudio.cpp} | 0 lasp/device/lasp_cpprtaudio.h | 74 ++++++++++++ lasp/device/lasp_cppuldaq.h | 10 +- lasp/device/{lasp_uldaq.pxd => lasp_daq.pxd} | 0 lasp/device/{lasp_uldaq.pyx => lasp_daq.pyx} | 0 lasp/device/lasp_daqconfig.py | 27 ++++- test/CMakeLists.txt | 5 + {lasp/device => test}/test_uldaq.cpp | 8 +- 14 files changed, 335 insertions(+), 32 deletions(-) create mode 100644 lasp/device/lasp_cppdaq.cpp rename lasp/device/{lasp_cpprtaudiodaq.h => lasp_cpprtaudio.cpp} (100%) create mode 100644 lasp/device/lasp_cpprtaudio.h rename lasp/device/{lasp_uldaq.pxd => lasp_daq.pxd} (100%) rename lasp/device/{lasp_uldaq.pyx => lasp_daq.pyx} (100%) rename {lasp/device => test}/test_uldaq.cpp (90%) diff --git a/.gitignore b/.gitignore index ce0256c..9879559 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ *.a +*.cxx *.pyc -lasp_rtaudio.cxx -lasp_uldaq.cxx dist CMakeFiles CMakeCache.txt @@ -20,6 +19,7 @@ test/test_bf test/test_fft test/test_math test/test_workers +test/test_uldaq doc LASP.egg-info lasp_octave_fir.* diff --git a/CMakeLists.txt b/CMakeLists.txt index e611130..7fa387a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required (VERSION 3.0) +# To allow linking to static libs from other directories +cmake_policy(SET CMP0079 NEW) + # This is used for code completion in vim set(CMAKE_EXPORT_COMPILE_COMMANDS=ON) project(LASP) @@ -72,6 +75,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") link_directories(C:\\mingw\\bin) link_directories(..\\rtaudio) link_directories(C:\\Users\\User\\Miniconda3) + add_definitions(-DHAS_RTAUDIO_WIN_WASAPI_API) else() set(win32 false) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -std=c11 \ @@ -79,6 +83,14 @@ else() include_directories(/usr/local/include/rtaudio) 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 + # well. + add_definitions(-DHAS_ULDAQ) + add_definitions(-DHAS_ULDAQ_LINUX_API) + endif(CMAKE_SYSTEM_NAME STREQUAL "Windows") diff --git a/lasp/device/CMakeLists.txt b/lasp/device/CMakeLists.txt index eed1a9c..f430ea7 100644 --- a/lasp/device/CMakeLists.txt +++ b/lasp/device/CMakeLists.txt @@ -1,21 +1,15 @@ include_directories(/usr/include/rtaudio) -add_library(cpp_daq lasp_cppuldaq.cpp) +add_library(cpp_daq lasp_cppdaq.cpp lasp_cppuldaq.cpp lasp_cpprtaudio.cpp) -set_source_files_properties(lasp_rtaudio.pyx PROPERTIES CYTHON_IS_CXX TRUE) -set_source_files_properties(lasp_uldaq.pyx PROPERTIES CYTHON_IS_CXX TRUE) -set_source_files_properties(lasp_rtaudio.cxx PROPERTIES COMPILE_FLAGS +set_source_files_properties(lasp_daq.pyx PROPERTIES CYTHON_IS_CXX TRUE) +set_source_files_properties(lasp_daq.cxx PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}") -cython_add_module(lasp_rtaudio lasp_rtaudio.pyx) -cython_add_module(lasp_uldaq lasp_uldaq.pyx) +cython_add_module(lasp_daq lasp_daq.pyx) -target_link_libraries(lasp_rtaudio pthread rtaudio) -target_link_libraries(lasp_uldaq cpp_daq uldaq pthread) +target_link_libraries(lasp_daq cpp_daq uldaq rtaudio pthread) if(win32) -target_link_libraries(lasp_rtaudio python37) -target_link_libraries(lasp_uldaq python37) +target_link_libraries(lasp_daq python37) endif(win32) -add_executable(test_uldaq test_uldaq.cpp) -target_link_libraries(test_uldaq cpp_daq uldaq pthread) diff --git a/lasp/device/__init__.py b/lasp/device/__init__.py index 545f53f..f29d046 100644 --- a/lasp/device/__init__.py +++ b/lasp/device/__init__.py @@ -1,6 +1,5 @@ #!/usr/bin/python3 from .lasp_daqconfig import * from .lasp_avtype import * -from .lasp_rtaudio import * -from .lasp_uldaq import * +from .lasp_daq import * diff --git a/lasp/device/lasp_cppdaq.cpp b/lasp/device/lasp_cppdaq.cpp new file mode 100644 index 0000000..bce6f1f --- /dev/null +++ b/lasp/device/lasp_cppdaq.cpp @@ -0,0 +1,92 @@ +#include "lasp_cppdaq.h" +#define MAX_DEV_COUNT_PER_API 20 + +#ifdef HAS_ULDAQ_LINUX_API +void fillUlDaqDeviceInfo(vector& devinfolist) { + + UlError err; + unsigned int numdevs = MAX_DEV_COUNT_PER_API; + unsigned deviceno; + + 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("Device inventarization failed"); + + for(unsigned i =0; i DaqDevices::getDeviceInfo() { + vector 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; +} + +Daq* DaqDevices::createDevice(const DeviceInfo&) { + + + return NULL; +} diff --git a/lasp/device/lasp_cppdaq.h b/lasp/device/lasp_cppdaq.h index efc4d05..2b16e95 100644 --- a/lasp/device/lasp_cppdaq.h +++ b/lasp/device/lasp_cppdaq.h @@ -1,18 +1,122 @@ -#ifndef LAP_CPPDAQ_H -#define LAP_CPPDAQ_H +#ifndef LASP_CPPDAQ_H +#define LASP_CPPDAQ_H + +#ifdef HAS_RTAUDIO +#include +#endif + +#ifdef HAS_ULDAQ +#include +#endif + #include "lasp_cppqueue.h" +#include "vector" +#include "string" +using std::vector; +using std::string; + +class DataType { + public: + const string name; + unsigned sw; + bool is_floating; + DataType(const char* name,unsigned sw,bool is_floating): + name(name), + sw(sw), + is_floating(is_floating) {} + +}; + +const DataType dtype_fl64("64-bits floating point",4,true); +const DataType dtype_int8("8-bits integers",1,false); +const DataType dtype_int16("16-bits integers",2,false); +const DataType dtype_int32("32-bits integers",4,false); + +const std::vector dataTypes = { + dtype_int8, + dtype_int16, + dtype_int32, + dtype_fl64, +}; + +class DaqApi { + public: + string apiname = ""; + unsigned apicode = 0; + unsigned api_specific_subcode = 0; + + DaqApi(string apiname, + unsigned apicode, + unsigned api_specific_subcode=0): + apiname(apiname), + apicode(apicode), + api_specific_subcode(api_specific_subcode) {} + DaqApi(){} +}; + +#ifdef HAS_ULDAQ_LINUX_API +const DaqApi uldaqapi = DaqApi("UlDaq", 0); +#endif +const vector compiledApis = { +#ifdef HAS_ULDAQ_LINUX_API + uldaqapi, +#endif +#ifdef HAS_RTAUDIO_ALSA_API + DaqApi("RtAudio Linux ALSA", 1, RtAudio::Api::LINUX_ALSA), +#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 +class DeviceInfo { + public: + DaqApi api; + string name = ""; + unsigned devindex; + + vector availableDataTypes; + vector availableSampleRates; + unsigned prefSampleRateIndex = 0; + double prefSampleRate = 0; + + unsigned ninchannels =0; + unsigned noutchannels =0; + + bool hasInputIEPE = false; + bool hasInputACCouplingSwitch = false; + bool hasInputTrigger = false; + +}; + +class Daq; +class DaqDevices { + public: + static vector getDeviceInfo(); + static Daq* createDevice(const DeviceInfo&); + +}; + class Daq{ public: + virtual void start( - SafeQueue *inqueue, - SafeQueue *outqueue) = 0; + SafeQueue *inqueue, + SafeQueue *outqueue) = 0; + virtual void stop() = 0; virtual double samplerate() const = 0; + virtual DataType getDataType() const = 0; virtual ~Daq() {}; }; -#endif // LAP_CPPDAQ_H +#endif // LASP_CPPDAQ_H diff --git a/lasp/device/lasp_cpprtaudiodaq.h b/lasp/device/lasp_cpprtaudio.cpp similarity index 100% rename from lasp/device/lasp_cpprtaudiodaq.h rename to lasp/device/lasp_cpprtaudio.cpp diff --git a/lasp/device/lasp_cpprtaudio.h b/lasp/device/lasp_cpprtaudio.h new file mode 100644 index 0000000..83beae8 --- /dev/null +++ b/lasp/device/lasp_cpprtaudio.h @@ -0,0 +1,74 @@ +#ifndef RTAUDIO_H +#define RTAUDIO_H +#include "lasp_cppqueue.h" +#include "lasp_cppdaq.h" +#include +#include +#include +#include +#include + +using std::vector; +using std::atomic; +typedef vector boolvec; + +typedef unsigned int us; + +class RtA: public Daq {h + us samplesPerBlock; + double _samplerate; + boolvec inChannels; + boolvec high_range; + boolvec outChannels; + bool monitorOutput; + atomic stopThread; + DaqDeviceHandle handle = 0; + + std::thread* thread = NULL; + mutable std::mutex mutex; + SafeQueue *inqueue = NULL; + SafeQueue *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 *inqueue, + SafeQueue *outqueue) final; + + virtual void stop() final; + + + friend void threadfcn(DT9837A*); +}; + +#endif // RTAUDIO_H + + + diff --git a/lasp/device/lasp_cppuldaq.h b/lasp/device/lasp_cppuldaq.h index d983998..d621ae3 100644 --- a/lasp/device/lasp_cppuldaq.h +++ b/lasp/device/lasp_cppuldaq.h @@ -1,5 +1,5 @@ -#ifndef ULDAQ_THREAD_H -#define ULDAQ_THREAD_H +#ifndef ULDAQ_H +#define ULDAQ_H #include "lasp_cppqueue.h" #include "lasp_cppdaq.h" #include @@ -59,8 +59,8 @@ class DT9837A: public Daq { bool isRunning() const { return bool(thread); } virtual void start( - SafeQueue *inqueue, - SafeQueue *outqueue) final; + SafeQueue *inqueue, + SafeQueue *outqueue) final; virtual void stop() final; @@ -68,6 +68,6 @@ class DT9837A: public Daq { friend void threadfcn(DT9837A*); }; -#endif // ULDAQ_THREAD_H +#endif // ULDAQ_H diff --git a/lasp/device/lasp_uldaq.pxd b/lasp/device/lasp_daq.pxd similarity index 100% rename from lasp/device/lasp_uldaq.pxd rename to lasp/device/lasp_daq.pxd diff --git a/lasp/device/lasp_uldaq.pyx b/lasp/device/lasp_daq.pyx similarity index 100% rename from lasp/device/lasp_uldaq.pyx rename to lasp/device/lasp_daq.pyx diff --git a/lasp/device/lasp_daqconfig.py b/lasp/device/lasp_daqconfig.py index 9bf812e..75c1628 100644 --- a/lasp/device/lasp_daqconfig.py +++ b/lasp/device/lasp_daqconfig.py @@ -9,10 +9,30 @@ Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves """ from dataclasses import dataclass, field -from dataclasses_json import dataclass_json -from ..lasp_common import lasp_shelve, Qty, SIQtys from typing import List +from dataclasses_json import dataclass_json + +from ..lasp_common import Qty, SIQtys, lasp_shelve + +@dataclass +class DAQApi: + backendname: str + apiname: str + internal_nr: int + + def description(self): + return self.backendname + ' - ' + self.apiname + + +class DAQApis: + apis = [] + + @staticmethod + def addApi(api): + DAQApis.apis.append(api) + + class InputMode: differential = 'Differential' @@ -20,16 +40,19 @@ class InputMode: pseudo_differential = 'Pseudo-differential' undefined = 'Undefined' + class CouplingMode: ac = 'AC' dc = 'DC' undefined = 'Undefined' + class Range: oneV = '+/- 1 V' tenV = '+/- 10 V' undefined = 'Undefined' + @dataclass class DeviceInfo: api: int diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b7f1a7e..660b093 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,9 +1,14 @@ include_directories(${CMAKE_SOURCE_DIR}/lasp/c) +include_directories(${CMAKE_SOURCE_DIR}/lasp/device) add_executable(test_bf test_bf.c) add_executable(test_workers test_workers.c) add_executable(test_fft test_fft.c) add_executable(test_math test_math.c) + target_link_libraries(test_bf lasp_lib) target_link_libraries(test_fft lasp_lib pthread) target_link_libraries(test_workers lasp_lib pthread) target_link_libraries(test_math lasp_lib pthread) + +add_executable(test_uldaq test_uldaq.cpp) +target_link_libraries(test_uldaq cpp_daq uldaq pthread) diff --git a/lasp/device/test_uldaq.cpp b/test/test_uldaq.cpp similarity index 90% rename from lasp/device/test_uldaq.cpp rename to test/test_uldaq.cpp index f180325..b2c03ca 100644 --- a/lasp/device/test_uldaq.cpp +++ b/test/test_uldaq.cpp @@ -22,8 +22,8 @@ int main() { true // monitor Output ); - SafeQueue inqueue; - SafeQueue outqueue; + SafeQueue inqueue; + SafeQueue outqueue; double totalTime = 5; double t = 0; @@ -52,7 +52,7 @@ int main() { daq.stop(); while(!inqueue.empty()) { - double* buf = inqueue.dequeue(); + double* buf = (double*) inqueue.dequeue(); for(us i=0;i