From 2412aedc58bd2be0c5ea8fbff8aea9fde56157f2 Mon Sep 17 00:00:00 2001 From: Ayzen Date: Thu, 10 Sep 2026 12:37:31 +0300 Subject: [PATCH] switch controller: shorten the gap-minimum window to adapt to dwell changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Окно минимума было 4096 отсчётов, и это давало опасную асимметрию: при УМЕНЬШЕНИИ межстадийной паузы минимум падает мгновенно, а при УВЕЛИЧЕНИИ (подняли dwell_us или задержку PLL прибора) устаревшее маленькое значение живёт тысячи стадий. Порог оказывался ниже реальной межстадийной паузы, детектор границы срабатывал на каждой стадии и залипал ключ в положении A на пару развёрток. Окно сокращено до 16 отсчётов. Длинное окно не давало точности: пауза задаётся счётчиком в FPGA и детерминирована, а межстадийная — самая частая (три из четырёх при четырёх стадиях), так что минимум по десятку отсчётов уже равен ей. Зато теперь смена настроек подхватывается за считанные точки, и случайная короткая пауза от помехи вымывается так же быстро. IFBW на порог не влияет и влиять не может: он меняет длительность оцифровки (фронт-спад), а меряется пауза (спад-фронт). Плюс ключ переключается по спаду, когда оцифровка закончена, а детектор границы во время оцифровки неактивен — boundaryPending_ сбрасывается на фронте. Разобрано в README. Прошито и проверено: после сброса ядро в loop, Verified OK. Co-Authored-By: Claude Opus 5 (1M context) --- device_firmware/switch_controller/README.md | 23 +++++++++++++++++++ .../switch_controller/src/main.cpp | 17 +++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/device_firmware/switch_controller/README.md b/device_firmware/switch_controller/README.md index 5c62f1e..8c02b23 100644 --- a/device_firmware/switch_controller/README.md +++ b/device_firmware/switch_controller/README.md @@ -68,6 +68,29 @@ умноженный на `kBoundaryFactorNum / kBoundaryFactorDen` (по умолчанию 1.5). Пока минимум не набран, восстановление молчит — чередование корректно и без него. +### Надо ли перекалибровывать паузу под каждую настройку + +Нет, порог подстраивается сам, и вот что на него влияет, а что нет. + +**IFBW не влияет.** Он меняет длительность оцифровки, то есть интервал от фронта +до спада, а контроллер меряет паузу от спада до следующего фронта. Это разные +интервалы. Плюс переключение делается по спаду, когда оцифровка уже закончилась, +а детектор границы во время оцифровки вообще неактивен — так что сдвинуть ключ +посреди измерения он не может ни при каком IFBW. + +**Число точек, полоса, мощность не влияют** — паузы от них не зависят. + +**Влияют `dwell_us` и задержка PLL прибора**: они и есть время успокоения, то +есть сама пауза. Но подстройка на это и рассчитана — окно минимума короткое (16 +отсчётов), поэтому новое значение подхватывается за считанные точки. Ручной +калибровки не требуется. + +**Смена диапазона внутри развёртки безопасна.** На точках нижнего диапазона +прибор останавливает развёртку и работает с Si5351 по I2C — такие паузы намного +длиннее обычных. Логика от этого не ломается: остановка всегда происходит на +границе точки, перед стадией 0, а значит «длинная пауза → следующая стадия +нулевая → положение A» остаётся верным. + Множитель намеренно щедрый. Ложное срабатывание **посреди** точки испортит данные, а несрабатывание всего лишь отключит страховку. Если по отчёту видно, что границы не распознаются вообще (`point boundaries` близко к нулю при diff --git a/device_firmware/switch_controller/src/main.cpp b/device_firmware/switch_controller/src/main.cpp index 1f442f6..a59e661 100644 --- a/device_firmware/switch_controller/src/main.cpp +++ b/device_firmware/switch_controller/src/main.cpp @@ -63,9 +63,20 @@ constexpr bool kSwitchActiveLow = false; constexpr uint32_t kBoundaryFactorNum = 3; constexpr uint32_t kBoundaryFactorDen = 2; -// Окно, по которому берётся минимальная пауза. Двух окон хватает, чтобы -// оценка пережила смену настроек развёртки за пару секунд. -constexpr uint32_t kGapWindowSamples = 4096; +// Окно, по которому берётся минимальная пауза. Оно намеренно КОРОТКОЕ. +// +// Межстадийная пауза — самая частая: при четырёх стадиях на точку это три паузы +// из четырёх, при двух — одна из двух. Значит минимум даже по десятку отсчётов +// уже равен ей, и длинное окно не даёт никакой точности (пауза задаётся +// счётчиком в FPGA, она детерминирована). +// +// Зато длинное окно вредит. Если пауза ВЫРОСЛА — подняли dwell_us или задержку +// PLL прибора — устаревший маленький минимум держит порог ниже реальной +// межстадийной паузы, и детектор границы начинает срабатывать на каждой стадии, +// залипая ключ в положении A. С таким окном это самоустраняется за считанные +// точки, а не за развёртку. По той же причине короткое окно быстро вымывает +// случайную короткую паузу от помехи. +constexpr uint32_t kGapWindowSamples = 16; // Защита от шума: пауза короче этого не считается настоящей стадией. constexpr uint32_t kMinPlausibleGapMicroseconds = 2;