PRUとLinuxアプリを連携してリアルタイム制御(任意波形を出力)

PRUをLinuxアプリから制御するプログラムを作ってみました。

Linuxアプリ
PRUプログラム

Linuxアプリからドレミ…という音階の周波数に応じた周期の値をメッセージとしてPRUに送り、PRUはメッセージで指示された周期でGPIOを制御します。

GPIOにトランジスタとスピーカを接続すると、ちゃんと「ドレミファソラシドー」と鳴ります。
-oオプションでオクターブも変えられます。

周波数を2倍(-o 1)にすると
1オクターブ上がり、
周波数を0.5倍(-o 3)にすると
1オクターブ下がります。

PRUをLinuxアプリから制御するプログラムを作ってみました。

Linuxアプリ
PRUプログラム

Linuxアプリからドレミ…という音階の周波数に応じた周期の値をメッセージとしてPRUに送り、PRUはメッセージで指示された周期でGPIOを制御します。

GPIOにトランジスタとスピーカを接続すると、ちゃんと「ドレミファソラシドー」と鳴ります。
-oオプションでオクターブも変えられます。

それほど高い周波数ではないので、Linuxアプリでも可能なことですが、Linuxアプリで音を鳴らそうとした場合、頻繁に遅延が発生して音が乱れます。

しかし、PRUは遅延が発生しないので、何度鳴らしても音が乱れることはありませんでした。

さて、肝心なメッセージを送信/受信する処理は、公式サイトのSDKにサンプルがあるので、こちらを参照してください。
このサンプルは、PRUにメッセージを送ると、同じ内容を返送してくる、というシンプルなものです。

SDKが無い場合、以下のサイトから入手します。
(起動イメージの /usr/lib/ti/pru-software-support-package にも入っています。)

解説:PRU Software Support Package
SDKパッケージ:master.gz
SDK内のメッセージ返送サンプル:PRU_RPMsg_Echo_Interrupt0(AM335xやBeagleBone用)

 

今回は、このサンプルに一手間加え、メッセージに含まれる命令に従ってGPIOにパルスを出力する様にしました(命令された間隔(周波数)でGPIO出力を反転させるプログラムにしました)。
これは、PWM出力のperiodと同じ機能ですが、PWMよりも制限が少ない事と、ch数に上限が無いことが利点です。

これにより、任意の周波数の波形を出力できるので、任意の音階の音が鳴らせるわけです。

PRUプログラムは、展開後 make clean install でコンパイル~バイナリファイルの配置まで実行されます。

その後、以下の様にしてPRUを再起動します。

echo ‘stop’ > /sys/class/remoteproc/remoteproc1/state
echo ‘start’ > /sys/class/remoteproc/remoteproc1/state
config-pin P1_36 pruout

アプリは、gcc msg_pru_app.c でコンパイルできます。

コンパイル後、以下の様に実行すると、ドレミの周波数がPRUに指示され、GPIO(P1_36)から音声信号が出力されます。

../a.out /dev/rpmsg_pru30

 

もう少し工夫すれば任意波形の出力が可能

今回は周波数(信号の間隔)のみ指定し、次の指示があるまで一定の周波数でGPIOを動かすだけのプログラムなのでシンプルなPWMと変わりありませんが、更に工夫すれば、任意の波形を出力したり、任意の通信パケットを送信したりすることも可能です。

例えば、16進数で波形パターンをPRUに送信、PRUはその波形パターンを繰り返し再生する…

例えば、HDLC等の通信パケットのバイナリデータとビット数、ビットレートをPRUに送信、PRUはそのバイナリデータを指定されたビットレートで指定されたビット数分GPIOに出力…

それほど難しい処理ではありません。

HDLCを装備したデバイスはもうほとんどありませんので、ISDN互換やS-BUS互換の通信機器を作っているメーカは高価なIPや変換機を購入して組み込んでいるようです。

しかし、Cで組める200MHzのプログラマブルロジックがここにあるのです。
315kbpsや1.2Mbpsくらいの通信ペリフェラルくらい作れそうなものですよね?