Files
ewsdr/doc/CAT_STATUS.md
T
ew8bakandClaude Opus 5 9b77809a73 fix(tci,cat): резерв бюджета переезжает писателю; строгий разбор полей ZZ-команд
Три замечания по 79132f1.

1. [P2] Лимит памяти рекордеров обходился при SAVE. Take собирал сплошную
   копию записи, а DropData тут же возвращал исходные куски в бюджет —
   копия жила дальше в асинхронном TTCIWavWriter уже неучтённой. Один SAVE
   поднимал настоящее потребление примерно вдвое, а на медленном или
   зависшем сетевом каталоге очередь writer-потоков и их буферов росла
   мимо потолка вовсе. Теперь копия НАСЛЕДУЕТ резерв кусков, из которых
   собрана: Take отдаёт его out-параметром Reserved, писатель держит до
   конца записи и отпускает в ReleaseData — ровно один раз, сколько бы
   путей выхода ни было у Execute. Новых денег у бюджета копия не берёт,
   так что потолок теперь считает и очередь сохранений тоже.

2. [P2] Пять ZZ-команд проверяли длину поля, но не содержимое:
   StrToIntDef(s, 0) превращал любую нечисловую пару символов в индекс 0.
   ZZBSxx; переключал диапазон на нулевой вместо ?;, ZZBMxx; и
   ZZAUxx;/ZZBPxx; двигали VFO, ZZFIxx; выбирал фильтр 0. Разбор приведён
   к идиоме ZZFL/ZZFH: TryStrToInt, иначе ошибка формата.

3. [P3] Сообщение об отказе запуска TCI звало в Settings → Advanced, а
   настройки там уже не живут — вкладка CAT (переезд был в de0830f).

Стенд 194/194: Take отдаёт резерв размером с копию, после Take занят ровно
он, писатель возвращает его по окончании. Без фикса первая проверка
краснеет. GUI (--ws=qt6) и демон зелёные. doc/TCI.md §2.5 и сводка стенда,
doc/CAT_STATUS.md — таблица разбора.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 12:50:21 +03:00

30 KiB
Raw Blame History

CAT-система EWSDR — статус реализации

Ветка разработки: feature/cat-tx-cw. Дата последнего обновления: 2026-08-17.

Документ описывает текущее состояние 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 (~2740 строк) Движок протокола: разбор <PREFIX><SUFFIX>;, формирование ответов, реализации всех команд Kenwood + ZZ*. Зависит только от RTL.
CATAdapter.pas (~910 строк) Мост к TRadioController. Строит TCATContext: геттеры читают поля контроллера напрямую (CAT-поток, read-only), сеттеры/команды маршалятся в поток контроллера через FController.Invoke. Владеет движком + транспортами.
CATSerial.pas (~330 строк) Менеджер до 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 ~120
Заглушки (отвечают валидным dummy, функции нет) ~190
Совсем не обрабатываются (вернут ?;) 5

Подписи всех 315 команд сверены с CATCommands.cs (см. §2.5) — комментарию у заглушки теперь можно верить. Оставшиеся заглушки в большинстве закрыть нечем: в EWSDR физически отсутствует соответствующий тракт (см. §4).

1.3 Осознанные отклонения от Thetis

Три места, где EWSDR намеренно расходится с эталоном. Больше таких нет.

Команда У Thetis У нас Почему
ZZBS код диапазона, 3 символа (160/040/WWV) индекс диапазона, 2 цифры формат заложен давно, на нём уже сидят клиенты
ZZMN пресеты DSP-фильтров, 180 символов имя режима по номеру имён режимов в протоколе нет вовсе, а ZZML опирается на эту команду
ZZST размер шага настройки (read-only) индекс шага FM (00..03) глобального шага у EWSDR нет, слот иначе мёртв; у шага FM своей команды в протоколе нет

Плюс одно ограничение диапазона, не формата: ZZCD (hang-time break-in) эталон принимает в 150..5000 мс, у нас потолок 2000 — столько же стоит в настройках телеграфа и уходит в поле HangDelay пакета DUC Specific. Значения выше подрезаются, как и всё прочее у Thetis.


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 0100 % Set/GetDriveLevel
NB шумоподавитель (NB) Set/GetNBMode
NT автонотч (ANF) Set/GetANFEnabled
SM S-метр (шкала Kenwood 00000030) 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 ZZVS, диапазоны: ZZBS ZZBU ZZBD, AGC/громкость/мощность/аттенюатор: ZZGT ZZAG ZZMA ZZPC ZZAR ZZRX, шумодав/нотч: ZZNA ZZNB ZZNR ZZNS ZZNT ZZNN, FM: ZZSQ ZZSO ZZTA ZZTB ZZST, CTUN: ZZCN, S-метр/телеметрия: ZZSM ZZRV, память: ZZMV, шаги VFO: ZZAU ZZBP ZZBM ZZSU ZZSA ZZSB, передача: ZZTX, сервис: ZZID 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 0255), ZZSQ (0100 %), ZZSO (вкл/выкл).
  • Маппинг: SetFMSquelch / SetFMSquelchLevel. Уровень>0 включает шумоподавитель.

Группа 3 — FM CTCSS

  • CT/ZZTA (вкл/выкл), CN (1-based тон 0138), ZZTB (0-based 0037).
  • Маппинг: 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 (индекс 0003: 6.25/12.5/20/25 кГц). Маппинг: SetFMStep.

Доп. команды (вторая итерация)

Команда Что Примечание
ZZSO Squelch on/off завершает группу squelch
ZZNT ANF on/off раньше ошибочно был алиасом NB
ZZCN CTUN (click-tune) RX1 новый callback Get/SetCTunSetCTun
ZZAR RX1 AGC-T / RF gain (±nnn) новый callback Get/SetAGCTopSetAGCTop (кламп 20120 dB)
ZZAU/ZZBP сдвиг VFO A/B вверх на шаг nn (0014) исправлен баг: были заалиашены на ZZFA/ZZAP
ZZSU шаг активного VFO вверх DoTuneUp

Шкала шагов ZZAU/ZZBPStepIdxToHz (зеркало 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.

2.4 Сделано в ветке feature/cat-tx-cw

К этому моменту в EWSDR появились TX-профили со всей «звуковой» цепью и телеграф (кейер, сайдтон, break-in) — команды, которые §4 когда-то объявил незакрываемыми, стали рабочими.

TX-тракт (правки уезжают в активный TX-профиль):

Команда Что Маппинг
MG / ZZMG усиление микрофона MicGainDB; MG — шкала Kenwood 100:70, ZZMG — дБ со знаком
MO / ZZMO кнопка MON self-monitor даунлинка: SetRxMuteOnTx (инверсия)
ZZTM громкость монитора SetTXMonVolume (новый метод контроллера)
ZZTL / ZZTH кромки TX-фильтра, Гц FilterLow / FilterHigh
PR / ZZPK речевой компрессор вкл/выкл CompressorOn
ZZPL усиление компрессора, дБ CompressorGain (0..20)
ZZET кнопка TXEQ EQOn
ZZEB значения TX-эквалайзера EQNumBands + EQGains (формат Thetis, 36 символов)
ZZTO мощность настройки TUNLevel
ZZTU кнопка TUN SetTune
ZZUT двухтональник 2TON SetTwoTone
ZZLI кнопка PS-A SetPureSignal
ZZUS одиночная калибровка PS PSSingleCal (write-only)
ZZTP активный TX-профиль SelectTXProfile / TXProfileCount
ZZFD девиация передачи (2.5/5 кГц) TTXSettings.FMDeviation

Телеграф (раньше были проброшены только KS/KY/ZZKM/ZZKS/ZZKY):

Команда Что Маппинг (TCWSettings)
ZZCS скорость кейера, WPM (2 разряда) .Speed — та же величина, что у KS
ZZCL тон приёма/сайдтона, Гц .Pitch
ZZCI иамбик вкл/выкл .KeyerMode (вкл выбирает iambic B, если стоял прямой ключ)
ZZCB break-in прошивки .BreakIn
ZZCD hang-time break-in, мс .HangTimeMS
ZZCM сайдтон (у Thetis — «monitor disable», значение инвертировано) .SidetoneSW или .SidetoneHW — тот, что отвечает за текущий источник манипуляции

Новое в контроллере. Правка TX-настроек получила одну публичную дверь — SetTXSettings(const T; Notify), по образцу SetCWSettings: применение к WDSP, перепосыл DUC Specific, живой TUN, запись в активный профиль и персист теперь там, а не в обработчике MainForm (тот делегирует с Notify=False, иначе rfTXProfile перезагрузил бы вкладку Transmit под руками у правящего). Добавлен SetTXMonVolume — громкость self-monitor'а адресно, вне TX-контекста.

Новое в движке. Хелперы OnOff и NumField — разбор двухпозиционных и числовых полей в одном месте, чтобы тела команд остались про смысл. Границы значений (MIC_GAIN_MIN… в шапке юнита) повторяют контролы вкладок Transmit и CW: по CAT прилетает что угодно, а контроллер принимает запись целиком и уже не знает, кто её правил.

Команды слайсов (CATSliceEndpoint) этих callback'ов не получают: TX-тракт один на радио, а профиль слайса переключается своим путём (SetSliceTXProfile). Все новые команды nil-безопасны и на слайс-порту отвечают дефолтом.

2.5 Ревизия алиасов и подписей

Подписи писались по буквам кода, а не по Thetis, и врали примерно в 150 местах. Хуже: часть работающих команд была привязана не к своей функции — внешний софт получал осмысленный, но неверный ответ, что хуже честной заглушки. Всё сверено с CATCommands.cs и исправлено.

Команда делала не своё дело — теперь делает своё:

Команда Было Стало
ZZMA режим (алиас ZZMD) кнопка MUTSetMute
ZZRX переход на приём шаговый аттенюатор RX1 0..31 дБ → SetAtten
ZZRV версия ПО напряжение питания PA (телеметрия)
ZZMV индекс текущего режима число записей памяти каналов
ZZNN заглушка «ручной нотч» SNB (спектральный бланкер)
ZZNS SNB кнопка NR2 (режим NR 2)
ZZVS алиас ZZSP (split) операции с парой VFO: 0=A→B, 1=B→A, 2=обмен, 3=IF→VFO
ZZBM режим (алиас ZZMD) VFO B вниз на nn шагов (пара к ZZBP)
ZZFI алиас ZZBI сам индекс фильтра
ZZBS алиас ZZAC сам выбор диапазона
ZZKM режим кейера запуск CW-макроса (ячейка памяти сообщений)
ZZFT всегда VFO A TX-частота с учётом split
ZZTX любое значение ≠ 0 поднимало передачу («2=TUNE» — выдумка) строго 0/1, иначе ?; и передача НЕ включается (настройка — ZZTU)

Ошибочные алиасы сняты — теперь честные заглушки (в скобках — где эта функция живёт на самом деле): ZZAA, ZZVG (громкость — ZZAG) · ZZOA (антенна RX1) · ZZAP (мощность — ZZPC) · ZZDN (мощность — ZZPC; сам ZZDN = низ водопада) · ZZAC (диапазон — ZZBS) · ZZBI (фильтр — ZZFI) · ZZMB (режим — ZZMD) · ZZVA (обмен VFO — ZZVS) · ZZPD, ZZPO (мощность и питание — ZZPC/ZZPS) · ZZQM (режим — ZZMD) · ZZSR (опорный уровень спектра) · ZZRD/ZZRU (RIT; шаг настройки — ZZSA/ZZSB).

Что заметят внешние клиенты: ZZRX; больше не уводит в приём (для этого есть ZZTX0; и кенвудовская RX;), ZZVA; больше не меняет VFO местами (теперь ZZVS0;), ZZKM не выставляет режим кейера (иамбик вкл/выкл — ZZCI), RD/RU больше не перестраивают VFO (шаг — UP/DN). Во всех случаях старое поведение было отсебятиной.

Кенвудовские команды. Сверены отдельно: все 40 команд, реализованных в Thetis, у нас есть, ширины полей совпадают с CATStructs.xml. Исправлено:

Команда Что было не так
SM ответ был 4 цифры вместо 5 (SM0015;SM00019;) — парсеры логгеров ждут пять; заодно принимаем селектор 2, как шлёт Thetis
RD / RU перестраивали VFO, хотя это RIT (его у нас нет) — стали заглушками, принимающими 5-значный аргумент
KY поле текста у Kenwood фиксированной ширины и добито пробелами — хвост уходил в эфир словесными паузами, теперь срезается
IF в комментарии значилось «37 байт», реальная и правильная длина ответа — 35
SH / SL обе крутят один и тот же индекс пресета; раздельных «сторон» у главного приёмника нет — оговорка добавлена в код
CT принимала любой символ: CT9; молча ГАСИЛ тон вместо ответа ?;. Теперь обёртка над ZZTA, как в эталоне, и сама ZZTA проверяет значение строго
OF / OS несли реализацию сами, а ZZOT/ZZOS были заглушками — клиент Thetis обращается как раз к ZZ* и не получал ничего. Реализация переехала в ZZOT/ZZOS, кенвудовские стали обёртками. Заодно OF с нечисловым полем больше не обнуляет сдвиг молча

Разбор и транспорты. Отдельный проход по валидации и вводу-выводу:

Где Что было не так
TCATEngine.Parse команды без параметров не проверяли суффикс: TXanything; доходил до CmdTX и поднимал передачу; так же вели себя RX UP DN BD BU QI RC ID IF. Эталон отбраковывает лишний суффикс в парсере, по таблице ширин; у нас таблицы нет — список безаргументных команд теперь в IsParamless
ZZFL / ZZFH принимали поле любой длины от 4 символов и гнали его через StrToIntDef: ZZFLabcd; молча схлопывал кромку в ноль. Поле фиксированное — ровно 5 символов со знаком, разбор строгий
ZZAU ZZBP ZZBM ZZBS ZZFI длину поля проверяли, а содержимое — нет: StrToIntDef(s, 0) превращал любую нечисловую пару символов в индекс 0. То есть ZZBSxx; переключал диапазон на нулевой вместо ?;, ZZBMxx; и ZZAUxx;/ZZBPxx; двигали VFO, а ZZFIxx; выбирал фильтр 0. Разбор приведён к идиоме ZZFL/ZZFH: TryStrToInt, иначе ошибка формата
KY / ZZKY текст не ограничивался; поле у Kenwood фиксированное, 25 символов. Длиннее — ?;: очередь передачи не должна расти произвольно, иначе один пакет уводит станцию в эфир на неопределённое время
CATTcp.SendStr один send на ответ. TCP не обязан отдать весь буфер за раз — длинный ответ (IF, ZZEB, список режимов) мог уехать обрезанным, и молча: усечение здесь не ошибка. Теперь дописываем остаток в цикле
CATSerial порт помечался активным ДО SerOpen; при отказе он навсегда оставался «работающим» в ActiveCount и UI, а причина нигде не оседала. Открытие переехало из потока в TCATSerialPort.Start (синхронно), появилось свойство LastError, поток теперь только читает, а закрывает владелец в Stop. Заодно Andromeda-порт назначается только на реально поднявшийся порт

Формат ZZOT сверен отдельно: эталон читает 9 цифр как МГц с шестью знаками после запятой (вставляет точку после третьего разряда) — численно это ровно те же герцы, что пишем мы, поле совместимо. Мусор в ZZOS эталон трактует как симплекс (default в String2OffsetDirection), и мы намеренно повторяем это, а не отвечаем ошибкой.

Формат ответа на ZZ* (ZZ + код + эхо суффикса запроса + значение) сверен с CATParser.ParseExtended — совпадает; это важно для ZZSM0;, где запрос несёт селектор приёмника.


3. Что нужно сделать (актуально / есть чем закрыть)

Эти команды — заглушки, но соответствующая функция в EWSDR уже есть или легко добавляется. Приоритетные кандидаты:

Команда(ы) Что Чем закрыть Сложность
ZZVL, ZZUX/ZZUY блокировка VFO (общая и раздельная) SetVfoLock низкая
ZZSW, ZZZW обмен VFO A/B VfoSwap низкая
ZZAD ZZAE ZZAF ZZBE ZZBF, ZZSG/ZZSH сдвиг VFO на nn шагов StepIdxToHz + DoTuneUp/Down, как у ZZAU/ZZBP низкая
ZZCU загрузка CPU (read) телеметрия процесса низкая
ZZSF фильтр «центр + ширина» одной командой SetFilterEdges низкая
ZZSG/ZZSH, ZZSD шаг VFO B и колеса — по одному шагу те же SetVfoB/DoTune* низкая
ZZMY ZZMZ ZZMW ZZMX ZZQR ZZQS ZZQM запись/чтение памяти каналов (счётчик ZZMV уже есть) ChannelStore / ChannelController средняя
ZZDN/ZZDO, ZZDP/ZZDQ/ZZDR низ/верх водопада, сетка спектра FSpecRefLevel/FSpecRange, per-pan дисплей средняя
ZZPD/ZZPE, ZZPY/ZZPZ пан и зум дисплея SetPanZoomPan средняя
ZZSN, ZZZM, ZZZV серийник, модель, версия железа BoardUtils низкая
ZZXN / ZZXV составные статусы RX1/VFO сборка из готовых геттеров средняя
ZZOC/ZZOD/ZZOE антенны SetAnt936x (порты AD936x) средняя
ZZDX / ZZDY кнопка DX и порог спотов флаг ShowSpots живёт в MainForm — сперва поднять в контроллер средняя
ZZAS RX2 AGC-T — только при появлении RX2

Прежде чем реализовывать новую команду, сверяйся с форматом поля в Thetis/.../CAT/CATStructs.xml (<nsetparms> / <ngetparms>) и телом метода в CATCommands.cs, чтобы ширина/знак значения совпадали. И проверяй смысл: подпись у заглушки в диспетчере может врать (см. §1.2).

3.1 Совсем не обрабатываются (вернут ?;)

ZZCU (CPU), ZZDY (DX threshold), 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 ZZBB ZZBT ZZMB ZZOB ZZRS ZZSV ZZSX ZZNC ZZND ZZNF ZZNO ZZNU ZZNW ZZFJ ZZFR ZZFS ZZGU ZZLE ZZLF ZZPB ZZRY ZZXO один приёмник
VAC / VAC2 ZZVC ZZVD ZZVF ZZVI ZZVK ZZVM ZZVO ZZVQ ZZVR ZZVT ZZVU ZZVV ZZVX ZZVY ZZVZ ZZYA ZZYB нет виртуального аудиокабеля
RTTY / DIGI-офсеты ZZRA ZZRB ZZRH ZZRL нет RTTY-движка
RIT / XIT RT XT RC, ZZRF ZZRT ZZXC ZZXD ZZXF ZZXS ZZXU нет тракта смещения приёма (CTUN — не замена)
Diversity ZZDB ZZDC ZZDD ZZDE ZZDF ZZDG ZZDH (но не ZZDA — это усреднение спектра) нет диверсити-приёма
Компандер, noise gate, APF, VOX ZZCP ZZCT, ZZGE ZZGL, ZZAA ZZAB ZZAT ZZAY, ZZVE ZZXH таких блоков в тракте нет (речевой компрессор — есть, это ZZPK/ZZPL)
Микшер Flex 5000 / F1500, FlexWire ZZWA…ZZWS, ZZWT…ZZWW, ZZFV ZZFW ZZFX ZZFY железо другого вендора
ATU (Aries/Ganymede) ZZOV ZZOW ZZOX ZZOZ ZZZA нет тюнера
DSP-буферы, JSON-команды ZZHA ZZHR ZZHT ZZHU ZZHV ZZHW ZZHX, ZZJP ZZJQ ZZJR ZZJS внутренние крутилки Thetis

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-команду (чек-лист)

  1. Сверить формат в CATStructs.xml + CATCommands.cs (Thetis).
  2. Если нужна новая возможность контроллера — есть ли публичный метод/поле в TRadioController? Если нет — добавить (по образцу SetSplit).
  3. В CATEngine.pas: добавить callback(и) в TCATContext, SafeGet*-хелпер для GET, переписать тело команды (CmdXX или ZZXX).
  4. В CATAdapter.pas: геттер (чтение FController.F*), сеттер + SyncXX (через Invoke), регистрация в TCATAdapter.Create.
  5. Если команда ZZ* ещё не в диспетчере — добавить ветку else if ext = '..'.
  6. Сборка-проверка: lazbuild -B --ws=qt6 ewsdr.lpr (GUI-граф включает CAT; headless-демон ewsdrd CAT не содержит).