2008-11-02

MSKをゼロクロスでデコード

MSK(CPFSKも含む)をゼロクロスを使ってデコードする方法について書いてみることにします。今回作成している私鉄空線のデコーダもこの方法を使っています。

ゼロクロスは、振幅の0をまたいだ時間を測定して、信号の周波数を測定するという方法としてよく知られている方法です。基本原理は、振幅が0を基準となる周期信号は1周期で2回符号が入れ替わる(すなわち、0をまたぐ)ということから、符号をが2回変わった時間を測定すれば、1周期の時間となりその逆数が周波数になるというものです。

MSK(CPFSK)の信号は、位相が連続して周波数が移行するといったものですが、シンボルが入れ替わるところは、一般的に振幅が0となるところになります。他には最大振幅点で変わるものもあるようですが、あまり多くはないようです。
ここでは、一般的となる振幅0で移行するもの(これをsin型という)をゼロクロスを使ってデコードする方法について書くことにします。

まずは、変調速度に同期するのですが、上記の条件の通りシンボルの入れ替わりは、常に振幅0の位置で起こるわけですから、ゼロクロスの点になります。同期の開始位置は、シンボルの入れ替わる場所となりますが、もし1つシンボルが変調速度の2倍の周波数となる場合、それだけでも、変調速度との同期が可能です。

この手の処理は、ハードウェアでは変調速度と同じクロックをPLLを使って同期させるというのは一般的な方法です。しかし、ソフトウェアでのデコードの場合、多少事情が異なります。
というのは、信号はサンプリングされてデジタル化されるわけですが、変調とは無関係なクロックでサンプリングされてしまっているので、完全な同期というのはできません。しかし、変調速度よりも比較的高い周波数でサンプリングされていれば、誤差は多少あるもののデコードはは可能です。

サンプリングされたデータからゼロクロスを検出するには、振幅が0以上か未満かで2つに分けて、1つ前のサンプルと比較して違っていれば、1つ前のサンプルとそのサンプルの間のどこかにゼロクロス点があるということになります。
そして、次のゼロクロスを見つけてその間のサンプル数を数えていけばよいわけです。ただし、サンプリングのクロックとの関係上1サンプル分の誤差が生じる可能性があるため、その分を考慮して同期をとるようにしていきます。

あとは、変調速度に相当するサンプル数(サンプリング周波数÷変調速度)毎にゼロクロスが存在することを確認しながら、その間に含まれるゼロクロスの数を数えていけばよいです。もし、変調速度と同じ周波数で変調されていれば、ゼロクロスは中間に1つ存在するわけですし、1/2の周波数ならば、ゼロクロスは0個といった具合になります。

といった方法でデコードは可能ですが、現実にはゼロクロスの位置が信号の歪みにより前後することがあります。なので、その分を考慮し多少前後しても許容するような作りのほうがデコード能力は高くなります。ただし、あまり甘くしすぎると誤検出することもあるので、その辺のさじ加減はチューニングのひとつとなるでしょう。

あと、ゼロクロスに限った話ではないですが、前処理としてフィルタをかけておくと、比較的簡単にデコード能力が向上します。もちろん、フィルタの選び方次第で良くも悪くもなるので、それなりに適切なフィルタを選ぶ必要はあります。
正直言って、ベストなフィルタというのはわかりません。基本的にはBPFをかけるのですが、通過域が広いとノイズの除去になりづらいですし、狭くしすぎると歪みが起きてゼロクロスがずれます。

ゼロクロスの処理は、アルゴリズムも比較的簡単でプロセッサの処理的には軽く実現することができるので、まずはMSKなどのデコーダを作ってみようという人にはおすすめです。
実際に作った空線のデコーダですが、上記の処理方法をベースに作成していますが、十分なデコード能力を持っていると思います。