Внешняя программа управляет отдельным слайсом как отдельным трансивером
через свой TCP-порт. COM-порты и 19090 остаются за главным приёмником
(слайс A) и не тронуты.
Протокол не дублируется: TCATEngine — чистый парсер поверх записи
callback'ов TCATContext, TCATTcpServer — транспорт поверх движка, поэтому
слайс-CAT = тот же движок с другим контекстом. Новый TCATSliceEndpoint
(движок + TCP-сервер на слот), массивом владеет TCATAdapter. Привязка к
СЛОТУ (буква B..G), не к Id: порт живёт, даже когда слайса нет (PS0).
Auto TX = «Auto Switch TX Slice» из SmartSDR CAT. Вся логика в одной точке
— TRadioController.RequestSliceTx, исполняется в потоке контроллера:
• пока кто-то уже в эфире (любой источник) — заявка игнорируется,
перехвата передачи нет никогда;
• без Auto TX слайс передаёт, только если уже выбран TX-источником;
• RX; снимает только СВОЮ передачу;
• TX-источник после отпускания остаётся на слайсе (как в SmartSDR).
На флаге слайса бейдж TX → AutoTX.
Частота слайса — TuneSliceInBand: свобода в пределах ВКЛЮЧЁННОГО диапазона
(трансвертер → его FreqBegin/FreqEnd, иначе band-план), другой диапазон —
отказ. Вне захваченной полосы окно DDC переезжает: доп. пан — центром на
цель (rfPanFreq → UI перекладывает флаги/шапку/зум-бар), пан 0 — центр
посередине между целью и главным VFO и только если оба влезают (общее
железное окно, главный приёмник не оглушаем).
Настройки: вкладка Slices (enable/порт 19091../Auto TX на слайс), персист
в секции cat + device-blob.
Попутно:
• ZZFL/ZZFH больше не заглушки — новые callback'и кромок фильтра
(у главного nil → прежний дефолт режима), хелпер SignedPad;
• FilterIdxFor, AGCModeToUI, BoardUtils.BandEdges;
• DSP-состояние слайса (NR/NB/SNB/ANF) зеркалится в TCtrlSlice — флаг
слайса рисовал нули и AGC главного;
• FUIReady в TMainForm.OnControllerState: адаптеры, создаваемые по ходу
FormCreate, больше не могут уронить старт рендером до постройки
виджетов (на этом падал Auto TX из настроек).
Проверено вживую: все порты 19091..19096 слушают, PS;/ZZFA;/MD;/ID;/SM0;/
ZZTX; отвечают; старт со всеми включёнными слайсами чист под gdb.
Документ — doc/CAT_SLICES.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
14 KiB
CAT-система EWSDR — статус реализации
Ветка разработки: feature/cat-commands-expansion.
Дата последнего обновления: 2026-06-26.
Документ описывает текущее состояние CAT-подсистемы EWSDR: архитектуру,
полный перечень реализованных команд, осознанные заглушки и план дальнейших
работ. За эталон протокола взят Thetis / PowerSDR (CATParser.cs,
CATCommands.cs, CATStructs.xml) — диалект Kenwood TS-2000 + расширения ZZ*.
1. Архитектура
CAT-транспорты ──► TCATEngine (парсер протокола) ──► TCATContext ──► TCATAdapter ──► TRadioController
serial (4×) CATEngine.pas (callbacks) CATAdapter.pas (ядро)
TCP-сервер разбор/формат команд мост, маршалинг
| Файл | Назначение |
|---|---|
CATEngine.pas (~2270 строк) |
Движок протокола: разбор <PREFIX><SUFFIX>;, формирование ответов, реализации всех команд Kenwood + ZZ*. Зависит только от RTL. |
CATAdapter.pas (~445 строк) |
Мост к TRadioController. Строит TCATContext: геттеры читают поля контроллера напрямую (CAT-поток, read-only), сеттеры/команды маршалятся в поток контроллера через FController.Invoke. Владеет движком + транспортами. |
CATSerial.pas (~313 строк) |
Менеджер до 4 последовательных портов (виртуальные COM-пары для rigctld/N1MM/WSJT-X). |
CATTcp.pas (~507 строк) |
TCP-сервер (Thetis-совместимый), управление клиентами по GUID (ZZGA/ZZGR). |
1.1 Принципы
- CAT — равноправный клиент контроллера наряду с
WebAdapterи GUI. Никаких обращений кMainForm. ТолькоTRadioController. - Потокобезопасность. Геттеры читают поля контроллера напрямую (атомарное
чтение в CAT-потоке). Сеттеры пишут параметр в scratch-поля
(
FSyncFreq/FSyncInt/FSyncBool) и зовутFController.Invoke(@SyncXxx)— GUI исполняет черезTThread.Synchronize, демон — своей очередью. TCATContext— плоская запись callback'ов (Get*/Set*/Do*). Чтобы пробросить новую возможность контроллера в CAT, достаточно: (1) добавить callback в запись, (2) реализовать в адаптере геттер/сеттер/sync, (3) зарегистрировать вTCATAdapter.Create, (4) переписать тело команды в движке.- Формат команд:
Расширенные
SET: <PREFIX><SUFFIX>; (suffix = значение) GET: <PREFIX>; (suffix пустой) Resp: <PREFIX><VALUE>; Err: ?; (неверный формат) | E; (ошибка выполнения)ZZ*дублируют Kenwood-команды и добавляют то, чего в Kenwood нет.
1.2 Статистика покрытия (ZZ-команды)
| Кол-во | |
|---|---|
Всего ZZ* в Thetis |
315 |
| Реально реализовано в EWSDR | 98 |
| Заглушки (отвечают валидным dummy, функции нет) | ~211 |
Совсем не обрабатываются (вернут ?;) |
7 |
Большинство заглушек закрыть нечем — в EWSDR физически отсутствует соответствующий тракт (см. §4).
2. Что сделано
2.1 Реализованные команды Kenwood (одиночный префикс)
| Команда | Функция | Маппинг на контроллер |
|---|---|---|
FA / FB |
VFO A / B частота (11 цифр, Гц) | Set/GetVfoA, Set/GetVfoB |
FR |
приёмный VFO (0/1) | Set/GetActiveVfo |
FT |
передающий VFO / split | → ZZSP |
FW / SH / SL |
ширина фильтра (индекс пресета) | Set/GetFilterIdx |
MD |
режим (Kenwood-код) | Set/GetMode |
GT |
режим AGC (0=FAST…4=OFF) | Set/GetAGCMode |
AG |
громкость AF | Set/GetVolume |
PC |
мощность TX 0–100 % | Set/GetDriveLevel |
NB |
шумоподавитель (NB) | Set/GetNBMode |
NT |
автонотч (ANF) | Set/GetANFEnabled |
SM |
S-метр (шкала Kenwood 0000–0030) | GetSMeter |
IF |
составной статус (37 байт) | freq/mode/tx/split |
ID |
идентификатор (TS-2000 = 019) | const |
PS |
питание/состояние | GetRunning |
TX / RX |
передача / приём | SetTransmitting |
BU / BD |
смена диапазона ±1 | DoBandUp/Down |
UP / DN / RU / RD |
шаг настройки ±1 | DoTuneUp/Down |
SQ |
шумоподавитель FM (шкала 0–255) | Set/GetSquelchLevel+On |
CN / CT |
CTCSS тон / вкл | Set/GetCTCSSTone, …On |
OF / OS |
репитер: offset / направление | Set/GetFMRptOffset, …Dir |
2.2 Реализованные расширенные ZZ* (выборочно, наиболее значимые)
VFO/режим/фильтр: ZZFA ZZFB ZZFI ZZFL ZZFH ZZFM ZZMD ZZFT ZZSP,
диапазоны: ZZBS ZZBU ZZBD ZZBA ZZBI ZZBM,
AGC/громкость/мощность: ZZGT ZZAG ZZPC ZZPD ZZAR,
шумодав/нотч: ZZNA ZZNB ZZNR ZZNS ZZNT ZZNL ZZNN,
FM: ZZSQ ZZSO ZZTA ZZTB ZZST, CTUN: ZZCN,
S-метр/телеметрия: ZZSM, шаги VFO: ZZAU ZZBP ZZSU ZZSA ZZSB,
передача: ZZTX ZZRX, сервис: ZZID ZZRV ZZGA ZZGR.
2.3 Сделано в ветке feature/cat-commands-expansion
Все команды ниже были заглушками и стали рабочими — функционал в
TRadioController уже существовал, но не был проброшен в CAT.
Группа 1 — Split TX
ZZSP,FT— split (TX на VFO-B),FR— выбор приёмного VFO, split-байт в составномIF.- В
TRadioControllerдобавлен публичный методSetSplit(TxOnB)(флагFSplitTxB+PushNetworkState+Changed(rfActiveVfo)). TX-частоту радио берёт изActiveTXFreqHz(учитывает split).
Группа 2 — FM Squelch
SQ(шкала Kenwood 0–255),ZZSQ(0–100 %),ZZSO(вкл/выкл).- Маппинг:
SetFMSquelch/SetFMSquelchLevel. Уровень>0 включает шумоподавитель.
Группа 3 — FM CTCSS
CT/ZZTA(вкл/выкл),CN(1-based тон 01–38),ZZTB(0-based 00–37).- Маппинг:
SetFMCTCSS/SetFMCTCSSTone, таблицаCTCSS_TONES[38].
Группа 4 — FM-репитер
OF(offset, 9 цифр Гц),OS(направление).- Трансляция направлений Kenwood (0=simplex,1=+,2=−) ↔ внутренние
RPT_NONE/MINUS/PLUS. Маппинг:SetFMRpt/SetFMRptOffset.
Группа 5 — FM tuning step
ZZST(индекс 00–03: 6.25/12.5/20/25 кГц). Маппинг:SetFMStep.
Доп. команды (вторая итерация)
| Команда | Что | Примечание |
|---|---|---|
ZZSO |
Squelch on/off | завершает группу squelch |
ZZNT |
ANF on/off | раньше ошибочно был алиасом NB |
ZZCN |
CTUN (click-tune) RX1 | новый callback Get/SetCTun → SetCTun |
ZZAR |
RX1 AGC-T / RF gain (±nnn) |
новый callback Get/SetAGCTop → SetAGCTop (кламп 20–120 dB) |
ZZAU/ZZBP |
сдвиг VFO A/B вверх на шаг nn (00–14) |
исправлен баг: были заалиашены на ZZFA/ZZAP |
ZZSU |
шаг активного VFO вверх | DoTuneUp |
Шкала шагов ZZAU/ZZBP — StepIdxToHz (зеркало Thetis Step2Freq):
1 Гц, 10, 25, 50, 100, 250, 500, 1к, 5к, 9к, 10к, 100к, 250к, 500к, 1 МГц.
Новые callback'и в TCATContext (этой ветки): split, squelch on/level,
CTCSS on/tone, FM repeater dir/offset, FM step, AGC-T, CTUN.
3. Что нужно сделать (актуально / есть чем закрыть)
Эти команды — заглушки, но соответствующая функция в EWSDR уже есть или легко добавляется. Приоритетные кандидаты:
| Команда(ы) | Что | Чем закрыть | Сложность |
|---|---|---|---|
ZZCU |
загрузка CPU (read) | телеметрия процесса | низкая |
ZZMY / ZZQR / ZZQS / ZZQM |
память каналов (запись/чтение/quick) | ChannelStore уже есть |
средняя |
ZZFD |
FM-девиация (radio button) | нужен публичный SetFMDeviation (сейчас только поле FFMDeviation) |
низкая |
ZZDM / ZZDA / ZZPO / ZZDY |
режим/усреднение/пик/порог спектра | UI-параметры спектра | средняя |
ZZAS |
RX2 AGC-T | — только при появлении RX2 | — |
Прежде чем реализовывать новую команду, сверяйся с форматом поля в
Thetis/.../CAT/CATStructs.xml(<nsetparms>/<ngetparms>) и телом метода вCATCommands.cs, чтобы ширина/знак значения совпадали.
3.1 Совсем не обрабатываются (вернут ?;)
ZZCU (CPU), ZZDY (DX threshold), ZZPK/ZZPL (речевой компрессор),
ZZQA/ZZQB (Quick Play/Rec), ZZVF (VAC stereo).
Из них реалистично добавить только ZZCU и (частично) ZZDY.
4. Осознанные заглушки (закрывать нечем)
Команды отвечают валидным dummy-значением для совместимости с управляющим ПО (rigctld, N1MM, WSJT-X, Log4OM), но функции в EWSDR нет. Это ~70 % всех заглушек.
| Область | Команды (примеры) | Причина |
|---|---|---|
| Второй приёмник RX2 / sub-RX | ZZAB ZZAS ZZBA ZZMB ZZOB, ext BF BG BR DO DQ DR OF OG OH OL SG SH SS |
один приёмник |
| TX-DSP тракт | mic gain ZZMG/MG, монитор ZZMO/MO, TX-EQ ZZEB/ER/ET, компрессор ZZPK/ZZPL/CF CI CL CM, two-tone ZZUS, VAC ZZVB/ZZVF |
нет обработки передачи |
| CW-кейер / CWX | ZZKM ZZKS ZZKY ZZCB ZZCD ZZCS, KY KS |
нет кейера |
| RTTY / DIGI | ZZRA ZZRL, ext RF RH RM RS RY |
нет RTTY-движка |
| RIT / XIT | RT XT RC RU RD (как RIT), ext RB RF RH |
нет смещения приёма |
| Diversity | ZZDA(div) ZZDB, ext DA |
нет диверсити-приёма |
| Спектр/водопад (внутр.) | ext SV SW SX SY SZ WT WU WV WW |
не управляется по CAT |
5. Транспорты
CAT дополнительных слайсов (свой TCP-порт на слайс B..G + Auto TX) вынесен в отдельный документ:
CAT_SLICES.md. Тот же движок, другой контекст; транспорты ниже принадлежат главному приёмнику (слайс A).
- Serial (
CATSerial.pas): до 4 портов, параметры (порт/скорость/биты/ чётность/стоп) изTGlobalSettings.CATSerial*, применяютсяTCATAdapter.ApplySettings. На текущей платформе сборки может быть{$DEFINE CAT_SERIAL_STUB}(см. начало файла) — проверить перед релизом. - TCP (
CATTcp.pas): сервер наCATTcpPort, включается флагомCATTcpEnabled. Клиенты идентифицируются GUID черезZZGA/ZZGR.
6. Как добавить новую CAT-команду (чек-лист)
- Сверить формат в
CATStructs.xml+CATCommands.cs(Thetis). - Если нужна новая возможность контроллера — есть ли публичный метод/поле
в
TRadioController? Если нет — добавить (по образцуSetSplit). - В
CATEngine.pas: добавить callback(и) вTCATContext,SafeGet*-хелпер для GET, переписать тело команды (CmdXXилиZZXX). - В
CATAdapter.pas: геттер (чтениеFController.F*), сеттер +SyncXX(черезInvoke), регистрация вTCATAdapter.Create. - Если команда
ZZ*ещё не в диспетчере — добавить веткуelse if ext = '..'. - Сборка-проверка:
lazbuild -B --ws=qt6 ewsdr.lpr(GUI-граф включает CAT; headless-демонewsdrdCAT не содержит).