RX62Nでファンクションジェネレータを作る
RX62Nで2chのファンクションジェネレータを作ることができました。
のこぎり波やサインカーブだけではなく、任意の波形を発生させることができます。
どういう原理かというと、次の図をご覧下さい。
タイマを使ってDMAコントローラを駆動し、内蔵RAMに書かれた波形データをDAコンバータに転送するというわけです。
この構成では、コンペア・マッチ・タイマCMT2を使って1MHzの割り込み信号を作ります。1MHzの割り込みというと尋常じゃない感じがしますが、CPUが受け取るのではなくDMAコントローラのトリガとして動くように設定するのです。この辺がRX62Nのアーキテクチャのすごいところです。
DMAC0をリピートモードに設定して、メインメモリから波形データの1ワードを読み出してきて、それをDAコンバータの出力値設定レジスタに書き込むようにします。このときに使われるデータバスは「内部メインバス2」というのが使われる(はず)なので、CPUの動作を介さずにハードウェアだけで上記の処理を1MHzのタイミングで行うことができるわけです。
CPUがどんな処理を実行していようとも、それの影響を受けずにハードウェアが粛々と波形を出力してくれることでしょう。
さて、DMAコントローラはノーマルモード、リピートモード、ブロックモードと3つのモードがありますが、ここではリピートモードを使います。リピートモードというのは、メモリの決まった範囲を順繰り順繰り読んで、内蔵ペリフェラルの決まったレジスタに書き込むといったような場合に使えます。
さて、技術的な課題がいくつかあります。
・出力チャネル数を2chにしたいかどうか
・DDSみたいにしたいか、FGでよいか
・出力周波数をきっちりとした値にしたいかどうか
【波形出力を2chにする方法】
まず、出力チャネル数を2チャネルにしたいかどうかです。2チャネルにするには、DA.DADR0とDA.DADR1という2つのレジスタに書き込まなければなりません。しかし、これらのレジスタに同時に値を書き込むには、DMACが1つでは足りません。2つのDMACを動かせばよいのですが、後述のDDSモードではDMACを「拡張リピートモード」と「オフセット加算」で使うので、2つ同時には使えません。
そこで、禁じ手を使いました。DA.DADR0とDA.DADR1は本来は16bitサイズのレジスタだが、アドレスが隣り合っているので、32bitサイズでアクセスすれば一括でアクセスできないだろうか?ということです。ルネサスのCPUの内蔵ペリフェラルはレジスタにアクセスするときのサイズが厳しく決められていて、本来はこういうことはできないはずなのですが、それを承知でやってみたところ、なんとなくうまくいきました。「なんとなく」というのはDA1とDA0の値がなぜか逆になっているためです。エンディアンの関係かもしれません。動いているように見えるけどやっぱり何かあるのでしょう。
【DDSみたいなものの実現方法】
次にDDSみたいなものにしたいかどうかです。DDSにするには、メモリから読み出していく値を、例えば5とか、決まった値だけ加算していく必要があります。それを実現するには、DMACのオフセット加算モードというのを使います。
しかし、オフセット加算モードだけでは、用意した波形バッファの範囲をオーバーしてしまう可能性があります。波形データを1024ポイント分作っておいて、次のデータが1022+5の場所だというときには、&1023してやって4番目のデータを見てやらねばなりませんが、ソフトウェアでやるわけにはいきません。
そこで、DMACの拡張リピートモードというのを使います。拡張リピートモードでは、アドレスの下何ビットかだけを有効にして、上のビットをマスクして順繰り順繰りしてくれるモードです。今回のようなDDSの機能を実現するにはうってつけです。
【周波数を正確な値にする方法】
最後に出力周波数を正確に1.000kHzのようなきっちりした値にしたいかどうかです。1.000kHzにするには、リピートモードの周期(データ数)を1000とか500とかにしてやらねばなりません。しかし、そうすると拡張リピートモードが使えなくなります。976Hz、1.953kHz、2.928kHzと、ちょっとずつ遅い周波数になってしまいますが、仕方がありません。
他のアプローチとしては、メインクロックの水晶の周波数を12MHzではなく、12.288Hzにしてやるという方法も考えられます。クロックの水晶を12.288MHzにしても、CPUの動作クロックは98MHzなので動作範囲内です。
それから、SDRAM上に大容量の4Mバイトくらいの大きな波形データを用意してやるという方法も考えられます。1周期が1MHz/1048576になるので、999.59Hzのようにより近い値が出せます。
DMACは高機能なので、まだ理解していない使い方があるかもしれません。DDSモードとFGモードの切り替えは簡単なので、両方に対応させておいてもいいかもしれません。今後にご期待ください。
今回のファンクションジェネレータの動作を動画にしたので、ぜひご覧下さい。
チップ単体でここまでできます。
音声帯域なら十分に実用的になるのではないかと思います。
このプログラムは下記のリンクから無償でダウンロードできるようにしたので、ぜひ、お試しください。
「fg.mot」をダウンロード
究極のRX62Nボード、RX-MEGA、RaXino♪など、RX62Nボードであれば何でも動作すると思います。
また、USB(RX62Nの仮想COMポート)を通じて周波数を操作することができます。'0'~'9'までの数字を打つと、約1~10kHzで周波数が変わります。's'を打つと、周波数のスウィープが楽しめます。
◆
追記。
ひとつ間違えていたことがありました。拡張リピートエリアを設定するときには、ノーマルモードにしたほうがよい??のかもしれません。
ノーマルモード+拡張リピートエリア設定にしたら、SDRAM上の巨大な波形バッファから上手く転送することができて、周波数を滑らかに変化させることができるようになりました。
カクカクではなく、うにょうにょと変わります。
つまり、メモリをたくさん積んだ究極のRX62Nボードなら約0.数Hz単位で周波数を変えられる。チップ単体で外付けメモリを持たないRaXino♪でも約1kHz刻みのステップで周波数を変えられるというわけです。
最近のコメント