mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(cat): нечисловое поле = индекс 0 ещё в семнадцати командах, ZZGT и ZZBE
Всё найдено новым стендом (test/cat), все правки им же и закрыты.
Нечисловое поле. Правку «TryStrToInt вместо StrToIntDef(s, 0)» однажды получили
пять команд (ZZAU, ZZBP, ZZBM, ZZBS, ZZFI), а остальные остались как были — в
том числе КЕНВУДОВСКИЕ ДВОЙНИКИ тех же самых величин, ходящие в те же сеттеры:
FWxxxx;, SHxx; и SLxx; ставили фильтр 0 (тот же индекс, что чинили у ZZFI),
AG0xxx; и SQ0xxx; — громкость и порог шумоподавителя в ноль, GTxxx; — АРУ в
FAST, PCxxx; и ZZPCxxx; — мощность в ноль. Всего семнадцать команд: CN, FW, GT,
NB, PC, SH/SL, AG, SQ и ZZAG, ZZAR, ZZNA, ZZNB, ZZNR, ZZPC, ZZSQ, ZZST, ZZTB.
Разбор везде приведён к идиоме ZZFL/ZZFH: не число — ошибка формата.
Не тронуты три места, где мягкий разбор безвреден или намеренный: FR сам
сверяет поле с '0'/'1' до преобразования; MD и ZZMD от нечислового получают 0, а
установка идёт от 1, то есть ничего не делают; ZZOS трактует мусор как симплекс
по эталону (default в String2OffsetDirection), и клиенты на это рассчитывают.
ZZGT. Опрос отвечал тремя цифрами (как кенвудовская GT), а установка принимала
ровно один символ: клиент, прочитавший «ZZGT000;» и написавший его назад,
получал «?;» — а читать значение и писать его обратно умеет любой логгер.
Принимаются обе ширины, поле разбирается строго.
ZZBE. Формы были перевёрнуты: опрос «ZZBE;» отвечал «?;», а установка
«ZZBE01;» возвращала данные ('1'), причём саму установку никто не исполнял.
Вся семья «сдвиг VFO на nn шагов» (ZZAD ZZAE ZZAF ZZBF ZZSG ZZSH) — однострочные
заглушки в таблице, и документ числит ZZBE среди нереализованных; приведено к
ним.
ZZEB. Выдача клампится туда же, куда и приём: сетка эквалайзера бывает только
трёх- или десятиполосной. Иначе опрос отдавал число полос, которое разбор той же
команды отвергал.
Стенд: 50 проверок, все зелёные; на коде до этого коммита падают 19.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+50
-40
@@ -321,7 +321,6 @@ type
|
||||
function ZZBA: string;
|
||||
function ZZBD: string;
|
||||
function ZZBP(const s: string): string;
|
||||
function ZZBE(const s: string): string;
|
||||
function ZZBI(const s: string): string;
|
||||
function ZZBM(const s: string): string;
|
||||
function ZZBS(const s: string): string;
|
||||
@@ -870,8 +869,8 @@ function TCATEngine.CmdAG(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 4 then begin
|
||||
v := Round(StrToIntDef(Copy(s,2,3), 0) / 2.55);
|
||||
v := EnsureRange(v, 0, 100);
|
||||
if not TryStrToInt(Copy(s, 2, 3), v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(Round(v / 2.55), 0, 100);
|
||||
if Assigned(FCtx.SetVolume) then FCtx.SetVolume(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 1 then begin
|
||||
@@ -904,7 +903,8 @@ function TCATEngine.CmdCN(const s: string): string;
|
||||
var idx: Integer;
|
||||
begin
|
||||
if Length(s) = 2 then begin
|
||||
idx := EnsureRange(StrToIntDef(s, 1) - 1, 0, 37);
|
||||
if not TryStrToInt(s, idx) then Exit(CAT_ERROR);
|
||||
idx := EnsureRange(idx - 1, 0, 37);
|
||||
if Assigned(FCtx.SetCTCSSTone) then FCtx.SetCTCSSTone(idx);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -979,7 +979,8 @@ function TCATEngine.CmdFW(const s: string): string;
|
||||
var idx: Integer;
|
||||
begin
|
||||
if Length(s) = 4 then begin
|
||||
idx := EnsureRange(StrToIntDef(s, 0), 0, 9);
|
||||
if not TryStrToInt(s, idx) then Exit(CAT_ERROR);
|
||||
idx := EnsureRange(idx, 0, 9);
|
||||
if Assigned(FCtx.SetFilterIdx) then FCtx.SetFilterIdx(idx);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -990,9 +991,11 @@ end;
|
||||
|
||||
function TCATEngine.CmdGT(const s: string): string;
|
||||
// GT: AGC mode (3 digits) — 0=FAST,1=MED,2=SLOW,3=LONG,4=OFF
|
||||
var m: Integer;
|
||||
begin
|
||||
if Length(s) = 3 then begin
|
||||
if Assigned(FCtx.SetAGCMode) then FCtx.SetAGCMode(EnsureRange(StrToIntDef(s,0),0,4));
|
||||
if not TryStrToInt(s, m) then Exit(CAT_ERROR);
|
||||
if Assigned(FCtx.SetAGCMode) then FCtx.SetAGCMode(EnsureRange(m, 0, 4));
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
Result := Pad(SafeGetAGCMode, 3)
|
||||
@@ -1112,10 +1115,11 @@ end;
|
||||
|
||||
function TCATEngine.CmdNB(const s: string): string;
|
||||
// NB: noise blanker on/off → maps to NBMode
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 1 then begin
|
||||
if Assigned(FCtx.SetNBMode) then
|
||||
FCtx.SetNBMode(StrToIntDef(s, 0));
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
if Assigned(FCtx.SetNBMode) then FCtx.SetNBMode(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
Result := IntToStr(EnsureRange(SafeGetNBMode, 0, 1))
|
||||
@@ -1194,7 +1198,8 @@ function TCATEngine.CmdPC(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 3 then begin
|
||||
v := EnsureRange(StrToIntDef(s,0), 0, 100);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(v, 0, 100);
|
||||
if Assigned(FCtx.SetDriveLevel) then FCtx.SetDriveLevel(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -1268,7 +1273,8 @@ function TCATEngine.CmdSH(const s: string): string;
|
||||
var idx: Integer;
|
||||
begin
|
||||
if Length(s) = 2 then begin
|
||||
idx := EnsureRange(StrToIntDef(s, 0), 0, 9);
|
||||
if not TryStrToInt(s, idx) then Exit(CAT_ERROR);
|
||||
idx := EnsureRange(idx, 0, 9);
|
||||
if Assigned(FCtx.SetFilterIdx) then FCtx.SetFilterIdx(idx);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -1304,7 +1310,8 @@ function TCATEngine.CmdSQ(const s: string): string;
|
||||
var lvl255, lvl100: Integer;
|
||||
begin
|
||||
if Length(s) = 4 then begin
|
||||
lvl255 := EnsureRange(StrToIntDef(Copy(s, 2, 3), 0), 0, 255);
|
||||
if not TryStrToInt(Copy(s, 2, 3), lvl255) then Exit(CAT_ERROR);
|
||||
lvl255 := EnsureRange(lvl255, 0, 255);
|
||||
lvl100 := Round(lvl255 * 100 / 255);
|
||||
if Assigned(FCtx.SetSquelchLevel) then FCtx.SetSquelchLevel(lvl100);
|
||||
if Assigned(FCtx.SetSquelchOn) then FCtx.SetSquelchOn(lvl100 > 0);
|
||||
@@ -1362,7 +1369,7 @@ begin
|
||||
else if ext = 'BA' then ans := ZZBA
|
||||
else if ext = 'BB' then ans := '' // STUB: bandswitch RX2 вверх — RX2 нет
|
||||
else if ext = 'BD' then begin ZZBD; ans := ''; end
|
||||
else if ext = 'BE' then ans := ZZBE(s)
|
||||
else if ext = 'BE' then ans := '' // STUB: VFO B вниз на nn пресетных шагов — см. ZZAE
|
||||
else if ext = 'BF' then ans := '' // STUB: VFO B вверх на nn пресетных шагов — см. ZZAE
|
||||
else if ext = 'BG' then ans := '' // STUB: группа диапазонов HF/VHF — не разделяем
|
||||
else if ext = 'BI' then ans := ZZBI(s)
|
||||
@@ -1701,7 +1708,8 @@ function TCATEngine.ZZAG(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 3 then begin
|
||||
v := EnsureRange(StrToIntDef(s, 0), 0, 100);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(v, 0, 100);
|
||||
if Assigned(FCtx.SetVolume) then FCtx.SetVolume(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -1731,7 +1739,7 @@ function TCATEngine.ZZAR(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 4 then begin
|
||||
v := StrToIntDef(s, 0); // StrToIntDef понимает ведущий +/-
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR); // Val понимает ведущий +/-
|
||||
if Assigned(FCtx.SetAGCTop) then FCtx.SetAGCTop(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then begin
|
||||
@@ -1796,15 +1804,6 @@ begin
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
function TCATEngine.ZZBE(const s: string): string;
|
||||
// ZZBE: VFO B вниз на nn пресетных шагов — STUB: глобального размера шага у
|
||||
// EWSDR нет (см. ZZAC). Шаг по индексу — это ZZBM/ZZBP.
|
||||
begin
|
||||
if Length(s) = 3 then Result := ''
|
||||
else if Length(s) = 2 then Result := '1'
|
||||
else Result := CAT_ERROR;
|
||||
end;
|
||||
|
||||
function TCATEngine.ZZBI(const s: string): string;
|
||||
// ZZBI: кнопка BIN (бинауральный приём) — STUB: такого режима нет.
|
||||
// (Индекс фильтра — это ZZFI; раньше он жил здесь.)
|
||||
@@ -1942,7 +1941,9 @@ begin
|
||||
begin
|
||||
FillChar(G, SizeOf(G), 0);
|
||||
if Assigned(FCtx.GetTXEQ) then nb := FCtx.GetTXEQ(G) else nb := 0;
|
||||
nb := EnsureRange(nb, 0, High(G));
|
||||
// Отдаём ровно то, что примем обратно (см. разбор SET ниже): сетка бывает
|
||||
// только трёх- или десятиполосной, а движок всё, что не 3, играет как 10.
|
||||
if nb <> 3 then nb := 10;
|
||||
ans := Pad(nb, 3);
|
||||
for i := 0 to nb do
|
||||
begin
|
||||
@@ -2089,17 +2090,18 @@ begin
|
||||
end;
|
||||
|
||||
function TCATEngine.ZZGT(const s: string): string;
|
||||
// ZZGT: AGC mode (1 char: 0=FAST,1=MED,2=SLOW,3=LONG,4=OFF) → 3-digit response
|
||||
// ZZGT: режим АРУ (0=FAST,1=MED,2=SLOW,3=LONG,4=OFF). Ответ — три цифры, как у
|
||||
// кенвудовской GT, и SET обязан принимать ту же ширину: клиент, прочитавший
|
||||
// «ZZGT000;», пишет назад ровно это, и односимвольная форма отдавала ему «?;».
|
||||
// Однобуквенную форму оставляем — на ней уже сидят клиенты.
|
||||
var m: Integer;
|
||||
begin
|
||||
if Length(s) = 1 then begin
|
||||
m := EnsureRange(StrToIntDef(s, 0), 0, 4);
|
||||
if Assigned(FCtx.SetAGCMode) then FCtx.SetAGCMode(m);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
Result := Pad(SafeGetAGCMode, 3)
|
||||
else
|
||||
Result := CAT_ERROR;
|
||||
if Length(s) = 0 then Exit(Pad(SafeGetAGCMode, 3));
|
||||
if (Length(s) <> 1) and (Length(s) <> 3) then Exit(CAT_ERROR);
|
||||
if not TryStrToInt(s, m) then Exit(CAT_ERROR);
|
||||
m := EnsureRange(m, 0, 4);
|
||||
if Assigned(FCtx.SetAGCMode) then FCtx.SetAGCMode(m);
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
function TCATEngine.ZZID: string;
|
||||
@@ -2245,7 +2247,7 @@ function TCATEngine.ZZNA(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 1 then begin
|
||||
v := StrToIntDef(s, 0);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
if Assigned(FCtx.SetNBMode) then FCtx.SetNBMode(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -2259,7 +2261,8 @@ function TCATEngine.ZZNB(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 1 then begin
|
||||
v := EnsureRange(StrToIntDef(s,0),0,4);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(v, 0, 4);
|
||||
if Assigned(FCtx.SetNBMode) then FCtx.SetNBMode(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -2287,7 +2290,8 @@ function TCATEngine.ZZNR(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 1 then begin
|
||||
v := EnsureRange(StrToIntDef(s,0),0,4);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(v, 0, 4);
|
||||
if Assigned(FCtx.SetNRMode) then FCtx.SetNRMode(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -2343,7 +2347,8 @@ function TCATEngine.ZZPC(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 3 then begin
|
||||
v := EnsureRange(StrToIntDef(s,0),0,100);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(v, 0, 100);
|
||||
if Assigned(FCtx.SetDriveLevel) then FCtx.SetDriveLevel(v);
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
@@ -2491,7 +2496,8 @@ function TCATEngine.ZZSQ(const s: string): string;
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 3 then begin
|
||||
v := EnsureRange(StrToIntDef(s, 0), 0, 100);
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
v := EnsureRange(v, 0, 100);
|
||||
if Assigned(FCtx.SetSquelchLevel) then FCtx.SetSquelchLevel(v);
|
||||
if Assigned(FCtx.SetSquelchOn) then FCtx.SetSquelchOn(v > 0);
|
||||
Result := '';
|
||||
@@ -2510,9 +2516,11 @@ end;
|
||||
|
||||
function TCATEngine.ZZST(const s: string): string;
|
||||
// ZZST: FM tuning step index (2 digits): 00=6.25k, 01=12.5k, 02=20k, 03=25k.
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 2 then begin
|
||||
if Assigned(FCtx.SetFMStep) then FCtx.SetFMStep(EnsureRange(StrToIntDef(s, 0), 0, 3));
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
if Assigned(FCtx.SetFMStep) then FCtx.SetFMStep(EnsureRange(v, 0, 3));
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
Result := Pad(EnsureRange(SafeGetFMStep, 0, 3), 2)
|
||||
@@ -2536,9 +2544,11 @@ end;
|
||||
|
||||
function TCATEngine.ZZTB(const s: string): string;
|
||||
// ZZTB: CTCSS tone index (2 digits, 0-based 00..37 в таблице CTCSS_TONES).
|
||||
var v: Integer;
|
||||
begin
|
||||
if Length(s) = 2 then begin
|
||||
if Assigned(FCtx.SetCTCSSTone) then FCtx.SetCTCSSTone(EnsureRange(StrToIntDef(s, 0), 0, 37));
|
||||
if not TryStrToInt(s, v) then Exit(CAT_ERROR);
|
||||
if Assigned(FCtx.SetCTCSSTone) then FCtx.SetCTCSSTone(EnsureRange(v, 0, 37));
|
||||
Result := '';
|
||||
end else if Length(s) = 0 then
|
||||
Result := Pad(EnsureRange(SafeGetCTCSSTone, 0, 37), 2)
|
||||
|
||||
Reference in New Issue
Block a user