Files
templates/python/set_devices/wavegen_protocol.py

71 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ctypes-привязка RTU-кодека генератора сигналов. Модуль преобразует аргументы и результаты, а
# построение запросов и проверка ответов выполняются общей реализацией set_wavegen.
"""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])