61 lines
2.3 KiB
Python
61 lines
2.3 KiB
Python
"""Thin Python adapter for the shared C99 PM67/TMS320F2812 protocol."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from .native import get_native_protocol
|
||
|
||
|
||
CMD_UPLOAD = 52
|
||
UPLOAD_RESPONSE_OVERHEAD = 8
|
||
|
||
|
||
def _core():
|
||
return get_native_protocol()
|
||
|
||
|
||
def crc16_modbus(data: bytes, initial: int = 0xFFFF) -> int:
|
||
if initial != 0xFFFF:
|
||
raise ValueError("Произвольное начальное значение CRC не входит в протокол ПМ67")
|
||
return _core().tms2812_crc16(bytes(data))
|
||
|
||
|
||
def build_upload_request(controller: int, word_address: int,
|
||
byte_count: int) -> bytes:
|
||
_range("адрес контроллера", controller, 0xFF)
|
||
_range("адрес слова", word_address, 0xFFFFFFFF)
|
||
if not 1 <= byte_count <= 0xFFFFFFFF:
|
||
raise ValueError("размер блока вне диапазона 1..0xFFFFFFFF")
|
||
return _core().tms2812_build_upload(controller, word_address, byte_count)
|
||
|
||
|
||
def expected_upload_response_size(byte_count: int) -> int:
|
||
if not 1 <= byte_count <= 0xFFFFFFFF:
|
||
raise ValueError("размер блока вне диапазона 1..0xFFFFFFFF")
|
||
return _core().tms2812_expected_upload_size(byte_count)
|
||
|
||
|
||
def decode_upload_reply(raw: bytes, controller: int, byte_count: int) -> bytes:
|
||
expected = expected_upload_response_size(byte_count)
|
||
if len(raw) != expected:
|
||
raise ValueError(
|
||
f"ответ CMD_UPLOAD: ожидалось {expected} байт, получено {len(raw)}"
|
||
)
|
||
status, data = _core().tms2812_decode_upload(
|
||
bytes(raw), controller, byte_count)
|
||
errors = {
|
||
-1: "неверные аргументы CMD_UPLOAD",
|
||
-2: "размер CMD_UPLOAD вне диапазона",
|
||
-3: "неверная длина ответа CMD_UPLOAD",
|
||
-4: "CRC ответа CMD_UPLOAD не совпадает",
|
||
-5: "ответ CMD_UPLOAD имеет неверный адрес или номер команды",
|
||
-6: "недостаточный буфер CMD_UPLOAD",
|
||
}
|
||
if status != 0:
|
||
raise ValueError(errors.get(status, f"ошибка ответа CMD_UPLOAD: {status}"))
|
||
return data
|
||
|
||
|
||
def _range(name: str, value: int, maximum: int) -> None:
|
||
if not 0 <= value <= maximum:
|
||
raise ValueError(f"{name} вне диапазона 0..{maximum}")
|