2022-12-31 13:00:23 +00:00
|
|
|
import ctypes
|
|
|
|
|
import sys
|
2023-01-03 09:22:54 +00:00
|
|
|
import platform
|
2022-12-31 13:00:23 +00:00
|
|
|
import time
|
|
|
|
|
from enum import Enum
|
|
|
|
|
|
2023-01-31 15:03:46 +00:00
|
|
|
from PyQt5.QtCore import QMutex, Qt, QTimer, pyqtSlot, pyqtSignal
|
2022-12-31 13:00:23 +00:00
|
|
|
|
|
|
|
|
from .component import Component
|
|
|
|
|
|
2023-01-30 15:50:02 +00:00
|
|
|
is_win = platform.system() == "Windows"
|
|
|
|
|
|
2022-12-31 13:00:23 +00:00
|
|
|
if "--sim-io" not in sys.argv:
|
2023-01-30 15:50:02 +00:00
|
|
|
if is_win:
|
2023-02-17 20:19:30 +00:00
|
|
|
from components.Automation.BDaq import *
|
|
|
|
|
from components.Automation.BDaq.InstantDoCtrl import InstantDoCtrl
|
|
|
|
|
from components.Automation.BDaq.InstantDiCtrl import InstantDiCtrl
|
2023-01-03 09:22:54 +00:00
|
|
|
else:
|
|
|
|
|
libbiodaq = ctypes.CDLL("/opt/advantech/libs/libbiodaq.so")
|
2022-12-31 13:00:23 +00:00
|
|
|
else:
|
2023-03-25 14:13:09 +00:00
|
|
|
from components.dummies.Automation.BDaq import *
|
|
|
|
|
from components.dummies.Automation.BDaq.InstantDoCtrl import InstantDoCtrl
|
|
|
|
|
from components.dummies.Automation.BDaq.InstantDiCtrl import InstantDiCtrl
|
|
|
|
|
#is_win=False
|
|
|
|
|
#import components.dummies.libbiodaq as libbiodaq
|
2023-03-03 17:51:35 +00:00
|
|
|
from components.dummies.libbiodaq import ErrorCode
|
2022-12-31 13:00:23 +00:00
|
|
|
|
2023-01-03 16:57:14 +00:00
|
|
|
class USB_586x(Component):
|
2022-12-31 13:00:23 +00:00
|
|
|
class DeviceInformation(ctypes.Structure):
|
|
|
|
|
_fields_ = [
|
|
|
|
|
('DeviceNumber', ctypes.c_uint32),
|
|
|
|
|
('DeviceMode', ctypes.c_uint32),
|
|
|
|
|
('ModuleIndex', ctypes.c_uint32),
|
|
|
|
|
('Description', ctypes.c_wchar_p)
|
|
|
|
|
]
|
2023-01-31 15:03:46 +00:00
|
|
|
update=pyqtSignal(object)
|
2023-02-01 10:51:57 +00:00
|
|
|
masks = [1 << n for n in range(8)]
|
2022-12-31 13:00:23 +00:00
|
|
|
|
2023-01-31 14:51:41 +00:00
|
|
|
def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True):
|
|
|
|
|
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
|
2022-12-31 13:00:23 +00:00
|
|
|
self.mutex = QMutex()
|
2023-02-17 17:41:45 +00:00
|
|
|
self.simulate="--sim-io" in sys.argv
|
2022-12-31 13:00:23 +00:00
|
|
|
# DEVICE INFORMATION
|
2023-01-31 14:51:41 +00:00
|
|
|
self.id=config["digital_io"]["id"]
|
2023-01-03 16:57:14 +00:00
|
|
|
if "5860" in self.id:
|
|
|
|
|
self.type = "5860"
|
|
|
|
|
self.in_size = 1
|
|
|
|
|
self.out_size = 1
|
|
|
|
|
if "5862" in self.id:
|
|
|
|
|
self.type = "5862"
|
|
|
|
|
self.in_size = 2
|
|
|
|
|
self.out_size = 2
|
2022-12-31 13:00:23 +00:00
|
|
|
self.info = self.DeviceInformation()
|
2023-01-31 14:51:41 +00:00
|
|
|
self.info.Description = self.id
|
2023-01-03 16:57:14 +00:00
|
|
|
|
|
|
|
|
# self.info.DeviceNumber = -1
|
2022-12-31 13:00:23 +00:00
|
|
|
self.info.DeviceMode = 1
|
|
|
|
|
self.info.ModuleIndex = 0
|
2023-02-16 14:58:09 +00:00
|
|
|
|
|
|
|
|
self.open_device()
|
|
|
|
|
|
|
|
|
|
# SET ALL RELAYS OFF
|
|
|
|
|
for bit in range(0, self.out_size*8):
|
|
|
|
|
self.set_bit(int(bit/8), bit%8, False)
|
|
|
|
|
|
|
|
|
|
self.state_delay = 1
|
|
|
|
|
self.last_get = None
|
|
|
|
|
self.state_count = None
|
|
|
|
|
self.last_out = None
|
|
|
|
|
|
|
|
|
|
def open_device(self):
|
2022-12-31 13:00:23 +00:00
|
|
|
# DIGITAL INPUTS CLASS
|
2023-03-30 10:06:45 +00:00
|
|
|
if not self.simulate:
|
|
|
|
|
if is_win:
|
|
|
|
|
self.di_ctrl = InstantDiCtrl(self.info.Description)
|
|
|
|
|
self.do_ctrl = InstantDoCtrl(self.info.Description)
|
|
|
|
|
self.di_read = self.di_ctrl.readAny
|
|
|
|
|
self.do_write_bit = self.do_ctrl.writeBit
|
|
|
|
|
self.buffer = ctypes.create_string_buffer(2)
|
|
|
|
|
else:
|
|
|
|
|
self.di_create = libbiodaq.AdxInstantDiCtrlCreate
|
|
|
|
|
self.di_create.restype = ctypes.c_void_p
|
|
|
|
|
self.di_setSelectedDevice = libbiodaq.InstantDiCtrl_setSelectedDevice
|
|
|
|
|
self.di_setSelectedDevice.argtypes = [ctypes.c_void_p, ctypes.POINTER(self.DeviceInformation)]
|
|
|
|
|
self.di_setSelectedDevice.restype = ctypes.c_uint32
|
|
|
|
|
# DIGITAL INPUTS READ FUNCTION
|
|
|
|
|
self.di_read = libbiodaq.InstantDiCtrl_ReadAny
|
|
|
|
|
self.di_read.argtypes = [ctypes.c_void_p, ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
|
|
|
|
|
self.di_read.restype = ctypes.c_int32
|
|
|
|
|
# DIGITAL OUTPUTS CLASS
|
|
|
|
|
self.do_create = libbiodaq.AdxInstantDoCtrlCreate
|
|
|
|
|
self.do_create.restype = ctypes.c_void_p
|
|
|
|
|
# SET SELECTED DEVICE
|
|
|
|
|
self.do_setSelectedDevice = libbiodaq.InstantDoCtrl_setSelectedDevice
|
|
|
|
|
self.do_setSelectedDevice.argtypes = [ctypes.c_void_p, ctypes.POINTER(self.DeviceInformation)]
|
|
|
|
|
self.do_setSelectedDevice.restype = ctypes.c_uint32
|
|
|
|
|
# get ports
|
|
|
|
|
self.get_ports = libbiodaq.InstantDoCtrl_getPortDirection
|
|
|
|
|
self.get_ports.argtypes = [ctypes.c_void_p]
|
|
|
|
|
self.get_ports.restype = ctypes.POINTER(ctypes.c_void_p)
|
|
|
|
|
# DIGITAL OUTPUTS WRITE FUNCTION
|
|
|
|
|
self.do_write_bit = libbiodaq.InstantDoCtrl_WriteBit
|
|
|
|
|
self.do_write_bit.argtypes = [ctypes.c_void_p, ctypes.c_int32, ctypes.c_int32, ctypes.c_char]
|
|
|
|
|
self.do_write_bit.restype = ctypes.c_int32
|
|
|
|
|
self.buffer = ctypes.create_string_buffer(2)
|
|
|
|
|
# INIT OBJECTS
|
|
|
|
|
self.di_ctrl = self.di_create()
|
|
|
|
|
self.do_ctrl = self.do_create()
|
|
|
|
|
self.di_init_status = self.di_setSelectedDevice(self.di_ctrl, ctypes.byref(self.info))
|
|
|
|
|
self.do_init_status = self.do_setSelectedDevice(self.do_ctrl, ctypes.byref(self.info))
|
|
|
|
|
else:
|
2023-01-03 09:22:54 +00:00
|
|
|
self.di_ctrl = InstantDiCtrl(self.info.Description)
|
|
|
|
|
self.do_ctrl = InstantDoCtrl(self.info.Description)
|
|
|
|
|
self.di_read = self.di_ctrl.readAny
|
|
|
|
|
self.do_write_bit = self.do_ctrl.writeBit
|
2023-02-01 10:51:57 +00:00
|
|
|
self.buffer = ctypes.create_string_buffer(2)
|
2023-03-30 10:06:45 +00:00
|
|
|
|
2023-02-16 14:58:09 +00:00
|
|
|
def close_device(self):
|
|
|
|
|
pass
|
2022-12-31 13:00:23 +00:00
|
|
|
|
|
|
|
|
@pyqtSlot()
|
|
|
|
|
def start(self):
|
|
|
|
|
# ACQUISITION TIMER
|
|
|
|
|
self.timer = QTimer()
|
|
|
|
|
self.timer.setTimerType(Qt.PreciseTimer)
|
|
|
|
|
self.timer.setInterval(int(1000 / 20))
|
|
|
|
|
self.timer.timeout.connect(self._get)
|
|
|
|
|
self.timer.start()
|
|
|
|
|
super().start()
|
|
|
|
|
|
|
|
|
|
# Read data for buffer
|
|
|
|
|
@pyqtSlot()
|
|
|
|
|
def _get(self):
|
|
|
|
|
get = self.get()
|
|
|
|
|
# print(self.last_get)
|
|
|
|
|
if self.state_count is None or self.last_get is None:
|
|
|
|
|
self.last_out = get
|
|
|
|
|
self.state_count = [[1 for bit in byte] for byte in get]
|
|
|
|
|
else:
|
|
|
|
|
for byte_n, byte in enumerate(get):
|
|
|
|
|
for bit_n, bit in enumerate(byte):
|
|
|
|
|
if bit == self.last_get[byte_n][bit_n]:
|
|
|
|
|
self.state_count[byte_n][bit_n] += 1
|
|
|
|
|
else:
|
|
|
|
|
self.state_count[byte_n][bit_n] = 1
|
|
|
|
|
if self.state_count[byte_n][bit_n] > self.state_delay:
|
|
|
|
|
self.last_out[byte_n][bit_n] = bit
|
|
|
|
|
self.last_get = get
|
2023-02-01 10:51:57 +00:00
|
|
|
#self.update.emit([time.time(), self.last_out])
|
|
|
|
|
super()._get([self.last_out])
|
2022-12-31 13:00:23 +00:00
|
|
|
|
|
|
|
|
def get_all(self):
|
|
|
|
|
return self.get()
|
|
|
|
|
|
2023-01-06 13:06:27 +00:00
|
|
|
# Read input bytes
|
2022-12-31 13:00:23 +00:00
|
|
|
def get(self):
|
|
|
|
|
self.mutex.lock()
|
|
|
|
|
read = []
|
2023-03-30 10:06:45 +00:00
|
|
|
if is_win or self.simulate:
|
2023-03-25 14:13:09 +00:00
|
|
|
if self.simulate:
|
2023-04-11 15:01:17 +00:00
|
|
|
read=[1,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0]
|
2023-01-03 09:22:54 +00:00
|
|
|
else:
|
2023-03-25 14:13:09 +00:00
|
|
|
ret = self.di_read(0, self.in_size)
|
|
|
|
|
if ret[0].value == ErrorCode.Success.value:
|
|
|
|
|
self.buffer = ret[1]
|
|
|
|
|
for byte_num in range(len(self.buffer)):
|
|
|
|
|
byte = self.buffer[byte_num]
|
|
|
|
|
read.append([bool(byte & m) for m in self.masks])
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
self.buffer = None
|
2023-01-03 09:22:54 +00:00
|
|
|
else:
|
2023-01-06 13:06:27 +00:00
|
|
|
self.di_read(self.di_ctrl, 0, self.in_size, self.buffer)
|
2023-01-03 09:22:54 +00:00
|
|
|
|
2023-01-03 16:57:14 +00:00
|
|
|
for byte_num in range(len(self.buffer)):
|
|
|
|
|
byte = int.from_bytes(self.buffer[byte_num], "little")
|
2023-01-03 09:22:54 +00:00
|
|
|
read.append([bool(byte & m) for m in self.masks])
|
|
|
|
|
|
2022-12-31 13:00:23 +00:00
|
|
|
self.mutex.unlock()
|
|
|
|
|
return read
|
|
|
|
|
|
|
|
|
|
# Read data bit
|
|
|
|
|
def get_bit(self, byte, bit):
|
|
|
|
|
return self.get()[byte][bit]
|
|
|
|
|
|
|
|
|
|
# Send data byte
|
|
|
|
|
def set(self, start_byte, val):
|
|
|
|
|
for byte, v in enumerate(val, start=start_byte):
|
|
|
|
|
for bit, bv in enumerate([bool(v & m) for m in self.masks]):
|
|
|
|
|
self.set_bit(byte, bit, bv)
|
|
|
|
|
|
|
|
|
|
# Write single bit
|
|
|
|
|
def set_bit(self, byte, bit, val):
|
|
|
|
|
self.mutex.lock()
|
|
|
|
|
# print("set", byte, bit, not val, flush=True)
|
2023-03-03 17:51:35 +00:00
|
|
|
if not self.simulate:
|
|
|
|
|
if is_win:
|
|
|
|
|
ret=self.do_write_bit(byte, bit, int(val))
|
|
|
|
|
else:
|
|
|
|
|
ret=self.do_write_bit(self.do_ctrl, byte, bit, int(val))
|
2023-01-03 09:22:54 +00:00
|
|
|
else:
|
2023-03-03 17:51:35 +00:00
|
|
|
ret = ErrorCode.Success
|
2022-12-31 13:00:23 +00:00
|
|
|
self.mutex.unlock()
|
2023-02-16 14:58:09 +00:00
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
def set_bit_verify(self, byte, bit, val):
|
|
|
|
|
|
|
|
|
|
ok = False
|
|
|
|
|
retry=0
|
|
|
|
|
max_retry = 3
|
|
|
|
|
while not ok and retry <max_retry:
|
2023-02-16 16:26:17 +00:00
|
|
|
ret = self.set_bit(byte, bit, val)
|
2023-02-21 08:26:43 +00:00
|
|
|
if ret.value != ErrorCode.Success.value and not self.simulate:
|
2023-02-16 14:58:09 +00:00
|
|
|
self.log.error(f"SET BIT ERROR")
|
|
|
|
|
self.open_device()
|
|
|
|
|
retry+=1
|
|
|
|
|
else:
|
|
|
|
|
ok = True
|
|
|
|
|
|
|
|
|
|
return ok
|
2022-12-31 13:00:23 +00:00
|
|
|
|
|
|
|
|
# val from buffer channel
|
|
|
|
|
def vfbc(self, buffer, channel):
|
|
|
|
|
return buffer[channel[0]][channel[1]]
|