mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-26 04:47:35 +00:00
Mic settings: auto PTT source, Mic In/Line In, Line In gain, Tip/Ring
- Remove manual "Mic Source" (Radio/SoundCard) setting from UI and storage; source is now determined automatically in ApplyMOX: HW PTT → txmsRadio, MOX button/CAT → txmsSoundCard if audio device configured, else txmsRadio - Replace "Line in" checkbox with "Mic jack" combo (Mic In / Line In); when Line In is selected, Mic Boost is hidden and Line In Gain (-34.5..+12 dB, step 1.5 dB) is shown and sent as DUC Specific byte 51 - Add Tip/Ring connector selector (Orion/OrionMkII boards 4/5 only, byte 50 bit 3); control is hidden for other board types - Fix byte 50 bit 1 (Mic Boost) suppressed when Line In is active - Fix byte 51 comment polarity (was reversed: 0=+12dB; correct: 0=-34.5dB) - New JSON fields: mic_line_in, mic_tip_ring, line_in_gain_db; mic_source removed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -250,7 +250,7 @@ type
|
|||||||
CWRampPeriod: Byte; // 17: ms, 0=default
|
CWRampPeriod: Byte; // 17: ms, 0=default
|
||||||
Reserved18: array[18..49] of Byte;
|
Reserved18: array[18..49] of Byte;
|
||||||
MicLineSelect: Byte; // 50
|
MicLineSelect: Byte; // 50
|
||||||
LineInGain: Byte; // 51: 0=+12dB, 31=-34.5dB
|
LineInGain: Byte; // 51: 0=-34.5dB .. 31=+12dB (шаг 1.5 dB)
|
||||||
Reserved52: array[52..56] of Byte;
|
Reserved52: array[52..56] of Byte;
|
||||||
StepAtten2: Byte; // 57: ADC2 atten during TX (0-31dB)
|
StepAtten2: Byte; // 57: ADC2 atten during TX (0-31dB)
|
||||||
StepAtten1: Byte; // 58: ADC1 atten during TX
|
StepAtten1: Byte; // 58: ADC1 atten during TX
|
||||||
|
|||||||
+48
-42
@@ -303,7 +303,6 @@ type
|
|||||||
FWebBindAddr: string;
|
FWebBindAddr: string;
|
||||||
FWebUser: string;
|
FWebUser: string;
|
||||||
FWebPass: string;
|
FWebPass: string;
|
||||||
FSavedMicSource: TTXMicSource; // сохраняется при переключении на txmsWeb
|
|
||||||
FWebMicActive: Boolean; // True если текущий TX идёт через txmsWeb
|
FWebMicActive: Boolean; // True если текущий TX идёт через txmsWeb
|
||||||
// --- CAT ---
|
// --- CAT ---
|
||||||
FCATEngine: TCATEngine;
|
FCATEngine: TCATEngine;
|
||||||
@@ -659,6 +658,7 @@ type
|
|||||||
procedure TrkVolumeChange(Sender: TObject);
|
procedure TrkVolumeChange(Sender: TObject);
|
||||||
function CalcDriveByte: Byte;
|
function CalcDriveByte: Byte;
|
||||||
function ActiveTXFreqHz: Double;
|
function ActiveTXFreqHz: Double;
|
||||||
|
function DefaultMicSource: TTXMicSource;
|
||||||
procedure ApplyMOX(Active: Boolean);
|
procedure ApplyMOX(Active: Boolean);
|
||||||
procedure OnTXIQReady(const Buf: array of Double; Count: Integer);
|
procedure OnTXIQReady(const Buf: array of Double; Count: Integer);
|
||||||
procedure OnPASettingsChange(MaxPower: Double; const BandCal: array of Double);
|
procedure OnPASettingsChange(MaxPower: Double; const BandCal: array of Double);
|
||||||
@@ -2884,7 +2884,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if FTransmitting then
|
if FTransmitting then
|
||||||
begin
|
begin
|
||||||
if FTXSettings.MicSource = 1 then
|
if FDSPEngine.TXMicSource = txmsSoundCard then
|
||||||
StatusBar1.Panels[5].Text :=
|
StatusBar1.Panels[5].Text :=
|
||||||
Format('TX sc: avail=%d ring=%d',
|
Format('TX sc: avail=%d ring=%d',
|
||||||
[FAudioIn.Available, FDSPEngine.TXMicRingAvail])
|
[FAudioIn.Available, FDSPEngine.TXMicRingAvail])
|
||||||
@@ -3283,7 +3283,7 @@ begin
|
|||||||
// HW mic-стрим уходит в WDSP только если выбран источник Radio.
|
// HW mic-стрим уходит в WDSP только если выбран источник Radio.
|
||||||
// Иначе сэмплы игнорируются (mic берётся со звуковой карты).
|
// Иначе сэмплы игнорируются (mic берётся со звуковой карты).
|
||||||
if FTransmitting and FWDSPReady and
|
if FTransmitting and FWDSPReady and
|
||||||
(FTXSettings.MicSource = Ord(txmsRadio)) then
|
(FDSPEngine.TXMicSource = txmsRadio) then
|
||||||
FDSPEngine.PushTXMicSamples16(Data.Samples, 64);
|
FDSPEngine.PushTXMicSamples16(Data.Samples, 64);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -3293,18 +3293,21 @@ end;
|
|||||||
|
|
||||||
function TMainForm.BuildMicLineSelectByte: Byte;
|
function TMainForm.BuildMicLineSelectByte: Byte;
|
||||||
// openHPSDR Ethernet Protocol v4.3, DUC Specific byte 50:
|
// openHPSDR Ethernet Protocol v4.3, DUC Specific byte 50:
|
||||||
// bit 0 — Line in (1 = line-in вместо mic-in)
|
// bit 0 — Line In (1 = line-in вместо mic-in)
|
||||||
// bit 1 — Mic Boost (+20 dB)
|
// bit 1 — Mic Boost (+20 dB); не ставим когда Line In
|
||||||
// bit 2 — 0 = Orion mic PTT enabled, 1 = disabled (инверсия!)
|
// bit 2 — 0 = Orion mic PTT enabled, 1 = disabled (инверсия!)
|
||||||
// bit 3 — PTT/bias polarity (не используем)
|
// bit 3 — Tip/Ring (0=Tip, 1=Ring; Orion/OrionMkII)
|
||||||
// bit 4 — Orion mic bias (1 = enable +5V bias)
|
// bit 4 — Orion mic bias (1 = enable +5V bias)
|
||||||
// bit 5 — Saturn 3.5mm/XLR (не используем)
|
// bit 5 — Saturn XLR/balanced (не используем)
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
if FTXSettings.MicLineIn then Result := Result or $01;
|
if FTXSettings.MicLineIn then
|
||||||
if FTXSettings.MicBoost then Result := Result or $02;
|
Result := Result or $01 // bit 0: Line In
|
||||||
if not FTXSettings.MicPTTEnabled then Result := Result or $04;
|
else if FTXSettings.MicBoost then
|
||||||
if FTXSettings.MicBias then Result := Result or $10;
|
Result := Result or $02; // bit 1: Boost только при Mic In
|
||||||
|
if not FTXSettings.MicPTTEnabled then Result := Result or $04; // bit 2: инверсия
|
||||||
|
if FTXSettings.MicTipRing then Result := Result or $08; // bit 3: Ring
|
||||||
|
if FTXSettings.MicBias then Result := Result or $10; // bit 4: bias
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.SendDUCSpecificFromSettings;
|
procedure TMainForm.SendDUCSpecificFromSettings;
|
||||||
@@ -3326,6 +3329,9 @@ begin
|
|||||||
DUCPkt.DUC0RateLo := Lo(RateKsps);
|
DUCPkt.DUC0RateLo := Lo(RateKsps);
|
||||||
DUCPkt.DUC0Bits := 24;
|
DUCPkt.DUC0Bits := 24;
|
||||||
DUCPkt.MicLineSelect := BuildMicLineSelectByte;
|
DUCPkt.MicLineSelect := BuildMicLineSelectByte;
|
||||||
|
// Line In Gain (byte 51): 0=-34.5dB .. 31=+12dB (шаг 1.5 dB, формула Thetis).
|
||||||
|
// При Mic In значение игнорируется железом, но шлём корректное для Line In.
|
||||||
|
DUCPkt.LineInGain := Byte(EnsureRange(Round((FTXSettings.LineInGainDB + 34.5) / 1.5), 0, 31));
|
||||||
// ATT on TX — RX-ADC step attenuator во время передачи (Thetis-style protection).
|
// ATT on TX — RX-ADC step attenuator во время передачи (Thetis-style protection).
|
||||||
// Дублируем значение во все три ADC-байта: на однопотоковых платах активен только
|
// Дублируем значение во все три ADC-байта: на однопотоковых платах активен только
|
||||||
// ADC0, на Saturn/Hermes Lite 2 — могут использоваться ADC1/ADC2.
|
// ADC0, на Saturn/Hermes Lite 2 — могут использоваться ADC1/ADC2.
|
||||||
@@ -3335,11 +3341,21 @@ begin
|
|||||||
FNetwork.SendDUCSpecific(DUCPkt);
|
FNetwork.SendDUCSpecific(DUCPkt);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TMainForm.DefaultMicSource: TTXMicSource;
|
||||||
|
// Mic source для MOX-кнопки и Web-TX: если настроена звуковая карта — берём с неё,
|
||||||
|
// иначе используем HW mic-стрим от трансивера.
|
||||||
|
// HW PTT всегда переключает на txmsRadio непосредственно в ApplyMOX.
|
||||||
|
begin
|
||||||
|
if FAudioInDevName <> '' then Result := txmsSoundCard
|
||||||
|
else Result := txmsRadio;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TMainForm.ApplyTXSettingsToDSP;
|
procedure TMainForm.ApplyTXSettingsToDSP;
|
||||||
begin
|
begin
|
||||||
if not FWDSPReady then Exit;
|
if not FWDSPReady then Exit;
|
||||||
// Mic source — сначала, чтобы PullSoundCardMic уже видел правильное значение
|
// Mic source — выставляем значение по умолчанию для MOX-кнопки;
|
||||||
FDSPEngine.SetTXMicSource(TTXMicSource(FTXSettings.MicSource));
|
// при реальном PTT ApplyMOX скорректирует источник.
|
||||||
|
FDSPEngine.SetTXMicSource(DefaultMicSource);
|
||||||
FDSPEngine.SetMicGain(FTXSettings.MicGainDB);
|
FDSPEngine.SetMicGain(FTXSettings.MicGainDB);
|
||||||
FDSPEngine.SetTXFilterFull(FTXSettings.FilterLow, FTXSettings.FilterHigh,
|
FDSPEngine.SetTXFilterFull(FTXSettings.FilterLow, FTXSettings.FilterHigh,
|
||||||
FTXSettings.FilterNC, FTXSettings.FilterMP,
|
FTXSettings.FilterNC, FTXSettings.FilterMP,
|
||||||
@@ -3368,7 +3384,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TMainForm.PullSoundCardMic(MaxN: Integer): Integer;
|
function TMainForm.PullSoundCardMic(MaxN: Integer): Integer;
|
||||||
// Колбэк, который TTXDSPThread зовёт при MicSource=SoundCard.
|
// Колбэк, который TTXDSPThread зовёт при TXMicSource=txmsSoundCard.
|
||||||
// Тянем только реально доступные сэмплы из FAudioIn — иначе мы пушили бы
|
// Тянем только реально доступные сэмплы из FAudioIn — иначе мы пушили бы
|
||||||
// нули и mic-цепь в WDSP получала бы тишину вместо реального сигнала.
|
// нули и mic-цепь в WDSP получала бы тишину вместо реального сигнала.
|
||||||
// Читаем пачкой в локальный буфер и пушим одним вызовом — экономим
|
// Читаем пачкой в локальный буфер и пушим одним вызовом — экономим
|
||||||
@@ -3849,15 +3865,13 @@ begin
|
|||||||
FAudioOutDevName := '';
|
FAudioOutDevName := '';
|
||||||
end;
|
end;
|
||||||
FAudioOut.Open;
|
FAudioOut.Open;
|
||||||
// Аудио устройство ввода (TX mic). Если в настройках выбрана конкретная
|
// Аудио устройство ввода (TX mic). MicSource (Radio/SoundCard) определяется
|
||||||
// soundcard — открываем её и принудительно переключаем MicSource на SoundCard,
|
// автоматически в ApplyMOX по источнику PTT — здесь только открываем устройство.
|
||||||
// иначе пользователь нажмёт MOX и не поймёт почему его микрофон молчит.
|
|
||||||
if G_Settings.AudioInDevice <> '' then
|
if G_Settings.AudioInDevice <> '' then
|
||||||
begin
|
begin
|
||||||
FAudioIn.DeviceIndex := FAudioIn.FindDeviceByName(G_Settings.AudioInDevice);
|
FAudioIn.DeviceIndex := FAudioIn.FindDeviceByName(G_Settings.AudioInDevice);
|
||||||
FAudioInDevName := G_Settings.AudioInDevice;
|
FAudioInDevName := G_Settings.AudioInDevice;
|
||||||
FAudioIn.Open;
|
FAudioIn.Open;
|
||||||
FTXSettings.MicSource := 1; // SoundCard
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@@ -5085,18 +5099,26 @@ begin
|
|||||||
end;
|
end;
|
||||||
if FWDSPReady then
|
if FWDSPReady then
|
||||||
begin
|
begin
|
||||||
// Переключаем источник микрофона: при TX из браузера — txmsWeb,
|
// Mic source — определяем автоматически по источнику TX:
|
||||||
// при TX с кнопки без веб-клиента — штатный источник из настроек.
|
// Web TX → txmsWeb
|
||||||
if FTransmitting and Assigned(FWebServer) and FWebServer.WebClientActive then
|
// HW PTT (FHWPTTActive при входе в ApplyMOX уже True) → txmsRadio
|
||||||
|
// MOX-кнопка/CAT → sound card если настроена, иначе txmsRadio
|
||||||
|
if FTransmitting then
|
||||||
|
begin
|
||||||
|
if Assigned(FWebServer) and FWebServer.WebClientActive then
|
||||||
begin
|
begin
|
||||||
FSavedMicSource := TTXMicSource(FTXSettings.MicSource);
|
|
||||||
FWebMicActive := True;
|
FWebMicActive := True;
|
||||||
FDSPEngine.SetTXMicSource(txmsWeb);
|
FDSPEngine.SetTXMicSource(txmsWeb);
|
||||||
end
|
end
|
||||||
else if not FTransmitting and FWebMicActive then
|
else if FHWPTTActive then
|
||||||
|
FDSPEngine.SetTXMicSource(txmsRadio)
|
||||||
|
else
|
||||||
|
FDSPEngine.SetTXMicSource(DefaultMicSource);
|
||||||
|
end
|
||||||
|
else if FWebMicActive then
|
||||||
begin
|
begin
|
||||||
FWebMicActive := False;
|
FWebMicActive := False;
|
||||||
FDSPEngine.SetTXMicSource(FSavedMicSource);
|
FDSPEngine.SetTXMicSource(DefaultMicSource);
|
||||||
end;
|
end;
|
||||||
// В non-DUP RX-IQ пакеты дропаются на входе DSP-потока во время TX,
|
// В non-DUP RX-IQ пакеты дропаются на входе DSP-потока во время TX,
|
||||||
// чтобы TX leakage не накапливался в RXA pipeline и FFT-истории
|
// чтобы TX leakage не накапливался в RXA pipeline и FFT-истории
|
||||||
@@ -6683,26 +6705,9 @@ begin
|
|||||||
on E: Exception do
|
on E: Exception do
|
||||||
StatusBar1.Panels[3].Text := 'Mic err: ' + E.Message;
|
StatusBar1.Panels[3].Text := 'Mic err: ' + E.Message;
|
||||||
end;
|
end;
|
||||||
// Автопереключение mic-источника: явный выбор PortAudio-устройства
|
|
||||||
// → берём mic со звуковой карты, иначе HW mic-стрим бы перебивал его.
|
|
||||||
FTXSettings.MicSource := 1; // SoundCard
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
|
||||||
StatusBar1.Panels[3].Text := 'Mic: none';
|
StatusBar1.Panels[3].Text := 'Mic: none';
|
||||||
// Нет выбранного soundcard mic → возвращаемся на HW mic-стрим.
|
|
||||||
FTXSettings.MicSource := 0; // Radio
|
|
||||||
end;
|
|
||||||
if FWDSPReady then
|
|
||||||
FDSPEngine.SetTXMicSource(TTXMicSource(FTXSettings.MicSource));
|
|
||||||
if FDevConnected then
|
|
||||||
begin
|
|
||||||
FSettings.SaveTX(FDevMAC, FTXSettings);
|
|
||||||
FSettings.Save;
|
|
||||||
end;
|
|
||||||
// Если открыт диалог настроек — синхронизировать UI
|
|
||||||
if Assigned(FSettingsForm) then
|
|
||||||
TSettingsForm(FSettingsForm).LoadTXSettings(FTXSettings);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.ApplyVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
procedure TMainForm.ApplyVisibility(ShowSpectrum, ShowWaterfall: Boolean);
|
||||||
@@ -6770,7 +6775,8 @@ begin
|
|||||||
SF.OnWebSettingsChange := ApplyWebSettings;
|
SF.OnWebSettingsChange := ApplyWebSettings;
|
||||||
end;
|
end;
|
||||||
SF := TSettingsForm(FSettingsForm);
|
SF := TSettingsForm(FSettingsForm);
|
||||||
SF.LoadTXSettings(FTXSettings);
|
SF.LoadTXSettings(FTXSettings,
|
||||||
|
IfThen(FNetwork.Connected, FNetwork.Device.BoardType, FPendingBoardType));
|
||||||
SF.LoadAlexSettings(FAlexSettings,
|
SF.LoadAlexSettings(FAlexSettings,
|
||||||
IfThen(FNetwork.Connected, FNetwork.Device.BoardType, FPendingBoardType));
|
IfThen(FNetwork.Connected, FNetwork.Device.BoardType, FPendingBoardType));
|
||||||
SF.LoadXvtrSettings(FXvtrSettings);
|
SF.LoadXvtrSettings(FXvtrSettings);
|
||||||
|
|||||||
+19
-19
@@ -44,16 +44,14 @@ type
|
|||||||
|
|
||||||
// TX-настройки per-device. Хранятся в JSON-секции "tx" под MAC,
|
// TX-настройки per-device. Хранятся в JSON-секции "tx" под MAC,
|
||||||
// отдельно от global/bands. Применяются к WDSP через SetTX* методы.
|
// отдельно от global/bands. Применяются к WDSP через SetTX* методы.
|
||||||
// (Тип TTXMicSource живёт в WDSPEngine — здесь храним как Integer,
|
|
||||||
// чтобы не тащить циклическую зависимость с WDSPEngine.)
|
|
||||||
TTXSettings = record
|
TTXSettings = record
|
||||||
// Mic source select
|
// Radio mic options (DUC Specific byte 50/51)
|
||||||
MicSource: Integer; // 0=Radio, 1=SoundCard
|
MicLineIn: Boolean; // bit0: 1=Line In, 0=Mic In
|
||||||
// Radio mic options (DUC Specific byte 50 bits)
|
MicBoost: Boolean; // bit1: +20 dB preamp (только когда Mic In)
|
||||||
MicBoost: Boolean; // bit0: +20 dB
|
MicPTTEnabled: Boolean; // bit2: Mic PTT enable (Orion)
|
||||||
MicBias: Boolean; // bit4: электретный bias
|
MicTipRing: Boolean; // bit3: False=Tip, True=Ring (Orion/OrionMkII)
|
||||||
MicLineIn: Boolean; // bit1: 1=Line in, 0=Mic in
|
MicBias: Boolean; // bit4: электретный +5V bias (Orion)
|
||||||
MicPTTEnabled: Boolean; // bit2: Mic PTT enable
|
LineInGainDB: Double; // byte51: -34.5..+12 dB (шаг 1.5; только когда Line In)
|
||||||
// Mic gain (dB, применяется в WDSP PanelGain1)
|
// Mic gain (dB, применяется в WDSP PanelGain1)
|
||||||
MicGainDB: Double; // -10..+30
|
MicGainDB: Double; // -10..+30
|
||||||
// ATT on TX — ослабление RX-ADC во время передачи (защита от утечки TX).
|
// ATT on TX — ослабление RX-ADC во время передачи (защита от утечки TX).
|
||||||
@@ -854,12 +852,12 @@ const
|
|||||||
100, 200, 400, 700, 1100, 1500, 2000, 2500, 3000, 3500);
|
100, 200, 400, 700, 1100, 1500, 2000, 2500, 3000, 3500);
|
||||||
begin
|
begin
|
||||||
FillChar(T, SizeOf(T), 0);
|
FillChar(T, SizeOf(T), 0);
|
||||||
// Mic source — Radio (HW). 0=Radio, 1=SoundCard (синхронно с TTXMicSource в WDSPEngine).
|
|
||||||
T.MicSource := 0;
|
|
||||||
T.MicBoost := False;
|
|
||||||
T.MicBias := True;
|
|
||||||
T.MicLineIn := False;
|
T.MicLineIn := False;
|
||||||
|
T.MicBoost := False;
|
||||||
T.MicPTTEnabled := False;
|
T.MicPTTEnabled := False;
|
||||||
|
T.MicTipRing := False; // Tip (mic at Tip, PTT at Ring)
|
||||||
|
T.MicBias := True;
|
||||||
|
T.LineInGainDB := 0.0; // 0 dB
|
||||||
T.MicGainDB := 10.0;
|
T.MicGainDB := 10.0;
|
||||||
// ATT on TX — Thetis default 31 dB (полная защита RX-ADC во время передачи)
|
// ATT on TX — Thetis default 31 dB (полная защита RX-ADC во время передачи)
|
||||||
T.AttOnTX := 31;
|
T.AttOnTX := 31;
|
||||||
@@ -933,11 +931,12 @@ begin
|
|||||||
if DevObj.Find('tx') = nil then Exit;
|
if DevObj.Find('tx') = nil then Exit;
|
||||||
O := EnsureObj(DevObj, 'tx');
|
O := EnsureObj(DevObj, 'tx');
|
||||||
|
|
||||||
T.MicSource := JI(O,'mic_source', T.MicSource);
|
|
||||||
T.MicBoost := JB(O,'mic_boost', T.MicBoost);
|
|
||||||
T.MicBias := JB(O,'mic_bias', T.MicBias);
|
|
||||||
T.MicLineIn := JB(O,'mic_line_in', T.MicLineIn);
|
T.MicLineIn := JB(O,'mic_line_in', T.MicLineIn);
|
||||||
|
T.MicBoost := JB(O,'mic_boost', T.MicBoost);
|
||||||
T.MicPTTEnabled := JB(O,'mic_ptt_enabled', T.MicPTTEnabled);
|
T.MicPTTEnabled := JB(O,'mic_ptt_enabled', T.MicPTTEnabled);
|
||||||
|
T.MicTipRing := JB(O,'mic_tip_ring', T.MicTipRing);
|
||||||
|
T.MicBias := JB(O,'mic_bias', T.MicBias);
|
||||||
|
T.LineInGainDB := EnsureRange(JD(O,'line_in_gain_db', T.LineInGainDB), -34.5, 12.0);
|
||||||
T.MicGainDB := JD(O,'mic_gain_db', T.MicGainDB);
|
T.MicGainDB := JD(O,'mic_gain_db', T.MicGainDB);
|
||||||
T.AttOnTX := EnsureRange(JI(O,'att_on_tx', T.AttOnTX), 0, 31);
|
T.AttOnTX := EnsureRange(JI(O,'att_on_tx', T.AttOnTX), 0, 31);
|
||||||
T.TUNLevel := EnsureRange(JI(O,'tun_level', T.TUNLevel), 0, 100);
|
T.TUNLevel := EnsureRange(JI(O,'tun_level', T.TUNLevel), 0, 100);
|
||||||
@@ -990,11 +989,12 @@ procedure TSettingsManager.SaveTX(const MAC: array of Byte;
|
|||||||
var O: TJSONObject; i: Integer;
|
var O: TJSONObject; i: Integer;
|
||||||
begin
|
begin
|
||||||
O := EnsureObj(GetDevObj(MacToStr(MAC)), 'tx');
|
O := EnsureObj(GetDevObj(MacToStr(MAC)), 'tx');
|
||||||
JW(O,'mic_source', T.MicSource);
|
|
||||||
JW(O,'mic_boost', T.MicBoost);
|
|
||||||
JW(O,'mic_bias', T.MicBias);
|
|
||||||
JW(O,'mic_line_in', T.MicLineIn);
|
JW(O,'mic_line_in', T.MicLineIn);
|
||||||
|
JW(O,'mic_boost', T.MicBoost);
|
||||||
JW(O,'mic_ptt_enabled', T.MicPTTEnabled);
|
JW(O,'mic_ptt_enabled', T.MicPTTEnabled);
|
||||||
|
JW(O,'mic_tip_ring', T.MicTipRing);
|
||||||
|
JW(O,'mic_bias', T.MicBias);
|
||||||
|
JW(O,'line_in_gain_db', T.LineInGainDB);
|
||||||
JW(O,'mic_gain_db', T.MicGainDB);
|
JW(O,'mic_gain_db', T.MicGainDB);
|
||||||
JW(O,'att_on_tx', T.AttOnTX);
|
JW(O,'att_on_tx', T.AttOnTX);
|
||||||
JW(O,'tun_level', T.TUNLevel);
|
JW(O,'tun_level', T.TUNLevel);
|
||||||
|
|||||||
+72
-31
@@ -129,12 +129,14 @@ type
|
|||||||
// ---- Transmit tab controls ----
|
// ---- Transmit tab controls ----
|
||||||
// Текущее состояние, отдаётся в OnTXChange целиком при любой правке.
|
// Текущее состояние, отдаётся в OnTXChange целиком при любой правке.
|
||||||
FTX: TTXSettings;
|
FTX: TTXSettings;
|
||||||
// Mic source / options
|
FCmbTXMicJack: TComboBox; // "Mic In" / "Line In"
|
||||||
FCmbTXMicSource: TComboBox;
|
FChkTXMicBoost: TCheckBox; // +20 dB (только Mic In)
|
||||||
FChkTXMicBoost: TCheckBox;
|
FLblLineInGain: TLabel; // метка "Line In gain" (только Line In)
|
||||||
|
FEdLineInGain: TFloatSpinEdit; // -34.5..+12 dB, шаг 1.5 (только Line In)
|
||||||
FChkTXMicBias: TCheckBox;
|
FChkTXMicBias: TCheckBox;
|
||||||
FChkTXMicLineIn: TCheckBox;
|
|
||||||
FChkTXMicPTT: TCheckBox;
|
FChkTXMicPTT: TCheckBox;
|
||||||
|
FCmbTXMicTR: TComboBox; // "Tip" / "Ring" (только Orion)
|
||||||
|
FLblTipRing: TLabel; // метка (только Orion)
|
||||||
FEdTXMicGain: TFloatSpinEdit;
|
FEdTXMicGain: TFloatSpinEdit;
|
||||||
FEdTXAttOnTX: TSpinEdit;
|
FEdTXAttOnTX: TSpinEdit;
|
||||||
// Tune (TUN button)
|
// Tune (TUN button)
|
||||||
@@ -296,6 +298,8 @@ type
|
|||||||
procedure CollectTXFromUI;
|
procedure CollectTXFromUI;
|
||||||
procedure FireTXChange;
|
procedure FireTXChange;
|
||||||
procedure OnTXAnyChange(Sender: TObject);
|
procedure OnTXAnyChange(Sender: TObject);
|
||||||
|
procedure OnMicJackChange(Sender: TObject);
|
||||||
|
procedure UpdateMicJackVisibility;
|
||||||
procedure ApplyTheme(const T: TAppTheme);
|
procedure ApplyTheme(const T: TAppTheme);
|
||||||
procedure NavClick(Sender: TObject);
|
procedure NavClick(Sender: TObject);
|
||||||
procedure SelectPage(APage: TWinControl; ANav: TFlatButton);
|
procedure SelectPage(APage: TWinControl; ANav: TFlatButton);
|
||||||
@@ -374,7 +378,7 @@ type
|
|||||||
const SerPort: array of string;
|
const SerPort: array of string;
|
||||||
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
|
const SerBaud, SerDataBits, SerStopBits, SerParity: array of Integer;
|
||||||
TcpEnabled: Boolean; TcpPort: Integer);
|
TcpEnabled: Boolean; TcpPort: Integer);
|
||||||
procedure LoadTXSettings(const T: TTXSettings);
|
procedure LoadTXSettings(const T: TTXSettings; BoardType: Integer = 0);
|
||||||
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
|
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
|
||||||
procedure LoadXvtrSettings(const X: TXvtrSettings);
|
procedure LoadXvtrSettings(const X: TXvtrSettings);
|
||||||
procedure LoadWfAGCNF(AGC, NF: Boolean);
|
procedure LoadWfAGCNF(AGC, NF: Boolean);
|
||||||
@@ -1083,31 +1087,43 @@ begin
|
|||||||
Font.Color := CLR_TEXTDIM;
|
Font.Color := CLR_TEXTDIM;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ---- Mic source / options ----
|
// ---- Mic options ----
|
||||||
|
// Mic source (Radio vs SoundCard) определяется автоматически по источнику PTT.
|
||||||
Y := 86;
|
Y := 86;
|
||||||
Grp := MakeGroupPanel(FPageTransmit, 'Microphone', MARGIN, Y, 700, 220);
|
Grp := MakeGroupPanel(FPageTransmit, 'Microphone', MARGIN, Y, 700, 188);
|
||||||
|
|
||||||
MakeLbl(Grp, 'Mic source', PAD, R1 + 5, LW);
|
// Row 0: Mic jack selector | Boost (Mic In) или LineInGain (Line In) | Bias | PTT
|
||||||
FCmbTXMicSource := MkCmb(Grp, CX, R1, CMB_W);
|
MakeLbl(Grp, 'Mic jack', PAD, R1 + 5, 65);
|
||||||
FCmbTXMicSource.Items.Add('Radio (HW mic)');
|
FCmbTXMicJack := MkCmb(Grp, PAD + 68, R1, 110);
|
||||||
FCmbTXMicSource.Items.Add('Sound card');
|
FCmbTXMicJack.Items.Add('Mic In');
|
||||||
FCmbTXMicSource.ItemIndex := 0;
|
FCmbTXMicJack.Items.Add('Line In');
|
||||||
|
FCmbTXMicJack.ItemIndex := 0;
|
||||||
|
FCmbTXMicJack.OnChange := OnMicJackChange;
|
||||||
|
|
||||||
FChkTXMicBoost := MkChk(Grp, PAD, R1 + STEP, 200, 'Mic boost +20 dB');
|
FChkTXMicBoost := MkChk(Grp, PAD + 190, R1, 165, 'Mic boost +20 dB');
|
||||||
FChkTXMicBias := MkChk(Grp, PAD + 200, R1 + STEP, 200, 'Mic bias');
|
FLblLineInGain := MakeLbl(Grp, 'Line In gain', PAD + 190, R1 + 5, 80);
|
||||||
FChkTXMicLineIn := MkChk(Grp, PAD + 400, R1 + STEP, 160, 'Line in');
|
FEdLineInGain := MkFloat(Grp, PAD + 190 + 82, R1, 0.0, -34.5, 12.0, 1.5);
|
||||||
FChkTXMicPTT := MkChk(Grp, PAD, R1 + 2 * STEP, 220, 'Mic-jack PTT');
|
FEdLineInGain.DecimalPlaces := 1;
|
||||||
|
FChkTXMicBias := MkChk(Grp, PAD + 375, R1, 105, 'Mic bias');
|
||||||
|
FChkTXMicPTT := MkChk(Grp, PAD + 490, R1, 160, 'Mic-jack PTT');
|
||||||
|
|
||||||
MakeLbl(Grp, 'Mic gain (dB)', PAD, R1 + 3 * STEP + 5, LW);
|
// Row 1: Connector Tip/Ring (только Orion boards 4 и 5)
|
||||||
FEdTXMicGain := MkFloat(Grp, CX, R1 + 3 * STEP, 10.0, -20.0, 60.0, 0.5);
|
FLblTipRing := MakeLbl(Grp, 'Connector', PAD, R1 + STEP + 5, 70);
|
||||||
|
FCmbTXMicTR := MkCmb(Grp, PAD + 73, R1 + STEP, 90);
|
||||||
|
FCmbTXMicTR.Items.Add('Tip'); // MicTipRing=False, bit3=0
|
||||||
|
FCmbTXMicTR.Items.Add('Ring'); // MicTipRing=True, bit3=1
|
||||||
|
FCmbTXMicTR.ItemIndex := 0;
|
||||||
|
FLblTipRing.Visible := False;
|
||||||
|
FCmbTXMicTR.Visible := False;
|
||||||
|
|
||||||
// ATT on TX — RX-ADC ослабление во время передачи (DUC Specific bytes 57/58/59).
|
// Row 2: Mic gain | ATT on TX
|
||||||
// Thetis-style default 31 dB. Помещаем на той же строке, что и Mic gain.
|
MakeLbl(Grp, 'Mic gain (dB)', PAD, R1 + 2 * STEP + 5, LW);
|
||||||
MakeLbl(Grp, 'ATT on TX (dB)', PAD + 320, R1 + 3 * STEP + 5, 110);
|
FEdTXMicGain := MkFloat(Grp, CX, R1 + 2 * STEP, 10.0, -20.0, 60.0, 0.5);
|
||||||
FEdTXAttOnTX := MkSpin(Grp, PAD + 320 + 120, R1 + 3 * STEP, 0, 31, 31);
|
MakeLbl(Grp, 'ATT on TX (dB)', PAD + 320, R1 + 2 * STEP + 5, 110);
|
||||||
|
FEdTXAttOnTX := MkSpin(Grp, PAD + 320 + 120, R1 + 2 * STEP, 0, 31, 31);
|
||||||
|
|
||||||
// ---- Tune (TUN button) ----
|
// ---- Tune (TUN button) ----
|
||||||
Inc(Y, 220 + 12);
|
Inc(Y, 188 + 12);
|
||||||
Grp := MakeGroupPanel(FPageTransmit, 'Tune (TUN)', MARGIN, Y, 700, 100);
|
Grp := MakeGroupPanel(FPageTransmit, 'Tune (TUN)', MARGIN, Y, 700, 100);
|
||||||
|
|
||||||
MakeLbl(Grp, 'Tune level (%)', PAD, R1 + 5, LW);
|
MakeLbl(Grp, 'Tune level (%)', PAD, R1 + 5, LW);
|
||||||
@@ -1287,12 +1303,12 @@ end;
|
|||||||
procedure TSettingsForm.CollectTXFromUI;
|
procedure TSettingsForm.CollectTXFromUI;
|
||||||
var i: Integer;
|
var i: Integer;
|
||||||
begin
|
begin
|
||||||
if FCmbTXMicSource <> nil then
|
if FCmbTXMicJack <> nil then FTX.MicLineIn := FCmbTXMicJack.ItemIndex = 1;
|
||||||
FTX.MicSource := Max(0, FCmbTXMicSource.ItemIndex);
|
|
||||||
if FChkTXMicBoost <> nil then FTX.MicBoost := FChkTXMicBoost.Checked;
|
if FChkTXMicBoost <> nil then FTX.MicBoost := FChkTXMicBoost.Checked;
|
||||||
|
if FEdLineInGain <> nil then FTX.LineInGainDB := FEdLineInGain.Value;
|
||||||
if FChkTXMicBias <> nil then FTX.MicBias := FChkTXMicBias.Checked;
|
if FChkTXMicBias <> nil then FTX.MicBias := FChkTXMicBias.Checked;
|
||||||
if FChkTXMicLineIn <> nil then FTX.MicLineIn := FChkTXMicLineIn.Checked;
|
|
||||||
if FChkTXMicPTT <> nil then FTX.MicPTTEnabled := FChkTXMicPTT.Checked;
|
if FChkTXMicPTT <> nil then FTX.MicPTTEnabled := FChkTXMicPTT.Checked;
|
||||||
|
if FCmbTXMicTR <> nil then FTX.MicTipRing := FCmbTXMicTR.ItemIndex = 1;
|
||||||
if FEdTXMicGain <> nil then FTX.MicGainDB := FEdTXMicGain.Value;
|
if FEdTXMicGain <> nil then FTX.MicGainDB := FEdTXMicGain.Value;
|
||||||
if FEdTXAttOnTX <> nil then FTX.AttOnTX := FEdTXAttOnTX.Value;
|
if FEdTXAttOnTX <> nil then FTX.AttOnTX := FEdTXAttOnTX.Value;
|
||||||
if FEdTUNLevel <> nil then FTX.TUNLevel := FEdTUNLevel.Value;
|
if FEdTUNLevel <> nil then FTX.TUNLevel := FEdTUNLevel.Value;
|
||||||
@@ -1368,18 +1384,43 @@ begin
|
|||||||
FireTXChange;
|
FireTXChange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSettingsForm.LoadTXSettings(const T: TTXSettings);
|
procedure TSettingsForm.UpdateMicJackVisibility;
|
||||||
var i: Integer;
|
var LineIn: Boolean;
|
||||||
|
begin
|
||||||
|
if FCmbTXMicJack = nil then Exit;
|
||||||
|
LineIn := FCmbTXMicJack.ItemIndex = 1;
|
||||||
|
if FChkTXMicBoost <> nil then FChkTXMicBoost.Visible := not LineIn;
|
||||||
|
if FLblLineInGain <> nil then FLblLineInGain.Visible := LineIn;
|
||||||
|
if FEdLineInGain <> nil then FEdLineInGain.Visible := LineIn;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.OnMicJackChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
UpdateMicJackVisibility;
|
||||||
|
FireTXChange;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.LoadTXSettings(const T: TTXSettings; BoardType: Integer = 0);
|
||||||
|
var i: Integer; IsOrion: Boolean;
|
||||||
begin
|
begin
|
||||||
FLoading := True;
|
FLoading := True;
|
||||||
try
|
try
|
||||||
FTX := T;
|
FTX := T;
|
||||||
if FCmbTXMicSource <> nil then
|
if FCmbTXMicJack <> nil then
|
||||||
FCmbTXMicSource.ItemIndex := EnsureRange(T.MicSource, 0, FCmbTXMicSource.Items.Count - 1);
|
FCmbTXMicJack.ItemIndex := IfThen(T.MicLineIn, 1, 0);
|
||||||
|
UpdateMicJackVisibility;
|
||||||
if FChkTXMicBoost <> nil then FChkTXMicBoost.Checked := T.MicBoost;
|
if FChkTXMicBoost <> nil then FChkTXMicBoost.Checked := T.MicBoost;
|
||||||
|
if FEdLineInGain <> nil then FEdLineInGain.Value := EnsureRange(T.LineInGainDB, -34.5, 12.0);
|
||||||
if FChkTXMicBias <> nil then FChkTXMicBias.Checked := T.MicBias;
|
if FChkTXMicBias <> nil then FChkTXMicBias.Checked := T.MicBias;
|
||||||
if FChkTXMicLineIn <> nil then FChkTXMicLineIn.Checked := T.MicLineIn;
|
|
||||||
if FChkTXMicPTT <> nil then FChkTXMicPTT.Checked := T.MicPTTEnabled;
|
if FChkTXMicPTT <> nil then FChkTXMicPTT.Checked := T.MicPTTEnabled;
|
||||||
|
// Tip/Ring (Orion boards 4 и 5)
|
||||||
|
IsOrion := BoardType in [4, 5];
|
||||||
|
if FLblTipRing <> nil then FLblTipRing.Visible := IsOrion;
|
||||||
|
if FCmbTXMicTR <> nil then
|
||||||
|
begin
|
||||||
|
FCmbTXMicTR.Visible := IsOrion;
|
||||||
|
FCmbTXMicTR.ItemIndex := IfThen(T.MicTipRing, 1, 0);
|
||||||
|
end;
|
||||||
if FEdTXMicGain <> nil then FEdTXMicGain.Value := T.MicGainDB;
|
if FEdTXMicGain <> nil then FEdTXMicGain.Value := T.MicGainDB;
|
||||||
if FEdTXAttOnTX <> nil then FEdTXAttOnTX.Value := EnsureRange(T.AttOnTX, 0, 31);
|
if FEdTXAttOnTX <> nil then FEdTXAttOnTX.Value := EnsureRange(T.AttOnTX, 0, 31);
|
||||||
if FEdTUNLevel <> nil then FEdTUNLevel.Value := EnsureRange(T.TUNLevel, 0, 100);
|
if FEdTUNLevel <> nil then FEdTUNLevel.Value := EnsureRange(T.TUNLevel, 0, 100);
|
||||||
|
|||||||
Reference in New Issue
Block a user