mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
feat(cat): CAT-порт на каждый слайс + Auto TX (эталон SmartSDR CAT)
Внешняя программа управляет отдельным слайсом как отдельным трансивером
через свой 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>
This commit is contained in:
+37
-1
@@ -16,6 +16,8 @@ const
|
||||
CFG_MODE_MIN = RadioModes.MODE_MIN;
|
||||
CFG_MODE_MAX = RadioModes.MODE_MAX;
|
||||
CFG_PANS_MAX = 4; // потолок панадаптеров (пан 0 + доп.) — = WDSPEngine.MAX_PANS
|
||||
CFG_CAT_SLICE_COUNT = 6; // слотов доп. слайсов (B..G) — = WDSPEngine.MAX_SLICES
|
||||
CFG_CAT_SLICE_PORT0 = 19091; // порт слайса B по умолчанию (главный — 19090)
|
||||
QO100_SLOT = CFG_XVTR_COUNT - 1; // последний слот зарезервирован под QO-100
|
||||
// (split-LO транспондер; настраивается на
|
||||
// отдельной странице, не в общей XVTR-таблице)
|
||||
@@ -448,9 +450,16 @@ type
|
||||
CATSerialStopBits: array[0..3] of Integer; // 1 или 2
|
||||
CATSerialParity: array[0..3] of Integer; // 0=None, 1=Odd, 2=Even
|
||||
CATSerialAndromeda:array[0..3] of Boolean; // порт — передняя панель Andromeda/G2
|
||||
// TCP CAT сервер (один, многоклиентский)
|
||||
// TCP CAT сервер (один, многоклиентский) — главный приёмник (слайс A)
|
||||
CATTcpEnabled: Boolean;
|
||||
CATTcpPort: Integer; // порт, по умолчанию 19090
|
||||
// Слайс-CAT: свой TCP-порт на каждый ДОПОЛНИТЕЛЬНЫЙ слайс (B, C, …).
|
||||
// Индекс = слот слайса (0 = слайс B), см. CFG_CAT_SLICE_COUNT.
|
||||
CATSliceEnabled: array[0..CFG_CAT_SLICE_COUNT-1] of Boolean;
|
||||
CATSlicePort: array[0..CFG_CAT_SLICE_COUNT-1] of Integer; // 19091, 19092, …
|
||||
// Auto TX (аналог «Auto Switch TX Slice» в SmartSDR CAT): команда TX по
|
||||
// CAT-порту слайса сама назначает этот слайс источником передачи.
|
||||
CATSliceAutoTX: array[0..CFG_CAT_SLICE_COUNT-1] of Boolean;
|
||||
end;
|
||||
|
||||
TSettingsManager = class
|
||||
@@ -652,6 +661,11 @@ begin
|
||||
end;
|
||||
G.CATTcpEnabled := False;
|
||||
G.CATTcpPort := 19090;
|
||||
for i := 0 to CFG_CAT_SLICE_COUNT-1 do begin
|
||||
G.CATSliceEnabled[i] := False;
|
||||
G.CATSlicePort[i] := CFG_CAT_SLICE_PORT0 + i;
|
||||
G.CATSliceAutoTX[i] := False;
|
||||
end;
|
||||
// ADC — включены по умолчанию: поддерживаются на Hermes, Angelia, Orion
|
||||
G.DitherEnabled := True;
|
||||
G.RandomEnabled := True;
|
||||
@@ -905,6 +919,11 @@ begin
|
||||
G.CATSerialParity[i] := JI(GObj,'cat_serial_parity_'+IntToStr(i), 0);
|
||||
G.CATSerialAndromeda[i]:= JB(GObj,'cat_serial_androm_'+IntToStr(i), False);
|
||||
end;
|
||||
for i := 0 to CFG_CAT_SLICE_COUNT-1 do begin
|
||||
G.CATSliceEnabled[i] := JB(GObj,'cat_slice_en_' +IntToStr(i), False);
|
||||
G.CATSlicePort[i] := JI(GObj,'cat_slice_port_' +IntToStr(i), CFG_CAT_SLICE_PORT0 + i);
|
||||
G.CATSliceAutoTX[i] := JB(GObj,'cat_slice_autotx_'+IntToStr(i), False);
|
||||
end;
|
||||
G.CATTcpEnabled := JB(GObj,'cat_tcp_enabled', False);
|
||||
G.CATTcpPort := JI(GObj,'cat_tcp_port', 19090);
|
||||
// ADC settings
|
||||
@@ -1039,6 +1058,11 @@ begin
|
||||
JW(O,'cat_serial_parity_'+IntToStr(i),G.CATSerialParity[i]);
|
||||
JW(O,'cat_serial_androm_'+IntToStr(i),G.CATSerialAndromeda[i]);
|
||||
end;
|
||||
for i := 0 to CFG_CAT_SLICE_COUNT-1 do begin
|
||||
JW(O,'cat_slice_en_' +IntToStr(i), G.CATSliceEnabled[i]);
|
||||
JW(O,'cat_slice_port_' +IntToStr(i), G.CATSlicePort[i]);
|
||||
JW(O,'cat_slice_autotx_'+IntToStr(i), G.CATSliceAutoTX[i]);
|
||||
end;
|
||||
JW(O,'cat_tcp_enabled',G.CATTcpEnabled);
|
||||
JW(O,'cat_tcp_port',G.CATTcpPort);
|
||||
// ADC settings
|
||||
@@ -1200,6 +1224,12 @@ begin
|
||||
JW(O, 'ser_parity_'+IntToStr(i), G.CATSerialParity[i]);
|
||||
JW(O, 'ser_androm_'+IntToStr(i), G.CATSerialAndromeda[i]);
|
||||
end;
|
||||
for i := 0 to CFG_CAT_SLICE_COUNT-1 do
|
||||
begin
|
||||
JW(O, 'slice_en_' +IntToStr(i), G.CATSliceEnabled[i]);
|
||||
JW(O, 'slice_port_' +IntToStr(i), G.CATSlicePort[i]);
|
||||
JW(O, 'slice_autotx_'+IntToStr(i), G.CATSliceAutoTX[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettingsManager.LoadCATSettings(var G: TGlobalSettings);
|
||||
@@ -1223,6 +1253,12 @@ begin
|
||||
G.CATSerialParity[i] := JI(O, 'ser_parity_'+IntToStr(i), 0);
|
||||
G.CATSerialAndromeda[i]:= JB(O, 'ser_androm_'+IntToStr(i), False);
|
||||
end;
|
||||
for i := 0 to CFG_CAT_SLICE_COUNT-1 do
|
||||
begin
|
||||
G.CATSliceEnabled[i] := JB(O, 'slice_en_' +IntToStr(i), False);
|
||||
G.CATSlicePort[i] := JI(O, 'slice_port_' +IntToStr(i), CFG_CAT_SLICE_PORT0 + i);
|
||||
G.CATSliceAutoTX[i] := JB(O, 'slice_autotx_'+IntToStr(i), False);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user