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
|
||||
*.pyc
|
||||
lasp_rtaudio.cxx
|
||||
lasp_uldaq.cxx
|
||||
dist
|
||||
CMakeFiles
|
||||
CMakeCache.txt
|
||||
|
@ -1,11 +1,14 @@
|
||||
include_directories(/usr/include/rtaudio)
|
||||
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
|
||||
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
|
||||
|
||||
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_uldaq uldaq)
|
||||
if(win32)
|
||||
target_link_libraries(lasp_rtaudio python37)
|
||||
endif(win32)
|
||||
|
@ -1,3 +1,6 @@
|
||||
#!/usr/bin/python3
|
||||
from .lasp_rtaudio 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
|
||||
|
||||
|
||||
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
|
||||
class DeviceInfo:
|
||||
api: int
|
||||
index: int
|
||||
probed: bool
|
||||
probed: bool #
|
||||
name: str
|
||||
outputchannels: int
|
||||
inputchannels: int
|
||||
@ -26,7 +42,7 @@ class DeviceInfo:
|
||||
samplerates: list
|
||||
sampleformats: list
|
||||
prefsamplerate: int
|
||||
|
||||
hasInputIEPE: bool = False
|
||||
|
||||
|
||||
@dataclass_json
|
||||
@ -36,6 +52,9 @@ class DAQChannel:
|
||||
channel_name: str
|
||||
sensitivity: float
|
||||
qty: Qty
|
||||
range_: str = 'Undefined'
|
||||
IEPE_enabled: bool = False
|
||||
|
||||
|
||||
|
||||
@dataclass_json
|
||||
|
@ -1,23 +1,8 @@
|
||||
import sys
|
||||
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
|
||||
include "lasp_common_decls.pxd"
|
||||
|
||||
__all__ = ['AvType', 'RtAudio', 'get_numpy_dtype_from_format_string',
|
||||
__all__ = ['RtAudio', 'get_numpy_dtype_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:
|
||||
ctypedef unsigned long RtAudioStreamStatus
|
||||
@ -141,33 +126,6 @@ cdef extern from "RtAudio.h" nogil:
|
||||
unsigned int getStreamSampleRate()
|
||||
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 = {
|
||||
'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]
|
||||
|
||||
|
||||
|
||||
# It took me quite a long time to fully understand Cython's idiosyncrasies
|
||||
# concerning C(++) callbacks, the GIL and passing Python objects as pointers
|
||||
# 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)
|
||||
|
||||
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:
|
||||
@ -522,9 +472,6 @@ cdef class RtAudio:
|
||||
}
|
||||
return apidict
|
||||
|
||||
cpdef unsigned int getDeviceCount(self):
|
||||
return self._rtaudio.getDeviceCount()
|
||||
|
||||
cpdef unsigned int getDefaultOutputDevice(self):
|
||||
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