# Pluto互換ボード FMトランスミッター HamGeek Pluto Nano向けのホスト側CLI。既存ファームウェアのlibiio経由で音声を逐次送信します。WAVE・MP3・AAC・FLACなどFFmpeg対応ファイルをPCMに変換しながらモノラルまたはステレオFMに変調するため、ファイル全体をメモリに読み込みません。標準ではステレオ入力をモノラルにミックスします。`--stereo`指定時は左右を保持してステレオFMを生成します。RDSは未対応です。 ## インストール(Ubuntu/Debian) ```sh sudo apt install python3-venv ffmpeg libiio0 libiio-utils libad9361-0 python3 -m venv .venv .venv/bin/pip install -e . ``` Python 3.10以上。ディストリビューションによりlibiioパッケージ名が異なります。Pythonの`iio`はpyadi-iio依存のpylibiioを利用します。 ## 使用 ```sh # 接続確認(標準PlutoのIP例。Nanoの実際のIPに合わせる) iio_info -u ip:192.168.2.1 # 再生開始。Ctrl+Cで停止 .venv/bin/pluto-fm audio.wav --frequency 80.0 --uri ip:192.168.2.1 .venv/bin/pluto-fm music.mp3 --frequency 90.5 --gain -40 --loop # ステレオFM .venv/bin/pluto-fm music.wav --frequency 80.0 --stereo --loop # RF送信せず、変調済みIQを保存して確認 .venv/bin/pluto-fm audio.wav --frequency 80 --dry-run /tmp/audio.cf32 ``` `--frequency`は76.0〜108.0 MHz、小数指定可。周波数変更は停止して別の周波数で再起動します。`--gain`は-89.75〜0 dB(初期値-40)、`--volume`は0〜1(初期値0.8)、`--deviation`は最大偏移Hz(初期値75000)、`--pre-emphasis`は0/50/75 µs(初期値50)。高域の強い音源で歪む場合はvolumeを下げてください。gainは校正済み出力電力ではありません。 使用する送信ポートは第1チャネル/TX1です。許可された条件下で、まずダミーロードや減衰器を使用して確認してください。 ## ファームウェアと76 MHz対応 このプログラムはファームウェア更新・SSH操作・U-Boot環境変更を行いません。既存のIIOドライバが指定LOを受け付ければそのまま動作します。起動時にLO(許容差10 Hz)と960 kS/sの読み戻しを検証し、指定を拒否された場合は送信開始せず終了します。 標準ADALM-Plutoは通常325 MHz以上で、ADIはAD9364互換設定で70 MHz以上に拡張する方法を公開しています。ただしHamGeek Pluto Nano固有の公式仕様・搭載チップ・設定方式は未確認です。標準Pluto用の設定をNanoへ無条件に適用しないでください。76 MHzを拒否する個体ではメーカーの資料と現在の設定を確認し、必要なら既存ファームウェアの周波数範囲設定だけを変更する方針です。ファームウェアの焼き直しは前提にしていません。 参照: [ADI周波数拡張設定](https://wiki.analog.com/university/tools/pluto/users/customizing)、[ADI Python導入](https://developer.analog.com/docs/system-level/solutions/platforms/pluto/software/python_install.html)、[pyadi-iio TX実装](https://github.com/analogdevicesinc/pyadi-iio/blob/main/adi/rx_tx.py)。 ## ストリーミング方式と制約 FFmpegから48 kHz float32モノラルPCMを100 ms単位で読み、プリエンファシス・15 kHz低域フィルタ・20倍の状態保持ポリフェーズFIR補間・位相連続FMを行います。IQは960 kS/s、complex64、非循環バッファです。転送ペースはlibiioのブロッキング送信で決まり、FFmpegに`-re`は付けません。IQ転送量はおよそ3.84 MB/s(16 bit I/Q)です。乾式出力は7.68 MB/sで、実時間待ちを行いません。最終ブロックはゼロ埋めするため最大100 msの無音が付きます。 Ctrl+C・通常終了・処理エラーではTXバッファを破棄しゲインを最小化します。ハードウェアのRF muteを保証するものではありません。接続個体ではAD9364互換設定後、76/80/108 MHzで3秒のバッファ送信と終了時ゲイン最小化を確認済みです。受信音質・アンダーラン・停止時RFは未検証です。USB/ネットワークやホスト負荷によるアンダーランを完全には検出できません。 ## 検証とセッション継続 ```sh PYTHONPATH=src python3 -m unittest discover -s tests -v ``` [作業状況](docs/STATUS.md)に検証結果と次の実機確認を記録しています。次回のセッションではREADME、AGENTS.md、STATUS.mdを読んで続けられます。 ## 接続個体のAD9364互換設定 既存FW v0.39-dirtyで、SSHから次のU-Boot環境設定だけを変更しました。ファームウェアイメージの更新は行っていません。 ```sh fw_setenv attr_name compatible fw_setenv attr_val ad9364 fw_setenv compatible ad9364 reboot ``` 変更前は3変数とも未定義でした。この個体を元に戻す場合は、各`fw_setenv`を変数名だけで実行して削除し、再起動します。他の個体では元の値を確認してから変更してください。設定後のTX LO公称範囲は46.875001〜6000 MHzでした。CLIの指定範囲は76〜108 MHzのままです。 ## ステレオFM `--stereo`は左右48 kHz音声を個別にプリエンファシス・帯域制限して補間し、`0.9 × ((L+R)/2 + (L−R)/2 × sin(38 kHz)) + 0.1 × sin(19 kHz)`のMPX信号でFM変調します。19 kHzパイロットと38 kHz副搬送波は同一サンプル時計から生成します。ステレオ音声の副搬送波側波帯は23〜53 kHzです。TX RF帯域は300 kHzに設定します。参考: [ITU-R BS.450-4](https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.450-4-201910-I%21%21PDF-E.pdf)。 ステレオモードではFFmpegから2チャネルPCMを受け取り、モノラル入力もFFmpegで2チャネル化します。モノラル受信機ではL+Rを聴けます。音量が高すぎるとリミッターで歪むため、必要に応じて`--volume`を下げてください。受信機のステレオ表示と左右音声は実際の受信環境で確認してください。