mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
docs: update Pluto integration plan for recent TX fixes
Document the TX-path work landed this session: - §4.6: polyphase FIR interpolator + sample-rate-scaled TX buffer + SoapyPlutoSDR confirmation of 32768 full-scale. - §4.8 (new): power-linear drive→atten mapping, full WDSP digital level, TX LO powerdown gated by PTT. - Phase 4 status updated. - Related fixes: per-band FM settings (SQL/CTCSS/step/repeater) restore on startup — was dropped by LoadDevice; affects all backends. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -239,14 +239,22 @@ end;
|
|||||||
|
|
||||||
- **RX:** `TPlutoBackend` читает int16 из `iio_buffer`, конвертирует 16→24-бит,
|
- **RX:** `TPlutoBackend` читает int16 из `iio_buffer`, конвертирует 16→24-бит,
|
||||||
упаковывает в `TDDCIQPacket` (seq синтезируется), вызывает `OnDDCIQ`.
|
упаковывает в `TDDCIQPacket` (seq синтезируется), вызывает `OnDDCIQ`.
|
||||||
- **TX:** ✅ `SendDUCIQ` апсемплит 192k→device-rate (целочисленно, линейная
|
- **TX:** ✅ `SendDUCIQ` апсемплит 192k→device-rate **полифазным FIR-интерполятором**
|
||||||
интерполяция; пресеты рейта кратны 192k), конвертирует 24→16-бит (`>>8`,
|
×L (`BuildTxResampler`: оконный sinc-ФНЧ, окно Блэкмана ~−58 дБ, `TX_FIR_TAPS=16`
|
||||||
full-scale MSB-aligned), инвертирует Q (симметрично RX) и кладёт в кольцевой
|
отводов/фазу, срез `TX_FIR_CUT=40 кГц`, нормировка на единичное DC-усиление фазы;
|
||||||
FIFO. Отдельный `TPlutoTXThread` льёт пары в tx-буфер libiio и `iio_buffer_push`
|
пресеты рейта кратны 192k → L целое), конвертирует 24→16-бит (`>>8`, full-scale
|
||||||
|
MSB-aligned), инвертирует Q (симметрично RX) и кладёт в кольцевой FIFO. Линия
|
||||||
|
задержки `FTxDlI/Q` живёт между вызовами, сбрасывается в `StartTX`/`ClearDUCIQQueue`.
|
||||||
|
Отдельный `TPlutoTXThread` льёт пары в tx-буфер libiio и `iio_buffer_push`
|
||||||
(блокирующий push = пейсинг на device-rate); при underrun — нули (непрерывный
|
(блокирующий push = пейсинг на device-rate); при underrun — нули (непрерывный
|
||||||
full-duplex). Решение rate-mismatch (риск §6.2) — апсемпл в host (RX/TX делят
|
full-duplex). Решение rate-mismatch (риск §6.2) — апсемпл в host (RX/TX делят
|
||||||
один `sampling_frequency`). TODO: полифазный FIR вместо линейной интерполяции
|
один `sampling_frequency`).
|
||||||
для лучшего подавления образов на аплинке.
|
- **Размер TX-буфера** масштабируется от device-rate (модель SoapyPlutoSDR):
|
||||||
|
`round(rate/60)` → следующая степень 2, кламп `[4096..65536]` (576k→16384,
|
||||||
|
1536k→32768). Фикс 4096 был мал для full-duplex выше ~1 Msps → дропы/щелчки.
|
||||||
|
FIFO держит ~4 таких буфера запаса (`TxBufPairsForRate`, пересчёт в `StartTX`).
|
||||||
|
- Подтверждено по каноничному драйверу (SoapyPlutoSDR): TX full-scale = 32768,
|
||||||
|
MSB-aligned → наш `>>8` (24→16) верен; занижения уровня по дизайну нет.
|
||||||
|
|
||||||
### 4.7 Усиление / телеметрия
|
### 4.7 Усиление / телеметрия
|
||||||
|
|
||||||
@@ -257,6 +265,23 @@ end;
|
|||||||
`ServicePlutoTelemetry` (контроллер, опрос ~2 Гц с фильтром выбросов) → поле 3
|
`ServicePlutoTelemetry` (контроллер, опрос ~2 Гц с фильтром выбросов) → поле 3
|
||||||
статус-бара (Temp/RSSI вместо Supply, т.к. у Pluto нет PA).
|
статус-бара (Temp/RSSI вместо Supply, т.к. у Pluto нет PA).
|
||||||
|
|
||||||
|
### 4.8 TX-мощность / drive (Pluto)
|
||||||
|
|
||||||
|
- ✅ **Мощность задаётся ОДИН раз — железной аттенюацией** (`hardwaregain`), а не
|
||||||
|
цифрой WDSP. `ApplyWDSPDrive` (контроллер): на Pluto `SetDriveLevel(1.0)` (полная
|
||||||
|
цифра), HPSDR — `Pct/100`. Раньше drive резался дважды (цифра × атт).
|
||||||
|
- ✅ **`PlutoTxAttForDrive` — power-linear:** `дБ = потолок + 20·log10(pct/100)`
|
||||||
|
(100% → потолок, 50% → −6, 10% → −20). Старый dB-линейный маппинг от −89.75 уводил
|
||||||
|
низкие % в −80 дБ — из-за этого TUN (TUNLevel 10%) давал −81.8 дБ → тон не слышен.
|
||||||
|
Потолок — `FPlutoTxMaxAttDb` (дефолт −10 дБ), на приёме −89.75 (≈выкл).
|
||||||
|
- ✅ **TX LO (`altvoltage1`) гасится по PTT** (`SetTxLOPowerdown`): на приёме
|
||||||
|
`powerdown=1` → нет утечки несущей TX на частоте VFO в RX-спектре и нет излучения в
|
||||||
|
простое; на передаче `powerdown=0`. `ApplyTxLO` ставит powerdown по `FTransmitting`
|
||||||
|
(заодно возвращает LO, если стороннее ПО его погасило). RX LO (`altvoltage0`) —
|
||||||
|
всегда вкл (приём непрерывен, QO-100 full-duplex не ломается). Цена: повторное
|
||||||
|
включение LO запускает калибровку синтезатора AD9361 (единицы–десятки мс) → первый
|
||||||
|
слог SSB может чуть подрезаться.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Поэтапный план (фазы)
|
## 5. Поэтапный план (фазы)
|
||||||
@@ -283,13 +308,16 @@ end;
|
|||||||
|
|
||||||
**Фаза 4 — TX-тракт Pluto** ✅
|
**Фаза 4 — TX-тракт Pluto** ✅
|
||||||
- ✅ `SendDUCIQ` 24→16 + апсемпл 192k→device-rate + пейсинг (FIFO + push-поток, §4.6).
|
- ✅ `SendDUCIQ` 24→16 + апсемпл 192k→device-rate + пейсинг (FIFO + push-поток, §4.6).
|
||||||
- ✅ Управление мощностью через TX-аттенюацию (ADI-модель): непрерывный full-duplex
|
- ✅ **Полифазный FIR-интерполятор** вместо линейной интерполяции (§4.6) — образы на
|
||||||
стрим, drive% → `hardwaregain` (потолок `PlutoTxMaxAttDb`, дефолт −10 дБ,
|
кратных 192k давятся ~−58 дБ (раньше только sinc²), чище аплинк, громкость не меняется.
|
||||||
настраиваемый под внешний усилитель); на приёме −89.75 дБ (≈выкл). Маппинг/
|
- ✅ **TX-буфер по sample-rate** (§4.6) — устранены щелчки/дропы на full-duplex >1 Msps.
|
||||||
политика — в контроллере (`PlutoTxAttForDrive`/`ApplyPlutoTxAtten`), бэкенд —
|
- ✅ Управление мощностью через TX-аттенюацию (ADI-модель), маппинг **power-linear**
|
||||||
тонкий `SetTxAtten`. Без PA → нет drive-байта/SWR/Alex/keyer.
|
+ полная цифра WDSP (§4.8). Без PA → нет drive-байта/SWR/Alex/keyer.
|
||||||
- TODO: проверка на железе (ориентация SSB по Q-инверсии, уровни); полифазный
|
- ✅ **TX LO powerdown по PTT** (§4.8) — нет утечки несущей TX в RX-спектре в простое.
|
||||||
ресэмпл (см. §4.6); опц. зануление IQ на приёме.
|
- TODO: проверка на железе на rate ≥1536k (ориентация SSB по Q-инверсии, уровни);
|
||||||
|
опц. headroom −6 дБ для FM (full-scale const-envelope → нелинейность ЦАП); опц.
|
||||||
|
зануление IQ на приёме. Опц. поддержка F5OEO-прошивки (PTT внешнего PA через
|
||||||
|
`hardwaregain=−40`) — отложено, нужно только под конкретное железо.
|
||||||
|
|
||||||
**Фаза 5 — Режим QO-100** ✅
|
**Фаза 5 — Режим QO-100** ✅
|
||||||
- ✅ Калибровка LNB по маяку (beacon lock) — стабилизация дрейфа.
|
- ✅ Калибровка LNB по маяку (beacon lock) — стабилизация дрейфа.
|
||||||
@@ -307,6 +335,14 @@ end;
|
|||||||
- Web/CAT-фронтенды (команды уже агностичны) + гейтинг полей; демон `ewsdrd.lpr`
|
- Web/CAT-фронтенды (команды уже агностичны) + гейтинг полей; демон `ewsdrd.lpr`
|
||||||
(discovery/connect Pluto headless); кросс-платформенная сборка с/без libiio; доки.
|
(discovery/connect Pluto headless); кросс-платформенная сборка с/без libiio; доки.
|
||||||
|
|
||||||
|
**Сопутствующие исправления (найдены при тесте Pluto VHF/UHF FM, но баги общие):**
|
||||||
|
- ✅ Восстановление per-band FM-настроек на старте (`Settings.LoadDevice`): bulk-
|
||||||
|
загрузчик бэндов читал только freq/mode/filter/AGC/CTun/center/span и **пропускал
|
||||||
|
FM-поля** (`fmsq_on`/`fmsq_level`/`ctcss_*`/`fmstep_*`/`fmrpt_*`), хотя `SaveBand`
|
||||||
|
их пишет, а `LoadBand` читает. Итог: SQL/CTCSS/шаг/репитер-сдвиг сохранялись на
|
||||||
|
выходе, но сбрасывались в дефолт при следующем запуске (смена бэндов работала —
|
||||||
|
идёт через in-memory band-cache). Затрагивало **все бэкенды**, не только Pluto.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Риски и открытые вопросы
|
## 6. Риски и открытые вопросы
|
||||||
@@ -314,8 +350,9 @@ end;
|
|||||||
1. **2 м / 70 см ниже 325 МГц** → требуется freq-range мод прошивки Pluto.
|
1. **2 м / 70 см ниже 325 МГц** → требуется freq-range мод прошивки Pluto.
|
||||||
Документировать; возможно гейтить эти кнопки при стоковой прошивке.
|
Документировать; возможно гейтить эти кнопки при стоковой прошивке.
|
||||||
2. ✅ **TX sample-rate mismatch** (192k WDSP vs ≥521k Pluto) — решено host-апсемплом
|
2. ✅ **TX sample-rate mismatch** (192k WDSP vs ≥521k Pluto) — решено host-апсемплом
|
||||||
192k→device-rate в `SendDUCIQ` (целочисленно, пресеты кратны 192k). Качество
|
192k→device-rate в `SendDUCIQ` (целочисленно, пресеты кратны 192k). ✅ Качество
|
||||||
образов — линейная интерполяция; апгрейд до полифазного FIR в бэклоге.
|
образов — **полифазный FIR-интерполятор** (окно Блэкмана ~−58 дБ). ✅ Щелчки на
|
||||||
|
full-duplex >1 Msps — TX-буфер масштабируется от rate (модель SoapyPlutoSDR).
|
||||||
3. **QO-100 display-duplex** — hardware full-duplex есть (Фаза 4), остаётся довести
|
3. **QO-100 display-duplex** — hardware full-duplex есть (Фаза 4), остаётся довести
|
||||||
`SetDuplex` (водопад RX во время TX); проверить латентность/буферы libiio.
|
`SetDuplex` (водопад RX во время TX); проверить латентность/буферы libiio.
|
||||||
4. **LNB дрейф** — калибровка `LnbPpm` по маяку (ручная/полуавтомат).
|
4. **LNB дрейф** — калибровка `LnbPpm` по маяку (ручная/полуавтомат).
|
||||||
|
|||||||
Reference in New Issue
Block a user