Skip to content
Snippets Groups Projects
Commit 8accf2c1 authored by Christoph Schmidt's avatar Christoph Schmidt
Browse files

Added inits to avoid import problems

parent 9be21198
No related branches found
No related tags found
No related merge requests found
Showing
with 3265 additions and 0 deletions
# -*- coding: utf-8 -*-
"""
Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at>
Created: 2023-10-19 12:35
Package Version:
"""
import confighandler as cfg
class CaptDeviceConfig(cfg.ConfigNode):
def __init__(self) -> None:
super().__init__()
self.sample_rate = cfg.Field(50000, friendly_name="Sample rate",
description="Sample rate of the device")
self.streaming_rate = cfg.Field(500, friendly_name="Streaming rate",
description="Streaming rate in Hz (should be below 1kHz)")
self.ain_channel = cfg.Field(0, friendly_name="Analog In Channel",
description="Analog in channel. Defines which channel is used for capturing.")
self.show_simulator = cfg.Field(True, friendly_name="Show Simulators",
description="Show available simulators in the device list "
"provided by the DreamWaves API.")
self.streaming_history = cfg.Field(2000, friendly_name="Streaming history (ms)",
description="Defines the range of the stream in ms")
# TODO: Old configs (not used and will probably removed in future)
self.total_samples = cfg.Field(200000)
self.sample_time = cfg.Field(45)
self.ad2_raw_out_file = cfg.Field("{output_directory}/measurement/ad2_raw/ad2_out_{wafer_nr}_{date}.csv")
self.register()
# -*- coding: utf-8 -*-
"""
Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at>
Created: 2023-10-19 12:35
Package Version:
"""
import sys
from .CaptDeviceConfig import CaptDeviceConfig as Config
from .controller.AD2CaptDeviceController import AD2CaptDeviceController as Controller
from .model.AD2CaptDeviceModel import AD2CaptDeviceModel as Model
from .view.AD2CaptDeviceView import ControlWindow as View
\ No newline at end of file
"""
DWFConstants (definitions file for DWF library)
Author: Digilent, Inc.
Revision: 2019-10-15
Must install:
Python 2.7 or 3
"""
from ctypes import *
# device handle
#HDWF
hdwfNone = c_int(0)
# device enumeration filters
enumfilterAll = c_int(0)
enumfilterType = c_int(0x8000000)
enumfilterUSB = c_int(0x0000001)
enumfilterNetwork = c_int(0x0000002)
enumfilterAXI = c_int(0x0000004)
enumfilterRemote = c_int(0x1000000)
enumfilterAudio = c_int(0x2000000)
enumfilterDemo = c_int(0x4000000)
# device ID
devidEExplorer = c_int(1)
devidDiscovery = c_int(2)
devidDiscovery2 = c_int(3)
devidDDiscovery = c_int(4)
devidADP3X50 = c_int(6)
# device version
devverEExplorerC = c_int(2)
devverEExplorerE = c_int(4)
devverEExplorerF = c_int(5)
devverDiscoveryA = c_int(1)
devverDiscoveryB = c_int(2)
devverDiscoveryC = c_int(3)
# trigger source
trigsrcNone = c_ubyte(0)
trigsrcPC = c_ubyte(1)
trigsrcDetectorAnalogIn = c_ubyte(2)
trigsrcDetectorDigitalIn = c_ubyte(3)
trigsrcAnalogIn = c_ubyte(4)
trigsrcDigitalIn = c_ubyte(5)
trigsrcDigitalOut = c_ubyte(6)
trigsrcAnalogOut1 = c_ubyte(7)
trigsrcAnalogOut2 = c_ubyte(8)
trigsrcAnalogOut3 = c_ubyte(9)
trigsrcAnalogOut4 = c_ubyte(10)
trigsrcExternal1 = c_ubyte(11)
trigsrcExternal2 = c_ubyte(12)
trigsrcExternal3 = c_ubyte(13)
trigsrcExternal4 = c_ubyte(14)
trigsrcHigh = c_ubyte(15)
trigsrcLow = c_ubyte(16)
trigsrcClock = c_ubyte(17)
# instrument states
DwfStateReady = c_ubyte(0)
DwfStateConfig = c_ubyte(4)
DwfStatePrefill = c_ubyte(5)
DwfStateArmed = c_ubyte(1)
DwfStateWait = c_ubyte(7)
DwfStateTriggered = c_ubyte(3)
DwfStateRunning = c_ubyte(3)
DwfStateDone = c_ubyte(2)
# DwfEnumConfigInfo
DECIAnalogInChannelCount = c_int(1)
DECIAnalogOutChannelCount = c_int(2)
DECIAnalogIOChannelCount = c_int(3)
DECIDigitalInChannelCount = c_int(4)
DECIDigitalOutChannelCount = c_int(5)
DECIDigitalIOChannelCount = c_int(6)
DECIAnalogInBufferSize = c_int(7)
DECIAnalogOutBufferSize = c_int(8)
DECIDigitalInBufferSize = c_int(9)
DECIDigitalOutBufferSize = c_int(10)
# acquisition modes:
acqmodeSingle = c_int(0)
acqmodeScanShift = c_int(1)
acqmodeScanScreen = c_int(2)
acqmodeRecord = c_int(3)
acqmodeOvers = c_int(4)
acqmodeSingle1 = c_int(5)
# analog acquisition filter:
filterDecimate = c_int(0)
filterAverage = c_int(1)
filterMinMax = c_int(2)
# analog in trigger mode:
trigtypeEdge = c_int(0)
trigtypePulse = c_int(1)
trigtypeTransition = c_int(2)
trigtypeWindow = c_int(3)
# trigger slope:
DwfTriggerSlopeRise = c_int(0)
DwfTriggerSlopeFall = c_int(1)
DwfTriggerSlopeEither = c_int(2)
# trigger length condition
triglenLess = c_int(0)
triglenTimeout = c_int(1)
triglenMore = c_int(2)
# error codes for the functions:
dwfercNoErc = c_int(0) # No error occurred
dwfercUnknownError = c_int(1) # API waiting on pending API timed out
dwfercApiLockTimeout = c_int(2) # API waiting on pending API timed out
dwfercAlreadyOpened = c_int(3) # Device already opened
dwfercNotSupported = c_int(4) # Device not supported
dwfercInvalidParameter0 = c_int(16) # Invalid parameter sent in API call
dwfercInvalidParameter1 = c_int(17) # Invalid parameter sent in API call
dwfercInvalidParameter2 = c_int(18) # Invalid parameter sent in API call
dwfercInvalidParameter3 = c_int(19) # Invalid parameter sent in API call
dwfercInvalidParameter4 = c_int(20) # Invalid parameter sent in API call
# analog out signal types
funcDC = c_ubyte(0)
funcSine = c_ubyte(1)
funcSquare = c_ubyte(2)
funcTriangle = c_ubyte(3)
funcRampUp = c_ubyte(4)
funcRampDown = c_ubyte(5)
funcNoise = c_ubyte(6)
funcPulse = c_ubyte(7)
funcTrapezium= c_ubyte(8)
funcSinePower= c_ubyte(9)
funcCustom = c_ubyte(30)
funcPlay = c_ubyte(31)
# analog io channel node types
analogioEnable = c_ubyte(1)
analogioVoltage = c_ubyte(2)
analogioCurrent = c_ubyte(3)
analogioPower = c_ubyte(4)
analogioTemperature = c_ubyte(5)
analogioDmm = c_ubyte(6)
analogioRange = c_ubyte(7)
analogioMeasure = c_ubyte(8)
analogioTime = c_ubyte(9)
analogioFrequency = c_ubyte(10)
analogioResistance = c_ubyte(11)
DwfDmmResistance = c_double(1)
DwfDmmContinuity = c_double(2)
DwfDmmDiode = c_double(3)
DwfDmmDCVoltage = c_double(4)
DwfDmmACVoltage = c_double(5)
DwfDmmDCCurrent = c_double(6)
DwfDmmACCurrent = c_double(7)
DwfDmmDCLowCurrent = c_double(8)
DwfDmmACLowCurrent = c_double(9)
DwfDmmTemperature = c_double(10)
AnalogOutNodeCarrier = c_int(0)
AnalogOutNodeFM = c_int(1)
AnalogOutNodeAM = c_int(2)
DwfAnalogOutIdleDisable = c_int(0)
DwfAnalogOutIdleOffset = c_int(1)
DwfAnalogOutIdleInitial = c_int(2)
DwfDigitalInClockSourceInternal = c_int(0)
DwfDigitalInClockSourceExternal = c_int(1)
DwfDigitalInSampleModeSimple = c_int(0)
# alternate samples: noise|sample|noise|sample|...
# where noise is more than 1 transition between 2 samples
DwfDigitalInSampleModeNoise = c_int(1)
DwfDigitalOutOutputPushPull = c_int(0)
DwfDigitalOutOutputOpenDrain = c_int(1)
DwfDigitalOutOutputOpenSource = c_int(2)
DwfDigitalOutOutputThreeState = c_int(3)
DwfDigitalOutTypePulse = c_int(0)
DwfDigitalOutTypeCustom = c_int(1)
DwfDigitalOutTypeRandom = c_int(2)
DwfDigitalOutTypeROM = c_int(3)
DwfDigitalOutTypeState = c_int(4)
DwfDigitalOutTypePlay = c_int(5)
DwfDigitalOutIdleInit = c_int(0)
DwfDigitalOutIdleLow = c_int(1)
DwfDigitalOutIdleHigh = c_int(2)
DwfDigitalOutIdleZet = c_int(3)
DwfAnalogImpedanceImpedance = c_int(0)
DwfAnalogImpedanceImpedancePhase = c_int(1)
DwfAnalogImpedanceResistance = c_int(2)
DwfAnalogImpedanceReactance = c_int(3)
DwfAnalogImpedanceAdmittance = c_int(4)
DwfAnalogImpedanceAdmittancePhase = c_int(5)
DwfAnalogImpedanceConductance = c_int(6)
DwfAnalogImpedanceSusceptance = c_int(7)
DwfAnalogImpedanceSeriesCapacitance = c_int(8)
DwfAnalogImpedanceParallelCapacitance = c_int(9)
DwfAnalogImpedanceSeriesInductance = c_int(10)
DwfAnalogImpedanceParallelInductance = c_int(11)
DwfAnalogImpedanceDissipation = c_int(12)
DwfAnalogImpedanceQuality = c_int(13)
DwfAnalogImpedanceVrms = c_int(14)
DwfAnalogImpedanceVreal = c_int(15)
DwfAnalogImpedanceVimag = c_int(16)
DwfAnalogImpedanceIrms = c_int(17)
DwfAnalogImpedanceIreal = c_int(18)
DwfAnalogImpedanceIimag = c_int(19)
DwfParamUsbPower = c_int(2) # 1 keep the USB power enabled even when AUX is connected, Analog Discovery 2
DwfParamLedBrightness = c_int(3) # LED brightness 0 ... 100%, Digital Discovery
DwfParamOnClose = c_int(4) # 0 continue, 1 stop, 2 shutdown
DwfParamAudioOut = c_int(5) # 0 disable / 1 enable audio output, Analog Discovery 1, 2
DwfParamUsbLimit = c_int(6) # 0..1000 mA USB power limit, -1 no limit, Analog Discovery 1, 2
DwfParamAnalogOut = c_int(7) # 0 disable / 1 enable
DwfParamFrequency = c_int(8) # Hz
DwfParamExtFreq = c_int(9) # Hz
DwfParamClockMode = c_int(10) # 0 internal, 1 output, 2 input, 3 IO
# obsolate
#STS
stsRdy = c_ubyte(0)
stsArm = c_ubyte(1)
stsDone = c_ubyte(2)
stsTrig = c_ubyte(3)
stsCfg = c_ubyte(4)
stsPrefill = c_ubyte(5)
stsNotDone = c_ubyte(6)
stsTrigDly = c_ubyte(7)
stsError = c_ubyte(8)
stsBusy = c_ubyte(9)
stsStop = c_ubyte(10)
#TRIGCOND
trigcondRisingPositive = c_int(0)
trigcondFallingNegative = c_int(1)
#use deiceid
enumfilterEExplorer = c_int(1)
enumfilterDiscovery = c_int(2)
enumfilterDiscovery2 = c_int(3)
enumfilterDDiscovery = c_int(4)
#!/.venv/Scripts/python
from ctypes import c_int, byref, create_string_buffer, cdll, c_int32, c_uint, c_double
from controller.BaseAD2CaptDevice import BaseAD2CaptDevice
from model.AD2CaptDeviceModel import AD2CaptDeviceModel
from constants.dwfconstants import enumfilterUSB, enumfilterType, enumfilterDemo
class AD2CaptDeviceController(BaseAD2CaptDevice):
def __init__(self, ad2capt_model: AD2CaptDeviceModel):
self.dwf = cdll.dwf
super().__init__(ad2capt_model)
# This is required for acquiring the data
def connect_device(self, device_id):
self.start_device_process(device_id)
return True
def read_hardware_config(self, iDevice):
hw_info_dict = {}
hdwf = c_int()
int0 = c_int()
int1 = c_int()
uint0 = c_uint()
dbl0 = c_double()
dbl1 = c_double()
dbl2 = c_double()
self.dwf.FDwfDeviceConfigOpen(c_int(iDevice), c_int(0), byref(hdwf))
if hdwf.value == 0:
szerr = create_string_buffer(512)
self.dwf.FDwfGetLastErrorMsg(szerr)
raise Exception(str(szerr.value))
self.dwf.FDwfAnalogInChannelCount(hdwf, byref(int0))
hw_info_dict["analog_in_channels"] = int(int0.value)
self.dwf.FDwfAnalogIOChannelCount(hdwf, byref(int0))
hw_info_dict["analog_io_channels"] = int(int0.value)
self.dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(int0))
hw_info_dict["buffer_size"] = int(int0.value)
self.dwf.FDwfAnalogInBitsInfo(hdwf, byref(int0))
hw_info_dict["adc_bits"] = int(int0.value)
self.dwf.FDwfAnalogInChannelRangeInfo(hdwf, byref(dbl0), byref(dbl1), byref(dbl2))
hw_info_dict["range"] = (int(dbl0.value), int(dbl1.value), int(dbl2.value))
self.dwf.FDwfAnalogInChannelOffsetInfo(hdwf, byref(dbl0), byref(dbl1), byref(dbl2))
hw_info_dict["offset"] = (int(dbl0.value), int(dbl1.value), int(dbl2.value))
return hw_info_dict
def discover_connected_devices(self):
# enumerate connected devices
connected_devices = []
# for filter_type in [(c_int32(enumfilterType.value | enumfilterUSB.value), 'USB'),
# (c_int32(enumfilterType.value | enumfilterNetwork.value), 'Network'),
# (c_int32(enumfilterType.value | enumfilterAXI.value), 'AXI'),
# (c_int32(enumfilterType.value | enumfilterRemote.value), 'Remote'),
# (c_int32(enumfilterType.value | enumfilterAudio.value), 'Audio'),
# (c_int32(enumfilterType.value | enumfilterDemo.value), 'Demo')]:
cDevice = c_int()
# filter, type = (c_int32(enumfilterType.value | enumfilterUSB.value), 'USB')
filter, type = (c_int32(enumfilterType.value | enumfilterUSB.value | enumfilterDemo.value), 'USB')
self.dwf.FDwfEnum(filter, byref(cDevice))
self.model.num_of_connected_devices = cDevice
devicename = create_string_buffer(64)
serialnum = create_string_buffer(16)
for iDevice in range(0, cDevice.value):
self.dwf.FDwfEnumDeviceName(c_int(iDevice), devicename)
self.dwf.FDwfEnumSN(c_int(iDevice), serialnum)
hw_info = self.read_hardware_config(iDevice)
srn = str(serialnum.value.decode('UTF-8'))
if "demo" in srn.lower():
type = "Simulator "
con_dev_dict = {
'type': type,
'device_id': int(iDevice),
'device_name': str(devicename.value.decode('UTF-8')),
'serial_number': srn
}
con_dev_dict = dict(con_dev_dict, **hw_info)
connected_devices.append(con_dev_dict)
self.logger.info(connected_devices)
self.model.connected_devices = connected_devices
self.logger.info(f"Discovered {len(self.model.connected_devices)} devices.")
return self.model.connected_devices
def close_device(self):
self.end_process_flag.value = 1
# def _open_device(self, device_index):
# devicename = create_string_buffer(64)
# serialnum = create_string_buffer(16)
#
# self.dwf.FDwfEnumDeviceName(c_int(device_index), devicename)
# self.dwf.FDwfEnumSN(c_int(device_index), serialnum)
#
# self.model.device_name = devicename
# self.model.device_serial_number = serialnum
# # open device
# self.logger.info(f"[{self.pref} Task] Opening device #{device_index}...")
#
# # Opens a device identified by the enumeration index and retrieves a handle. To automatically
# # enumerate all connected devices and open the first discovered device, use index -1.
# self.dwf.FDwfDeviceOpen(c_int(device_index), byref(self.model.hdwf))
#
# if self.model.hdwf.value == hdwfNone.value:
# szerr = create_string_buffer(512)
# self.dwf.FDwfGetLastErrorMsg(szerr)
# # print(str(szerr.value))
# self.model.connected = False
# raise Exception(f"Failed to open device: {szerr.value}")
# else:
# self.model.connected = True
# self.get_analog_in_status()
# self.logger.info(f"[{self.pref} Task] Device connected!")
#
# def _setup_acquisition(self):
# # set up acquisition
# self.get_analog_in_status()
# self.logger.debug(f"[{self.pref} Task] Setup for acquisition. Wait 2 seconds for the offset to stabilize.")
# self.dwf.FDwfAnalogInChannelEnableSet(self.model.hdwf, c_int(self.model.analog_in_channel), c_int(1))
# self.dwf.FDwfAnalogInChannelRangeSet(self.model.hdwf, c_int(self.model.analog_in_channel), c_double(5))
# self.dwf.FDwfAnalogInAcquisitionModeSet(self.model.hdwf, acqmodeRecord)
# self.dwf.FDwfAnalogInFrequencySet(self.model.hdwf, c_double(self.model.hz_acquisition))
# self.dwf.FDwfAnalogInRecordLengthSet(self.model.hdwf, 0) # -1 infinite record length
# self.get_analog_in_status()
# # wait at least 2 seconds for the offset to stabilize
# time.sleep(2)
# self.logger.info(f"[{self.pref} Task] Setup for acquisition done.")
# return True
#
# # # ==================================================================================================================
# # # Acquisition
# # # ==================================================================================================================
# # @Slot()
# # def start_capture(self, capture):
# # if not self.model.connected:
# # self.logger.warning(f"[{self.pref} Task] No device connected. Connecting to first device.")
# # self.connect_device(0)
# # return False
# #
# # if capture:
# # self.logger.info(f"[{self.pref} Task] Setting up device for capturing.")
# # self.gen_sine()
# # self._setup_acquisition()
# # # if self._setup_acquisition():
# # # self.logger.info(f"[{self.pref} Task] Started capturing thread")
# # self.set_ad2_acq_status(True)
# # return self.thread_manager.start(self._capture)
# # else:
# # self.set_ad2_acq_status(False)
# # # return self._capture()
# #
# # def _capture(self):
# # self.model.capturing_finished = False
# # self.model.device_capturing = False
# # cAvailable = c_int()
# # cLost = c_int()
# # cCorrupted = c_int()
# #
# # self.logger.info(f"[{self.pref} Report] Capturing started. "
# # f"Waiting for start command: "
# # f"{self.model.start_recording}<->{self.model.stop_recording}")
# #
# # # Configures the instrument and start or stop the acquisition. To reset the Auto trigger timeout, set
# # # fReconfigure to TRUE.
# # # print("Starting oscilloscope")
# # self.dwf.FDwfAnalogInConfigure(self.model.hdwf, c_int(0), c_int(1))
# #
# # t0 = -1
# #
# # cSamples = 0
# # self.model.device_ready = True
# # self.logger.info(f"[{self.pref} Report] Capturing device is ready.")
# # while True:
# #
# # if self.model.start_recording and not self.model.stop_recording:
# # if t0 < 0:
# # self.logger.info(f"[{self.pref} Report] Start command received.")
# # self.model.capturing_finished = False
# # self.model.device_capturing = True
# # self.model.current_recorded_samples = []
# # timestamp = datetime.now()
# # t0 = time.time()
# # # print(f"Start ({cSamples})")
# # sts = self.get_analog_in_status()
# #
# # if cSamples == 0 and (
# # sts == DwfStateConfig or
# # sts == DwfStatePrefill or
# # sts == DwfStateArmed):
# # print('idle')
# # continue # Acquisition not yet started.
# #
# # # Retrieves information about the recording process. The data loss occurs when the device acquisition
# # # is faster than the read process to PC. In this case, the device recording buffer is filled and data
# # # samples are overwritten. Corrupt samples indicate that the samples have been overwritten by the
# # # acquisition process during the previous read. In this case, try optimizing the loop process for faster
# # # execution or reduce the acquisition frequency or record length to be less than or equal to the device
# # # buffer size (record length <= buffer size/frequency).
# # self.dwf.FDwfAnalogInStatusRecord(self.model.hdwf, # Interface handle
# # byref(cAvailable),
# # byref(cLost),
# # byref(cCorrupted))
# #
# # cSamples += cLost.value
# #
# # if cLost.value:
# # self.logger.warning(f"[{self.pref} Report] - Sample(s) lost ({cLost.value})")
# # self.model.fLost += int(cLost.value)
# # if cCorrupted.value:
# # self.logger.warning(f"[{self.pref} Report] - Samples(s) corrupted ({cCorrupted.value})")
# # self.model.fCorrupted += int(cCorrupted.value)
# #
# # # self.dwf.FDwfAnalogInStatusSamplesValid(self.hdwf, byref(self.cValid))
# # if cAvailable.value == 0:
# # # print(f"Nothing available {cAvailable.value}")
# # continue
# # else:
# # # print(f"Available: {cAvailable.value}")
# #
# # # if cSamples + cAvailable.value > self.ad2capt_model.n_samples:
# # # cAvailable = c_int(self.ad2capt_model.n_samples - cSamples)
# # rgdSamples = (c_double * cAvailable.value)()
# # # Retrieves the acquired data samples from the specified idxChannel on the AnalogIn instrument. It
# # # copies the data samples to the provided buffer.
# # self.dwf.FDwfAnalogInStatusData(self.model.hdwf,
# # c_int(self.model.analog_in_channel),
# # byref(rgdSamples),
# # cAvailable) # get channel 1 data
# # for s in rgdSamples:
# # self.model.current_recorded_samples.append(float(s))
# #
# # cSamples += cAvailable.value
# #
# # elif not self.model.start_recording and self.model.stop_recording:
# # t1 = time.time()
# # self.model.measurement_time = t1 - t0
# # self.get_analog_in_status()
# # self.model.capturing_finished = True
# # self.model.device_capturing = False
# # self.logger.info(f"Finished Thread. Acquisition took {self.model.measurement_time} s. "
# # f"Process captured {len(self.model.current_recorded_samples)} samples.")
# # # 1. Assign the current captured samples to a dict
# # self.model.all_recorded_samples.append({'timestamp': timestamp,
# # 'measurement_time': self.model.measurement_time,
# # 'num_samples': len(
# # self.model.current_recorded_samples),
# # 'acqRate': self.model.hz_acquisition,
# # 'samples': self.model.current_recorded_samples})
# # # Reset status bits
# # try:
# # time.sleep(1)
# # self.close_device()
# # except Exception as e:
# # print(e)
# # return
# # # return self.model.current_recorded_samples, self.model.measurement_time
# # else:
# # self.model.device_capturing = False
#
# # # ==================================================================================================================
# # #
# # # ==================================================================================================================
# # def gen_sine(self, channel=0, frequency=1):
# # self.logger.debug(f"[{self.pref} Task] Generating sine wave on output 0...")
# # self.dwf.FDwfAnalogOutNodeEnableSet(self.model.hdwf, c_int(channel), AnalogOutNodeCarrier, c_int(1))
# # self.dwf.FDwfAnalogOutNodeFunctionSet(self.model.hdwf, c_int(channel), AnalogOutNodeCarrier,
# # funcTrapezium) # sine
# # self.dwf.FDwfAnalogOutNodeFrequencySet(self.model.hdwf, c_int(channel), AnalogOutNodeCarrier,
# # c_double(frequency)) # 1Hz
# # self.dwf.FDwfAnalogOutNodeAmplitudeSet(self.model.hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(2))
# # self.dwf.FDwfAnalogOutConfigure(self.model.hdwf, c_int(channel), c_int(1))
# # return self.model.hdwf
#
# # ==================================================================================================================
# #
# # ==================================================================================================================
# def close_device(self):
# # Resets and configures (by default, having auto configure enabled) all AnalogOut instrument
# # parameters to default values for the specified channel. To reset instrument parameters across all
# # channels, set idxChannel to -1.
# self.model.fLost = 0
# self.model.fCorrupted = 0
# self.model.start_recording = True
# self.model.stop_recording = False
# self.model.capturing_finished = False
# self.model.device_capturing = False
# self.model.connected = False
# self.model.device_state = 0
# self.model.dwf_version = "Unknown"
# self.model.device_serial_number = "Unknown"
# self.model.device_name = "Unknown"
# self.model.analog_in_channel = -1
#
# self.dwf.FDwfAnalogOutReset(self.model.hdwf, c_int(self.model.analog_in_channel))
# self.dwf.FDwfDeviceCloseAll()
# self.logger.info(f"[{self.pref} Task] Device closed.")
# def get_analog_in_status(self):
# sts: c_byte = c_byte()
# # Checks the state of the acquisition. To read the data from the device, set fReadData to TRUE. For
# # single acquisition mode, the data will be read only when the acquisition is finished.
# self.dwf.FDwfAnalogInStatus(self.model.hdwf, # Interface handle.
# c_int(1), # True, if data should be read
# byref(sts)) # Variable to receive the acquisition state
# self.model.device_state = sts.value
# return sts
# ==================================================================================================================
#
# ==================================================================================================================
import time
from datetime import datetime
import scipy
from PySide6.QtCore import Slot
from controller.BaseAD2CaptDevice import BaseAD2CaptDevice
from model.AD2CaptDeviceModel import AD2CaptDeviceModel
class AD2CaptDeviceSimulator(BaseAD2CaptDevice):
def __init__(self, ad2capt_model: AD2CaptDeviceModel):
super().__init__(ad2capt_model)
def connect_device(self, device_id):
self.logger.info("Connecting to simulator")
self._init_device_parameters()
self.model.dwf_version = "DWF SIM 1.0"
self.logger.info(f"[{self.pref} Report] DWF Version: {self.model.dwf_version}")
self.logger.info(f"[{self.pref} Task] Opening device Simulator...")
self.model.device_name = "ADC Simulator"
self.model.device_serial_number = "Simulator"
#
self.model.ain_device_state = 0
self.model.connected = True
self.update_device_information()
self.logger.info(f"[{self.pref} Task] Device connected!")
return True
def discover_connected_devices(self):
self.model.connected_devices = {
'type': "Simulator",
'device_id': 0,
'device_name': "Simulator AD2",
'serial_number': "0000"
}
@Slot()
def start_capture(self, capture):
if capture:
self.logger.info(f"[{self.pref} Task] Setting up device for capturing.")
# if self._setup_acquisition():
# self.logger.info(f"[{self.pref} Task] Started capturing thread")
self.set_ad2_acq_status(True)
return self.thread_manager.start(self._capture)
else:
self.set_ad2_acq_status(False)
# return self._capture()
def _capture(self):
self.model.capturing_finished = False
self.model.device_capturing_state = False
# Read the mat file from ./support
matf = scipy.io.loadmat("./support/simulator_support.mat")
self.model.device_ready = True
t0 = -1
curr_sample = 0
while True:
if self.model.start_recording and not self.model.stop_recording:
if t0 < 0:
self.logger.info(f"[{self.pref} Report] Start command received.")
self.model.capturing_finished = False
self.model.device_capturing_state = True
self.model.recorded_samples = []
timestamp = datetime.now()
t0 = time.time()
else:
curr_sample += 1
try:
# print(matf['amplitude'].flatten()[curr_sample])
if curr_sample % 200 == 0:
t2 = time.time()
# Append 10 samples at a time
self.model.recorded_samples.extend(
matf['amplitude'].flatten()[curr_sample-99:curr_sample]
)
t3 = time.time()
#print(f"{curr_sample}: Time took {t3-t2}")
except Exception as e:
print(e)
elif not self.model.start_recording and self.model.stop_recording:
t1 = time.time()
self.model.measurement_time = t1 - t0
# self.get_analog_in_status()
self.model.capturing_finished = True
self.model.device_capturing_state = False
self.logger.info(f"Finished Thread. Acquisition took {self.model.measurement_time} s. "
f"Process captured {len(self.model.recorded_samples)} samples.")
# 1. Assign the current captured samples to a dict
self.model.all_recorded_samples.append({'timestamp': timestamp,
'measurement_time': self.model.measurement_time,
'num_samples': len(
self.model.recorded_samples),
'acqRate': self.model.sample_rate,
'samples': self.model.recorded_samples})
try:
time.sleep(1)
self.close_device()
except Exception as e:
print(e)
return
def update_device_information(self):
self.model.ain_channels = [0]
self.model.ain_buffer_size = 1
self.model.aout_channels = [0]
self.model.selected_ain_channel = 1
def close_device(self):
# Resets and configures (by default, having auto configure enabled) all AnalogOut instrument
# parameters to default values for the specified channel. To reset instrument parameters across all
# channels, set idxChannel to -1.
self.model.fLost = 0
self.model.fCorrupted = 0
self.model.start_recording = True
self.model.stop_recording = False
self.model.capturing_finished = False
self.model.device_capturing_state = False
self.model.connected = False
self.model.ain_device_state = 0
self.model.dwf_version = "Unknown"
self.model.device_serial_number = "Unknown"
self.model.device_name = "Unknown"
self.model.selected_ain_channel = -1
self.logger.info(f"[{self.pref} Task] Device closed.")
import logging
import time
from abc import abstractmethod
from collections import deque
from PySide6.QtCore import QObject, QThreadPool
from controller.mp_AD2Capture.AD2StateMPSetter import AD2State
from controller.mp_AD2Capture.MPDeviceControl import mp_capture
from model.AD2CaptDeviceModel import AD2CaptDeviceModel, AD2CaptDeviceSignals
from model.AD2Constants import AD2Constants
from multiprocessing import Process, Queue, Value, Lock
class BaseAD2CaptDevice(QObject):
def __init__(self, ad2capt_model: AD2CaptDeviceModel):
super().__init__()
self.model = ad2capt_model
self.pref = "AD2CaptDev"
self.logger = logging.getLogger(f"AD2 Device")
self.signals = AD2CaptDeviceSignals()
self.thread_manager = QThreadPool()
self.kill_thread = False
# self.thread_manager.setMaxThreadCount(3)
# self.thread_manager.se
# self.thread_manager.setThreadPriority(QThread.HighestPriority)
self.lock = Lock()
self.proc = None
self.stream_data_queue = Queue()
self.capture_data_queue = Queue()
self.state_queue = Queue()
self.start_capture_flag = Value('i', 0, lock=self.lock)
self.end_process_flag = Value('i', False, lock=self.lock)
# Number of sa
self.streaming_data_dqueue: deque = None # a dqueue, initialize later
self.status_dqueue = deque(maxlen=int(1))
self.unconsumed_capture_data = 0
self.discover_connected_devices()
@abstractmethod
def connect_device(self, device_id):
raise NotImplementedError
@abstractmethod
def discover_connected_devices(self):
raise NotImplementedError
@abstractmethod
def update_device_information(self):
raise NotImplementedError
@abstractmethod
def _capture(self):
raise NotImplementedError
@abstractmethod
def close_device(self):
raise NotImplementedError
def set_ad2_acq_status(self, record):
if record:
self.model.start_recording = True
self.model.stop_recording = False
self.logger.info(f"[{self.pref} Task] >>>>>>>>>> Started acquisition!")
elif record == False:
self.model.start_recording = False
self.model.stop_recording = True
self.logger.info(f"[{self.pref} Task] >>>>>>>>>>> Stopped acquisition!")
else:
self.model.start_recording = False
self.model.stop_recording = False
self.logger.info(f"[{self.pref} Task] >>>>>>>>>>> Reset acquisition!")
def _init_device_parameters(self):
pass
#sample_rate = int(self.model.ad2captdev_config.get_sample_rate())
#total_samples = int(self.model.ad2captdev_config.get_total_samples())
#channel = 0 # TODO Read channel from input
#self.model.sample_rate = int(sample_rate)
#self.model.n_samples = int(total_samples)
#self.model.selected_ain_channel = int(channel)
#self.logger.info(f"AD2 device initialized {self.model.selected_ain_channel} with "
# f"acquisition rate {self.model.sample_rate} Hz and "
# f"samples {self.model.n_samples}")
# ==================================================================================================================
#
# ==================================================================================================================
def clear_data(self):
self.model.recorded_samples = []
self.model.recorded_sample_stream = []
def start_capture(self, clear=True):
print(f"Start capture. Clear {clear}")
self.start_capture_flag.value = 1
if clear:
self.model.recorded_samples = []
self.model.recorded_sample_stream = []
self.model.start_recording = True
self.model.stop_recording = False
self.model.device_capturing_state = AD2Constants.CapturingState.RUNNING()
def stop_capture(self):
print("Stop capture")
self.start_capture_flag.value = 0
self.model.start_recording = False
if self.model.reset_recording:
self.model.device_capturing_state = AD2Constants.CapturingState.STOPPED()
self.model.stop_recording = True
else:
self.model.device_capturing_state = AD2Constants.CapturingState.PAUSED()
def capture(self, start, clear=True):
if start:
self.start_capture(clear)
else:
self.stop_capture()
def reset_capture(self):
self.logger.info("Resetting captured samples for new measurement.")
self.model.recorded_samples = []
self.model.measurement_time = 0
self.model.capturing_finished = False
# ==================================================================================================================
def start_device_process(self, device_id):
self.logger.info(f"[{self.pref} Task] Starting capturing process...")
#self.logger.debug(f"Dataqueue maxlen={int(self.model.duration_streaming_history * self.model.sample_rate)}")
self.streaming_data_dqueue = deque(maxlen=int(self.model.duration_streaming_history * self.model.sample_rate))
#print(self.model.duration_streaming_history * self.model.sample_rate)
self.stream_data_queue.maxsize = int(self.model.duration_streaming_history * self.model.sample_rate)
self.proc = Process(target=mp_capture,
args=(
self.stream_data_queue, self.capture_data_queue, self.state_queue,
self.start_capture_flag, self.end_process_flag,
device_id, self.model.selected_ain_channel, self.model.sample_rate)
)
self.proc.start()
# self.thread_manager.moveToThread(())
self.thread_manager.start(self.qt_consume_data)
self.thread_manager.start(self.qt_stream_data)
self.thread_manager.start(self.qt_get_state)
def qt_consume_data(self):
"""Consume data from the queue and plot it. This is a QThread."""
while not self.kill_thread and not bool(self.end_process_flag.value):
while self.capture_data_queue.qsize() > 0:
self.model.unconsumed_capture_data = self.capture_data_queue.qsize()
d, s = self.capture_data_queue.get()
[self.model.recorded_samples.append(e) for e in d]
# self.model.samples_captured = len(self.model.recorded_samples)
self.status_dqueue.append(s)
#time.sleep(0.01)
self.logger.info("Capture Data consume thread ended")
def qt_stream_data(self):
nth_cnt = 1
nth = 2
while not self.kill_thread and not bool(self.end_process_flag.value):
while self.stream_data_queue.qsize() > 0:
self.model.unconsumed_stream_samples = self.stream_data_queue.qsize()
for d in self.stream_data_queue.get()[0]:
#if nth_cnt == nth:
self.streaming_data_dqueue.append(d)
# nth_cnt = 0
#nth_cnt += 1
#time.sleep(0.01)
self.logger.info("Streaming data consume thread ended")
def qt_get_state(self):
while not self.kill_thread and not bool(self.end_process_flag.value):
while self.state_queue.qsize() > 0:
self._set_ad2state_from_process(self.state_queue.get())
#time.sleep(0.1)
self.logger.info("Status data consume thread ended")
def _set_ad2state_from_process(self, ad2state: AD2State):
# print(ad2state.__dict__)
self.model.pid = ad2state.pid
self.model.dwf_version = ad2state.dwf_version
self.model.connected = ad2state.connected
self.model.device_name = ad2state.device_name
self.model.device_serial_number = ad2state.device_serial_number
self.model.device_index = ad2state.device_index
if ad2state.acquisition_state == AD2Constants.CapturingState.RUNNING():
self.logger.info("[START ACQ] Started acquisition")
self.model.capturing_finished = False
self.model.start_recording = True
self.model.stop_recording = False
elif ad2state.acquisition_state == AD2Constants.CapturingState.STOPPED():
if self.model.start_recording:
self.model.capturing_finished = True
self.logger.info(f"[STOP ACQ] Finished acquisition {self.model.capturing_finished}.")
# Emit a signal, that the Capturing has finished
self.model.start_recording = False
self.model.stop_recording = True
self.model.device_capturing_state = ad2state.acquisition_state
self.model.sample_rate = ad2state.sample_rate
self.model.selected_ain_channel = ad2state.selected_ain_channel
self.model.ain_channels = ad2state.ain_channels
self.model.ain_buffer_size = ad2state.ain_buffer_size
self.model.ain_bits = ad2state.ain_bits
self.model.ain_device_state = ad2state.ain_device_state
self.model.recording_time = ad2state.recording_time
# ==================================================================================================================
# Destructor
# ==================================================================================================================
def stop_process(self):
self.end_process_flag.value = True
time_start = time.time()
while self.proc.is_alive():
time.sleep(0.1)
self.logger.warning(f"AD2 process exited after {time.time()-time_start}s")
self.kill_thread = True
def __del__(self):
self.logger.info("Exiting AD2 controller")
self.stop_process()
self.logger.warning("AD2 controller exited")
\ No newline at end of file
from ctypes import c_int, c_byte
from model.AD2Constants import AD2Constants
class AD2State:
def __init__(self):
# Multiprocessing Information
self._pid = None
# WaveForms Runtime (DWF) Information
self._dwf_version: str = "Unknown"
# Device information
self._connected: bool = False
self._device_name: str = "Unknown"
self._serial_number: str = "Unknown"
self._device_index: int = -1
# Acquisition Settings
self._sample_rate: int = -1
self._selected_ain_channel: int = -1
# Analog In Information
self._ain_channels: list = []
self._ain_buffer_size: int = -1
self._ain_bits: int = -1
self._ain_device_state: c_byte = c_byte()
# Analog Out Information
self._aout_channels: list = []
# Acquired Signal Information
self._acquisition_state: int = AD2Constants.CapturingState.STOPPED()
self._recording_time: float = -1
self._samples_captured: int = 0
self._samples_lost: int = -1
self._samples_corrupted: int = -1
# Device Status
self._device_ready: bool = False
self._device_capturing = False
def reinit(self, fields: dict):
for k, v in fields.items():
setattr(self, k, v)
# =========== Multiprocessing Information
@property
def pid(self):
return self._pid
# =========== WaveForms Runtime (DWF) Information
@property
def dwf_version(self):
return self._dwf_version
# =========== Device Information
@property
def connected(self):
return self._connected
@property
def device_name(self):
return self._device_name
@property
def device_serial_number(self):
return self._serial_number
@property
def device_index(self):
return self._device_index
# ========== Acquisition Settings
@property
def sample_rate(self):
return self._sample_rate
@property
def selected_ain_channel(self):
return self._selected_ain_channel
# =========== Analog In Information
@property
def ain_channels(self):
return self._ain_channels
@property
def ain_buffer_size(self):
return self._ain_buffer_size
@property
def ain_bits(self):
return self._ain_bits
@property
def ain_device_state(self):
return self._ain_device_state
# =========== Analog Out Information
@property
def aout_channels(self):
return self._aout_channels
# =========== Acquired Signal Information
@property
def acquisition_state(self):
return self._acquisition_state
@property
def recording_time(self):
return self._recording_time
@property
def samples_captured(self):
return self._samples_captured
@property
def samples_lost(self):
return self._samples_lost
@property
def samples_corrupted(self):
return self._samples_corrupted
# =========== Device Status
@property
def device_ready(self):
return self._device_ready
@property
def device_capturing(self):
return self._device_capturing
class AD2StateMPSetter(AD2State):
def __init__(self, state_queue):
super().__init__()
self._state_queue = state_queue
# =========== Multiprocessing Information
@AD2State.pid.setter
def pid(self, value):
self._pid = value
self._state_queue.put(self.to_simple_class())
# =========== WaveForms Runtime (DWF) Information
@AD2State.dwf_version.setter
def dwf_version(self, value):
self._dwf_version = value
self._state_queue.put(self.to_simple_class())
# =========== Device Information
@AD2State.connected.setter
def connected(self, value):
self._connected = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_name.setter
def device_name(self, value):
self._device_name = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_serial_number.setter
def device_serial_number(self, value):
self._serial_number = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_index.setter
def device_index(self, value):
self._device_index = value
self._state_queue.put(self.to_simple_class())
# ========== Acquisition Settings
@AD2State.sample_rate.setter
def sample_rate(self, value):
self._sample_rate = value
self._state_queue.put(self.to_simple_class())
@AD2State.selected_ain_channel.setter
def selected_ain_channel(self, value):
self._selected_ain_channel = value
self._state_queue.put(self.to_simple_class())
# =========== Analog In Information
@AD2State.ain_channels.setter
def ain_channels(self, value):
self._ain_channels = value
self._state_queue.put(self.to_simple_class())
@AD2State.ain_buffer_size.setter
def ain_buffer_size(self, value):
self._ain_buffer_size = value
self._state_queue.put(self.to_simple_class())
@AD2State.ain_bits.setter
def ain_bits(self, value):
self._ain_bits = value
self._state_queue.put(self.to_simple_class())
@AD2State.ain_device_state.setter
def ain_device_state(self, value):
self._ain_device_state = value
self._state_queue.put(self.to_simple_class())
# =========== Analog Out Information
@AD2State.aout_channels.setter
def aout_channels(self, value):
self._aout_channels = value
self._state_queue.put(self.to_simple_class())
# =========== Acquired Signal Information
@AD2State.acquisition_state.setter
def acquisition_state(self, value):
self._acquisition_state = value
self._state_queue.put(self.to_simple_class())
@AD2State.recording_time.setter
def recording_time(self, value):
self._recording_time = value
self._state_queue.put(self.to_simple_class())
@AD2State.samples_captured.setter
def samples_captured(self, value):
self._samples_captured = value
self._state_queue.put(self.to_simple_class())
@AD2State.samples_lost.setter
def samples_lost(self, value):
self._samples_lost = value
self._state_queue.put(self.to_simple_class())
@AD2State.samples_corrupted.setter
def samples_corrupted(self, value):
self._samples_corrupted = value
self._state_queue.put(self.to_simple_class())
# =========== Device Status
@AD2State.device_ready.setter
def device_ready(self, value):
self._device_ready = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_capturing.setter
def device_capturing(self, value):
self._device_capturing = value
self._state_queue.put(self.to_simple_class())
def to_simple_class(self) -> AD2State:
exclude = ["_state_queue"]
ad2state = AD2State()
to_dict = {}
for item, value in self.__dict__.items():
if item in exclude:
continue
else:
to_dict[item] = value
ad2state.reinit(to_dict)
return ad2state
"""
File for methods that run the multiporcessing capture.
Here we can init the device capturing and stream the data using ques.
(c) Christoph Schmidt, 2023
christoph.schmidt@tugraz.at
"""
import os
import random
import sys
import time
from ctypes import c_int, byref, c_double, cdll, create_string_buffer, c_int32
from controller.mp_AD2Capture.AD2StateMPSetter import AD2StateMPSetter
from model.AD2Constants import AD2Constants
from constants.dwfconstants import acqmodeRecord, DwfStateConfig, DwfStatePrefill, DwfStateArmed, enumfilterType, \
enumfilterUSB, enumfilterDemo
# ======================================================================================================================
# Process logging function
# ======================================================================================================================
def _mp_log_debug(msg, prefix="AD2 Thread"):
print(f"DBG | [{prefix}/{os.getpid()}]: {msg}")
def _mp_log_error(msg, prefix="AD2 Thread"):
print(f"ERR | [{prefix}/{os.getpid()}]: {msg}")
def _mp_log_info(msg, prefix="AD2 Thread"):
print(f"INF | [{prefix}/{os.getpid()}]: {msg}")
def _mp_log_warning(msg, prefix="AD2 Thread"):
print(f"WARN | [{prefix}/{os.getpid()}]: {msg}")
# ======================================================================================================================
# Process Main function, used for capturing and streaming data
# ======================================================================================================================
def mp_capture(stream_data_queue, capture_data_queue, state_queue,
start_capture, end_process,
device_id, channel, sample_rate):
"""
Captures data from the device and puts it into a queue.
:param capture_data_queue:
:param state_queue:
:param start_capture:
:param end_process:
:param device_id:
:param sample_rate:
:param stream_data_queue: Queue to put the data into.
:param channel: Channel to capture data from.
:return: None
"""
# Streaming the data should only be set to 1000Hz, otherwise the UI will freeze. The capturing however should
# stay at the given sample rate.
# Using the modulo operation allow us to determine the variable stream_n that is required
# to scale down the streaming rate.
stream_rate = 1000 # Hz
#stream_n = sample_rate / stream_rate
#stream_sample_cnt = 0
time_capture_started = 0
capturing_notified = False
# Print pid and ppid
_mp_log_info(f"Starting capture thread, pid={os.getpid()}, ppid={os.getppid()}")
ad2_state = AD2StateMPSetter(state_queue)
ad2_state.pid = os.getpid()
ad2_state.selected_ain_channel = channel
ad2_state.sample_rate = sample_rate
_mp_log_debug(f"Setting up device {device_id} with "
f"channel {ad2_state.selected_ain_channel} and "
f"acquisition rate {ad2_state.sample_rate} Hz")
dwf, hdwf = _mp_open_device(device_id, ad2_state)
# acquisition_state = c_byte()
cAvailable = c_int()
cLost = c_int()
cCorrupted = c_int()
# FDwfAnalogInStatus(HDWF hdwf, BOOL fReadData, DwfState* psts)
_t_setup_aquisition(dwf, hdwf, ad2_state)
_t_setup_sine_wave(dwf, hdwf, ad2_state)
_mp_log_info("Configuring acquisition. Starting oscilloscope.")
# FDwfAnalogInConfigure(HDWF hdwf, int fReconfigure, int fStart)
# Configures the instrument and start or stop the acquisition. To reset the Auto trigger timeout, set
# fReconfigure to TRUE.
# hdwf – Interface handle.
# fReconfigure – Configure the device.
# fStart – Start the acquisition.
dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
_mp_log_info("Device configured. Starting acquisition.")
cSamples = 0
ad2_state.device_ready = True
capture_samples = 0
while end_process.value == False:
# Checks the state of the acquisition. To read the data from the device, set fReadData to TRUE. For
# single acquisition mode, the data will be read only when the acquisition is finished
dwf.FDwfAnalogInStatus(hdwf, c_int(1),
byref(ad2_state.ain_device_state)) # Variable to receive the acquisition state
if cSamples == 0 and (
ad2_state.ain_device_state == DwfStateConfig or
ad2_state.ain_device_state == DwfStatePrefill or
ad2_state.ain_device_state == DwfStateArmed):
_mp_log_info("Device in idle state. Waiting for acquisition to start.")
continue # Acquisition not yet started.
dwf.FDwfAnalogInStatusRecord(hdwf,
byref(cAvailable),
byref(cLost),
byref(cCorrupted))
cSamples += cLost.value
if cLost.value:
ad2_state.samples_lost += cLost.value
if cCorrupted.value:
ad2_state.samples_corrupted += cCorrupted.value
# self.dwf.FDwfAnalogInStatusSamplesValid(self.hdwf, byref(self.cValid))
if cAvailable.value == 0:
continue
else:
# print(f"Available: {cAvailable.value}")
# if cSamples + cAvailable.value > self.ad2capt_model.n_samples:
# cAvailable = c_int(self.ad2capt_model.n_samples - cSamples)
rgdSamples = (c_double * cAvailable.value)()
dwf.FDwfAnalogInStatusData(hdwf, c_int(ad2_state.selected_ain_channel), byref(rgdSamples),
cAvailable) # get channel data
# Print how many samples are available
status = {"available": cAvailable.value, 'captured': 0, 'lost': cLost.value,
'corrupted': cCorrupted.value, "time": time.time()}
print(status)
time.sleep(random.random())
#print(len(rgdSamples))
stream_data_queue.put(
([(float(s)) for s in rgdSamples], status)
)
if start_capture.value == 1:
if not capturing_notified:
time_capture_started = time.time()
capture_samples = 0
_mp_log_info("Starting command recieved. Acquisition started.")
ad2_state.acquisition_state = AD2Constants.CapturingState.RUNNING()
capturing_notified = True
capture_samples = capture_samples + len(rgdSamples)
status = {
"available": cAvailable.value,
"captured": capture_samples,
"lost": cLost.value,
"corrupted": cCorrupted.value,
"recording_time": time.time() - time_capture_started}
capture_data_queue.put(([float(s) for s in rgdSamples], status))
# capture_data_queue.put([float(s) for s in rgdSamples])
elif start_capture.value == 0:
if capturing_notified:
ad2_state.acquisition_state = AD2Constants.CapturingState.STOPPED()
time_capture_stopped = time.time()
time_captured = time_capture_stopped - time_capture_started
ad2_state.recording_time = time_captured
_mp_log_info(f"Acquisition stopped after {time_captured} seconds. Captured {capture_samples} "
f"samples. Resulting in a time of {capture_samples / ad2_state.sample_rate} s.")
status = {
"available": cAvailable.value,
"captured": capture_samples,
"lost": cLost.value,
"corrupted": cCorrupted.value,
"recording_time": time.time() - time_capture_started}
capture_data_queue.put(([float(s) for s in rgdSamples], status))
capturing_notified = False
cSamples += cAvailable.value
_mp_close_device(dwf, hdwf, channel, ad2_state)
def _mp_update_device_information(dwf, hdwf, ad2_state: AD2StateMPSetter):
in_channel = c_int()
out_channel = c_int()
buffer_size = c_int()
# Get the Analog In Channels and Buffer Size
dwf.FDwfAnalogInChannelCount(hdwf, byref(in_channel))
ad2_state.ain_channels = list(range(0, int(in_channel.value)))
dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(buffer_size))
# Get the Analog Out Channels and Buffer Size
ad2_state.analog_analog_in_buffer_size = int(buffer_size.value)
dwf.FDwfAnalogOutCount(hdwf, byref(out_channel))
ad2_state.aout_channels = list(range(0, int(out_channel.value)))
# # Select the first Analog In Channel
# ad2_state.selected_channel = ad2_state.list_of_analog_in_channels[0]
def _mp_get_dwf_information(dwf, ad2_state: AD2StateMPSetter):
_mp_log_debug(f"Getting DWF version information...")
version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
ad2_state.dwf_version = version.value.decode("utf-8")
_mp_log_debug(f"DWF Version: {ad2_state.dwf_version}")
# ======================================================================================================================
# Setup the device
# ======================================================================================================================
def _t_setup_sine_wave(dwf, hdwf, ad2_state: AD2StateMPSetter):
_mp_log_debug("Generating AM sine wave...")
dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1)) # carrier
dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_int(1)) # sine
dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(0.1))
dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1))
# dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0.5))
# dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(2), c_int(1)) # AM
# dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(2), c_int(3)) # triangle
# dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(2), c_double(0.1))
# dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(2), c_double(50))
dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
_mp_log_debug("Sine wave on output channel 0 configured.")
def _t_setup_aquisition(dwf, hdwf, ad2_state: AD2StateMPSetter):
dwf.FDwfAnalogInStatus(hdwf, c_int(1),
byref(ad2_state.ain_device_state)) # Variable to receive the acquisition state
_mp_log_info(f"[Task] Setup for acquisition on channel"
f" {ad2_state.selected_ain_channel} with rate {ad2_state.sample_rate} Hz.")
dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(ad2_state.selected_ain_channel), c_int(1))
dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(ad2_state.selected_ain_channel), c_double(5))
dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
dwf.FDwfAnalogInFrequencySet(hdwf, c_double(ad2_state.sample_rate))
dwf.FDwfAnalogInRecordLengthSet(hdwf, 0) # -1 infinite record length
# Variable to receive the acquisition state
dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(ad2_state.ain_device_state))
_mp_log_info(f"[Task] Wait 2 seconds for the offset to stabilize.")
# wait at least 2 seconds for the offset to stabilize
time.sleep(2)
_mp_log_info(f"[Task] Setup for acquisition done.")
def _mp_discover_connected_devices(dwf):
_mp_log_info(f"Discovering connected devices...")
# enumerate connected devices
connected_devices = []
# for filter_type in [(c_int32(enumfilterType.value | enumfilterUSB.value), 'USB'),
# (c_int32(enumfilterType.value | enumfilterNetwork.value), 'Network'),
# (c_int32(enumfilterType.value | enumfilterAXI.value), 'AXI'),
# (c_int32(enumfilterType.value | enumfilterRemote.value), 'Remote'),
# (c_int32(enumfilterType.value | enumfilterAudio.value), 'Audio'),
# (c_int32(enumfilterType.value | enumfilterDemo.value), 'Demo')]:
cDevice = c_int()
filter, type = (c_int32(enumfilterType.value | enumfilterDemo.value| enumfilterUSB.value), 'USB')
# filter, type = (c_int32(enumfilterType.value | enumfilterDemo.value), 'DEMO')
_mp_log_debug(f"Filtering {type} devices...")
dwf.FDwfEnum(filter, byref(cDevice))
num_of_connected_devices = cDevice
devicename = create_string_buffer(64)
serialnum = create_string_buffer(16)
for iDevice in range(0, cDevice.value):
dwf.FDwfEnumDeviceName(c_int(iDevice), devicename)
dwf.FDwfEnumSN(c_int(iDevice), serialnum)
connected_devices.append({
'type': type,
'device_id': int(iDevice),
'device_name': str(devicename.value.decode('UTF-8')),
'serial_number': str(serialnum.value.decode('UTF-8'))
})
#_mp_log_debug(f"Found {type} device: {devicename.value.decode('UTF-8')} ({serialnum.value.decode('UTF-8')})")
# print(connected_devices)
# print(f"Discoverd {len(self.model.connected_devices)} devices.")
return connected_devices
def _mp_open_device(device_index, ad2_state: AD2StateMPSetter):
"""
Opens the device and returns the handle.
:return: Device handle.
"""
_mp_log_debug(f"Importing dwf library for {sys.platform}...")
if sys.platform.startswith("win"):
dwf = cdll.dwf
elif sys.platform.startswith("darwin"):
dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
dwf = cdll.LoadLibrary("libdwf.so")
hdwf = c_int()
_mp_get_dwf_information(dwf, ad2_state)
# This is needed, otherwise, the device is not found.
_mp_discover_connected_devices(dwf)
# Opens the device specified by idxDevice. The device handle is returned in hdwf. If idxDevice is -1, the
# first available device is opened.
_mp_log_info(f"[Task] Opening device #{device_index}...")
dwf.FDwfDeviceOpen(c_int(device_index), byref(hdwf))
devicename = create_string_buffer(64)
serialnum = create_string_buffer(16)
dwf.FDwfEnumDeviceName(c_int(device_index), devicename)
dwf.FDwfEnumSN(c_int(device_index), serialnum)
ad2_state.device_name = str(devicename.value.decode("utf-8"))
ad2_state.device_serial_number = str(serialnum.value.decode("utf-8")).replace("SN:", "")
# open device
if hdwf.value == 0:
szerr = create_string_buffer(512)
dwf.FDwfGetLastErrorMsg(szerr)
_mp_log_error(f"Failed to open device: {szerr.value}")
ad2_state.connected = False
raise Exception(f"Failed to open device: {szerr.value}")
else:
_mp_log_info(f"Device opened: {ad2_state.device_name} ({ad2_state.device_serial_number})")
ad2_state.connected = True
return dwf, hdwf
def _mp_close_device(dwf, hdwf, channel, ad2_state: AD2StateMPSetter):
dwf.FDwfAnalogOutReset(hdwf, c_int(channel))
_mp_log_info(f"[Task] Closing device...")
dwf.FDwfDeviceClose(hdwf)
ad2_state.connected = False
_mp_log_info(f"[Task] Device closed.")
This diff is collapsed.
from generics.GenericProperties import GenericProperties
class AD2CaptDeviceProperties(GenericProperties):
def __init__(self, samples_lost: float, samples_currputed: float,
acquisition_rate: float, n_samples: int,
measurement_time: float):
super().__init__()
# Laser properties
self._samples_lost: float = self.to_float(samples_lost)
self._samples_currputed: float = self.to_float(samples_currputed)
self._sample_rate: float = self.to_float(acquisition_rate)
self._n_samples: int = self.to_int(n_samples)
self._measurement_time: float = self.to_float(measurement_time)
@property
def samples_lost(self):
return self._samples_lost
@samples_lost.setter
def samples_lost(self, value):
self._samples_lost = value
@property
def samples_corrupted(self):
return self._samples_currputed
@samples_corrupted.setter
def samples_corrupted(self, value):
self._samples_currputed = value
@property
def n_samples(self):
return self._n_samples
@n_samples.setter
def n_samples(self, value):
self._n_samples = value
@property
def measurement_time(self):
return self._measurement_time
@measurement_time.setter
def measurement_time(self, value):
self._measurement_time = value
@property
def sample_rate(self):
return self._sample_rate
@sample_rate.setter
def sample_rate(self, value):
self._sample_rate = value
def fields(self) -> dict:
return {
'samples_lost': self.samples_lost,
'samples_corrupted': self.samples_corrupted,
'n_samples': self.n_samples,
'measurement_time': self.measurement_time,
'sample_rate': self.sample_rate
}
\ No newline at end of file
class AD2Constants:
class CapturingState:
# Capturing States
@staticmethod
def RUNNING(description: bool = False):
if description:
return "Capturing running"
return 1
@staticmethod
def PAUSED(description: bool= False):
if description:
return "Capturing paused"
return 2
@staticmethod
def STOPPED(description: bool= False):
if description:
return "Capturing stopped"
return 3
This diff is collapsed.
#!/bin/bash
# Convert .ui files to .py files
for ui in *.ui; do
pyside6-uic $ui > ../view/Ui_${ui%.*}.py
done
pyside6-rcc ./resources.qrc -o ../resources_rc.py
src/CaptDeviceControl/resources/icons/cil-3d.png

1.91 KiB

src/CaptDeviceControl/resources/icons/cil-4k.png

1.9 KiB

src/CaptDeviceControl/resources/icons/cil-account-logout.png

1.82 KiB

src/CaptDeviceControl/resources/icons/cil-action-redo.png

1.83 KiB

src/CaptDeviceControl/resources/icons/cil-action-undo.png

1.84 KiB

src/CaptDeviceControl/resources/icons/cil-airplane-mode-off.png

1.94 KiB

src/CaptDeviceControl/resources/icons/cil-airplane-mode.png

1.9 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment