Commit Graph
29 Commits
Author SHA1 Message Date
ew8bakandClaude Opus 4.8 42610b304e feat: QO-100 beacon lock — stabilise LNB drift to NB transponder beacon
Click the beacon on the spectrum; the controller tracks it and continuously
trims the transverter LO so the whole downlink stays put as the LNB drifts.

- BeaconLock.pas: TBeaconTracker scaffold (narrowband NCO/FLL) — kept but no
  longer in the control path (FLL diverged on the suppressed-carrier BPSK
  beacon + Pluto DC offset). Measurement now uses the proven display-FFT path.
- RadioController: FBeaconLockHz folded into XvtrTranslate (on top of LOError).
  MeasureBeaconFFT finds the beacon by POWER-WEIGHTED CENTROID of the lobe
  (BPSK has a suppressed carrier → broad symmetric ~2.4 kHz lobe, not a line;
  a peak-finder jitters, the centroid sits on the carrier). Track position in
  ABSOLUTE display Hz (FBeaconTrackHz) so scrolling the waterfall/centre never
  moves the search window off the beacon. Closed loop: e = tracked - ref,
  d(e)/d(LockHz) = -1 -> LockHz += gain*e; settle cooldown after each correction
  (display-FFT lags the LO retune -> avoids overshoot); deadband 75 Hz +
  centroid/prominence smoothing + lock hysteresis for a steady lock.
  Correction applied only after the user clicks (manual seed), so a crowded
  band can't pull a neighbour to the reference.
- WDSPEngine: SetBeaconTracker + RX-IQ tap (tracker idle now, ~1 check/sample).
- SpectrumView + GL: beacon markers — green = reference (10489.750), orange =
  tracked centroid.
- MainForm: BEACON button (RX block, XVTR-only). Flow: BEACON -> "CLICK BCN"
  -> click beacon -> "L<corr> /<prom>". ServiceBeaconLock driven by MeterTimer.

Reference defaults to the middle BPSK beacon 10489.750. Tested on-air against
Es'hail-2: locks and holds, survives waterfall drag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 11:04:14 +03:00
Uladzimir KarpenkaandClaude Opus 4.8 655d242d02 Add Spectrum gradient fill toggle in settings
Mirror the existing Wideband gradient fill option for the main spectrum:
a "Spectrum gradient fill" checkbox on the Display settings tab gates the
under-curve gradient in TSpectrumView.DrawSpectrum. The curve, grid,
filter band and VFO markers always draw; only the gradient is optional.

Persisted as spectrum_fill in settings JSON (default True, preserving
current appearance). Wired through Settings -> SettingsForm visibility
event -> MainForm -> TSpectrumView.FillSpectrum, same path as
WidebandFill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 15:24:33 +03:00
Uladzimir KarpenkaandClaude Opus 4.8 c3a8a14110 Drop per-frame alpha-restore pass on macOS spectrum
On Cocoa the full-bitmap alpha-restore pass is unnecessary: Canvas
operations keep alpha at $FF and the cached grid background is opaque,
so removing it cuts a full-frame O(W*H) pass per spectrum frame with no
visual change (verified on macOS).

Kept under {$IFNDEF DARWIN} for Qt6/win32 (different drawing backends
may zero alpha on antialiased edges) until visually verified there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 14:31:18 +03:00
Uladzimir KarpenkaandClaude Opus 4.8 55d5bf01cf Optimize CPU waterfall/spectrum rendering
WaterfallView: drop per-frame TLazIntfImage + LoadFromIntfImage (device
bitmap recreation + full pixel-format conversion every frame). Write
pixels directly into the bitmap via BeginUpdate/ScanLine like
SpectrumView already does, with platform-native byte order (ARGB on
Cocoa, BGRA elsewhere).

Replace per-pixel float colorization with a 512-entry dB->color LUT
rebuilt only when WfLow/WfHigh/theme change beyond a small threshold.

Turn the bitmap itself into a ring buffer: each frame builds a single
new row and writes one ScanLine; scrolling is done at paint time via two
CopyRect calls. Removes both full-frame passes per frame (image memmove
+ buffer->bitmap copy), cutting per-frame cost from O(W*H) to O(W). TX
mode preserved by leaving out-of-span columns untouched in the row buf.

SpectrumView: rewrite the per-frame alpha-restore pass from a strided
per-byte loop to a sequential per-dword OR with the alpha mask
(bit-identical output, sequential memory access).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 14:21:40 +03:00
Uladzimir Karpenka a02d35fcce Fix macOS pixel format: use ARGB byte order in all raw ScanLine blending
On macOS Cocoa, TBitmap.pf32bit stores pixels in ARGB order
   (byte0=A, byte1=R, byte2=G, byte3=B) rather than BGRA used on
   Linux/Windows. All raw ScanLine pixel blending and channel mapping
   is now guarded with { DARWIN} to use the correct offsets.

   Also fix PortAudio library discovery on macOS: probe .dylib names
   (including Homebrew paths) before falling through to .so/.dll.
2026-05-28 21:47:54 +03:00
ew8bak 08c5f0ddb7 Add OpenGL waterfall renderer 2026-05-25 20:41:06 +03:00
ew8bak 5090838563 Add OpenGL spectrum renderer 2026-05-25 20:16:37 +03:00
ew8bakandClaude Sonnet 4.6 1eecd974fc Reduce timer-tick CPU load by removing per-tick ResizeSMeter and throttling AGC line updates
- Remove ResizeSMeter (Pango font measurement + multiple SetBounds) from 60 Hz timer tick;
  it is still called on actual resize events
- Throttle UpdateAGCLines WDSP API calls from 60 Hz to ~10 Hz (every 6 ticks)
- Optimize spectrum alpha-fix loop: write-only byte access instead of read-modify-write DWORD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 18:51:41 +03:00
ew8bak 0dc04ffcad Fix TX spectrum filter alpha accumulation 2026-05-24 16:03:48 +03:00
ew8bakandClaude Sonnet 4.6 3bfd9adf0d Fix spectrum invisible on win32 and mask WDSP FPU exceptions
SpectrumView: rewrite DrawSpectrumGradient to blend directly into
FSpectrumBitmap via ScanLine instead of TLazIntfImage+BitBlt (stale DC
on win32). Add alpha=$FF fixup pass so pf32bit Canvas.Draw renders via
StretchBlt not AlphaBlend. Remove FSpecGradImg/FSpecGradBmp fields.

MainForm: mask exZeroDivide/exInvalidOp in FormCreate so WDSP DLL
divide-by-zero does not crash the DSP thread on win32 (Qt6 already
masks FPU exceptions globally).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 13:51:13 +03:00
ew8bak c5f225332b Add audio buffer setting and optimize overlays 2026-05-22 18:07:05 +03:00
ew8bak 26aa55ddde Render sample rate overlay into spectrum bitmap 2026-05-22 17:15:29 +03:00
ew8bakandClaude Sonnet 4.6 d99c19ec9a Split SpectrumView into WaterfallView, SMeterView, RulerView modules
TSpectrumView remains the public facade for MainForm; waterfall, S-meter,
and ruler rendering are now in isolated units. Dead code removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 11:16:55 +03:00
ew8bak 960cadd4b0 add alert ADC overload 2026-05-21 15:42:59 +03:00
ew8bak b5103bf474 add alert overlay 2026-05-21 15:38:56 +03:00
ew8bakandClaude Sonnet 4.6 7b4ea733a2 Align spectrum grid and ruler to FM tuning step
When FM mode is active, vertical grid lines and frequency labels snap to
FM channel boundaries (FM_STEP_HZ) instead of the fixed 8-division layout.
Grid and label density auto-adapt: lines thinner than 4px are thinned,
labels are spaced so they never overlap (short tick shown between labeled
lines). Grid cache invalidates on center-freq, step, or span changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:44:32 +03:00
ew8bakandClaude Sonnet 4.6 e8561dcc18 TX meter: add minor tick marks between main scale labels
Power bar: minor ticks every 5% (between 0/25/50/75/100% main marks)
SWR bar: minor ticks at integer values 2,3,4,6,7,8,9 (between 1/2.5/5/10)
Applied to both desktop (SpectrumView) and web (paintTXMeter JS)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 14:27:00 +03:00
ew8bakandClaude Sonnet 4.6 96b0ccb2c7 TX meter: show power and SWR in S-meter panel during transmit
- S-meter panel switches to TX mode when transmitting: single bar splits
  into two sub-bars (power top, SWR bottom) at the same position/size
- Power bar: 0..PAMaxPower W, green; SWR bar: 1..10, amber/red past 2.5
- SWR > 2.5: red border, red label, "SWR High" warning text
- Remove PWR/SWR bars and labels from TX panel (left column)
- Remove FWD/SWR from status bar; remove frequency from RUNNING status

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 14:10:04 +03:00
ew8bakandClaude Sonnet 4.6 efc21b92e6 Add configurable VFO frequency range with GHz support
- Settings > Display: new "VFO Display" control to select max frequency
  range (999 MHz / 9.999 GHz / 99.999 GHz), persisted as freq_mhz_digits
- FreqDisplay: extend digit map [0..10] to support up to 11 digit positions;
  keyboard navigation adapts to MinMhzDigits dynamically
- MainForm/LayoutTopVfoBlock: VFO panel width scales automatically with
  selected digit count using dynamic text measurement
- Web VFO: fix broken HTML (class attr not closed before data-s — wheel and
  hover were completely non-functional); rewrite fmtVfo to use variable MHz
  digit count synced from server state; fix missing </span> for .vfo-hz
- WebServer: publish freq_mhz_digits in state JSON; updated from
  ApplyFreqMhzDigits so desktop and web stay in sync
- Fix Int32 overflow on frequencies above ~2.15 GHz: CATEngine.Pad V param
  Int64, FormatFreq/FormatFreqSV Mhz var Int64 (Mhz*1000000 overflowed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 13:13:52 +03:00
ew8bak 88687b4e70 DUP (display duplex) + ATT on TX
- DUP: локальный режим отображения, при TX данные RX1, поверх рисуется
  TX-фильтр. Кнопка на левой панели рядом с CTUN. Аппаратной командой
  не является. Отдельный SetDisplaySourceTX в WDSPEngine, разделение
  TXMode (data) и TXOverlay (filter band) в SpectrumView.
- ATT on TX: 0..31 dB, default 31 (Thetis-style). UI на вкладке Transmit
  в группе Microphone. Передаётся в DUC Specific bytes 57/58/59
  (StepAtten0/1/2). Перепосылается при изменении.
2026-05-06 15:51:33 +03:00
ew8bakandClaude Opus 4.7 96d7e0c759 TX: фиксированный sample rate, per-device grid, CTUN-aware overlay, alpha-blend filter bands
Декаплинг TX от RX sample rate (как в Thetis):
- WDSPEngine.pas: константа TX_SAMPLE_RATE=192000, поля FTXSampleRate/FTXOutBufSize.
  TXA OpenChannel теперь использует FTXSampleRate как out_rate, TX-анализатор
  через SetDisplaySampleRate(TX_DISP_ID, FTXSampleRate). ProcessTXBlock работает
  с FTXOutBufSize вместо FBufSize. Public TXSampleRate для MainForm.
- MainForm.SendDUCSpecificFromSettings: DUC0Rate теперь берётся из
  FDSPEngine.TXSampleRate, а не из RX-настроек — TX всегда 192k независимо от
  выбранного RX-rate (48/96/192/384k).

DUC Specific cache + keepalive resend (HPSDRNetwork.pas):
- FCachedDUCSpec/FCachedDUCValid параллельно DDC-кэшу.
- KeepAlive thread в первые 5s после Run=1 переотправляет и DDC, и DUC
  Specific — устраняет гонку, когда DUC настройки терялись железом.
- Disconnect сбрасывает оба valid-флага.

Per-device TX grid settings (Thetis-style):
- Settings.pas: TXSpecRefLevel/TXSpecRange/TXSpecGridStep в TTXSettings
  (defaults 0.0/80.0/10.0). LoadTX/SaveTX — ключи tx_spec_ref_level/range/grid_step.
- SettingsForm.pas: новая группа \"TX Grid\" во вкладке Transmit
  (RefLevel edit, Range edit, GridStep combo). CollectTXFromUI читает значения,
  LoadTXSettings заполняет UI.
- MainForm.pas: поля FTXSpecRefLevel/Range/GridStep, ApplySpecViewGridFromState
  пушит в FSpecView либо TX, либо RX параметры в зависимости от FTransmitting.
  ApplyGridParams (RX-путь) уважает FTransmitting и не перебивает TX-grid.
  OnTXSettingsChange при активном TX моментально применяет новый grid.

TX-aware spectrum/waterfall с CTUN-выравниванием (SpectrumView.pas):
- Поля FTXMode/FTXFreq/FTXSpanHz/FTXVfoIndex. TXSpanHz=192000 при создании.
- DrawSpectrum/DrawWaterfall в FTXMode мапят данные TX-анализатора (192k вокруг
  FTXFreq) в RX-координаты FCenterFreq/FSpanHz. Формула:
    freq = FCenterFreq - FSpanHz/2 + x*FSpanHz/W
    idx  = (freq-FTXFreq + TXSpanHz/2)/TXSpanHz * (SrcCount-1)
  Вне диапазона — спектр уходит в -200 dB; водопад копирует пиксель из
  предыдущей строки (FWfPixels[X+W]) — вместо чёрной полосы продолжает
  скроллиться старая RX-картинка.
- Эффект: при CTUN ON TX-сигнал рисуется на полосе фильтра (на VFO), а не в
  центре. При RX rate ≠ 192k частотная сетка совпадает между RX и TX
  автоматически (ruler всегда в RX-координатах).
- MainForm.SyncSpecViewFreq/ApplyMOX обновляют TXFreq/TXVfoIndex/TXMode при
  каждом PTT и смене VFO; учитывается split (FSplitTxB → TXVfoIndex=1).

Alpha-blended filter bands (визуальный feedback TX/RX):
- SpectrumView: PixelFormat:=pf32bit, процедура BlendBand через ScanLine[Y]
  внутри BeginUpdate/EndUpdate. Альфа-смешение по формуле
  (a*src + (255-a)*dst) / 255 для каждого канала BGR.
- В FTXMode полоса фильтра становится полупрозрачно красной. Если split
  (FTXVfoIndex<>FActiveVfo): на RX-частоте полоса зелёная, на TX-частоте —
  красная (CalcFilterBandX вычисляет границы для произвольной VFO-freq).
- При FTXMode=False — старое поведение (сплошная заливка SpecFilter).

Build: lazbuild --ws=qt6 ewsdr.lpi — clean, 0 errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 14:17:49 +03:00
ew8bakandClaude Opus 4.7 ce97ee486c WIP: TX implementation — per-device settings, separate analyzer, sound-card mic
- Settings: TTXSettings record + LoadTX/SaveTX, JSON section "tx" per MAC
- WDSPEngine: separate TX_DISP_ID analyzer with own FFT/Window/Det/Avg
  parameters, ApplyTXAnalyzerSettings + setters
- WDSPEngine: full TX chain setters (Filter/Compressor/Leveler/ALC/
  PhaseRot/EQ/AMCarrier/FM/CTCSS) + ApplyTXChainSettings
- WDSPEngine: ProcessTXBlock now feeds TX analyzer in DISPLAY_BLOCK_SIZE
  chunks (was passing whole FTXOut → analyzer ignored most of it)
- WDSPEngine: ActiveDisplayID switches RX/TX in UpdateSpectrum
- WDSPEngine: RX audio muted while TX active to avoid local feedback
- WDSPEngine: default EQ frequencies in Create (zero freqs broke TX chain)
- WDSPEngine: PushTXMicSampleD + OnPullMicSamples for sound-card path
- AudioInput: Available counter for non-blocking pull
- MainForm: PullSoundCardMic, BuildMicLineSelectByte, SendDUCSpecific
  with mic bias/boost/line/PTT bits, OnTXSettingsChange
- MainForm: auto-switch MicSource on TX device select, TX diagnostic
  in StatusBar panel [5]
- SettingsForm: new Transmit nav page with Microphone, Filter, Dynamic
  processing, EQ, AM/FM/CTCSS, TX Display sections

NOT YET WORKING: sound-card mic produces ring activity but signal still
not visible on TX spectrum/waterfall — needs further investigation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 08:06:58 +03:00
ew8bakandClaude Sonnet 4.6 fa38e433e1 fix waterfall init color to match surrounding panel
Empty waterfall now fills with FTheme.Panel (same color as PanelRight)
instead of FTheme.BG, so there's no visible seam before stream starts.
Correct TColor→BGRA conversion (R/B swap) applied.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 21:48:12 +03:00
ew8bakandClaude Sonnet 4.6 d5000ac99f light theme: waterfall palette + VFO hover colors + global theme fix
- SpectrumView: WaterfallLightTheme() — кремовый→зелень→бирюза→индиго
- FreqDisplay: ColorHoverBG свойство, убран хардкод фона hover
- AppTheme: FreqHover/FreqHoverBG/FreqDimDot для обеих тем
- Settings: SaveTheme/LoadTheme в корневой секции preferences
- MainForm: тема загружается при старте, сохраняется при изменении

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 19:21:07 +03:00
ew8bakandClaude Sonnet 4.6 d9a2157719 add light/dark theme with global persistence
- AppTheme.pas: новый файл, TAppTheme record + DarkTheme()/LightTheme()
- FlatSlider: цвета через SetThemeColors вместо хардкода
- SpectrumView: все цвета из TAppTheme (SetTheme)
- SettingsForm: ApplyTheme(T) с рекурсивным обходом контролов
- DeviceForm: SetTheme(T) — перекраска всех элементов включая TEdit
- Settings: SaveTheme/LoadTheme в корневой секции preferences (не привязано к устройству)
- MainForm: тема загружается при старте, сохраняется при изменении

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 19:00:45 +03:00
ew8bak d70c4a96ae Fix S-meter top layout 2026-04-28 21:42:12 +03:00
ew8bak 22832a1163 Rework S-meter left label zone and bar layout 2026-04-28 15:01:25 +03:00
ew8bakandClaude Sonnet 4.6 a149b18435 Fix ruler not updating on sample rate change
Add FRulerLastSpan to ruler cache — previously only FCenterFreq
and ActiveVfoFreq were tracked, so span changes left the ruler
showing stale frequency step marks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 18:37:02 +03:00
ew8bakandClaude Sonnet 4.6 5421e57f9c Extract spectrum/waterfall rendering into SpectrumView.pas
- New unit SpectrumView.pas (TSpectrumView): encapsulates all
  spectrum, waterfall, ruler and S-meter rendering; ~900 lines
  removed from MainForm.pas
- Fix marker bug: FMarkerActive/FMarkerX were duplicated in
  MainForm and TSpectrumView — mouse handlers now write directly
  to FSpecView, stale MainForm fields removed
- Fix filter band and ruler not following VFO: add SyncSpecViewFreq
  helper called at every draw site and at top of SpectrumTimerTick
- Remove dead code: WFALL_PALETTE (34 lines), FSplitter, LblAGC,
  LblVol, WinFirewall/IntfGraphics/FPImage from uses
- Fix pre-existing bug: SidetoneFreqLo := 600 overflowed Byte,
  replaced with Hi(600)/Lo(600)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 18:28:20 +03:00