feat: Pluto TX path — attenuation-based power, full-duplex IQ stream

TX path for Pluto/AD936x (RX was already working):
- PlutoBackend: continuous full-duplex TX stream (cf-ad9361-dds-core-lpc)
  with FIFO + push thread; SendDUCIQ upsamples WDSP 192k -> device rate
  (integer, linear interp), 24->16 bit, Q inverted; zeros on underrun.
- Power via output attenuator (ADI-recommended): SetTxAtten writes
  hardwaregain on voltage0(out). Controller maps drive% -> dB
  (PlutoTxAttForDrive/ApplyPlutoTxAtten); -89.75 dB on RX (~off),
  ceiling PlutoTxMaxAttDb on 100% drive.
- Configurable max-att (default -10 dB, ADI-linear) for external amp:
  persisted in global settings, UI spin on PA page, routed through
  controller SetPlutoTxMaxAtt (UI stays decoupled from logic).
- RadioBackend: virtual SetTxAtten (no-op for HPSDR).
- Update doc/PLUTO_INTEGRATION_PLAN.md: phases 3/4/5 + risks.

Builds clean (headless + qt6 GUI). Not yet verified on hardware.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 12:27:49 +03:00
co-authored by Claude Opus 4.8
parent 1321e415f7
commit d08fc17056
7 changed files with 376 additions and 19 deletions
+33 -15
View File
@@ -239,16 +239,23 @@ end;
- **RX:** `TPlutoBackend` читает int16 из `iio_buffer`, конвертирует 16→24-бит,
упаковывает в `TDDCIQPacket` (seq синтезируется), вызывает `OnDDCIQ`.
- **TX:** `SendDUCIQ` конвертирует 24→16-бит, пишет в tx-буфер libiio с пейсингом
(модель FIFO-cushion, см. memory `project_txiq_pacing`). ⚠️ TX-rate Pluto
≥ 521 ksps, WDSP TXA отдаёт 192k — нужен ресэмпл 192k→PlutoTX или смена TX-rate.
- **TX:** `SendDUCIQ` апсемплит 192k→device-rate (целочисленно, линейная
интерполяция; пресеты рейта кратны 192k), конвертирует 24→16-бит (`>>8`,
full-scale MSB-aligned), инвертирует Q (симметрично RX) и кладёт в кольцевой
FIFO. Отдельный `TPlutoTXThread` льёт пары в tx-буфер libiio и `iio_buffer_push`
(блокирующий push = пейсинг на device-rate); при underrun — нули (непрерывный
full-duplex). Решение rate-mismatch (риск §6.2) — апсемпл в host (RX/TX делят
один `sampling_frequency`). TODO: полифазный FIR вместо линейной интерполяции
для лучшего подавления образов на аплинке.
### 4.7 Усиление / телеметрия
- RX gain: контрол manual gain (073 дБ) / режим hw-AGC при `Caps.HasHWGain`
(можно расширить UI step-atten). WDSP AGC поверх.
- Телеметрия: S-meter (WDSP) — для обоих. fwd/SWR/supply/PLL/overload — скрыть при
`not Caps.HasPA`. Опц.: RSSI/температура Pluto.
`not Caps.HasPA`. RSSI/температура Pluto: `ReadTelemetry` (backend) →
`ServicePlutoTelemetry` (контроллер, опрос ~2 Гц с фильтром выбросов) → поле 3
статус-бара (Temp/RSSI вместо Supply, т.к. у Pluto нет PA).
---
@@ -270,16 +277,26 @@ end;
- Гейтинг UI по caps. ✅ приём на Pluto (спектр/водопад/аудио на 2м/70см/23см/13см).
**Фаза 3 — Управление/калибровка**
- RX gain / hw-AGC, XO ppm, транспорт (USB/IP), buffer/timeout, температура/RSSI.
- Persist per-device по synthetic-MAC из serial.
- RX gain / hw-AGC, транспорт (USB/IP), persist per-device по synthetic-MAC.
- ✅ Имя платы (Pluto/LibreSDR + serial) и телеметрия (температура/RSSI) в статус-бар.
- TODO: XO ppm-калибровка, buffer/timeout-контролы.
**Фаза 4 — TX-тракт Pluto**
- `SendDUCIQ` 24→16 + пейсинг; ресэмпл/смена TX-rate (§4.6); TX atten вместо
drive/PA; гейтинг PA/SWR/Alex/keyer. ✅ передача (SSB/CW/FM).
**Фаза 4 — TX-тракт Pluto**
- `SendDUCIQ` 24→16 + апсемпл 192k→device-rate + пейсинг (FIFO + push-поток, §4.6).
- ✅ Управление мощностью через TX-аттенюацию (ADI-модель): непрерывный full-duplex
стрим, drive% → `hardwaregain` (потолок `PlutoTxMaxAttDb`, дефолт 10 дБ,
настраиваемый под внешний усилитель); на приёме −89.75 дБ (≈выкл). Маппинг/
политика — в контроллере (`PlutoTxAttForDrive`/`ApplyPlutoTxAtten`), бэкенд —
тонкий `SetTxAtten`. Без PA → нет drive-байта/SWR/Alex/keyer.
- TODO: проверка на железе (ориентация SSB по Q-инверсии, уровни); полифазный
ресэмпл (см. §4.6); опц. зануление IQ на приёме.
**Фаза 5 — Режим QO-100**
- `TQO100Settings` + раздельные RX/TX LO (§3.2), дисплей в downlink-терминах,
калибровка LNB по маяку, **full-duplex** (довести `SetDuplex`).
- ✅ Калибровка LNB по маяку (beacon lock) — стабилизация дрейфа.
- ✅ Hardware full-duplex: TX-стрим живёт всё время Run (Фаза 4), RX+TX
одновременно. Остаётся display-duplex (`SetDuplex` — водопад RX во время TX).
- TODO: `TQO100Settings` + раздельные RX/TX LO (§3.2), дисплей в downlink-терминах,
довести `SetDuplex`.
- UI: вход/выход в режим QO-100 (как XVTR-слот), поля LNB LO / ppm / TX atten.
- ✅ полноценная работа через спутник.
@@ -293,10 +310,11 @@ end;
1. **2 м / 70 см ниже 325 МГц** → требуется freq-range мод прошивки Pluto.
Документировать; возможно гейтить эти кнопки при стоковой прошивке.
2. **TX sample-rate mismatch** (192k WDSP vs ≥521k Pluto) — ресэмпл или смена
TX-rate WDSP.
3. **QO-100 full-duplex** — довести `SetDuplex` (сейчас TODO) до реального
одновременного RX+TX; проверить латентность/буферы libiio.
2. **TX sample-rate mismatch** (192k WDSP vs ≥521k Pluto) — решено host-апсемплом
192k→device-rate в `SendDUCIQ` (целочисленно, пресеты кратны 192k). Качество
образов — линейная интерполяция; апгрейд до полифазного FIR в бэклоге.
3. **QO-100 display-duplex** — hardware full-duplex есть (Фаза 4), остаётся довести
`SetDuplex` (водопад RX во время TX); проверить латентность/буферы libiio.
4. **LNB дрейф** — калибровка `LnbPpm` по маяку (ручная/полуавтомат).
5. **Ключ настроек** — synthetic-MAC из serial (быстро) vs обобщение до строки.
6. **libiio как зависимость** — динамическая загрузка, поведение при отсутствии.