- README §12.8: таблица gate (PER0 3/5/14, PER2 1-11 при FBGAIN -80..0,
доставка STATUS 0% при <=-40, плато ~50% при -20..0), вердикт
- NOTES §2.2: разбор плато 50% (структурное: fb-RX платы A глохнет в её же
TX-бёрсты, duty 57% при -p 4000), окно fb-TX -20..-10, пересмотр критерия
доставки (STATUS кумулятивен, 5 Гц эффективных достаточно), TDD не нужен
- BENCHMARK.md: framegen 570.6 мкс/кадр 255 Б -> STATUS 10 Гц ~0.6% ядра
Четыре workflow по образу и подобию runner-tests/examples, уровень C:
- 01-smoke — runner жив, какие инструменты/либы есть в образе
- 02-guardrails — grep-страж жёстких правил CLAUDE.md (rate 1920000,
header_len=12 на TX и RX, только local:, static/ARM-флаги, нет тяжёлых
зависимостей); логика в scripts/ci_guardrails.sh, гоняется и локально
- 03-gftest — make gftest: нативная (не кросс-) сборка group_fec.c
с -DGF_SELFTEST, 774 400 кейсов GF(256)
- 04-cross-build — make check-env && make all под armhf; приёмка
ARM-тулчейна проверяется реальной компиляцией + разбором e_machine
из ELF-заголовка (od), а не command -v — на Alpine/musl наличие
файла ничего не доказывает, если это glibc-бинарь без ld-linux
E2E по радио и деплой на платы сознательно вне CI — нужны две живые
Pluto-платы, это остаётся ручным чек-листом (scripts/test_file_link.sh).
Групповой FEC над GF(256), RAID-6-стиль: 16 кадров данных + P(⊕) + Q(Σgⁱ·dᵢ)
закрывают до 2 стёртых кадров на группу. Потеря (пропуск seq или битый CRC) —
это стирание с известной позицией, поэтому 2 паритета оптимальны (overhead 12.5%,
~99% передач 10 МБ байт-в-байт при PER 0.26%).
- src/group_fec.{c,h}: GF(256) polynom 0x11d, gf_encode/gf_recover + self-test
(make gftest, нативный cc). Восстановление 1 стирания через P или Q, 2 — P+Q.
- transmitter.c: флаг -G, вынесен tx_frame(); копит группу, шлёт k данных +
P/Q с флагами в hdr[11]. Мета паритета: k′ + длина хвостового кадра.
- receiver.c: групповой ассемблер в потоке C, автодетект по hdr[11], финализация
группы на смене базы seq и на выходе потока. Счётчики Rec/GrpF в статистике.
- hdr[11] (был резерв): bit7 режим, bit6 паритет, bit5 Q, bits4-0 idx. RS/CRC
слой прозрачен — геометрия кадра не тронута, PHY-бенчмарк не требуется.
- test_file_link.sh: GROUPFEC=1 по умолчанию (TX -G, RX автодетект).
README §12.7 + перенумерация роадмапа — отдельным коммитом после верификации.
По диагностике §12.5: sync+RS на ядре 0 — узкое место (sync сам
1.65 Msps < 1.92, RS 26% эфира). Разделено на 3 потока/2 ядра:
- A (ядро 1): refill+convert → кольцо сэмплов (без изменений)
- B (ядро 0): ТОЛЬКО ofdmflexframesync_execute; callback худеет до
копии сырого кадра в новую очередь fq (SPSC, 32 слота, drop-newest)
- C (ядро 1): из fq → seq-детектор + RS + CRC-поверх-RS + запись
Статистику печатает main (C спит без кадров). Новый столбец FQdrp.
Завершение: A→ring.eof→B дочищает→fq.eof→C дочищает→join A,B,C.
Счётчики без разделяемых записей (B-owned / C-owned), телеметрия в
main — косметически неатомарна, итог после join корректен.
Цель: p_min ~8→~1.5-2 мс. PHY/TX/makefile не тронуты.
По данным §12.5 (sync+RS на одном ядре — узкое место) роадмап
скорректирован: п.5 — 3-стадийный конвейер (RS на ядро 1, p_min
~1.3 мс), FDD+ARQ сдвинут на п.6, туннель/видео на 7/8.
§9 — статусы техдолга: #1,#2,#3,#4,#5,#7 → ✅ исправлено; #6 → ⚙️ частично (детектор seq есть, ARQ нет).
§10 — дорожная карта: этап 2 закрыт
§12 (новый раздел «Журнал ввода в строй») — таблица результатов BIST-loopback (2 мс: 76/100, md5 ✗; 20 мс: 100/100, md5 ✅) с выводом, что пайплайн исправен, а потери на 2 мс — CPU-contention одной платы
- src: transmitter, receiver, ofdm_bench, common (libiio local: + liquid-dsp)
- scripts: кросс-сборка зависимостей, деплой scp -O, e2e-тест с md5
- docs: бенчмарк CPU (выбор rate 1.92 MSPS), грабли FDD/регуляторика
- все текстовые файлы нормализованы в LF (.gitattributes принудительно):
CRLF в toolchain.env/makefile ломал source и make на Linux
- .vscode: IntelliSense в режиме linux-gcc-arm, заголовки из .xarm/include
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>