mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-18 19:13:58 +00:00
docs
This commit is contained in:
33
docs_analysis/crc_shift_findings.md
Normal file
33
docs_analysis/crc_shift_findings.md
Normal file
@ -0,0 +1,33 @@
|
||||
# CRC при сдвиге битов — симуляция (воспроизведение и оценка сжатия)
|
||||
|
||||
> Скрипт: `crc_shift_sim.py` (рядом). `crc8` точно как в `IR_config.cpp` (MSB-first, init=0xFF, без final-xor). `poly1=0x31`, `poly2=0x8C` (битовое зеркало 0x31). Модель ошибки: сдвиг битов в СЕРЕДИНЕ данных (бит-слип / циклический сдвиг), длина кадра сохраняется; «чек» сверяется как `check(искажённые данные) == check(оригинал)`. 200000 попыток на модель, данные 3/5/8 байт.
|
||||
|
||||
## 1. Твой исторический баг ВОСПРОИЗВЕДён
|
||||
Одиночный CRC8 (один полином) реально пропускает сдвиг в середине пакета. Примеры (данные → сдвиг → искажённые):
|
||||
- `26 0b 05` → `26 16 0a`: `crc1=0x78` совпал → **single ПРОШЁЛ**; двойная схема: `crc2 0xd8≠0x5c` → **поймала**.
|
||||
- `cc4fb8f633` → `cc5f71ec66`: `crc1=0x20` совпал → single прошёл; double поймала (`crc2 0xfc≠0x90`).
|
||||
- `b983315b416440c3` → `b983315e82c88186`: `crc1=0x3a` совпал → single прошёл; double поймала.
|
||||
|
||||
## 2. Частота пропуска (доля НЕобнаруженных сдвигов)
|
||||
| Схема | slip-delete | rotate-all | rotate-mid-window |
|
||||
|---|---|---|---|
|
||||
| **single** (1×CRC8, 8 бит) | 0.29–0.41 % | ~0.78 % | 0.55–0.78 % |
|
||||
| **double** (2×CRC8, 16 бит) — текущая | **0.007–0.015 %** | **0.025–0.03 %** | **0.008–0.026 %** |
|
||||
| nibble-fold (4+4 бит) | 0.76–0.80 % | ~1.58 % | 1.18–1.55 % |
|
||||
| nibble-trunc (4+4 бит) | 1.37–1.57 % | ~1.53 % | 1.22–1.57 % |
|
||||
|
||||
Вывод: **double примерно в 20–40× надёжнее single** и ловит практически все сдвиги, которые single пропускает. Это подтверждает, зачем добавляли второй полином (0x8C = зеркало 0x31 ловит «зеркальные» сдвиговые ошибки, слепые для 0x31).
|
||||
|
||||
## 3. Идея «склеить 2 байта в 1» (полбайта на полином) — ХУЖЕ, чем есть
|
||||
- **nibble-fold** (свернуть каждый CRC8 в 4 бита xor'ом) и **nibble-trunc** (взять по 4 бита) дают **0.6–1.6 % пропусков — это ХУЖЕ даже одиночного полного CRC8** и в ~50–150× хуже текущей двойной схемы.
|
||||
- Burst-ошибки (подряд искажённые биты — типичный IR-сбой: бит-слипы/всплески). Гарантия обнаружения = ширине контроля:
|
||||
- single 8 бит и double — надёжны на коротких burst (≥8 бит), эмпирически в выборке не пропускали и длиннее;
|
||||
- **nibble-fold** — гарантия ~4 бита (эмпирически до 7);
|
||||
- **nibble-trunc** — **пропускает даже ОДИНОЧНЫЙ бит** (усечение теряет старший ниббл) → так делать нельзя.
|
||||
|
||||
## 4. Рекомендация
|
||||
- **CRC — не то место, где стоит экономить байт.** Сжатие контроля до 1 байта повышает пропуск сдвигов/burst в ~50–150× (с ~0.01 % до ~1 %) — прямо в том классе ошибок, ради которого второй полином и вводили.
|
||||
- Если байт очень нужен — забирать его **не из CRC**, а из уже выявленного резерва: свободные `msgType` (3,5), «пустая» зона длины (компактные кадры), или переупаковка адресов/полей. 16-битный контроль (2×CRC8) сохранить.
|
||||
- Если всё же сжимать CRC до 1 байта — только **fold (xor нибблов)**, никогда не truncate; и принять ~1 % пропуска на сдвигах (в ~50–100× хуже текущего). Как отдельный компромисс — обсуждать вместе с обратной совместимостью.
|
||||
|
||||
(Обратную совместимость версий протокола обсудим отдельно — по запросу Даши.)
|
||||
Reference in New Issue
Block a user