402 lines
32 KiB
Markdown
402 lines
32 KiB
Markdown
# Lab046: текущее состояние
|
||
|
||
## Статус
|
||
|
||
**LAB046 SOFTWARE OBJECT TRANSPORT = COMPLETE.**
|
||
|
||
**CONTINUOUS STREAM VALIDATION = PASS (NORMALIZED SOFT-SYMBOL LEVEL).**
|
||
|
||
**ПРОГРАММНАЯ ПРОВЕРКА НЕПРЕРЫВНОГО СЫРОГО IQ-ПОТОКА = PASS.**
|
||
|
||
**LAB046C HARDWARE RESULT = C.**
|
||
|
||
**RF TX COUNT = 1.**
|
||
|
||
**PREAMBLE CANDIDATES = 0. VALID FRAMES = 0. CRC PASS = 0.**
|
||
|
||
**OBJECT COMPLETE = NO.**
|
||
|
||
**POST-RUN TX-REFERENCE DIAGNOSTIC = 68/68 WAVEFORM TRACES DETECTED.**
|
||
|
||
**OFFICIAL RESULT CHANGED BY POST-RUN DIAGNOSTICS = NO.**
|
||
|
||
Lab046A/B остаются только программными лабами. Для Lab046C выполнен ровно один
|
||
заранее разрешённый непрерывный RF-сеанс без повтора. Ни JPEG, ни видео, ни
|
||
QPSK не запускались.
|
||
|
||
## Lab046C: подготовка аппаратного непрерывного объекта
|
||
|
||
Добавлен `experiments/lab046c_hackrf_bpsk_object.py`, который не меняет
|
||
протокол и только связывает готовые Lab043--Lab046B. Подготовительный режим
|
||
создаёт новый криптографически случайный объект 16384 байта вне Git, разбивает
|
||
его существующим Lab046 API на 68 фрагментов и последовательно записывает
|
||
68 полных Lab045 waveform в один `tx_stream.cs8`. Полные 313 670 400 байт не
|
||
удерживаются в ОЗУ одновременно; SHA-256 объекта и потока сохраняются в
|
||
`tx_metadata.json`.
|
||
|
||
24-секундный RX был запланирован как 192 000 000 complex cs8 samples,
|
||
384 000 000 байт. Такой capture даёт 0,75 с до передачи и около 3,65 с после
|
||
потока длительностью 19,6044 с. Приёмный API получает только путь к сырому
|
||
cs8 и PHY safety limits. Он читает файл через memmap окнами `complex64`, ищет
|
||
локальные PRBS7-кандидаты без обязательного global peak/second gate, получает
|
||
длину кадра из принятого PHY header и передаёт прошедшие CRC payload в
|
||
`ObjectAssembler`. TX start, границы 68 waveform, ожидаемое число фрагментов,
|
||
пакеты, coded bits и исходный объект приёмнику не передаются.
|
||
|
||
Аппаратный runner фиксирует доказанные serial и PHY-параметры, запускает RX
|
||
раньше TX, содержит один `TransmitGuard.register_transmit()` и cleanup в
|
||
`finally`. `--preflight-only` не регистрирует передачу и выполняет только
|
||
inventory/common-clock gate с последующим CLKOUT OFF. RF-режим требует два
|
||
отдельных CLI-ключа. После отдельной точной авторизации он был выполнен один
|
||
раз; повторный запуск не выполнялся и не разрешён.
|
||
|
||
Фактическая подготовка 1 сентября 2026 года создала внешний каталог
|
||
`C:\Users\user\Documents\SDR_Rover_Lab046_raw\20260901_145339_bpsk_object`:
|
||
|
||
- `tx_object.bin`: 16384 байта, SHA-256
|
||
`f7568a5d1a6dc5dd907fa1e971a171578315de740bd6788136f447e409fc6bf8`;
|
||
- `tx_stream.cs8`: 313670400 байт, 156835200 complex samples, 19,6044 с,
|
||
SHA-256 `8941eb231f1f2f99cde51f3cc5426472dbedf1a61675543e7774faec4b935f5e`;
|
||
- `tx_metadata.json`: `LAB046C_PREPARATION_ONLY`, `rf_tx_count = 0`.
|
||
|
||
Software gate подготовки: quick gate PASS с 482 тестами и 8 функциональными
|
||
лабами; полный `pytest` = 482 passed. Безопасный common-clock preflight также PASS:
|
||
MASTER reg29 `0x26`, SLAVE CLKIN `DETECTED` после 141,51 мс, SLAVE reg29
|
||
`0x26`; после проверки оба CLKOUT выключены, процессов `hackrf_transfer` нет,
|
||
`RF TX = 0` на этапе подготовки.
|
||
|
||
## Lab046C: первый аппаратный результат
|
||
|
||
Выполнен ровно один непрерывный RF TX всего `tx_stream.cs8`; автоматического
|
||
или ручного повтора не было. MASTER/TX
|
||
`000000000000000097c063dc323b97d3`, SLAVE/RX
|
||
`000000000000000097c063dc2e5327d3`, RF 1080 МГц, Fs 8 MS/s, BPSK 20 ксимв/с,
|
||
TX VGA 10 дБ, RX LNA/VGA 24/24 дБ, RF amp и bias OFF. Common clock прошёл
|
||
fail-closed gate: MASTER reg29 `0x26`, SLAVE CLKIN `DETECTED`, SLAVE reg29
|
||
`0x26`. Передача длилась 19,60632 с и полностью находилась внутри RX capture
|
||
длительностью 24,00386 с. USB-журналы чистые: TX underruns 0, RX overruns 0.
|
||
|
||
Независимый приёмник без TX oracle вернул официальный `RESULT C`:
|
||
|
||
- `PREAMBLE CANDIDATES = 0`;
|
||
- `VALID FRAMES = 0`;
|
||
- `PHY HEADER PASS = 0`;
|
||
- `CRC PASS = 0`;
|
||
- `OBJECT COMPLETE = NO`;
|
||
- восстановленный объект не создавался.
|
||
|
||
Рабочий порог PRBS7 оставался `0.65`; максимальная независимая корреляция
|
||
равна `0.126562`. Фоновая медиана мощности `-34.467535 dBFS`, кратковременный
|
||
максимум `-34.307678 dBFS`; максимальный средний подъём на интервале 19,6 с
|
||
всего `0.012049 dB`. Обычный power/PSD-анализ не показывает заметной передачи.
|
||
|
||
После завершения и фиксации независимого `RESULT C` выполнена разрешённая
|
||
read-only диагностика с TX reference. Она обнаружила следы всех 68 waveform с
|
||
точным периодом 2 306 400 samples. Нормированная корреляция в выровненных
|
||
позициях: min `0.065784`, median `0.089991`, max `0.122379`; контроль со
|
||
смещением: median `0.004275`, max `0.010075`. Медианное преимущество 26,46 дБ,
|
||
все 68 aligned значений выше максимума контроля.
|
||
|
||
Эта post-run диагностика использует знание TX только после официального
|
||
решения и **не** превращает опыт в PASS: `OBJECT TRANSPORT PASS` и
|
||
`LAB046C COMPLETE SUCCESS` не заявляются. TX-файл, его спектр около +50 кГц,
|
||
первый/средний/последний self-decode и runner проверены; дефекта формирования
|
||
или управления, объясняющего результат, не найдено. Сохранённый официальный
|
||
исход остаётся `LAB046C HARDWARE RESULT = C`, `RF TX COUNT = 1`,
|
||
`OBJECT COMPLETE = NO`.
|
||
|
||
## Назначение
|
||
|
||
Lab046 переходит от одиночной 256-байтной полезной нагрузки к передаче
|
||
произвольного бинарного объекта последовательностью независимо защищённых
|
||
радиокадров. Два уровня строго разделены и не смешиваются:
|
||
|
||
- **Уровень 1 (внутри одного кадра) — Lab045.** Свёрточный код R=1/2 K=7,
|
||
перемежитель, мягкий декодер Витерби, CRC пакета. Исправляет неизвестные
|
||
битовые ошибки внутри принятого кадра.
|
||
- **Уровень 2 (большой объект) — существующий `protocol/image_fragments`.**
|
||
Фрагментация, нумерация фрагментов, идентификатор объекта, сборка. Собирает
|
||
объект из нескольких независимо принятых кадров.
|
||
|
||
Новый код в `experiments/lab046_bpsk_object_transport.py` минимален: он
|
||
связывает два готовых уровня и добавляет fail-closed сборщик объекта.
|
||
Отдельный модуль формата фрагмента НЕ создавался: переиспользован 12-байтовый
|
||
заголовок `image_fragments` (`>IHHI`: object_id u32, fragment_index u16,
|
||
fragment_count u16, original_size u32).
|
||
|
||
## Аудит: что переиспользовано, чего не хватало, минимальный новый слой
|
||
|
||
1. **Переиспользовано.** `protocol/image_fragments` уже даёт нужную семантику
|
||
фрагмента: идентификатор объекта, индекс, число фрагментов, общий размер,
|
||
а также fail-closed `reassemble_image` (несовпадение id/count/size,
|
||
конфликтующие дубликаты, недостающие фрагменты, финальная проверка длины).
|
||
Слой Lab045 даёт кадр целиком: `build_transmission_plan`,
|
||
`analyze_post_preamble_soft`, `simulate_soft_channel`, диагностику pre/post-FEC.
|
||
2. **Чего не хватало.** Не было (а) упаковки фрагмента в 256-байтную нагрузку
|
||
Lab045 с обрезкой добивки на приёме по длине из заголовка и (б) сборщика,
|
||
который принимает по одному независимо декодированному кадру и **никогда не
|
||
бросает** на плохом входе, возвращая `object_complete = False` вместо
|
||
фиктивного объекта.
|
||
3. **Минимальный новый слой.** `recover_fragment_from_payload` (fail-closed
|
||
декод + обрезка добивки) и класс `ObjectAssembler` (offer/missing/complete/
|
||
recovered). Erasure-код 12+3 GF(256) (`protocol/packet_erasure_fec`) НЕ
|
||
использован и НЕ изменён — он остаётся будущим расширением для потери целых
|
||
фрагментов, а не для битовых ошибок (это работа свёрточного кода).
|
||
|
||
После этого Lab046A закрыла оставшийся пробел: до неё Lab046 передавала каждый
|
||
кадр отдельным вызовом и выбирала его из TX-плана по известному индексу. Функции
|
||
поиска нескольких кадров в одном потоке не было. Теперь
|
||
`scan_continuous_soft_stream` получает только один массив soft-символов,
|
||
самостоятельно ищет PRBS7 после монотонного cursor, проверяет защищённый PHY
|
||
header, вычисляет длину coded body из принятого packet length, выполняет готовые
|
||
FEC/CRC Lab045 и передаёт принятый fragment в `ObjectAssembler`.
|
||
|
||
TX offsets, список длин кадров, ожидаемое число 68, порядок/индексы TX,
|
||
исходный объект, TX packets и coded bits scanner-у не передаются. TX-side
|
||
`frame_starts` остаётся только в генераторе потока и используется тестом для
|
||
сравнения уже после независимого receive.
|
||
|
||
## Граница доказательства Lab046A
|
||
|
||
Lab046A работает на уровне **одного непрерывного нормализованного soft BPSK
|
||
stream** (`float32`). Это разрешённый интерфейс после уже проверенного в Lab045
|
||
sample-level front-end: PRBS7 detection, matched filtering, timing, CFO и
|
||
phase/polarity recovery. Внутри нового длинного теста эти sample-level операции
|
||
заново не моделируются для каждого кадра. Поэтому результат доказывает
|
||
самостоятельный поиск границ, header-driven длину, FEC/CRC и сборку объекта в
|
||
непрерывном soft stream, но не является аппаратной или непрерывной IQ-проверкой.
|
||
|
||
Каждый фрагмент содержит полный активный Lab045 PHY frame: 1280 бит PRBS7,
|
||
144 бита защищённого header и 4300 coded bits. Точная полная sample-level форма
|
||
с guard и хвостом ФРК учитывается как 2 306 400 отсчётов на кадр, однако все
|
||
156 835 200 IQ-отсчётов одновременно в памяти не создаются. Это намеренное
|
||
ограничение памяти, а не использование известных границ приёмником.
|
||
|
||
Scanner fail-closed:
|
||
|
||
- cursor всегда растёт, после принятого кадра переносится за вычисленный конец;
|
||
- все PRBS7 candidates выше порога рассматриваются в порядке stream; после
|
||
принятого кадра cursor переносится за вычисленный конец и не даёт
|
||
декодировать этот кадр повторно;
|
||
- плохой header, усечённое body, ошибка FEC/CRC отвергают candidate, но поиск
|
||
следующего продолжается;
|
||
- `MAX_FRAMES` и `MAX_SEARCH_ITERATIONS` дают явную причину остановки, а не
|
||
частичный объект, объявленный полным;
|
||
- scan продолжается до конца capture и не останавливается на числе 68.
|
||
|
||
## Сценарии continuous stream
|
||
|
||
| Сценарий | Получено |
|
||
|---|---|
|
||
| Идеальный, кадры подряд | candidates 68, valid headers 68, FEC PASS 68, CRC PASS 68/68, fragments 68, complete=True, SHA совпал, 0 байт-ошибок |
|
||
| Фон до/между/после | 37/37/43 soft-символа, valid frames 68, complete=True, SHA совпал |
|
||
| Непрерывный AWGN, sigma=0.40, seed=46001 | frames 68, pre-FEC 1791, post-FEC 0, CRC 68/0, complete=True, SHA совпал |
|
||
| Valid-looking preamble + bad protected header | candidates 71, rejected 3, последующие valid frames 68, complete=True, SHA совпал |
|
||
|
||
Фон между кадрами добавлен только после кадров 7, 23 и 51: 11, 19 и 7
|
||
soft-символов, всего 37. В baseline дополнительного inter-frame gap нет.
|
||
Отдельный тест с валидным header для 12-байтного packet и повреждённым body
|
||
проверяет, что scanner берёт длину именно из принятого header, отвергает этот
|
||
candidate и затем находит настоящий кадр.
|
||
|
||
Verifier нашёл опасный вариант прежнего глобального non-maximum suppression:
|
||
более сильный ложный PRBS7 peak мог удалить более поздний настоящий старт
|
||
кадра. Поэтому suppression убран из списка кандидатов, а добавленный
|
||
регрессионный тест проверяет, что ложный peak не скрывает настоящий кадр.
|
||
|
||
## Lab046B: непрерывный сырой IQ-поток
|
||
|
||
Lab046B закрывает только программный sample-level пробел Lab046A. Новый
|
||
`experiments/lab046b_continuous_iq.py` формирует пять полных Lab045 waveform с
|
||
PRBS7, защищённым PHY header, interleaved convolutional body, BPSK, RRC и
|
||
guards, размещает их в одном `complex64` массиве и передаёт scanner-у только
|
||
этот массив. TX start offsets, длины TX waveform, номера кадров, payload,
|
||
packet и coded bits в `scan_continuous_iq` не передаются.
|
||
|
||
Переиспользованы существующие функции Lab043-Lab045: BPSK/RRC waveform,
|
||
PRBS7 reference, normalized sliding correlation, локальное уточнение sample
|
||
start, matched filter, preamble-only timing, non-data-aided CFO и комплексный
|
||
gain, `normalized.real`, защищённый PHY header, deinterleave, soft Viterbi и
|
||
protocol CRC. Новый слой только перечисляет локальные IQ-кандидаты, вызывает
|
||
этот тракт на окне кандидата и монотонно продолжает поиск.
|
||
|
||
Глобальное требование «главный пик значительно выше второго» не используется.
|
||
В идеальном пятикадровом опыте peak/second для настоящих кадров лежит около
|
||
0 dB, поскольку вторым пиком является другой настоящий кадр; тем не менее все
|
||
пять кадров приняты. Все локальные максимумы выше порога сохраняются, а после
|
||
CRC PASS cursor переносится за вычисленный по принятому header конец кадра.
|
||
После плохого кандидата cursor также строго растёт, но следующий кандидат не
|
||
скрывается. Выход ограничен `MAX_FRAMES` и `MAX_SEARCH_ITERATIONS`.
|
||
|
||
### Фактические сценарии Lab046B
|
||
|
||
| Сценарий | Получено |
|
||
|---|---|
|
||
| Идеальный continuous IQ | PRBS7 candidates 32, processed 5, accepted 5, rejected 0, PHY/FEC/CRC 5/5/5, CRC FAIL 0, sample offset error 0 для всех |
|
||
| CFO + phase + amplitude | внесено 0.2 Hz / 0.7 rad / 0.65; медианная оценка 0.200003768 Hz / 0.699634288 rad; CRC 5/0 |
|
||
| Комплексный AWGN | sigma=0.17, seed=46002; accepted 5, pre-FEC 0, post-FEC 0, CRC 5/0 |
|
||
| PRBS7 + неверный PHY header перед настоящим кадром | candidates 11, processed 8, rejected 7, следующий настоящий кадр найден, CRC 1/0 |
|
||
|
||
Начало первого waveform: sample 137, то есть не sample 0 и не граница сетки
|
||
400 samples/symbol. Дополнительные gaps: 211/353/587/809 samples. Найденные
|
||
фазы символьной выборки: 137/348/301/88/97 samples modulo 400. Точные TX
|
||
offsets используются только постфактум после CRC PASS; ошибки обнаруженного
|
||
start во всех пяти случаях равны нулю.
|
||
|
||
Шумовая точка зафиксирована честно. Первый разумный однокадровый запуск при
|
||
sigma=0.12 дал CRC PASS, но 0 pre-FEC ошибок. Выполнена одна разрешённая
|
||
обоснованная корректировка до sigma=0.17; она также дала 0 pre-FEC ошибок и
|
||
CRC PASS. Дальнейший подбор не выполнялся. Поэтому этот сценарий доказывает
|
||
устойчивый многокадровый IQ receive с комплексным детерминированным шумом, но
|
||
не является новым доказательством реального исправления ошибок FEC; такое
|
||
доказательство уже относится к аппаратной Lab045.
|
||
|
||
Основной массив содержит 11 534 330 `complex64` отсчётов и занимает
|
||
92 274 640 байт (88.0 MiB). Пять waveform занимают 11 532 000 samples, остальное
|
||
— leading/gaps/trailing. Полные CFO/phase-corrected копии не создаются:
|
||
первичный поиск работает с decimated stream, а matched filtering и soft
|
||
extraction выполняются на локальном окне одного кандидата. Это размер именно
|
||
основного IQ-массива, а не peak RSS процесса: RRC/FFT, локальный matched stream
|
||
и временные массивы SciPy требуют дополнительную рабочую память.
|
||
|
||
## Память continuous stream
|
||
|
||
Основной 68-кадровый soft stream содержит 389 232 значения `float32` и занимает
|
||
1 556 928 байт (1,485 MiB). Массив correlation scores занимает 1 551 812 байт,
|
||
накопленная энергия `float64` — 3 113 864 байта. FFT и denominator создают
|
||
временное рабочее пространство, размер которого зависит от SciPy, но стратегия
|
||
остается в пределах десятков MiB, а не нескольких GiB. Для сравнения, один
|
||
материализованный continuous `complex64` IQ stream из 156 835 200 отсчётов
|
||
занял бы около 1,17 GiB ещё до временных копий.
|
||
|
||
## Детерминированный объект
|
||
|
||
- Размер **16384 байта (16 KiB)**. Это не JPEG, а воспроизводимый
|
||
псевдослучайный поток `numpy.random.default_rng(seed).integers(0,256,...)`.
|
||
- **Выбор размера.** 16 KiB — компромисс: достаточно велик, чтобы кадров было
|
||
много (68) и учёт фрагментации/сборки был содержательным, но достаточно мал,
|
||
чтобы программный прогон 68 кадров с мягким Витерби считался секунды. Ровный
|
||
размер (не кратный 244) специально оставляет короткий последний фрагмент.
|
||
- Seed объекта по умолчанию `46`, идентификатор объекта `0x4C303436` («L046»).
|
||
- SHA-256 объекта по умолчанию:
|
||
`748013b5f670c82bd52650be5454555355dbd8528538753df4558f1c3408d515`.
|
||
- Объект не сохраняется в Git (крупный генерируемый артефакт); при
|
||
необходимости он детерминированно восстанавливается по seed.
|
||
|
||
## Раскладка нагрузки пакета
|
||
|
||
Полезная нагрузка Lab045 остаётся 256 байт (доказанная рабочая точка):
|
||
|
||
[12 байт метаданных фрагмента][244 байта данных фрагмента]
|
||
|
||
`FRAGMENT_DATA_SIZE = 256 − 12 = 244`. Последний фрагмент короче; его нагрузка
|
||
добивается нулями до 256 байт перед Lab045 и обрезается на приёме по длине,
|
||
вычисленной **только из полей заголовка** (`expected_fragment_data_length`).
|
||
Для 16384 байт последний, 68-й фрагмент несёт 36 байт данных (16384 − 67·244).
|
||
|
||
## Fail-closed сборка (без оракула)
|
||
|
||
Приёмник независим: переданный объект и TX-биты не используются ни для приёма
|
||
пакета, ни для FEC, ни для восстановления метаданных, ни для решения о
|
||
завершении объекта. Сравнение с оригиналом делается только в диагностике,
|
||
**после** независимого CRC-решения и независимой сборки.
|
||
|
||
`ObjectAssembler.offer(fragment)` возвращает `accepted/duplicate/conflicting/
|
||
rejected` и никогда не бросает. Отвергаются: чужой object_id, несогласованные
|
||
count/original_size, невозможный индекс, конфликтующий дубликат (тот же индекс,
|
||
другие данные), malformed/усечённые метаданные. Идентичный дубликат
|
||
игнорируется. Пока не собраны все индексы, `object_complete()` = False, а
|
||
`recovered_object()` = None — фиктивный объект не создаётся. Поле original_size
|
||
проверяется на обе границы (`(count−1)·244 < original_size ≤ count·244`), чтобы
|
||
абсурдное значение не управляло размером аллокаций.
|
||
|
||
## Программные сценарии (seed фиксирован)
|
||
|
||
| Сценарий | Условие | Ожидалось | Получено |
|
||
|---|---|---|---|
|
||
| A. Идеальный канал | шума нет | объект точен | complete=True, sha совпал, 0 байт-ошибок, CRC 68/0 |
|
||
| B. Распределённые битовые ошибки | гауссов шум sigma=0.40 | pre-FEC>0, post-FEC=0, все CRC PASS, объект точен | pre-FEC 1805, post-FEC 0, CRC 68/0, complete=True, sha совпал |
|
||
| C. Приём не по порядку | обратный порядок кадров | объект точен | complete=True, sha совпал |
|
||
| D. Дубликаты фрагментов | повтор кадров 0,2,2 | объект точен, дубликаты учтены | duplicates≥1, complete=True, sha совпал |
|
||
| E. Один потерянный фрагмент | кадр 1 не дошёл | OBJECT COMPLETE = NO | complete=False, 1 в missing, recovered SHA = None |
|
||
| F. Повреждённый пакет | инверсия coded-потока кадра 0 | CRC FAIL, объекта нет | crc_fail≥1, complete=False, recovered SHA = None |
|
||
|
||
Сценарий B — честная точка: уровень sigma выбран так, чтобы мягкий Витерби
|
||
исправлял **все** 68 кадров (при sigma=0.45+ отдельный кадр не декодируется, и
|
||
без erasure-FEC объект оказывается неполным — это по сути сценарий E, а не
|
||
подгон). Числа не подкручивались ради прохождения: до FEC присутствуют 1805
|
||
реальных ошибок кодированных бит, после мягкого Витерби — ноль, объект
|
||
побитово точен.
|
||
|
||
## Метрики (объект 16384 байта, идеальный канал)
|
||
|
||
| Величина | Значение |
|
||
|---|---:|
|
||
| Размер объекта | 16384 байта |
|
||
| SHA-256 объекта | `748013b5…3408d515` |
|
||
| Размер метаданных фрагмента | 12 байт/пакет |
|
||
| Размер данных фрагмента | 244 байта (последний 36) |
|
||
| Число фрагментов | 68 |
|
||
| Размер протокольного пакета | 268 байт (256 нагрузка + 8 header + 4 CRC) |
|
||
| Число BPSK-кадров | 68 |
|
||
| Всего информационных BPSK-символов | 389 232 (5724 × 68) |
|
||
| Всего отсчётов формы сигнала | 156 835 200 (2 306 400 × 68) |
|
||
| Baseline: дополнительный inter-frame gap | 0 отсчётов |
|
||
| Baseline: полная длительность | 19,604400 с |
|
||
| Baseline: полезный goodput | 835,7 байт/с = 6,685846 кбит/с |
|
||
| Фоновый тест: leading/inter-frame/trailing | 14 800 / 14 800 / 17 200 отсчётов |
|
||
| Фоновый тест: полная длина и длительность | 156 882 000 отсчётов, 19,610250 с |
|
||
| Фоновый тест: фактический goodput | 6,683852 кбит/с |
|
||
| Полезных бит на символ | ≈ 0,337 |
|
||
|
||
Учёт кадра совпадает с Lab045: 2144 информационных бита, 6 tail-бит, 4300
|
||
кодированных бит (R=1/2), перемежитель 4300, PHY header 48→144 бит (×3),
|
||
преамбула PRBS7 1280 бит, итого 5724 информационных символа кадра. Форма
|
||
сигнала добавляет 42 символо-времени (32 нулевых guard + 10 хвост ФРК,
|
||
`shape_frame_like_lab042`, режим `full`): 5766 символо-времён = 2 306 400
|
||
отсчётов = 288,3 мс на кадр при 8 MS/s.
|
||
|
||
### Разбор накладных расходов
|
||
|
||
- **Фрагментация (уровень 2):** 12 байт метаданных на пакет × 68 = 816 байт.
|
||
- **Протокольный header+CRC (уровень 1):** 12 байт на пакет × 68 = 816 байт.
|
||
- **Свёрточный код R=1/2:** удваивает число кодированных бит (2144→4300 с tail).
|
||
- **PHY преамбула и защищённый header:** 1280 + 144 = 1424 бита на кадр.
|
||
- **Guard/фильтр:** 42 символо-времени на кадр (32 guard + 10 хвост ФРК).
|
||
- **Добивка последнего фрагмента:** 208 нулевых байт (только 68-й кадр).
|
||
|
||
Goodput 6,69 кбит/с — это честная baseline при 20 ксимв/с с полной
|
||
преамбулой и guard на каждый кадр; в реальной серии кадров преамбула на кадр
|
||
доминирует в накладных расходах, и это направление для будущей оптимизации,
|
||
а не дефект.
|
||
|
||
## Фактические программные результаты
|
||
|
||
- Новый набор `tests/test_lab046_bpsk_object_transport.py`: все проверки
|
||
проходят (фрагмент туда-обратно, короткий последний фрагмент, чужой
|
||
object_id, невозможный индекс, несогласованный счётчик, усечённые и абсурдные
|
||
метаданные без крупной аллокации, полный тракт PHY для сценариев A–F,
|
||
отсутствие оракула, последовательный continuous scan, rejected candidate,
|
||
MAX_FRAMES/MAX_SEARCH_ITERATIONS, регрессия против удаления настоящего кадра
|
||
ложным PRBS7 peak, детерминизм и SHA объекта).
|
||
- Полный тракт `объект → фрагменты → кадр Lab045 → канал → приём → сборка`
|
||
проверен для всех шести сценариев значениями выше.
|
||
|
||
## Software gate Lab046B на момент его фиксации
|
||
|
||
- `python tools/quick_gate.py`: PASS; 468 тестов ядра, 7 функциональных
|
||
проверок лабораторий выполнено, 13 штатно пропущено.
|
||
- `python -m pytest tests/ -q`: 468 passed, 0 failed, 0 errors, 0 skipped.
|
||
Единственное предупреждение связано с отсутствием прав на создание
|
||
`.pytest_cache`; на выполнение и результат тестов оно не повлияло.
|
||
- `git diff --check`: чист.
|
||
|
||
Актуальный общий gate после добавления Lab046C указан в начале документа.
|
||
|
||
## Ограничения и следующий шаг
|
||
|
||
Для Lab046A/B RF TX = 0; первый аппаратный Lab046C завершён с RESULT C и одним
|
||
RF TX без повтора. Erasure-код 12+3 GF(256) не задействован. Порог PRBS7,
|
||
gain, PHY, FEC и detector после результата не менялись. Следующий этап
|
||
определяется отдельной постановкой; новый RF-сеанс автоматически не разрешён.
|