# -*- coding: utf-8 -*- # Симуляция CRC-схем IR-protocol на "сдвиговых" ошибках. # crc8 воспроизводит IR_config.cpp: MSB-first, init=0xFF, без final-xor. import random random.seed(1) POLY1 = 0x31 POLY2 = 0x8C # битовое зеркало 0x31 def crc8(data, poly): crc = 0xFF for b in data: crc ^= b for _ in range(8): crc = ((crc << 1) ^ poly) & 0xFF if (crc & 0x80) else (crc << 1) & 0xFF return crc def fold4(x): # свернуть 8-бит CRC в 4 бита (xor старший^младший ниббл) return (x ^ (x >> 4)) & 0x0F # --- схемы контроля: считают "чек" от данных и сверяют --- def single_chk(d): return (crc8(d, POLY1),) # 8 бит, 1 полином def double_chk(d): c1 = crc8(d, POLY1); return (c1, crc8(d + [c1], POLY2)) # текущая: 16 бит def nib_fold_chk(d):return ((fold4(crc8(d, POLY1)) << 4) | fold4(crc8(d, POLY2)),) # предложенная: 4+4 бит def nib_trunc_chk(d):return (((crc8(d, POLY1) & 0x0F) << 4) | (crc8(d, POLY2) & 0x0F),) def bits_of(data): return [(b >> (7 - j)) & 1 for b in data for j in range(8)] def bytes_of(bits): return [sum(bits[i + j] << (7 - j) for j in range(8)) for i in range(0, len(bits), 8)] # --- модели "сдвига" в середине пакета (над битами данных, длина сохраняется) --- def slip_delete(data, p): # выкинуть бит p, сдвинуть хвост влево, добить 0 в конец b = bits_of(data); b = b[:p] + b[p+1:] + [0]; return bytes_of(b) def rotate_all_right(data, _): # циклический сдвиг ВСЕХ бит вправо на 1 b = bits_of(data); b = [b[-1]] + b[:-1]; return bytes_of(b) def rotate_mid_window(data, p): # циклический сдвиг окна [p, p+16) на 1 (локальный сдвиг в середине) b = bits_of(data); q = min(p+16, len(b)) w = b[p:q]; w = [w[-1]] + w[:-1]; b = b[:p] + w + b[q:]; return bytes_of(b) MODELS = [("slip-delete (бит-слип)", slip_delete), ("rotate-all (сдвиг всего на 1)", rotate_all_right), ("rotate-mid-window (сдвиг окна в середине)", rotate_mid_window)] SCHEMES = [("single (1×CRC8, 8бит)", single_chk), ("double (2×CRC8, 16бит) — текущая", double_chk), ("nibble-fold (4+4бит)", nib_fold_chk), ("nibble-trunc (4+4бит)", nib_trunc_chk)] def run(datalen, trials): print(f"\n===== данные {datalen} байт, {trials} попыток на модель =====") for mname, model in MODELS: # для каждой схемы: сколько ошибок НЕ обнаружено (чек совпал, а данные изменились) undetected = {s[0]: 0 for s in SCHEMES} changed = 0 first_single_miss = None for _ in range(trials): d = [random.randint(0, 255) for _ in range(datalen)] p = random.randint(datalen*8//4, datalen*8*3//4) # позиция в середине c = model(d, p) if c == d: continue changed += 1 for sname, chk in SCHEMES: if chk(c) == chk(d): undetected[sname] += 1 if sname.startswith("single") and first_single_miss is None: first_single_miss = (d[:], c[:], p) print(f" модель: {mname} (изменённых кадров: {changed})") for sname, _ in SCHEMES: u = undetected[sname] rate = u / changed if changed else 0 print(f" {sname:38s}: пропущено {u:6d} ({rate*100:.4f}%)") if first_single_miss: d, c, p = first_single_miss print(f" ПРИМЕР пропуска single (poly1): data={bytes(d).hex()} -> shift@{p} -> {bytes(c).hex()}") print(f" single: crc1(orig)={crc8(d,POLY1):02x} == crc1(shift)={crc8(c,POLY1):02x} -> ПРОШЁЛ") print(f" double: crc2(orig)={double_chk(d)[1]:02x} vs crc2(shift)={double_chk(c)[1]:02x} -> {'ПРОШЁЛ (не поймал!)' if double_chk(d)==double_chk(c) else 'ПОЙМАЛ'}") for L in (3, 5, 8): run(L, 200000) # Гарантированное покрытие burst-ошибок (подряд идущие искажённые биты) — ключ для IR (бит-слипы/всплески) print("\n===== Гарантия обнаружения BURST-ошибок (100% всех burst данной длины?) =====") def burst_guaranteed(chk, datalen, blen): # перебор всех burst длины blen по всем позициям на нескольких случайных базах; ищем ХОТЬ ОДИН пропуск for _ in range(300): d = [random.randint(0,255) for _ in range(datalen)] base = bits_of(d) for start in range(len(base)-blen+1): b2 = base[:] for k in range(blen): b2[start+k] ^= 1 c = bytes_of(b2) if c != d and chk(c) == chk(d): return False # найден необнаруженный burst return True for sname, chk in SCHEMES: maxb = 0 for blen in range(1, 25): if burst_guaranteed(chk, 5, blen): maxb = blen else: break print(f" {sname:38s}: 100%% ловит burst до {maxb} бит подряд")