mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix fft, waterfall
This commit is contained in:
+65
-23
@@ -6,7 +6,7 @@ unit Settings;
|
||||
}
|
||||
{$mode objfpc}{$H+}
|
||||
interface
|
||||
uses SysUtils, Classes, fpJSON, jsonparser, jsonscanner;
|
||||
uses SysUtils, Classes, Math, fpJSON, jsonparser, jsonscanner;
|
||||
|
||||
const
|
||||
SETTINGS_FILE = 'hpsdr_settings.json';
|
||||
@@ -53,12 +53,13 @@ type
|
||||
WindowType: Integer; // 0=Rect,1=BH4,2=Hann,3=FlatTop,4=Hamming,5=Kaiser,6=BH7
|
||||
SpecDetector: Integer; // 0=Peak,1=Rosenfell,2=Average,3=Sample,4=RMS
|
||||
SpecAvgMode: Integer; // 0=None,1=Recursive,2=TimeWindow,3=LogRecursive
|
||||
SpecAvgCount: Integer; // frames to average
|
||||
SpecBackmult: Double; // 0.0..1.0 recursive averaging multiplier
|
||||
SpecAvgTimeMS: Double; // averaging time in milliseconds
|
||||
WfDetector: Integer; // waterfall detector
|
||||
WfAvgMode: Integer; // waterfall average mode
|
||||
WfAvgCount: Integer; // waterfall average count
|
||||
WfBackmult: Double; // waterfall backmult
|
||||
WfAvgTimeMS: Double; // waterfall averaging time in milliseconds
|
||||
WfManualHigh: Double; // manual waterfall high threshold
|
||||
WfManualLow: Double; // manual waterfall low threshold
|
||||
WfAGCOffset: Double; // AGC offset in dB
|
||||
SpecRefLevel: Double; // dBm reference (top of scale), e.g. -20
|
||||
SpecRange: Double; // dB range, e.g. 110 (bottom = ref - range)
|
||||
SpecGridStep: Double; // grid step in dB, e.g. 10
|
||||
@@ -70,7 +71,7 @@ type
|
||||
ShowSpectrum: Boolean; // True = draw spectrum on main form
|
||||
ShowWaterfall: Boolean; // True = draw waterfall on main form
|
||||
// --- Display FPS ---
|
||||
DisplayFPS: Integer; // spectrum/waterfall timer fps (5..30)
|
||||
DisplayFPS: Integer; // spectrum/waterfall timer fps (1..100)
|
||||
// --- PA (Power Amplifier) settings ---
|
||||
PAMaxPower: Double; // максимальная выходная мощность, Вт (5..200)
|
||||
PABandCal: array[0..CFG_BAND_COUNT-1] of Double; // калибровка на диапазон 38.8..100.0
|
||||
@@ -117,6 +118,26 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
function LegacyAverageTimeMS(FPS, AvgMode, AvgCount: Integer;
|
||||
Backmult, DefaultMS: Double): Double;
|
||||
var
|
||||
FPSv: Integer;
|
||||
begin
|
||||
if AvgMode <= 0 then
|
||||
Exit(0.0);
|
||||
|
||||
FPSv := EnsureRange(FPS, 1, 100);
|
||||
if (Backmult > 0.0) and (Backmult < 1.0) then
|
||||
Result := -1000.0 / (FPSv * Ln(Backmult))
|
||||
else
|
||||
Result := (1000.0 * Max(1, AvgCount)) / FPSv;
|
||||
|
||||
if IsNan(Result) or IsInfinite(Result) or (Result <= 0.0) then
|
||||
Result := DefaultMS;
|
||||
|
||||
Result := EnsureRange(Result, 10.0, 5000.0);
|
||||
end;
|
||||
|
||||
class function TSettingsManager.MacToStr(const MAC: array of Byte): string;
|
||||
begin
|
||||
Result := Format('%02X:%02X:%02X:%02X:%02X:%02X',
|
||||
@@ -144,20 +165,23 @@ begin
|
||||
G.Volume := 70; G.DriveLevel := 50; G.ActiveVfo := 0;
|
||||
G.NRMode := 0; G.NBMode := 0; G.SNBEnabled := False; G.ANFEnabled := False;
|
||||
G.AGCSlope := 0; G.AGCHangThreshold := 100; G.LastBand := 5;
|
||||
G.WfAGCEnabled := True;
|
||||
G.WfNFEnabled := False;
|
||||
G.SampleRate := 192000;
|
||||
G.PAMaxPower := 100.0;
|
||||
for i := 0 to CFG_BAND_COUNT-1 do G.PABandCal[i] := 100.0;
|
||||
// Display defaults
|
||||
G.FFTSize := 4096;
|
||||
G.WindowType := 5; // Kaiser
|
||||
G.WindowType := 2; // Hann
|
||||
G.SpecDetector := 0; // Peak
|
||||
G.SpecAvgMode := 3; // Log Recursive
|
||||
G.SpecAvgCount := 2;
|
||||
G.SpecBackmult := 0.45;
|
||||
G.WfDetector := 2; // Average
|
||||
G.SpecAvgTimeMS := 30.0;
|
||||
G.WfDetector := 0; // Peak
|
||||
G.WfAvgMode := 3; // Log Recursive
|
||||
G.WfAvgCount := 2;
|
||||
G.WfBackmult := 0.45;
|
||||
G.WfAvgTimeMS := 120.0;
|
||||
G.WfManualHigh := -80.0;
|
||||
G.WfManualLow := -130.0;
|
||||
G.WfAGCOffset := 0.0;
|
||||
G.SpecRefLevel := -20.0;
|
||||
G.SpecRange := 110.0;
|
||||
G.SpecGridStep := 10.0;
|
||||
@@ -307,7 +331,7 @@ begin
|
||||
G.ANFEnabled := JB(GObj,'anf_enabled',False);
|
||||
G.AGCSlope := JI(GObj,'agc_slope',0);
|
||||
G.AGCHangThreshold := JI(GObj,'agc_hang_threshold',100);
|
||||
G.WfAGCEnabled := JB(GObj,'wf_agc_enabled',False);
|
||||
G.WfAGCEnabled := JB(GObj,'wf_agc_enabled',True);
|
||||
G.WfNFEnabled := JB(GObj,'wf_nf_enabled',False);
|
||||
G.LastBand := JI(GObj,'last_band',5);
|
||||
G.SampleRate := JI(GObj,'sample_rate',192000);
|
||||
@@ -315,13 +339,30 @@ begin
|
||||
G.FFTSize := JI(GObj,'fft_size',4096);
|
||||
G.WindowType := JI(GObj,'win_type',5);
|
||||
G.SpecDetector := JI(GObj,'spec_detector',0);
|
||||
G.SpecAvgMode := JI(GObj,'spec_avg_mode',3);
|
||||
G.SpecAvgCount := JI(GObj,'spec_avg_count',2);
|
||||
G.SpecBackmult := JD(GObj,'spec_backmult',0.45);
|
||||
G.SpecAvgMode := JI(GObj,'spec_avg_mode',0);
|
||||
if GObj.Find('spec_avg_time_ms') <> nil then
|
||||
G.SpecAvgTimeMS := JD(GObj,'spec_avg_time_ms',120.0)
|
||||
else
|
||||
G.SpecAvgTimeMS := LegacyAverageTimeMS(
|
||||
JI(GObj,'display_fps',20),
|
||||
G.SpecAvgMode,
|
||||
JI(GObj,'spec_avg_count',1),
|
||||
JD(GObj,'spec_backmult',0.0),
|
||||
120.0);
|
||||
G.WfDetector := JI(GObj,'wf_detector',2);
|
||||
G.WfAvgMode := JI(GObj,'wf_avg_mode',3);
|
||||
G.WfAvgCount := JI(GObj,'wf_avg_count',2);
|
||||
G.WfBackmult := JD(GObj,'wf_backmult',0.45);
|
||||
G.WfAvgMode := JI(GObj,'wf_avg_mode',1);
|
||||
if GObj.Find('wf_avg_time_ms') <> nil then
|
||||
G.WfAvgTimeMS := JD(GObj,'wf_avg_time_ms',120.0)
|
||||
else
|
||||
G.WfAvgTimeMS := LegacyAverageTimeMS(
|
||||
JI(GObj,'display_fps',20),
|
||||
G.WfAvgMode,
|
||||
JI(GObj,'wf_avg_count',2),
|
||||
JD(GObj,'wf_backmult',0.25),
|
||||
120.0);
|
||||
G.WfManualHigh := JD(GObj,'wf_manual_high',-80.0);
|
||||
G.WfManualLow := JD(GObj,'wf_manual_low',-130.0);
|
||||
G.WfAGCOffset := JD(GObj,'wf_agc_offset',0.0);
|
||||
G.SpecRefLevel := JD(GObj,'spec_ref_level',-20.0);
|
||||
G.SpecRange := JD(GObj,'spec_range',110.0);
|
||||
G.SpecGridStep := JD(GObj,'spec_grid_step',10.0);
|
||||
@@ -376,12 +417,13 @@ begin
|
||||
JW(O,'win_type',G.WindowType);
|
||||
JW(O,'spec_detector',G.SpecDetector);
|
||||
JW(O,'spec_avg_mode',G.SpecAvgMode);
|
||||
JW(O,'spec_avg_count',G.SpecAvgCount);
|
||||
JW(O,'spec_backmult',G.SpecBackmult);
|
||||
JW(O,'spec_avg_time_ms',G.SpecAvgTimeMS);
|
||||
JW(O,'wf_detector',G.WfDetector);
|
||||
JW(O,'wf_avg_mode',G.WfAvgMode);
|
||||
JW(O,'wf_avg_count',G.WfAvgCount);
|
||||
JW(O,'wf_backmult',G.WfBackmult);
|
||||
JW(O,'wf_avg_time_ms',G.WfAvgTimeMS);
|
||||
JW(O,'wf_manual_high',G.WfManualHigh);
|
||||
JW(O,'wf_manual_low',G.WfManualLow);
|
||||
JW(O,'wf_agc_offset',G.WfAGCOffset);
|
||||
JW(O,'spec_ref_level',G.SpecRefLevel);
|
||||
JW(O,'spec_range',G.SpecRange);
|
||||
JW(O,'spec_grid_step',G.SpecGridStep);
|
||||
|
||||
Reference in New Issue
Block a user