First work on uldaq implementatio for DT9837A
This commit is contained in:
parent
2192f5a7fc
commit
a3a7c37548
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
*.a
|
*.a
|
||||||
*.pyc
|
*.pyc
|
||||||
lasp_rtaudio.cxx
|
lasp_rtaudio.cxx
|
||||||
|
lasp_uldaq.cxx
|
||||||
dist
|
dist
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
include_directories(/usr/include/rtaudio)
|
include_directories(/usr/include/rtaudio)
|
||||||
set_source_files_properties(lasp_rtaudio.pyx PROPERTIES CYTHON_IS_CXX TRUE)
|
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_rtaudio.cxx PROPERTIES COMPILE_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
|
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
|
||||||
|
|
||||||
cython_add_module(lasp_rtaudio lasp_rtaudio.pyx)
|
cython_add_module(lasp_rtaudio lasp_rtaudio.pyx)
|
||||||
|
cython_add_module(lasp_uldaq lasp_uldaq.pyx)
|
||||||
|
|
||||||
target_link_libraries(lasp_rtaudio pthread rtaudio)
|
target_link_libraries(lasp_rtaudio pthread rtaudio)
|
||||||
|
target_link_libraries(lasp_uldaq uldaq)
|
||||||
if(win32)
|
if(win32)
|
||||||
target_link_libraries(lasp_rtaudio python37)
|
target_link_libraries(lasp_rtaudio python37)
|
||||||
endif(win32)
|
endif(win32)
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from .lasp_rtaudio import *
|
|
||||||
from .lasp_daqconfig import *
|
from .lasp_daqconfig import *
|
||||||
|
from .lasp_avtype import *
|
||||||
|
from .lasp_rtaudio import *
|
||||||
|
from .lasp_uldaq import *
|
||||||
|
|
||||||
|
9
lasp/device/lasp_avtype.py
Normal file
9
lasp/device/lasp_avtype.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
__all__ = ['AvType']
|
||||||
|
|
||||||
|
class AvType:
|
||||||
|
"""Specificying the type of data, for adding and removing callbacks from
|
||||||
|
the stream."""
|
||||||
|
audio_input = 1
|
||||||
|
audio_output = 2
|
||||||
|
video = 4
|
54
lasp/device/lasp_common_decls.pxd
Normal file
54
lasp/device/lasp_common_decls.pxd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import sys
|
||||||
|
include "config.pxi"
|
||||||
|
cimport cython
|
||||||
|
from .lasp_daqconfig import DeviceInfo
|
||||||
|
from .lasp_avtype import AvType
|
||||||
|
from libcpp.string cimport string
|
||||||
|
from libcpp.vector cimport vector
|
||||||
|
from libc.stdlib cimport malloc, free
|
||||||
|
from libc.stdio cimport printf, fprintf, stderr
|
||||||
|
from libc.string cimport memcpy, memset
|
||||||
|
from cpython.ref cimport PyObject,Py_INCREF, Py_DECREF
|
||||||
|
|
||||||
|
__all__ = ['RtAudio', 'get_numpy_dtype_from_format_string',
|
||||||
|
'get_sampwidth_from_format_string']
|
||||||
|
|
||||||
|
|
||||||
|
cdef extern from "lasp_cppthread.h" nogil:
|
||||||
|
cdef cppclass CPPThread[T,F]:
|
||||||
|
CPPThread(F threadfunction, T data)
|
||||||
|
void join()
|
||||||
|
|
||||||
|
void CPPsleep(unsigned int ms)
|
||||||
|
|
||||||
|
cdef extern from "lasp_cppqueue.h" nogil:
|
||||||
|
cdef cppclass SafeQueue[T]:
|
||||||
|
SafeQueue()
|
||||||
|
void enqueue(T t)
|
||||||
|
T dequeue()
|
||||||
|
size_t size() const
|
||||||
|
bool empty() const
|
||||||
|
|
||||||
|
|
||||||
|
cdef extern from "atomic" namespace "std" nogil:
|
||||||
|
cdef cppclass atomic[T]:
|
||||||
|
T load()
|
||||||
|
void store(T)
|
||||||
|
|
||||||
|
cdef extern from "lasp_pyarray.h":
|
||||||
|
PyObject* data_to_ndarray(void* data,
|
||||||
|
int n_rows,int n_cols,
|
||||||
|
int typenum,
|
||||||
|
bool transfer_ownership,
|
||||||
|
bool F_contiguous)
|
||||||
|
|
||||||
|
|
||||||
|
cdef inline void copyChannel(void* to, void* from_,
|
||||||
|
unsigned bytesperchan,
|
||||||
|
unsigned toindex,
|
||||||
|
unsigned fromindex) nogil:
|
||||||
|
memcpy(<void*> &((<char*> to)[bytesperchan*toindex]),
|
||||||
|
<void*> &((<char*> from_)[bytesperchan*fromindex]),
|
||||||
|
bytesperchan)
|
||||||
|
|
||||||
|
|
@ -14,11 +14,27 @@ from ..lasp_common import lasp_shelve, Qty, SIQtys
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
class InputMode:
|
||||||
|
differential = 'Differential'
|
||||||
|
single_ended = 'Single-ended'
|
||||||
|
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
|
@dataclass
|
||||||
class DeviceInfo:
|
class DeviceInfo:
|
||||||
api: int
|
api: int
|
||||||
index: int
|
index: int
|
||||||
probed: bool
|
probed: bool #
|
||||||
name: str
|
name: str
|
||||||
outputchannels: int
|
outputchannels: int
|
||||||
inputchannels: int
|
inputchannels: int
|
||||||
@ -26,7 +42,7 @@ class DeviceInfo:
|
|||||||
samplerates: list
|
samplerates: list
|
||||||
sampleformats: list
|
sampleformats: list
|
||||||
prefsamplerate: int
|
prefsamplerate: int
|
||||||
|
hasInputIEPE: bool = False
|
||||||
|
|
||||||
|
|
||||||
@dataclass_json
|
@dataclass_json
|
||||||
@ -36,6 +52,9 @@ class DAQChannel:
|
|||||||
channel_name: str
|
channel_name: str
|
||||||
sensitivity: float
|
sensitivity: float
|
||||||
qty: Qty
|
qty: Qty
|
||||||
|
range_: str = 'Undefined'
|
||||||
|
IEPE_enabled: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass_json
|
@dataclass_json
|
||||||
|
@ -1,23 +1,8 @@
|
|||||||
import sys
|
include "lasp_common_decls.pxd"
|
||||||
include "config.pxi"
|
|
||||||
cimport cython
|
|
||||||
from .lasp_daqconfig import DeviceInfo
|
|
||||||
from libcpp.string cimport string
|
|
||||||
from libcpp.vector cimport vector
|
|
||||||
from libc.stdlib cimport malloc, free
|
|
||||||
from libc.stdio cimport printf, fprintf, stderr
|
|
||||||
from libc.string cimport memcpy, memset
|
|
||||||
from cpython.ref cimport PyObject,Py_INCREF, Py_DECREF
|
|
||||||
|
|
||||||
__all__ = ['AvType', 'RtAudio', 'get_numpy_dtype_from_format_string',
|
__all__ = ['RtAudio', 'get_numpy_dtype_from_format_string',
|
||||||
'get_sampwidth_from_format_string']
|
'get_sampwidth_from_format_string']
|
||||||
|
|
||||||
class AvType:
|
|
||||||
"""Specificying the type of data, for adding and removing callbacks from
|
|
||||||
the stream."""
|
|
||||||
audio_input = 1
|
|
||||||
audio_output = 2
|
|
||||||
video = 4
|
|
||||||
|
|
||||||
cdef extern from "RtAudio.h" nogil:
|
cdef extern from "RtAudio.h" nogil:
|
||||||
ctypedef unsigned long RtAudioStreamStatus
|
ctypedef unsigned long RtAudioStreamStatus
|
||||||
@ -141,33 +126,6 @@ cdef extern from "RtAudio.h" nogil:
|
|||||||
unsigned int getStreamSampleRate()
|
unsigned int getStreamSampleRate()
|
||||||
void showWarnings(bool value)
|
void showWarnings(bool value)
|
||||||
|
|
||||||
cdef extern from "lasp_cppthread.h" nogil:
|
|
||||||
cdef cppclass CPPThread[T,F]:
|
|
||||||
CPPThread(F threadfunction, T data)
|
|
||||||
void join()
|
|
||||||
|
|
||||||
void CPPsleep(unsigned int ms)
|
|
||||||
|
|
||||||
cdef extern from "lasp_cppqueue.h" nogil:
|
|
||||||
cdef cppclass SafeQueue[T]:
|
|
||||||
SafeQueue()
|
|
||||||
void enqueue(T t)
|
|
||||||
T dequeue()
|
|
||||||
size_t size() const
|
|
||||||
bool empty() const
|
|
||||||
|
|
||||||
|
|
||||||
cdef extern from "atomic" namespace "std" nogil:
|
|
||||||
cdef cppclass atomic[T]:
|
|
||||||
T load()
|
|
||||||
void store(T)
|
|
||||||
|
|
||||||
cdef extern from "lasp_pyarray.h":
|
|
||||||
PyObject* data_to_ndarray(void* data,
|
|
||||||
int n_rows,int n_cols,
|
|
||||||
int typenum,
|
|
||||||
bool transfer_ownership,
|
|
||||||
bool F_contiguous)
|
|
||||||
|
|
||||||
_formats_strkey = {
|
_formats_strkey = {
|
||||||
'8-bit integers': (RTAUDIO_SINT8, 1, np.int8),
|
'8-bit integers': (RTAUDIO_SINT8, 1, np.int8),
|
||||||
@ -192,7 +150,6 @@ def get_sampwidth_from_format_string(format_string):
|
|||||||
return _formats_strkey[format_string][-2]
|
return _formats_strkey[format_string][-2]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# It took me quite a long time to fully understand Cython's idiosyncrasies
|
# It took me quite a long time to fully understand Cython's idiosyncrasies
|
||||||
# concerning C(++) callbacks, the GIL and passing Python objects as pointers
|
# concerning C(++) callbacks, the GIL and passing Python objects as pointers
|
||||||
# into C(++) functions. But finally, here it is!
|
# into C(++) functions. But finally, here it is!
|
||||||
@ -205,13 +162,6 @@ def get_sampwidth_from_format_string(format_string):
|
|||||||
# """
|
# """
|
||||||
# memcpy(buf, arr.data, arr.size*arr.itemsize)
|
# memcpy(buf, arr.data, arr.size*arr.itemsize)
|
||||||
|
|
||||||
cdef void copyChannel(void* to, void* from_,
|
|
||||||
unsigned bytesperchan,
|
|
||||||
unsigned toindex,
|
|
||||||
unsigned fromindex) nogil:
|
|
||||||
memcpy(<void*> &((<char*> to)[bytesperchan*toindex]),
|
|
||||||
<void*> &((<char*> from_)[bytesperchan*fromindex]),
|
|
||||||
bytesperchan)
|
|
||||||
|
|
||||||
|
|
||||||
ctypedef struct _Stream:
|
ctypedef struct _Stream:
|
||||||
@ -522,9 +472,6 @@ cdef class RtAudio:
|
|||||||
}
|
}
|
||||||
return apidict
|
return apidict
|
||||||
|
|
||||||
cpdef unsigned int getDeviceCount(self):
|
|
||||||
return self._rtaudio.getDeviceCount()
|
|
||||||
|
|
||||||
cpdef unsigned int getDefaultOutputDevice(self):
|
cpdef unsigned int getDefaultOutputDevice(self):
|
||||||
return self._rtaudio.getDefaultOutputDevice()
|
return self._rtaudio.getDefaultOutputDevice()
|
||||||
|
|
||||||
|
387
lasp/device/lasp_uldaq.pxd
Normal file
387
lasp/device/lasp_uldaq.pxd
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
include "lasp_common_decls.pxd"
|
||||||
|
|
||||||
|
cdef extern from "uldaq.h" nogil:
|
||||||
|
|
||||||
|
ctypedef enum DaqDeviceInterface:
|
||||||
|
USB_IFC
|
||||||
|
BLUETOOTH_IFC
|
||||||
|
ETHERNET_IFC
|
||||||
|
ANY_IFC
|
||||||
|
|
||||||
|
ctypedef struct DaqDeviceDescriptor:
|
||||||
|
char productName[64]
|
||||||
|
unsigned int productId
|
||||||
|
DaqDeviceInterface devInterface
|
||||||
|
char devString[64]
|
||||||
|
char uniqueId[64]
|
||||||
|
char reserved[512]
|
||||||
|
|
||||||
|
ctypedef long long DaqDeviceHandle
|
||||||
|
|
||||||
|
ctypedef struct TransferStatus:
|
||||||
|
unsigned long long currentScanCount
|
||||||
|
unsigned long long currentTotalCount
|
||||||
|
long long currentIndex
|
||||||
|
char reserved[64]
|
||||||
|
|
||||||
|
ctypedef enum UlError:
|
||||||
|
ERR_NO_ERROR
|
||||||
|
ERR_UNHANDLED_EXCEPTION
|
||||||
|
ERR_BAD_DEV_HANDLE
|
||||||
|
ERR_BAD_DEV_TYPE
|
||||||
|
ERR_USB_DEV_NO_PERMISSION
|
||||||
|
ERR_USB_INTERFACE_CLAIMED
|
||||||
|
ERR_DEV_NOT_FOUND
|
||||||
|
ERR_DEV_NOT_CONNECTED
|
||||||
|
ERR_DEAD_DEV
|
||||||
|
ERR_BAD_BUFFER_SIZE
|
||||||
|
ERR_BAD_BUFFER
|
||||||
|
ERR_BAD_MEM_TYPE
|
||||||
|
ERR_BAD_MEM_REGION
|
||||||
|
ERR_BAD_RANGE
|
||||||
|
ERR_BAD_AI_CHAN
|
||||||
|
ERR_BAD_INPUT_MODE
|
||||||
|
ERR_ALREADY_ACTIVE
|
||||||
|
ERR_BAD_TRIG_TYPE
|
||||||
|
ERR_OVERRUN
|
||||||
|
ERR_UNDERRUN
|
||||||
|
ERR_TIMEDOUT
|
||||||
|
ERR_BAD_OPTION
|
||||||
|
ERR_BAD_RATE
|
||||||
|
ERR_BAD_BURSTIO_COUNT
|
||||||
|
ERR_CONFIG_NOT_SUPPORTED
|
||||||
|
ERR_BAD_CONFIG_VAL
|
||||||
|
ERR_BAD_AI_CHAN_TYPE
|
||||||
|
ERR_ADC_OVERRUN
|
||||||
|
ERR_BAD_TC_TYPE
|
||||||
|
ERR_BAD_UNIT
|
||||||
|
ERR_BAD_QUEUE_SIZE
|
||||||
|
ERR_BAD_CONFIG_ITEM
|
||||||
|
ERR_BAD_INFO_ITEM
|
||||||
|
ERR_BAD_FLAG
|
||||||
|
ERR_BAD_SAMPLE_COUNT
|
||||||
|
ERR_INTERNAL
|
||||||
|
ERR_BAD_COUPLING_MODE
|
||||||
|
ERR_BAD_SENSOR_SENSITIVITY
|
||||||
|
ERR_BAD_IEPE_MODE
|
||||||
|
ERR_BAD_AI_CHAN_QUEUE
|
||||||
|
ERR_BAD_AI_GAIN_QUEUE
|
||||||
|
ERR_BAD_AI_MODE_QUEUE
|
||||||
|
ERR_FPGA_FILE_NOT_FOUND
|
||||||
|
ERR_UNABLE_TO_READ_FPGA_FILE
|
||||||
|
ERR_NO_FPGA
|
||||||
|
ERR_BAD_ARG
|
||||||
|
ERR_MIN_SLOPE_VAL_REACHED
|
||||||
|
ERR_MAX_SLOPE_VAL_REACHED
|
||||||
|
ERR_MIN_OFFSET_VAL_REACHED
|
||||||
|
ERR_MAX_OFFSET_VAL_REACHED
|
||||||
|
ERR_BAD_PORT_TYPE
|
||||||
|
ERR_WRONG_DIG_CONFIG
|
||||||
|
ERR_BAD_BIT_NUM
|
||||||
|
ERR_BAD_PORT_VAL
|
||||||
|
ERR_BAD_RETRIG_COUNT
|
||||||
|
ERR_BAD_AO_CHAN
|
||||||
|
ERR_BAD_DA_VAL
|
||||||
|
ERR_BAD_TMR
|
||||||
|
ERR_BAD_FREQUENCY
|
||||||
|
ERR_BAD_DUTY_CYCLE
|
||||||
|
ERR_BAD_INITIAL_DELAY
|
||||||
|
ERR_BAD_CTR
|
||||||
|
ERR_BAD_CTR_VAL
|
||||||
|
ERR_BAD_DAQI_CHAN_TYPE
|
||||||
|
ERR_BAD_NUM_CHANS
|
||||||
|
ERR_BAD_CTR_REG
|
||||||
|
ERR_BAD_CTR_MEASURE_TYPE
|
||||||
|
ERR_BAD_CTR_MEASURE_MODE
|
||||||
|
ERR_BAD_DEBOUNCE_TIME
|
||||||
|
ERR_BAD_DEBOUNCE_MODE
|
||||||
|
ERR_BAD_EDGE_DETECTION
|
||||||
|
ERR_BAD_TICK_SIZE
|
||||||
|
ERR_BAD_DAQO_CHAN_TYPE
|
||||||
|
ERR_NO_CONNECTION_ESTABLISHED
|
||||||
|
ERR_BAD_EVENT_TYPE
|
||||||
|
ERR_EVENT_ALREADY_ENABLED
|
||||||
|
ERR_BAD_EVENT_PARAMETER
|
||||||
|
ERR_BAD_CALLBACK_FUCNTION
|
||||||
|
ERR_BAD_MEM_ADDRESS
|
||||||
|
ERR_MEM_ACCESS_DENIED
|
||||||
|
ERR_DEV_UNAVAILABLE
|
||||||
|
ERR_BAD_RETRIG_TRIG_TYPE
|
||||||
|
ERR_BAD_DEV_VER
|
||||||
|
ERR_BAD_DIG_OPERATION
|
||||||
|
ERR_BAD_PORT_INDEX
|
||||||
|
ERR_OPEN_CONNECTION
|
||||||
|
ERR_DEV_NOT_READY
|
||||||
|
ERR_PACER_OVERRUN
|
||||||
|
ERR_BAD_TRIG_CHANNEL
|
||||||
|
ERR_BAD_TRIG_LEVEL
|
||||||
|
ERR_BAD_CHAN_ORDER
|
||||||
|
ERR_TEMP_OUT_OF_RANGE
|
||||||
|
ERR_TRIG_THRESHOLD_OUT_OF_RANGE
|
||||||
|
ERR_INCOMPATIBLE_FIRMWARE
|
||||||
|
ERR_BAD_NET_IFC
|
||||||
|
ERR_BAD_NET_HOST
|
||||||
|
ERR_BAD_NET_PORT
|
||||||
|
ERR_NET_IFC_UNAVAILABLE
|
||||||
|
ERR_NET_CONNECTION_FAILED
|
||||||
|
ERR_BAD_CONNECTION_CODE
|
||||||
|
ERR_CONNECTION_CODE_IGNORED
|
||||||
|
ERR_NET_DEV_IN_USE
|
||||||
|
ERR_BAD_NET_FRAME
|
||||||
|
ERR_NET_TIMEOUT
|
||||||
|
ERR_DATA_SOCKET_CONNECTION_FAILED
|
||||||
|
ERR_PORT_USED_FOR_ALARM
|
||||||
|
ERR_BIT_USED_FOR_ALARM
|
||||||
|
ERR_CMR_EXCEEDED
|
||||||
|
ERR_NET_BUFFER_OVERRUN
|
||||||
|
ERR_BAD_NET_BUFFER
|
||||||
|
|
||||||
|
ctypedef enum AiInputMode:
|
||||||
|
AI_DIFFERENTIAL = 1,
|
||||||
|
AI_SINGLE_ENDED = 2,
|
||||||
|
AI_PSEUDO_DIFFERENTIAL = 3
|
||||||
|
|
||||||
|
ctypedef enum Range:
|
||||||
|
BIP10VOLTS
|
||||||
|
BIP5VOLTS
|
||||||
|
BIP4VOLTS
|
||||||
|
BIP2PT5VOLTS
|
||||||
|
BIP2VOLTS
|
||||||
|
BIP1PT25VOLTS
|
||||||
|
BIP1VOLTS
|
||||||
|
BIPPT625VOLTS
|
||||||
|
BIPPT5VOLTS
|
||||||
|
BIPPT25VOLTS
|
||||||
|
BIPPT125VOLTS
|
||||||
|
BIPPT2VOLTS
|
||||||
|
BIPPT1VOLTS
|
||||||
|
BIPPT078VOLTS
|
||||||
|
BIPPT05VOLTS
|
||||||
|
BIPPT01VOLTS
|
||||||
|
BIPPT005VOLTS
|
||||||
|
BIP3VOLTS
|
||||||
|
BIPPT312VOLTS
|
||||||
|
BIPPT156VOLTS
|
||||||
|
UNI15VOLTS
|
||||||
|
UNI20VOLTS
|
||||||
|
UNI10VOLTS
|
||||||
|
UNI5VOLTS
|
||||||
|
UNI4VOLTS
|
||||||
|
UNI2PT5VOLTS
|
||||||
|
UNI2VOLTS
|
||||||
|
UNI1PT25VOLTS
|
||||||
|
UNI1VOLTS
|
||||||
|
UNIPT625VOLTS
|
||||||
|
UNIPT5VOLTS
|
||||||
|
UNIPT25VOLTS
|
||||||
|
UNIPT125VOLTS
|
||||||
|
UNIPT2VOLTS
|
||||||
|
UNIPT1VOLTS
|
||||||
|
UNIPT078VOLTS
|
||||||
|
UNIPT05VOLTS
|
||||||
|
UNIPT01VOLTS
|
||||||
|
UNIPT005VOLTS
|
||||||
|
MA0TO20
|
||||||
|
|
||||||
|
ctypedef enum AdcTimingMode:
|
||||||
|
ADC_TM_AUTO
|
||||||
|
ADC_TM_HIGH_RES
|
||||||
|
ADC_TM_HIGH_SPEED
|
||||||
|
|
||||||
|
ctypedef enum IepeMode:
|
||||||
|
IEPE_ENABLED
|
||||||
|
IEPE_DISABLED
|
||||||
|
|
||||||
|
ctypedef enum CouplingMode:
|
||||||
|
CM_DC
|
||||||
|
CM_AC
|
||||||
|
|
||||||
|
ctypedef enum TriggerType:
|
||||||
|
TRIG_NONE
|
||||||
|
TRIG_POS_EDGE
|
||||||
|
TRIG_NEG_EDGE
|
||||||
|
TRIG_HIGH
|
||||||
|
TRIG_LOW
|
||||||
|
GATE_HIGH
|
||||||
|
GATE_LOW
|
||||||
|
TRIG_RISING
|
||||||
|
TRIG_FALLING
|
||||||
|
TRIG_ABOVE
|
||||||
|
TRIG_BELOW
|
||||||
|
GATE_ABOVE
|
||||||
|
GATE_BELOW
|
||||||
|
GATE_IN_WINDOW
|
||||||
|
GATE_OUT_WINDOW
|
||||||
|
TRIG_PATTERN_EQ
|
||||||
|
TRIG_PATTERN_NE
|
||||||
|
TRIG_PATTERN_ABOVE
|
||||||
|
TRIG_PATTERN_BELOW
|
||||||
|
|
||||||
|
ctypedef enum ScanStatus:
|
||||||
|
SS_IDLE
|
||||||
|
SS_RUNNING
|
||||||
|
|
||||||
|
ctypedef enum ScanOption:
|
||||||
|
SO_DEFAULTIO
|
||||||
|
SO_SINGLEIO
|
||||||
|
SO_BLOCKIO
|
||||||
|
SO_BURSTIO
|
||||||
|
SO_CONTINUOUS
|
||||||
|
SO_EXTCLOCK
|
||||||
|
SO_EXTTRIGGER
|
||||||
|
SO_RETRIGGER
|
||||||
|
SO_BURSTMODE
|
||||||
|
SO_PACEROUT
|
||||||
|
SO_EXTTIMEBASE
|
||||||
|
SO_TIMEBASEOUT
|
||||||
|
|
||||||
|
ctypedef enum DaqInScanFlag:
|
||||||
|
DAQINSCAN_FF_DEFAULT
|
||||||
|
DAQINSCAN_FF_NOSCALEDATA
|
||||||
|
DAQINSCAN_FF_NOCALIBRATEDATA
|
||||||
|
DAQINSCAN_FF_NOCLEAR
|
||||||
|
|
||||||
|
ctypedef enum DaqOutScanFlag:
|
||||||
|
DAQOUTSCAN_FF_DEFAULT
|
||||||
|
DAQOUTSCAN_FF_NOSCALEDATA
|
||||||
|
DAQOUTSCAN_FF_NOCALIBRATEDATA
|
||||||
|
|
||||||
|
ctypedef enum DaqInChanType:
|
||||||
|
DAQI_ANALOG_DIFF
|
||||||
|
DAQI_ANALOG_SE
|
||||||
|
DAQI_DIGITAL
|
||||||
|
DAQI_CTR16
|
||||||
|
DAQI_CTR32
|
||||||
|
DAQI_CTR48
|
||||||
|
DAQI_DAC
|
||||||
|
|
||||||
|
ctypedef struct DaqInChanDescriptor:
|
||||||
|
int channel
|
||||||
|
DaqInChanType type
|
||||||
|
Range range
|
||||||
|
|
||||||
|
ctypedef enum DaqOutChanType:
|
||||||
|
DAQO_ANALOG
|
||||||
|
DAQO_DIGITAL
|
||||||
|
|
||||||
|
ctypedef struct DaqOutChanDescriptor:
|
||||||
|
int channel
|
||||||
|
DaqOutChanType type
|
||||||
|
Range range
|
||||||
|
|
||||||
|
ctypedef enum DaqEventType:
|
||||||
|
DE_NONE
|
||||||
|
DE_ON_DATA_AVAILABLE
|
||||||
|
DE_ON_INPUT_SCAN_ERROR
|
||||||
|
DE_ON_END_OF_INPUT_SCAN
|
||||||
|
DE_ON_OUTPUT_SCAN_ERROR
|
||||||
|
DE_ON_END_OF_OUTPUT_SCAN
|
||||||
|
|
||||||
|
ctypedef enum WaitType:
|
||||||
|
WAIT_UNTIL_DONE
|
||||||
|
|
||||||
|
ctypedef enum DevInfoItem:
|
||||||
|
DEV_INFO_HAS_AI_DEV
|
||||||
|
DEV_INFO_HAS_AO_DEV
|
||||||
|
DEV_INFO_HAS_DIO_DEV
|
||||||
|
DEV_INFO_HAS_CTR_DEV
|
||||||
|
DEV_INFO_HAS_TMR_DEV
|
||||||
|
DEV_INFO_HAS_DAQI_DEV
|
||||||
|
DEV_INFO_HAS_DAQO_DEV
|
||||||
|
DEV_INFO_DAQ_EVENT_TYPES
|
||||||
|
DEV_INFO_MEM_REGIONS
|
||||||
|
|
||||||
|
ctypedef enum AiInfoItem:
|
||||||
|
AI_INFO_RESOLUTION
|
||||||
|
AI_INFO_NUM_CHANS
|
||||||
|
AI_INFO_NUM_CHANS_BY_MODE
|
||||||
|
AI_INFO_NUM_CHANS_BY_TYPE
|
||||||
|
AI_INFO_CHAN_TYPES
|
||||||
|
AI_INFO_SCAN_OPTIONS
|
||||||
|
AI_INFO_HAS_PACER
|
||||||
|
AI_INFO_NUM_DIFF_RANGES
|
||||||
|
AI_INFO_NUM_SE_RANGES
|
||||||
|
AI_INFO_DIFF_RANGE
|
||||||
|
AI_INFO_SE_RANGE
|
||||||
|
AI_INFO_TRIG_TYPES
|
||||||
|
AI_INFO_MAX_QUEUE_LENGTH_BY_MODE
|
||||||
|
AI_INFO_QUEUE_TYPES
|
||||||
|
AI_INFO_QUEUE_LIMITS
|
||||||
|
AI_INFO_FIFO_SIZE
|
||||||
|
AI_INFO_IEPE_SUPPORTED
|
||||||
|
|
||||||
|
ctypedef enum AiConfigItem:
|
||||||
|
AI_CFG_CHAN_TYPE
|
||||||
|
AI_CFG_CHAN_TC_TYPE
|
||||||
|
AI_CFG_SCAN_CHAN_TEMP_UNIT
|
||||||
|
AI_CFG_SCAN_TEMP_UNIT
|
||||||
|
AI_CFG_ADC_TIMING_MODE
|
||||||
|
AI_CFG_AUTO_ZERO_MODE
|
||||||
|
AI_CFG_CAL_DATE
|
||||||
|
AI_CFG_CHAN_IEPE_MODE
|
||||||
|
AI_CFG_CHAN_COUPLING_MODE
|
||||||
|
AI_CFG_CHAN_SENSOR_CONNECTION_TYPE
|
||||||
|
AI_CFG_CHAN_OTD_MODE
|
||||||
|
AI_CFG_OTD_MODE
|
||||||
|
AI_CFG_CAL_TABLE_TYPE
|
||||||
|
AI_CFG_REJECT_FREQ_TYPE
|
||||||
|
AI_CFG_EXP_CAL_DATE
|
||||||
|
|
||||||
|
ctypedef enum AoConfigItem:
|
||||||
|
AO_CFG_SYNC_MODE
|
||||||
|
AO_CFG_CHAN_SENSE_MODE
|
||||||
|
|
||||||
|
ctypedef enum AiConfigItemDbl:
|
||||||
|
AI_CFG_CHAN_SLOPE
|
||||||
|
AI_CFG_CHAN_OFFSET
|
||||||
|
AI_CFG_CHAN_SENSOR_SENSITIVITY
|
||||||
|
AI_CFG_CHAN_DATA_RATE
|
||||||
|
|
||||||
|
ctypedef enum AInScanFlag:
|
||||||
|
AINSCAN_FF_DEFAULT
|
||||||
|
AINSCAN_FF_NOSCALEDATA
|
||||||
|
AINSCAN_FF_NOCALIBRATEDATA
|
||||||
|
|
||||||
|
UlError ulGetDaqDeviceInventory(DaqDeviceInterface interfaceTypes, DaqDeviceDescriptor daqDevDescriptors[], unsigned int* numDescriptors )
|
||||||
|
|
||||||
|
DaqDeviceHandle ulCreateDaqDevice(DaqDeviceDescriptor daqDevDescriptor)
|
||||||
|
UlError ulConnectDaqDevice(DaqDeviceHandle daqDeviceHandle);
|
||||||
|
|
||||||
|
UlError ulDisconnectDaqDevice(DaqDeviceHandle daqDeviceHandle);
|
||||||
|
UlError ulReleaseDaqDevice(DaqDeviceHandle daqDeviceHandle);
|
||||||
|
|
||||||
|
UlError ulAISetConfig(DaqDeviceHandle daqDeviceHandle, AiConfigItem configItem, unsigned int index, long long configValue)
|
||||||
|
UlError ulAISetConfigDbl(DaqDeviceHandle daqDeviceHandle, AiConfigItemDbl configItem, unsigned int index, double configValue)
|
||||||
|
UlError ulAIGetConfig(DaqDeviceHandle daqDeviceHandle, AiConfigItem configItem, unsigned int index, long long* configValue);
|
||||||
|
|
||||||
|
UlError ulDaqInScan(DaqDeviceHandle daqDeviceHandle, DaqInChanDescriptor chanDescriptors[], int numChans, int samplesPerChan, double* rate, ScanOption options, DaqInScanFlag flags, double data[]);
|
||||||
|
UlError ulDaqInScanStatus(DaqDeviceHandle daqDeviceHandle, ScanStatus* status, TransferStatus* xferStatus);
|
||||||
|
UlError ulDaqInScanStop(DaqDeviceHandle daqDeviceHandle);
|
||||||
|
UlError ulDaqInScanWait(DaqDeviceHandle daqDeviceHandle, WaitType waitType, long long waitParam, double timeout);
|
||||||
|
|
||||||
|
UlError ulDaqOutScan(DaqDeviceHandle daqDeviceHandle, DaqOutChanDescriptor chanDescriptors[], int numChans, int samplesPerChan, double* rate, ScanOption options, DaqOutScanFlag flags, double data[]);
|
||||||
|
UlError ulDaqOutScanStatus(DaqDeviceHandle daqDeviceHandle, ScanStatus* status, TransferStatus* xferStatus);
|
||||||
|
UlError ulDaqOutScanStop(DaqDeviceHandle daqDeviceHandle);
|
||||||
|
UlError ulDaqOutSetTrigger(DaqDeviceHandle daqDeviceHandle, TriggerType type, DaqInChanDescriptor trigChanDescriptor, double level, double variance, unsigned int retriggerSampleCount);
|
||||||
|
|
||||||
|
|
||||||
|
# UlError ulAIGetConfigDbl(DaqDeviceHandle daqDeviceHandle, AiConfigItemDbl configItem, unsigned int index, double* configValue);
|
||||||
|
# UlError ulAIGetConfigStr(DaqDeviceHandle daqDeviceHandle, AiConfigItemStr configItem, unsigned int index, char* configStr, unsigned int* maxConfigLen);
|
||||||
|
# ctypedef enum AiIn
|
||||||
|
# {
|
||||||
|
# /** Returns the minimum scan rate in samples per second to the \p infoValue argument. Index is ignored. */
|
||||||
|
# AI_INFO_MIN_SCAN_RATE = 1000,
|
||||||
|
|
||||||
|
# /** Returns the maximum scan rate in samples per second to the \p infoValue argument. Index is ignored. */
|
||||||
|
# AI_INFO_MAX_SCAN_RATE = 1001,
|
||||||
|
|
||||||
|
# /** Returns the maximum throughput in samples per second to the \p infoValue argument. Index is ignored. */
|
||||||
|
# AI_INFO_MAX_THROUGHPUT = 1002,
|
||||||
|
|
||||||
|
# /** Returns the maximum scan rate in samples per second when using the ::SO_BURSTIO ScanOption to the \p infoValue argument. Index is ignored. */
|
||||||
|
# AI_INFO_MAX_BURST_RATE = 1003,
|
||||||
|
|
||||||
|
# /** Returns the maximum throughput in samples per second when using the ::SO_BURSTIO ScanOption to the \p infoValue argument. Index is ignored. */
|
||||||
|
# AI_INFO_MAX_BURST_THROUGHPUT = 1004
|
||||||
|
# }AiInfoItemDbl
|
||||||
|
|
624
lasp/device/lasp_uldaq.pyx
Normal file
624
lasp/device/lasp_uldaq.pyx
Normal file
@ -0,0 +1,624 @@
|
|||||||
|
from cpython.ref cimport PyObject,Py_INCREF, Py_DECREF
|
||||||
|
from .lasp_daqconfig import (DeviceInfo, InputMode, Range as pyRange,
|
||||||
|
DAQChannel)
|
||||||
|
from .lasp_avtype import AvType
|
||||||
|
|
||||||
|
__all__ = ['UlDT9837A', 'UlDaq']
|
||||||
|
|
||||||
|
DEF MAX_DEF_COUNT = 100
|
||||||
|
|
||||||
|
cdef struct DaqThreadData:
|
||||||
|
|
||||||
|
unsigned int samplesPerBlock
|
||||||
|
double samplerate
|
||||||
|
|
||||||
|
DaqDeviceHandle handle
|
||||||
|
|
||||||
|
SafeQueue[void*] *inputQueue
|
||||||
|
SafeQueue[void*] *outputQueue
|
||||||
|
|
||||||
|
DaqInChanDescriptor* inChanDescriptors
|
||||||
|
unsigned ninputChanDescriptors
|
||||||
|
|
||||||
|
DaqOutChanDescriptor* outChanDescriptors
|
||||||
|
unsigned noutputChanDescriptors
|
||||||
|
|
||||||
|
atomic[bool] stopThread
|
||||||
|
CPPThread[void*, void (*)(void*)] *thread
|
||||||
|
|
||||||
|
cdef void eventCallbackFunction(DaqDeviceHandle handle, DaqEventType eventType,
|
||||||
|
unsigned long long eventData, void* userData):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
cdef void ulThreadFunction(void* threaddata_void) nogil:
|
||||||
|
"""
|
||||||
|
Stream thread function
|
||||||
|
"""
|
||||||
|
cdef:
|
||||||
|
DaqThreadData* td = <DaqThreadData*> threaddata_void
|
||||||
|
TransferStatus instatus
|
||||||
|
TransferStatus outstatus
|
||||||
|
UlError err
|
||||||
|
ScanOption scanoptions
|
||||||
|
DaqInScanFlag inscanflags
|
||||||
|
DaqOutScanFlag outscanflags
|
||||||
|
# AScanFlag inscanflags
|
||||||
|
double* outbuffer, inbuffer
|
||||||
|
|
||||||
|
# inbuffer = NULL
|
||||||
|
# outbuffer = NULL
|
||||||
|
|
||||||
|
inscanflags = DAQINSCAN_FF_NOSCALEDATA
|
||||||
|
outscanflags = DAQOUTSCAN_FF_NOSCALEDATA
|
||||||
|
|
||||||
|
scanoptions = SO_CONTINUOUS
|
||||||
|
|
||||||
|
if td.noutputChanDescriptors > 0:
|
||||||
|
|
||||||
|
# Enable input and outputs
|
||||||
|
err = ulDaqOutScan(td.handle,
|
||||||
|
td.outChanDescriptors,
|
||||||
|
td.noutputChanDescriptors,
|
||||||
|
td.samplesPerBlock,
|
||||||
|
&td.samplerate,
|
||||||
|
scanoptions,
|
||||||
|
outscanflags,
|
||||||
|
outbuffer)
|
||||||
|
if err:
|
||||||
|
fprintf(stderr, 'Error starting data output\n')
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if td.ninputChanDescriptors > 0:
|
||||||
|
# Enable input and outputs
|
||||||
|
# err = ulDaqOutScan(td.handle,
|
||||||
|
# td.outChanDescriptors,
|
||||||
|
# td.noutputChanDescriptors,
|
||||||
|
# td.samplesPerBlock,
|
||||||
|
# &td.samplerate,
|
||||||
|
# scanoptions,
|
||||||
|
# outscanflags,
|
||||||
|
# outbuffer)
|
||||||
|
# if err:
|
||||||
|
# fprintf(stderr, 'Error starting data output\n')
|
||||||
|
# return
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
cdef class UlDT9837A:
|
||||||
|
cdef:
|
||||||
|
DaqDeviceHandle handle
|
||||||
|
bint handle_connected
|
||||||
|
bint stream_running
|
||||||
|
unsigned int ninputchannels
|
||||||
|
unsigned int noutputchannels
|
||||||
|
object input_range
|
||||||
|
object enabled_inputs
|
||||||
|
bint output_enabled
|
||||||
|
bint monitor_gen
|
||||||
|
DaqThreadData *threaddata
|
||||||
|
|
||||||
|
def __cinit__(self, unsigned int deviceno):
|
||||||
|
self.handle = 0
|
||||||
|
self.handle_connected = False
|
||||||
|
self.ninputchannels = 4
|
||||||
|
self.noutputchannels = 1
|
||||||
|
self.input_range = 4*[False]
|
||||||
|
self.enabled_inputs = 4*[False]
|
||||||
|
self.output_enabled = False
|
||||||
|
self.threaddata = NULL
|
||||||
|
self.monitor_gen = False
|
||||||
|
|
||||||
|
cdef:
|
||||||
|
DaqDeviceDescriptor devdescriptors[MAX_DEF_COUNT]
|
||||||
|
DaqDeviceDescriptor descriptor
|
||||||
|
DaqDeviceInterface interfaceType = ANY_IFC
|
||||||
|
|
||||||
|
UlError err
|
||||||
|
|
||||||
|
unsigned int numdevs = MAX_DEF_COUNT
|
||||||
|
|
||||||
|
err = ulGetDaqDeviceInventory(interfaceType,
|
||||||
|
devdescriptors,
|
||||||
|
&numdevs)
|
||||||
|
if(err != ERR_NO_ERROR):
|
||||||
|
raise RuntimeError(f'Device inventarization failed: {err}')
|
||||||
|
|
||||||
|
if deviceno >= numdevs:
|
||||||
|
raise ValueError(f'Device number {deviceno} too high {err}. This could happen when the device is currently not connected')
|
||||||
|
|
||||||
|
descriptor = devdescriptors[deviceno]
|
||||||
|
# get a handle to the DAQ device associated with the first descriptor
|
||||||
|
self.handle = ulCreateDaqDevice(descriptor);
|
||||||
|
|
||||||
|
if self.handle == 0:
|
||||||
|
raise RuntimeError ("Unable to create a handle to the specified DAQ device. Is the device currently in use?");
|
||||||
|
|
||||||
|
err = ulConnectDaqDevice(self.handle)
|
||||||
|
if err != ERR_NO_ERROR:
|
||||||
|
raise RuntimeError(f'Unable to connect to device: {err}')
|
||||||
|
|
||||||
|
|
||||||
|
cdef void startScan(self,
|
||||||
|
unsigned int samplesPerBlock,
|
||||||
|
SafeQueue[void*] *inputQueue,
|
||||||
|
SafeQueue[void*] *outputQueue):
|
||||||
|
|
||||||
|
cdef:
|
||||||
|
int i, j
|
||||||
|
# Sanity checks
|
||||||
|
if inputQueue and (not any(self.enabled_inputs) and (not self.monitor_gen)):
|
||||||
|
raise ValueError('Input queue given, but no input channels enabled and monitor output disabled')
|
||||||
|
if outputQueue and not self.output_enabled:
|
||||||
|
raise ValueError('Output queue given, but output channel is not enabled')
|
||||||
|
# End sanity checks
|
||||||
|
|
||||||
|
cdef:
|
||||||
|
DaqThreadData *threaddata
|
||||||
|
threaddata = <DaqThreadData*> malloc(sizeof(threaddata))
|
||||||
|
if not threaddata:
|
||||||
|
raise MemoryError()
|
||||||
|
|
||||||
|
threaddata.samplesPerBlock = samplesPerBlock
|
||||||
|
threaddata.handle = self.handle
|
||||||
|
threaddata.inputQueue = inputQueue
|
||||||
|
threaddata.outputQueue = outputQueue
|
||||||
|
threaddata.inChanDescriptors = NULL
|
||||||
|
threaddata.outChanDescriptors = NULL
|
||||||
|
threaddata.ninputChanDescriptors = 0
|
||||||
|
threaddata.noutputChanDescriptors = 0
|
||||||
|
|
||||||
|
neninputchannels = sum([1 if self.enabled_inputs == True else 0])
|
||||||
|
|
||||||
|
threaddata.inputQueue = inputQueue
|
||||||
|
threaddata.outputQueue = inputQueue
|
||||||
|
threaddata.thread = NULL
|
||||||
|
|
||||||
|
j = 0
|
||||||
|
if self.monitor_gen:
|
||||||
|
neninputchannels +=1
|
||||||
|
j+=1
|
||||||
|
|
||||||
|
threaddata.inChanDescriptors = <DaqInChanDescriptor*> malloc(neninputchannels*sizeof(DaqInChanDescriptor))
|
||||||
|
if not threaddata.inChanDescriptors:
|
||||||
|
self.cleanupThreadData(threaddata)
|
||||||
|
raise MemoryError()
|
||||||
|
|
||||||
|
if self.monitor_gen:
|
||||||
|
threaddata.inChanDescriptors[0].chantype = DAQI_DAC
|
||||||
|
threaddata.inChanDescriptors[0].channel = 7
|
||||||
|
threaddata.inChanDescriptors[0].range = BIP10VOLTS
|
||||||
|
|
||||||
|
for i in range(neninputchannels):
|
||||||
|
if self.enabled_inputs[i]:
|
||||||
|
threaddata.inChanDescriptors[j].chantype = DAQI_ANALOG_DIFF
|
||||||
|
threaddata.inChanDescriptors[j].channel = i
|
||||||
|
threaddata.inChanDescriptors[j].range = BIP10VOLTS if self.input_range[i] else BIP1VOLTS
|
||||||
|
j+=1
|
||||||
|
|
||||||
|
threaddata.ninputChanDescriptors = neninputchannels
|
||||||
|
|
||||||
|
if self.output_enabled:
|
||||||
|
threaddata.outChanDescriptors = <DaqOutChanDescriptor*> malloc(sizeof(DaqInChanDescriptor))
|
||||||
|
if not threaddata.outChanDescriptors:
|
||||||
|
self.cleanupThreadData(threaddata)
|
||||||
|
raise MemoryError()
|
||||||
|
self.threaddata.outChanDescriptors[0].channel = 0
|
||||||
|
self.threaddata.outChanDescriptors[0].type = DAQO_ANALOG
|
||||||
|
self.threaddata.outChanDescriptors[0].range = BIP10VOLTS
|
||||||
|
|
||||||
|
self.threaddata.thread = new CPPThread[void*, void (*)(void*)](
|
||||||
|
ulThreadFunction,
|
||||||
|
self.threaddata)
|
||||||
|
|
||||||
|
|
||||||
|
def setInputChannelConfig(self, unsigned chnum, channelconfig: DAQChannel):
|
||||||
|
if self.threaddata:
|
||||||
|
raise RuntimeError('Cannot change settings while sampling')
|
||||||
|
cdef:
|
||||||
|
int i
|
||||||
|
UlError err
|
||||||
|
IepeMode iepe
|
||||||
|
CouplingMode cm
|
||||||
|
|
||||||
|
if chnum >= self.ninputchannels:
|
||||||
|
raise RuntimeError('Invalid input channel number')
|
||||||
|
|
||||||
|
self.input_range[chnum] = True if channelconfig.range_ == pyRange.tenV else False
|
||||||
|
self.enabled_input[chnum] = channelconfig.channel_enabled
|
||||||
|
|
||||||
|
iepe = IEPE_ENABLED if channelconfig.IEPE_enabled else IEPE_DISABLED
|
||||||
|
cm = CM_AC if channelconfig.IEPE_enabled else CM_DC
|
||||||
|
|
||||||
|
err = ulAISetConfig(self.handle, AI_CFG_CHAN_IEPE_MODE, chnum,
|
||||||
|
iepe)
|
||||||
|
if err != ERR_NO_ERROR:
|
||||||
|
raise RuntimeError('Fatal: could not set IEPE mode')
|
||||||
|
|
||||||
|
err = ulAISetConfig(self.handle, AI_CFG_CHAN_COUPLING_MODE, chnum, cm);
|
||||||
|
if err != ERR_NO_ERROR:
|
||||||
|
raise RuntimeError('Fatal: could not set coupling mode')
|
||||||
|
|
||||||
|
err = ulAISetConfigDbl(self.handle, AI_CFG_CHAN_SENSOR_SENSITIVITY,
|
||||||
|
chnum, channelconfig.sensitivity)
|
||||||
|
if err != ERR_NO_ERROR:
|
||||||
|
raise RuntimeError('Fatal: could not set sensitivity')
|
||||||
|
|
||||||
|
def setOutputChannelConfig(self, unsigned chnum, channelconfig:
|
||||||
|
DAQChannel, bint monitor_gen):
|
||||||
|
if self.threaddata:
|
||||||
|
raise RuntimeError('Cannot change settings while sampling')
|
||||||
|
if chnum >= self.noutputchannels:
|
||||||
|
raise RuntimeError('Invalid output channel number')
|
||||||
|
|
||||||
|
if monitor_gen and not channelconfig.channel_enabled:
|
||||||
|
raise RuntimeError('Output channel should be enabled to enable channel monitoring')
|
||||||
|
self.output_enabled = channelconfig.channel_enabled
|
||||||
|
self.monitor_gen = monitor_gen
|
||||||
|
|
||||||
|
def __dealloc__(self):
|
||||||
|
|
||||||
|
if self.handle_connected:
|
||||||
|
ulDisconnectDaqDevice(self.handle)
|
||||||
|
ulReleaseDaqDevice(self.handle)
|
||||||
|
|
||||||
|
cdef cleanupThreadData(self, DaqThreadData* td):
|
||||||
|
if td is NULL:
|
||||||
|
return
|
||||||
|
if td.thread:
|
||||||
|
td.stopThread.store(True)
|
||||||
|
td.thread.join()
|
||||||
|
del td.thread
|
||||||
|
td.thread = NULL
|
||||||
|
|
||||||
|
if td.inChanDescriptors:
|
||||||
|
free(td.inChanDescriptors)
|
||||||
|
td.inChanDescriptors = NULL
|
||||||
|
|
||||||
|
if td.outChanDescriptors:
|
||||||
|
free(td.outChanDescriptors)
|
||||||
|
td.outChanDescriptors = NULL
|
||||||
|
free(td)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cdef class UlDaq:
|
||||||
|
cdef:
|
||||||
|
DaqDeviceHandle handle
|
||||||
|
|
||||||
|
def __cinit__(self):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Acquires a daq handle, and opens the device
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.handle = 0
|
||||||
|
|
||||||
|
# # Open the device to probe the number of input and output ch.
|
||||||
|
# handle = ulCreateDaqDevice(descriptor)
|
||||||
|
# if not handle:
|
||||||
|
# raise RuntimeError('Unable to create device handle on device')
|
||||||
|
|
||||||
|
cpdef int getDeviceCount(self):
|
||||||
|
cdef:
|
||||||
|
DaqDeviceDescriptor devdescriptors[MAX_DEF_COUNT]
|
||||||
|
DaqDeviceInterface interfaceType = ANY_IFC
|
||||||
|
UlError err
|
||||||
|
|
||||||
|
unsigned int numdevs = MAX_DEF_COUNT
|
||||||
|
|
||||||
|
err = ulGetDaqDeviceInventory(interfaceType,
|
||||||
|
devdescriptors,
|
||||||
|
&numdevs)
|
||||||
|
if(err != ERR_NO_ERROR):
|
||||||
|
raise RuntimeError(f'Device inventarization failed: {err}')
|
||||||
|
|
||||||
|
devices = []
|
||||||
|
return numdevs
|
||||||
|
|
||||||
|
def getDeviceInfo(self, unsigned int deviceno):
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
cdef:
|
||||||
|
DaqDeviceDescriptor devdescriptors[MAX_DEF_COUNT]
|
||||||
|
DaqDeviceDescriptor descriptor
|
||||||
|
DaqDeviceInterface interfaceType = ANY_IFC
|
||||||
|
DaqDeviceHandle handle
|
||||||
|
|
||||||
|
UlError err
|
||||||
|
|
||||||
|
unsigned int numdevs = MAX_DEF_COUNT
|
||||||
|
|
||||||
|
err = ulGetDaqDeviceInventory(interfaceType,
|
||||||
|
devdescriptors,
|
||||||
|
&numdevs)
|
||||||
|
if(err != ERR_NO_ERROR):
|
||||||
|
raise RuntimeError(f'Device inventarization failed: {err}')
|
||||||
|
|
||||||
|
if deviceno >= numdevs:
|
||||||
|
raise ValueError(f'Device number {deviceno} too high {err}')
|
||||||
|
|
||||||
|
descriptor = devdescriptors[deviceno]
|
||||||
|
|
||||||
|
|
||||||
|
if descriptor.productName == b'DT9837A':
|
||||||
|
# Create proper interface name
|
||||||
|
if descriptor.devInterface == DaqDeviceInterface.USB_IFC:
|
||||||
|
name = 'USB - '
|
||||||
|
elif descriptor.devInterface == DaqDeviceInterface.BLUETOOTH_IFC:
|
||||||
|
name = 'Bluetooth - '
|
||||||
|
elif descriptor.devInterface == DaqDeviceInterface.ETHERNET_IFC:
|
||||||
|
name = 'Ethernet - '
|
||||||
|
|
||||||
|
name += descriptor.productName.decode('utf-8') + ', id ' + \
|
||||||
|
descriptor.uniqueId.decode('utf-8')
|
||||||
|
|
||||||
|
return DeviceInfo(
|
||||||
|
api = -1,
|
||||||
|
index = deviceno,
|
||||||
|
probed = True,
|
||||||
|
name = name,
|
||||||
|
outputchannels = 1,
|
||||||
|
inputchannels = 4,
|
||||||
|
duplexchannels = 0,
|
||||||
|
samplerates = [100, 500, 1000, 2000, 4000, 8000, 16000, 20000, 32000, 48000, 50000] ,
|
||||||
|
sampleformats = ['64-bit floats'],
|
||||||
|
prefsamplerate = 48000,
|
||||||
|
hasInputIEPE = True)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise RuntimeError(f"No config found for device \"{descriptor.productName.decode('utf-8')}\".")
|
||||||
|
|
||||||
|
# @cython.nonecheck(True)
|
||||||
|
# def openStream(self,
|
||||||
|
# avstream
|
||||||
|
# ):
|
||||||
|
# """
|
||||||
|
# Opens a stream with specified parameters
|
||||||
|
|
||||||
|
# Args:
|
||||||
|
# avstream: AvStream instance
|
||||||
|
|
||||||
|
# Returns: None
|
||||||
|
# """
|
||||||
|
|
||||||
|
# if self._stream is not NULL:
|
||||||
|
# raise RuntimeError('Stream is already opened.')
|
||||||
|
|
||||||
|
# daqconfig = avstream.daqconfig
|
||||||
|
# avtype = avstream.avtype
|
||||||
|
# device = avstream.device
|
||||||
|
|
||||||
|
# cdef:
|
||||||
|
# bint duplex_mode = daqconfig.duplex_mode
|
||||||
|
# bint monitorOutput = daqconfig.monitor_gen
|
||||||
|
# size_t sw # Sample width in bytes
|
||||||
|
# unsigned int nFramesPerBlock = unsigned int(daqconfig.nFramesPerBlock)
|
||||||
|
# int firstinputchannel, firstoutputchannel
|
||||||
|
# int lastinputchannel, lastoutputchannel
|
||||||
|
# unsigned int ninputchannels_forwarded=0
|
||||||
|
# unsigned int ninputchannels_uldaq=0
|
||||||
|
# unsigned int noutputchannels_uldaq=0
|
||||||
|
# unsigned int noutputchannels_forwarded=0
|
||||||
|
# unsigned int samplerate
|
||||||
|
# int i
|
||||||
|
# bint input_stream=False, output_stream=False
|
||||||
|
# bool* inputChannelsEnabled
|
||||||
|
# bool* outputChannelsEnabled
|
||||||
|
|
||||||
|
# if daqconfig.nFramesPerBlock > 8192 or daqconfig.nFramesPerBlock < 512:
|
||||||
|
# raise ValueError('Invalid number of nFramesPerBlock')
|
||||||
|
|
||||||
|
# if daqconfig.outputDelayBlocks < 0 or daqconfig.outputDelayBlocks > 10:
|
||||||
|
# raise ValueError('Invalid number of outputDelayBlocks')
|
||||||
|
|
||||||
|
# try:
|
||||||
|
|
||||||
|
# # Determine sample rate and sample format, determine whether we are an
|
||||||
|
# # input or an output stream, or both
|
||||||
|
# if avtype == AvType.audio_input or duplex_mode:
|
||||||
|
# # Here, we override the sample format in case of duplex mode.
|
||||||
|
# sampleformat = daqconfig.en_input_sample_format
|
||||||
|
# samplerate = int(daqconfig.en_input_rate)
|
||||||
|
# input_stream = True
|
||||||
|
# if duplex_mode:
|
||||||
|
# output_stream = True
|
||||||
|
# else:
|
||||||
|
# sampleformat = daqconfig.en_output_sample_format
|
||||||
|
# samplerate = int(daqconfig.en_output_rate)
|
||||||
|
# output_stream = True
|
||||||
|
|
||||||
|
# sw = 64
|
||||||
|
|
||||||
|
# # All set, allocate the stream!
|
||||||
|
# self._stream = <_Stream*> malloc(sizeof(_Stream))
|
||||||
|
# if self._stream == NULL:
|
||||||
|
# raise MemoryError('Could not allocate stream: memory error.')
|
||||||
|
|
||||||
|
# self._stream.pyCallback = <PyObject*> avstream._audioCallback
|
||||||
|
# # Increase reference count to the callback
|
||||||
|
# Py_INCREF(<object> avstream._audioCallback)
|
||||||
|
|
||||||
|
# self._stream.sw = sw
|
||||||
|
# self._stream.stopThread.store(False)
|
||||||
|
# self._stream.inputQueue = NULL
|
||||||
|
# self._stream.outputQueue = NULL
|
||||||
|
# self._stream.outputDelayQueue = NULL
|
||||||
|
|
||||||
|
# self._stream.thread = NULL
|
||||||
|
|
||||||
|
# self._stream.outputDelayBlocks = outputDelayBlocks
|
||||||
|
# self._stream.ninputchannels_forwarded = 0
|
||||||
|
# self._stream.noutputchannels_forwarded = 0
|
||||||
|
# self._stream.inputChannelsEnabled = NULL
|
||||||
|
# self._stream.outputChannelsEnabled = NULL
|
||||||
|
|
||||||
|
# # Create channel maps for input channels, set input stream
|
||||||
|
# # parameters
|
||||||
|
# if input_stream:
|
||||||
|
# firstinputchannel = daqconfig.firstEnabledInputChannelNumber()
|
||||||
|
# lastinputchannel = daqconfig.lastEnabledInputChannelNumber()
|
||||||
|
# ninputchannels_uldaq = lastinputchannel-firstinputchannel+1
|
||||||
|
|
||||||
|
# if lastinputchannel < 0 or ninputchannels_uldaq < 1:
|
||||||
|
# raise ValueError('Not enough input channels selected')
|
||||||
|
# input_ch = daqconfig.input_channel_configs
|
||||||
|
|
||||||
|
# inputChannelsEnabled = <bool*> malloc(sizeof(bool)*ninputchannels_uldaq)
|
||||||
|
# self._stream.inputChannelsEnabled = inputChannelsEnabled
|
||||||
|
|
||||||
|
# for i in range(firstinputchannel, lastinputchannel+1):
|
||||||
|
# ch_en = input_ch[i].channel_enabled
|
||||||
|
# if ch_en:
|
||||||
|
# ninputchannels_forwarded += 1
|
||||||
|
# inputChannelsEnabled[i] = ch_en
|
||||||
|
|
||||||
|
|
||||||
|
# self._stream.inputQueue = new SafeQueue[void*]()
|
||||||
|
# self._stream.ninputchannels_forwarded = ninputchannels_forwarded
|
||||||
|
|
||||||
|
|
||||||
|
# # Create channel maps for output channels
|
||||||
|
# if output_stream:
|
||||||
|
# firstoutputchannel = daqconfig.firstEnabledOutputChannelNumber()
|
||||||
|
# lastoutputchannel = daqconfig.lastEnabledOutputChannelNumber()
|
||||||
|
# noutputchannels_uldaq = lastoutputchannel-firstoutputchannel+1
|
||||||
|
|
||||||
|
# if lastoutputchannel < 0 or noutputchannels_uldaq < 1:
|
||||||
|
# raise ValueError('Not enough output channels selected')
|
||||||
|
# output_ch = daqconfig.output_channel_configs
|
||||||
|
|
||||||
|
# outputChannelsEnabled = <bool*> malloc(sizeof(bool)*noutputchannels_uldaq)
|
||||||
|
# self._stream.outputChannelsEnabled = outputChannelsEnabled
|
||||||
|
# for i in range(firstoutputchannel, lastoutputchannel+1):
|
||||||
|
# ch_en = output_ch[i].channel_enabled
|
||||||
|
# if ch_en:
|
||||||
|
# noutputchannels_forwarded += 1
|
||||||
|
# outputChannelsEnabled[i] = ch_en
|
||||||
|
|
||||||
|
# rtOutputParams_ptr = &self._stream.outputParams
|
||||||
|
# rtOutputParams_ptr.deviceId = device.index
|
||||||
|
# rtOutputParams_ptr.nChannels = noutputchannels_uldaq
|
||||||
|
# rtOutputParams_ptr.firstChannel = firstoutputchannel
|
||||||
|
|
||||||
|
# self._stream.outputQueue = new SafeQueue[void*]()
|
||||||
|
# self._stream.noutputchannels_forwarded = noutputchannels_forwarded
|
||||||
|
|
||||||
|
# if monitorOutput and duplex_mode:
|
||||||
|
# self._stream.ninputchannels_forwarded += noutputchannels_forwarded
|
||||||
|
|
||||||
|
# # self._uldaq.openStream(rtOutputParams_ptr,
|
||||||
|
# # rtInputParams_ptr,
|
||||||
|
# # _formats_strkey[sampleformat][0],
|
||||||
|
# # samplerate,
|
||||||
|
# # &nFramesPerBlock,
|
||||||
|
# # audioCallback,
|
||||||
|
# # <void*> self._stream,
|
||||||
|
# # &streamoptions, # Stream options
|
||||||
|
# # errorCallback # Error callback
|
||||||
|
# # )
|
||||||
|
|
||||||
|
# # self._stream.nBytesPerChan = nFramesPerBlock*sw
|
||||||
|
# # self._stream.nFramesPerBlock = nFramesPerBlock
|
||||||
|
|
||||||
|
# except Exception as e:
|
||||||
|
# print('Exception occured in stream opening: ', e)
|
||||||
|
# self.cleanupStream(self._stream)
|
||||||
|
# self._stream = NULL
|
||||||
|
# raise e
|
||||||
|
|
||||||
|
# with nogil:
|
||||||
|
# self._stream.thread = new CPPThread[void*, void (*)(void*)](audioCallbackPythonThreadFunction,
|
||||||
|
# <void*> self._stream)
|
||||||
|
# # Allow it to start
|
||||||
|
# CPPsleep(500)
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# return nFramesPerBlock
|
||||||
|
|
||||||
|
# cdef cleanupStream(self, _Stream* stream):
|
||||||
|
# # printf('Entrance function cleanupStream...\n')
|
||||||
|
# cdef:
|
||||||
|
# void* ptr
|
||||||
|
# if stream == NULL:
|
||||||
|
# return
|
||||||
|
|
||||||
|
# with nogil:
|
||||||
|
# if stream.thread:
|
||||||
|
# stream.stopThread.store(True)
|
||||||
|
# if stream.inputQueue:
|
||||||
|
# # If waiting in the input queue, hereby we let it run.
|
||||||
|
# stream.inputQueue.enqueue(NULL)
|
||||||
|
# # printf('Joining thread...\n')
|
||||||
|
# # HERE WE SHOULD RELEASE THE GIL, as exiting the thread function
|
||||||
|
# # will require the GIL, which is locked by this thread!
|
||||||
|
# stream.thread.join()
|
||||||
|
# # printf('Thread joined!\n')
|
||||||
|
# del stream.thread
|
||||||
|
# stream.thread = NULL
|
||||||
|
|
||||||
|
# if stream.inputChannelsEnabled:
|
||||||
|
# free(stream.inputChannelsEnabled)
|
||||||
|
# if stream.outputChannelsEnabled:
|
||||||
|
# free(stream.outputChannelsEnabled)
|
||||||
|
|
||||||
|
# if stream.outputQueue:
|
||||||
|
# while not stream.outputQueue.empty():
|
||||||
|
# free(stream.outputQueue.dequeue())
|
||||||
|
# del stream.outputQueue
|
||||||
|
# if stream.inputQueue:
|
||||||
|
# while not stream.inputQueue.empty():
|
||||||
|
# free(stream.inputQueue.dequeue())
|
||||||
|
# del stream.inputQueue
|
||||||
|
# if stream.outputDelayQueue:
|
||||||
|
# while not stream.outputDelayQueue.empty():
|
||||||
|
# free(stream.outputDelayQueue.dequeue())
|
||||||
|
# del stream.outputDelayQueue
|
||||||
|
# fprintf(stderr, "End cleanup stream queues...\n")
|
||||||
|
|
||||||
|
# if stream.pyCallback:
|
||||||
|
# Py_DECREF(<object> stream.pyCallback)
|
||||||
|
# stream.pyCallback = NULL
|
||||||
|
# # fprintf(stderr, "End cleanup callback...\n")
|
||||||
|
# free(stream)
|
||||||
|
|
||||||
|
# def startStream(self):
|
||||||
|
# self._uldaq.startStream()
|
||||||
|
|
||||||
|
# def stopStream(self):
|
||||||
|
# if self._stream is NULL:
|
||||||
|
# raise RuntimeError('Stream is not opened')
|
||||||
|
# try:
|
||||||
|
# self._uldaq.stopStream()
|
||||||
|
# except:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# def closeStream(self):
|
||||||
|
# # print('closeStream')
|
||||||
|
# if self._stream is NULL:
|
||||||
|
# raise RuntimeError('Stream is not opened')
|
||||||
|
# # Closing stream
|
||||||
|
# self._uldaq.closeStream()
|
||||||
|
# self.cleanupStream(self._stream)
|
||||||
|
# self._stream = NULL
|
||||||
|
|
||||||
|
# def abortStream(self):
|
||||||
|
# if self._stream is NULL:
|
||||||
|
# raise RuntimeError('Stream is not opened')
|
||||||
|
# self._uldaq.abortStream()
|
||||||
|
|
||||||
|
# def isStreamOpen(self):
|
||||||
|
# return self._uldaq.isStreamOpen()
|
||||||
|
|
||||||
|
# def isStreamRunning(self):
|
||||||
|
# return self._uldaq.isStreamRunning()
|
||||||
|
|
||||||
|
# def getStreamTime(self):
|
||||||
|
# return self._uldaq.getStreamTime()
|
||||||
|
|
||||||
|
# def setStreamTime(self, double time):
|
||||||
|
# return self._uldaq.setStreamTime(time)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user