発振周波数と同調周波数の非同期問題
RFフロントエンドハードウェアであるRS-HFIQのSI5351A局部発振器(LO:Local Oscillator)の周波数は、Quiskの同調(Tune)周波数で制御するものと考えていました。しかし、QuiskのGUI操作時のTune周波数とLO周波数は同期していませんでした。
Quisk初期状態
具体的には、下記に示すように、Quisk立ち上げ時にはLO周波数とTune周波数は例えば初期設定値の7.021MHzで一致しています。Tune周波数はスペクトルグラフで赤線で示されています。LO周波数はLOノイズが発生している箇所で、ウォーターフォール上で明瞭に顕在化しています。
LO周波数変更
初期状態からLO周波数ステップアップボタン[・](右側)をクリックすることにより、LO周波数を1kHzステップアップして7.022MHzに設定した時の挙動を下記に示します。Tune周波数は7.021MHzから変化していません。
逆に、初期状態からLO周波数ステップアップボタン[・](左側)をクリックすることにより、LO周波数を1kHzステップダウンして7.020MHzに設定した時の挙動を下記に示します。Tune周波数はやはり7.021MHzから変化していません。
LOノイズがLSBフィルタの2.5kHz帯域に入ってきたため、ノイズが復調され再生音がPCから響きました。
Tune周波数変更
初期状態からTune周波数エントリ内のkHz桁の数字の上部をクリックすることにより、Tune周波数を1kHzアップして7.022MHzに設定した時の挙動を下記に示します。LO周波数は7.021MHzから変化していません。
LOノイズがLSBフィルタの2.5kHz帯域に入ってきたため、ノイズが復調され再生音がPCから響きました。
逆に、初期状態からTune周波数エントリ内のkHz桁の数字の下部をクリックすることにより、Tune周波数を1kHzダウンして7.020MHzに設定した時の挙動を下記に示します。LO周波数はやはり7.021MHzから変化していません。
他のSDRソフトウェアのように、LOとTuneの同期設定や解除を行うオプションは見つかっていません。SDRの理論的建付けとしては両者が一致していなくても問題ありません。例えば、LO周波数固定のハードウェアに対してもTune周波数を可変できることはSDRの利点です。
しかし、LOノイズがTune周波数と関係のない位置に出現し、時には復調されてしまうことに違和感が生じました。そこで、GUIの操作に対して両者を一致させる改造を検討することにしました。
Quiskのドキュメント調査
Quisk GUIの周波数変更イベントの発生元は複数あります。これらに逐一改造を加えていては管理が大変になります。Quiskのドキュメントを精査したところ、N2ADR局 James C. Ahlstrom OMが重要なヒントを乗せてくれていました。
後半部分の意訳はこんな感じでしょうか。
ほとんどの場合、「GUIの周波数変更イベントの発生元」について気にする必要はありません。ユーザの操作にChangeFrequency関数で応答すれば良く、おそらくはハードウェアのVFO周波数を変更すればよいのです。必ずしも要求された変更を実際に行うことを遵守する必要はありません。ただ、必要に応じてハードウェアを調整し、あなたが望んで実際に設定した(Tune周波数、VFO周波数)の組み合わせを返して下さい。Quiskは、要求値の組み合わせを無視し、代わりにあなたが返した実際の設定値の組み合わせを使用します。
これをChangeFrequency関数の引数と返値に当てはめると、
実際の設定値(Tune, LO)= ChangeFrequency(ユーザの要求値(Tune, LO))
となり、ユーザの要求値(要求Tune周波数、 要求LO周波数)に対して、Quiskに反映される実際の設定値(設定Tune周波数、設定LO周波数)をどう管理するかは、ハードウェアを制御するChangeFrequency関数の実装に依存することになります。
Quiskハードウェアファイルの改造
ハードウェハに依存するChangeFrequency関数は、Quiskハードウェアファイルの中のHardwareクラスのメンバ関数として定義されています。RS-HFIQをサポートするQuiskハードウェアファイルとしては、DL1KSV局Volker Schroer OMが公開してくれているhardware_usbserial.pyを利用しています。
改造前のChangeFrequency関数
hardware_usbserial.pyのHardwareクラスに継承定義されたChangeFrequency関数を下記に示します。
def ChangeFrequency(self, tune, vfo, source='', band='', event=None): if self.vfo != vfo : if serialport.isOpen() : self.vfo =vfo vfo_string = '*F' + str(self.vfo) + '\r' if DEBUG == 1: print("Tuning to: ", vfo_string) print("Tuning to: ", self.vfo) serialport.write(vfo_string.encode()) return tune, self.vfo
LO周波数はQuiskプログラムの変数名ではvfoと定義されています。SDRの同調周波数(tune)とハードウェアの発振器周波数(vfo)の2つを引数に取っていますが、vfoのRS-HFIQへの設定のみを行い、tuneは引数をそのまま返値としていることが分かります。tuneの変更はRS-HFIQに対して何ら影響を与えていないことになります。また、vfoの変更はRS-HFIQの局部発振器(SI5351A)の周波数を変更しますが、tuneに影響を与えていないことが分かります。tuneとvfoは非同期とする実装になっています。
改造後のChangeFrequency関数
Quisk GUIでは、tune要求値が変更される場合と、vfo要求値が変更される場合の2つのケースがあります。そこで、tune要求値が変更された場合を検出するために、tuneの前回設定値を格納するクラス変数 self.tune をまず追加しました。
class Hardware(BaseHardware): def __init__(self, app, conf): ... self.tune = None ## Added to synchronize vfo and tune. (2022/12/09) ...
つづいて、tuneとvfoを同期させるために、ChangeFrequency関数に以下の改造を施しました。
def ChangeFrequency(self, tune, vfo, source='', band='', event=None): ## Added to synchronize vfo and tune. (2022/12/09) ##-------------------------------------------------------------------- if self.tune != tune : if serialport.isOpen() : self.tune = tune vfo = tune ##-------------------------------------------------------------------- if self.vfo != vfo : if serialport.isOpen() : self.vfo = vfo self.tune = vfo ## Added to synchronize vfo and tune. vfo_string = '*F' + str(self.vfo) + '\r' if DEBUG == 1: print("Tuning to: ", vfo_string) print("Tuning to: ", self.vfo) serialport.write(vfo_string.encode()) return self.tune, self.vfo ## modified to retune self.tune
tuneの要求値と前回設定値を比較して、tune要求値変更を検出します。変更を検出した場合は、tuneの前回設定値を今回の要求値に更新し、今回のvfo要求値も引数を無視してtune要求値に強制的に書き換えます。これで、tune要求値変更を優先したvfo同期制御ができます。
つづいて、vfo要求値変更を検出します。変更を検出した場合は、vfoの前回設定値を今回の要求値に更新し、tuneの前回設定値も今回のvfo要求値に設定します。これで、vfo要求値変更の場合のtune同期制御もできます。
以上により、tune要求値変更の場合も、vfo要求値変更の場合も、ハードウェアRS-HFIQのvfo周波数の変更が行われます。ChangeFrequency関数からは更新されたtune設定値とvfo設定値が返されます。Quiskはこれら返値を利用します。
Quiskハードウェアファイル改造後の動作検証
改造前と同じQuiskの初期状態から改造後の動作検証を行いました。すなわち、LO周波数とTune周波数の初期設定値は7.021MHzとしました。
LO周波数変更
初期状態からLO周波数ステップアップボタン[・](右側)をクリックすることにより、LO周波数を1kHzステップアップして7.022MHzに設定した時の挙動を下記に示します。Tune周波数もLO周波数に同期して7.022MHzに変化しています。
逆に、初期状態からLO周波数ステップアップボタン[・](左側)をクリックすることにより、LO周波数を1kHzステップダウンして7.020MHzに設定した時の挙動を下記に示します。Tune周波数もLO周波数に同期して7.020MHzに変化しています。。
何れの場合も、LOノイズがLSBフィルタの帯域内に侵入して復調されるようなことはありませんでした。
Tune周波数変更
初期状態からTune周波数エントリ内のkHz桁の数字の上部をクリックすることにより、Tune周波数を1kHzアップして7.022MHzに設定した時の挙動を下記に示します。LO周波数もTune周波数に同期して7.022MHzに変化しています。
逆に、初期状態からTune周波数エントリ内のkHz桁の数字の下部をクリックすることにより、Tune周波数を1kHzダウンして7.020MHzに設定した時の挙動を下記に示します。LO周波数もTune周波数に同期して7.020MHzに変化しています。
何れの場合も、LOノイズがLSBフィルタの帯域内に侵入して復調されるようなことはありませんでした。
RS-HFIQ Built-In Test(BIT)信号の挙動
最後に、RS-HFIQ内臓テスト信号の挙動を確認しました。下記に結果を示します。上段は初期状態で、LO = Tune = 7.020MHz、BIT周波数を1kHzアップの7.021MHzに設定しています。下段はTune掃引後の状態で、Tune = 7.0187MHzに設定されています。
上段の初期状態では、BIT信号がLOで折り返して、1kHzダウンの鏡像位置7.019MHzにイメージが発生しています。下段のTune掃引後の状態では、Tuneに同期したLO(= 7.0187MHz)でBIT信号が折り返して、2.3kHzダウンの鏡像位置7.0164MHzにイメージが移動しています。Tune掃引(7.020 ⇒ 7.0187MHz)によってLOも同期して連続変化するため、イメージの再生音が1kHzから2.3kHzに連続変化することが確認できました。
気付きとして、ウォーターフォール上でBIT周波数にノイズが発生しています。Tune掃引(LO掃引)はPLLシンセサイザ(SI5351A)のCK0の周波数を変えているだけで、BIT信号が利用するCK2は変更していません。今のところ下記の理由が考えられます。
- SI5351A周辺回路のパターン上でBIT信号にノイズが載る。
- BIT信号をダイレクトコンバージョンするQSD回路の過渡応答でノイズが発生する。
- 過渡応答信号に対するQuisk SDRの短時間FFT演算でノイズが発生する。
スイープ音に聴覚上の違和感はないため、3つ目のFFTノイズの可能性が高いと考えています。短時間FFTのバッファ長等は未調査です。