Add shared waveform processing, generation and firmware image support

This commit is contained in:
2026-09-27 01:45:08 +03:00
parent 2ad29e7ffd
commit cc22c803d1
36 changed files with 2591 additions and 61 deletions

View File

@@ -0,0 +1,48 @@
"""Models for the C99 Intel HEX parser. No Python parser fallback."""
import ctypes as ct
from functools import lru_cache
from protocan.native import _load_library
class Cell(ct.Structure):
_fields_ = [('address', ct.c_uint32), ('value', ct.c_uint8)]
@lru_cache(maxsize=1)
def library():
lib = _load_library()
try:
lib.firmware_hex_parse.argtypes = [ct.c_char_p, ct.c_size_t, ct.POINTER(Cell),
ct.c_size_t, ct.c_size_t, ct.POINTER(ct.c_size_t), ct.POINTER(ct.c_size_t)]
lib.firmware_hex_parse.restype = ct.c_int
lib.firmware_hex_segment_size.argtypes = [ct.POINTER(Cell), ct.c_size_t, ct.c_size_t]
lib.firmware_hex_segment_size.restype = ct.c_size_t
except AttributeError as exc:
raise RuntimeError('Rebuild SETProtocol: native firmware image API is missing') from exc
return lib
def parse_segments(text, max_records, error_type, segment_type):
try:
raw = bytes(text) if isinstance(text, (bytes, bytearray)) else str(text or '').encode('ascii')
except UnicodeError as exc:
raise error_type('Intel HEX должен состоять из ASCII') from exc
if max_records < 1 or len(raw) > 64 * 1024 * 1024:
raise error_type('Файл Intel HEX превышает допустимый размер')
cells = (Cell * max(1, len(raw) // 2))()
count, line = ct.c_size_t(), ct.c_size_t()
lib = library()
status = lib.firmware_hex_parse(raw, len(raw), cells, len(cells), max_records,
ct.byref(count), ct.byref(line))
if status:
messages = {1: 'неверный формат', 2: 'неверная checksum записи',
3: 'неизвестный тип или неверная длина записи', 4: 'нет данных/EOF или данные после записи EOF',
5: 'адрес описан повторно', 6: 'адрес выходит за uint32',
7: 'превышено допустимое число записей',
8: "запись должна начинаться с ':'", 9: 'запись содержит не пары HEX-символов',
10: 'длина записи не совпадает с полем count'}
raise error_type('Intel HEX, строка %d: %s' % (line.value, messages.get(status, 'ошибка')))
result, offset = [], 0
while offset < count.value:
size = lib.firmware_hex_segment_size(cells, count.value, offset)
result.append(segment_type(cells[offset].address,
bytes(cells[i].value for i in range(offset, offset + size))))
offset += size
return result