Files
templates/python/set_devices/wavegen_protocol.py

68 lines
3.6 KiB
Python

"""ctypes port of the shared wave generator RTU codec."""
import ctypes as C
from .signal_reconstruction import library
class WaveProtocol:
def __init__(self, address=16):
if not 1 <= address <= 247:
raise ValueError("Адрес должен быть 1…247")
self.address = address
self.lib = library()
p = C.POINTER(C.c_uint8)
self.lib.set_wave_request.argtypes = [C.c_uint, C.c_uint, C.c_uint, C.c_uint, p, C.c_size_t]
self.lib.set_wave_request.restype = C.c_size_t
self.lib.set_wave_response.argtypes = [p, p, C.c_size_t, C.POINTER(C.c_uint16), C.c_size_t]
self.lib.set_wave_response.restype = C.c_int
self.lib.set_wave_block_request.argtypes = [C.c_uint, C.c_uint, C.POINTER(C.c_uint16), C.c_size_t, p, C.c_size_t]
self.lib.set_wave_block_request.restype = C.c_size_t
self.lib.set_wave_block_response.argtypes = [p, C.c_size_t, p, C.c_size_t, C.POINTER(C.c_uint16), C.c_size_t]
self.lib.set_wave_block_response.restype = C.c_int
def block_request(self, index, values=None, count=None):
count = len(values) if values is not None else count
if count is None or not 1 <= count <= 120:
raise ValueError("Блок должен содержать 1…120 отсчётов")
if values is not None and any(not 0 <= value <= 4095 for value in values):
raise ValueError("Коды ЦАП должны быть 0…4095")
samples = (C.c_uint16 * count)(*values) if values is not None else None
output = (C.c_uint8 * 249)()
size = self.lib.set_wave_block_request(self.address, index, samples, count, output, len(output))
if not size:
raise ValueError("Недопустимый блок генератора")
return bytes(output[:size])
def block_response(self, request, reply):
words = (C.c_uint16 * 120)()
code = self.lib.set_wave_block_response((C.c_uint8 * len(request)).from_buffer_copy(request), len(request),
(C.c_uint8 * len(reply)).from_buffer_copy(reply), len(reply), words, len(words))
if code == 0:
return None
if code < 0:
raise ValueError(f"Неверный ответ блока генератора ({code})")
return tuple(words[:code])
def request(self, operation, index=0, value=0):
output = (C.c_uint8 * 8)()
if self.lib.set_wave_request(self.address, operation, index, value, output, 8) != 8:
raise ValueError("Недопустимая команда генератора")
return bytes(output)
def response(self, request, reply):
if len(request) != 8:
raise ValueError("Неверный запрос")
words = (C.c_uint16 * 8)()
code = self.lib.set_wave_response((C.c_uint8 * 8).from_buffer_copy(request),
(C.c_uint8 * len(reply)).from_buffer_copy(reply), len(reply), words, len(words))
if code == 0:
return None
if code < 0:
raise ValueError(f"Неверный ответ генератора или исключение устройства ({code})")
return tuple(words[:code])
@staticmethod
def status(words, rate_high=0):
if len(words) != 8 or words[0] != 0x5747 or words[1] not in (1, 2, 3):
raise ValueError("Устройство не поддерживает генератор WG v1/v2/v3")
return dict(version=words[1], running=bool(words[2]), rate=(rate_high << 16) | words[3], count=words[4],
received=words[5], ready=bool(words[6]), capacity=words[7])