mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feat(ui): настройки показывают только то, что есть у активного железа
В TBackendCaps восемь флагов заполнялись обоими бэкендами и не читались нигде, а в ApplyBackendCapsToUI на этом месте стояла расписка «(TODO) гейтинг полей, которых нет у бэкенда». Из-за этого на AD936x оператору предлагали крутить то, чего у платы нет, — и хуже всего страница PA: калибровка драйва по диапазонам там просто ничего не делает (мощность задаётся железной аттенюацией, drive-байта нет вовсе), но выглядела рабочей. Теперь гейт идёт по возможностям, а не по виду устройства: - HasPA — потолок мощности и калибровки драйва (HF + трансвертеры) против «TX att @100% drive»; заголовок и подзаголовок страницы следуют содержимому; - HasHWMic — строка микрофонного разъёма (DUC Specific байт 50). Mic gain остаётся: он идёт в WDSP и работает с любым источником, включая звук с ПК, поэтому поднимается в освободившуюся строку; - HasWideband — галки широкополосного АЦП; сам режим принудительно гасится, иначе сохранённый в конфиге wideband оставлял бы пустую панель без способа её выключить; - HasDitherRandom — группа ADC целиком, Web Server встаёт на её место. Вкладка QO-100 убрана на openHPSDR: TRadioController.InQO100 требует IsPluto, то есть транспондер там недостижим. Симметрично OC Control, которого нет у AD936x. Измеритель: TSMeterView.HasPATelemetry. Без моста детектора FLastFwdW/FLastSWR стоят на значениях инициализации, и «0W / SWR 1.0» на передаче — не показание, а выдумка. Шкала рисуется пустой: деления и рамка на месте, заливки нет, ватты на делениях не подписаны (они считаются от Max power, которого у AD936x нет). ★Отдельно — дефект раскладки, который всё это вскрыло. Перекладка страницы настроек ломается в двух случаях, и оба случались при смене трансивера на живой программе (Stop/Discover/Connect/Start), а не при старте: 1. Страница ПРОКРУЧЕНА. TScrollBox двигает детей, и SetBounds задаёт координаты относительно прокрученного клиента: всё уезжало вверх, а первая группа оставалась на месте — под переключателями Profile/EQ/Hardware зияла дыра. Лечение — сброс прокрутки первой строкой (так уже делал RelayoutCalTab). 2. Страница СПРЯТАНА. Тогда сброс не доходит до виджета, а сохранённое смещение возвращается при показе — и дыра та же. А попадает перекладка почти всегда именно на спрятанную страницу: гейты отрабатывают при открытии окна, когда активна одна вкладка, а до Transmit/Calibration оператор доходит потом. Лечение — перекладка спрятанной страницы взводит флаг и выходит, а SelectPage исполняет её в момент показа (RunDueRelayout). Гард стоит внутри каждой Relayout*, а не у вызывающих: у RelayoutCalTab их два, и второй (LoadXvtrSettings) приходит как раз на спрятанную страницу. Проверено офскрин-рендером окна настроек в обе стороны (openHPSDR ↔ AD936x) для Transmit/Power Amplifier/Calibration/Advanced, в том числе на прокрученной и спрятанной странице. При полном железе координаты совпадают со старыми. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M37eCTZZ9aqppKWkZRxXkP
This commit is contained in:
+38
-14
@@ -30,6 +30,11 @@ type
|
||||
FLastFwdW: Double;
|
||||
FLastSWR: Double;
|
||||
FPAMaxPower: Double;
|
||||
// Есть ли у железа мост детектора мощности (Caps.HasPA). У AD936x его нет:
|
||||
// FLastFwdW/FLastSWR так и стоят на значениях инициализации, и «0W / SWR
|
||||
// 1.0» на передаче — не показание, а выдумка. Шкала в этом случае рисуется
|
||||
// пустой: деления есть, заливки и цифр нет.
|
||||
FHasPATelemetry: Boolean;
|
||||
FTransmitting: Boolean;
|
||||
FPbSMeterRight: TPaintBox;
|
||||
// Масштаб канвы: 2 на Retina, 1 на Windows/Linux. Битмап растёт во столько
|
||||
@@ -52,6 +57,7 @@ type
|
||||
property LastFwdW: Double read FLastFwdW write FLastFwdW;
|
||||
property LastSWR: Double read FLastSWR write FLastSWR;
|
||||
property PAMaxPower: Double read FPAMaxPower write FPAMaxPower;
|
||||
property HasPATelemetry: Boolean read FHasPATelemetry write FHasPATelemetry;
|
||||
property Transmitting: Boolean read FTransmitting write FTransmitting;
|
||||
property PbSMeterRight: TPaintBox write FPbSMeterRight;
|
||||
|
||||
@@ -76,6 +82,7 @@ begin
|
||||
FLastFwdW := 0;
|
||||
FLastSWR := 1;
|
||||
FPAMaxPower := 100.0;
|
||||
FHasPATelemetry := True;
|
||||
FTransmitting := False;
|
||||
FScale := 1;
|
||||
end;
|
||||
@@ -358,9 +365,17 @@ begin
|
||||
W := R.Right - R.Left; H := R.Bottom - R.Top;
|
||||
if (W < 80 * Sc) or (H < 16 * Sc) then Exit;
|
||||
|
||||
SWRHigh := FLastSWR > SWR_HIGH_THRESH;
|
||||
LblPwr := Format('%.0fW', [FLastFwdW]);
|
||||
LblSWR := Format('SWR:%.1f', [FLastSWR]);
|
||||
SWRHigh := FHasPATelemetry and (FLastSWR > SWR_HIGH_THRESH);
|
||||
if FHasPATelemetry then
|
||||
begin
|
||||
LblPwr := Format('%.0fW', [FLastFwdW]);
|
||||
LblSWR := Format('SWR:%.1f', [FLastSWR]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
LblPwr := ''; // измерять нечем — показания не выдумываем
|
||||
LblSWR := '';
|
||||
end;
|
||||
|
||||
ACanvas.Font.Name := 'Courier New'; ACanvas.Font.Style := [fsBold];
|
||||
ACanvas.Font.Size := 10 * Sc;
|
||||
@@ -394,18 +409,24 @@ begin
|
||||
FillBar(BX, SY1, S_WarnX, SY2, CLR_BAR_GREEN);
|
||||
FillBar(S_WarnX, SY1, BX + BW, SY2, CLR_BAR_OVER);
|
||||
|
||||
if FPAMaxPower > 0 then PwrPct := FLastFwdW / FPAMaxPower else PwrPct := 0;
|
||||
PBarEnd := PwrToX(PwrPct);
|
||||
FillBar(BX, PY1 + Sc, PBarEnd, PY2 - Sc, SM_CLR_METER_ON);
|
||||
|
||||
SBarEnd := SWRToX(FLastSWR);
|
||||
if not SWRHigh then
|
||||
FillBar(BX, SY1 + Sc, SBarEnd, SY2 - Sc, SM_CLR_AMBER)
|
||||
else
|
||||
if FHasPATelemetry then
|
||||
begin
|
||||
FillBar(BX, SY1 + Sc, Min(S_WarnX, SBarEnd), SY2 - Sc, SM_CLR_AMBER);
|
||||
if SBarEnd > S_WarnX then
|
||||
FillBar(S_WarnX, SY1 + Sc, SBarEnd, SY2 - Sc, CLR_SWR_HIGH);
|
||||
if FPAMaxPower > 0 then PwrPct := FLastFwdW / FPAMaxPower else PwrPct := 0;
|
||||
PBarEnd := PwrToX(PwrPct);
|
||||
FillBar(BX, PY1 + Sc, PBarEnd, PY2 - Sc, SM_CLR_METER_ON);
|
||||
end;
|
||||
|
||||
if FHasPATelemetry then
|
||||
begin
|
||||
SBarEnd := SWRToX(FLastSWR);
|
||||
if not SWRHigh then
|
||||
FillBar(BX, SY1 + Sc, SBarEnd, SY2 - Sc, SM_CLR_AMBER)
|
||||
else
|
||||
begin
|
||||
FillBar(BX, SY1 + Sc, Min(S_WarnX, SBarEnd), SY2 - Sc, SM_CLR_AMBER);
|
||||
if SBarEnd > S_WarnX then
|
||||
FillBar(S_WarnX, SY1 + Sc, SBarEnd, SY2 - Sc, CLR_SWR_HIGH);
|
||||
end;
|
||||
end;
|
||||
|
||||
VLine(S_WarnX, SY1, SY2, FTheme.SMeterDivider);
|
||||
@@ -437,6 +458,9 @@ begin
|
||||
begin
|
||||
X := PwrToX(PWR_MARKS[i]);
|
||||
VLine(X, PY1 - TICK_LONG * Sc, PY1 - Sc, CLR_TICK_WHITE);
|
||||
// Ватты на делениях считаются от Max power, а он есть только там, где есть
|
||||
// детектор. Без него оставляем голые деления: подписать их нечем.
|
||||
if not FHasPATelemetry then Continue;
|
||||
Lbl := Format('%.0f', [PWR_MARKS[i] * FPAMaxPower]);
|
||||
TW := ACanvas.TextWidth(Lbl);
|
||||
ACanvas.Font.Color := CLR_SCALE_DBM;
|
||||
|
||||
Reference in New Issue
Block a user