From 6195c80ce3b9b0528ffb3a69afa042858490ad3f Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 5 Aug 2026 19:09:31 +0300 Subject: [PATCH] =?UTF-8?q?fix(tx):=20=D0=BF=D0=BE=D0=BB=D0=BE=D1=81=D0=B0?= =?UTF-8?q?=20=D0=A7=D0=9C=20=D0=BD=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=20=E2=80=94=20=D0=B7=D0=B0=D0=BD=D0=B8=D0=BC?= =?UTF-8?q?=D0=B0=D0=B5=D0=BC=D0=B0=D1=8F=20=D0=BF=D0=BE=D0=BB=D0=BE=D1=81?= =?UTF-8?q?=D0=B0,=20=D0=B0=20=D0=BD=D0=B5=20=D0=BA=D1=80=D0=BE=D0=BC?= =?UTF-8?q?=D0=BA=D0=B8=20bp0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TXFilterEdgesHz была тонкой обёрткой над TXSignedEdges, то есть отдавала в отрисовку кромки аудио-полосовика перед модулятором. У SSB/CW/DIGI/AM это то же самое, что полоса вокруг несущей, а у ЧМ — нет: FM RAW рисовался как (20..7000), WFM как (20..15000), то есть полоса уезжала вверх от несущей и визуально «переключалась на USB». Теперь у экранных кромок своя семантика — Карсон ±(девиация + верхний срез аудио) для FM/WFM/FM RAW, остальные режимы как были. TXSignedEdges и SetTXABandpassFreqs не тронуты: bp0 остаётся портом Thetis, в эфире ничего не меняется. Попутно 20.0/7000.0 из трёх мест FM RAW сведены в RAW_AF_LOW/RAW_AF_HIGH. Co-Authored-By: Claude Opus 5 --- WDSPEngine.pas | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/WDSPEngine.pas b/WDSPEngine.pas index 46c3a2b..6607bc1 100644 --- a/WDSPEngine.pas +++ b/WDSPEngine.pas @@ -78,6 +78,10 @@ const WFM_AF_HIGH = 15000.0; WFM_TAU_DE_US = 50.0e-6; // Европа/Россия (Америка — 75 мкс) DMR_DEVIATION = 2500.0; + // FM RAW: плоский baseband для внешних декодеров — одна величина на RX-AF, + // TX-AF и bp0 (раньше 20/7000 стояли числами в трёх местах). + RAW_AF_LOW = 20.0; + RAW_AF_HIGH = 7000.0; // Потолок dsp_rate для WFM. Вещательному каналу (200 кГц) хватает 192 кГц, // а гнать цепь на полном IQ-rate нельзя: при 576 кГц dsp_size стал бы 12288, // и fircore спланировал бы FFT на 2*12288 = 24576 точек. Это не степень @@ -1167,7 +1171,7 @@ procedure TWDSPEngine.ApplyRXRawToChan(Chan: Integer); begin // Decoder-grade discriminator: no broadcast de-emphasis or limiter. SetRXAWFMDeviation (Chan, FRawFMDeviation); - SetRXAWFMAFFilter (Chan, 20.0, 7000.0); + SetRXAWFMAFFilter (Chan, RAW_AF_LOW, RAW_AF_HIGH); SetRXAWFMDeemphRun (Chan, 0); SetRXAWFMLimRun (Chan, 0); end; @@ -1221,7 +1225,7 @@ begin // Плоский baseband для внешних декодеров (совпадает с RX AF в ApplyRXRawToChan // и с явным SetTXABandpassFreqs в ApplyTXModeSettings). РЧ-ширина FILT_RAW_BW // (6..25 кГц) — селективность RX, к аудио-полосовику отношения не имеет. - begin Lo := 20.0; Hi := 7000.0; end; + begin Lo := RAW_AF_LOW; Hi := RAW_AF_HIGH; end; else begin Lo := L; Hi := H; end; // прочее — как есть end; @@ -1236,9 +1240,9 @@ begin // selected peak deviation. Keep only a broad linear-phase AF bandpass; // APRS and other external modems must not see voice EQ, dynamics or emphasis. SetTXAWFMDeviation (TXA_CHAN, FRawFMDeviation); - SetTXAWFMAFFreqs (TXA_CHAN, 20.0, 7000.0); + SetTXAWFMAFFreqs (TXA_CHAN, RAW_AF_LOW, RAW_AF_HIGH); SetTXAWFMPreEmphRun (TXA_CHAN, 0); - SetTXABandpassFreqs (TXA_CHAN, 20.0, 7000.0); + SetTXABandpassFreqs (TXA_CHAN, RAW_AF_LOW, RAW_AF_HIGH); SetTXAPanelGain1 (TXA_CHAN, 1.0); SetTXACompressorRun (TXA_CHAN, 0); SetTXALevelerSt (TXA_CHAN, 0); @@ -3715,8 +3719,27 @@ begin end; procedure TWDSPEngine.TXFilterEdgesHz(out Lo, Hi: Integer); -var L, H: Double; +// ЭКРАННЫЕ кромки — занимаемая полоса вокруг несущей, а НЕ bp0. У SSB/CW/DIGI/ +// AM/DSB это одно и то же, поэтому здесь и стояла обёртка над TXSignedEdges. +// Но у ЧМ bp0 — АУДИО-полосовик ПЕРЕД модулятором: у FM RAW он (20..7000), у +// WFM (20..15000), и полоса на спектре уезжала вверх от несущей — визуально +// «переключалась на USB». Для ЧМ считаем по Карсону: ±(девиация + верхний срез +// аудио), симметрично несущей. У MODE_FM TXSignedEdges отдаёт ровно эту +// величину и без нас (порт Thetis), но пусть формула будет в одном месте. +var L, H, Half: Double; begin + Half := 0.0; + case FTXMode of + MODE_FM: Half := FTXFMDeviation + FTXFMHighCut; + MODE_WFM: Half := WFM_DEVIATION + WFM_AF_HIGH; + MODE_FMRAW: Half := FRawFMDeviation + RAW_AF_HIGH; + end; + if Half > 0.0 then + begin + Lo := -Round(Half); + Hi := Round(Half); + Exit; + end; TXSignedEdges(FTXMode, L, H); Lo := Round(L); Hi := Round(H);