« Raspberry PiのSPIを使う。wiringPiを使った方法。 | トップページ | ビットスワップ LSBファーストにビットの順番を入れ替える。 »

2013年12月31日 (火)

Raspberry Piにプレステのコントローラをつなぐ SPIの詳細な利用方法

RaspberryPiをミニゲーム機に仕立て上げるべく、プレステのコントローラをつなぐことにした。

Evernote_snapshot_20131231_211620
我が家のタンスの中にしまいこまれていたPS1のHORIパッド。
捨てる前に!!


プレステのコントローラ(以下PSパッド)は、SPI通信でボタン情報を読み出せるようになっている。通信フォーマットや動作波形の様子は別途このページを参照されたし。

PSパッドは通信フォーマットの解説にあるとおり、LSBファーストでバイトを送信しなければならない。またクロックの位相も、前回wiringPiという便利ライブラリを使った時とは違っているので、いちいち指定してやらなければならない。そこで今回は、wiringPiライブラリを使わずに、linuxプログラミングでより詳細な設定を利用する。



一番参考にしたのがこのソースで、
raspberryのSPIに設定できるオプションを全て試せると思った。
大抵の英語サイトも上記のリンクを参考にしていた。


ここではまず、PSパッドを使おうとする上で最も重要な、ビットオーダーをひっくり返すオプションを指定したい。ソースの76行目に"-L"を指定せよとある。
"  -L --lsb      least significant bit first\n"

コマンドラインでこんな風に打ち込んだ
$ ./spidev_test -D /etc/spidev1.1 -s 100000 -L

ところがまともに実行できない。
ソース中に書いてあるオプションを試してみたのだが、speedとdeviceしか受け付けてくれない。キー入力されたオプションを読み込むらしき部分は

c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);

となっているので、オプションの指定の順番があるような気がしてきた。そこで、オプションの入力の順番、-Lを最初のほうに入れ替えてみた。

しかし上手くいかない。
このエラーが繰り返し出てくるだけであった。
can't set spi mode: Invalid argument


コマンドライン引数からのオプション指定が上手くいっていないのだと思い、ソースを一旦消して、modeという変数に直接数値を入れるように書き直してみた。しかしこれも上手くいかず。どうもSPI_LSB_FIRSTというオプションが定義されていないのだろうか。

uname -a

でカーネルのバージョンを調べてみたが、3.6.11だったのでこれは最新で問題なし。

-----

ずばりPS2のパッドを使おうとしている人のページを発見。
しかしハードでやるのをあきらめて、ソフトでやっている。。。
ビットの順序逆転についてはあまり調べなかったが、この人はテーブル参照方式とやらを使っているらしい。

-----

同じソースをベースに書いているが、ちょっと変えてあるページを発見。
defineのところで一括して指定するらしい。
掲載されているC言語の文法がなんだかおかしい。コンパイルが通らず・・・。

-----


ラズベリーの仕様書や使い方が載っているこのページを見ると、
SPIクロックのスピードについて。サポートしているスピードはUARTと同様決まっているとある。そして決まった周波数以外を指定すると、規定の周波数のなかで指定した周波数より低いものが自動で選択される。

しばらく見ると、Supported Mode bitsという項目があり、クロックのフェーズについてと、CSの扱いについてのもの。下記4項目しかかかれていない。ということはこれ以外のオプションはRaspberryではサポートしていないということか??

    * SPI_CPOL - Clock polarity
    * SPI_CPHA - Clock phase
    * SPI_CS_HIGH - Chip Select active high
    * SPI_NO_CS - 1 dev/bus, no chipselect



これら4つのオプションを全て試したところ、確かに実行することができた。

pi@raspberrypi ~/TameshiSpace/131230 $ sudo ./spidev_test -s 100000 -D /dev/spidev0.1 -HOCN
spi mode: 71
bits per word: 8
max speed: 100000 Hz (100 KHz)

FF FF FF FF FF



そして、これ以外のオプションについてはどれもInvalid argumentのエラーが出た。つまりそれらのオプションはおそらく、ヘッダで宣言されてない。

サンプルソースを見て、LSBファーストを指定できるのかと思いきや、対応していないことがわかった。

broadcomのARM-peripherals.pdfを見てみたが、LSB firstについてはどうやら見当たらなかった。ハードが対応していなかったらしい。
linux全般で調べてしまうとまずいこともあるということか。


-----

ようやく、

SPIが使えるようになったので、PSパッドをつないだ。

PspadPspadpin_2

このソースが半完成品。
「spidev_ps.c」をダウンロード

実行すると、こんな感じでパッドからデータが返ってくる。

pi@raspberrypi ~/TameshiSpace/131230 $ sudo ./spidev_ps
spi mode: 3
bits per word: 8
max speed: 61000 Hz (61 KHz)

FF 82 5A FF FF

RaspberryのSPIではLSBファーストのオプションが使えなかったので、とりあえず手計算でビットを逆順にして送信し、パッドからのIDを受け取れるようにした。

注意: トラブルシュート
もしこの時点で00しか出てきてなかったら、DATのプルアップを付けたか確認する。
DATだけオープンドレインなので注意。


いつもなら、下記のバイト列をLSBファーストで送る。
0x01,0x42,0x00,0x00,0x00

手動でLSBファーストに書き直して、ソース内の送信バッファに書き込んだ。
0x80,0x42,0x00,0x00,0x00

するとパッドからの返答が、
FF 82 5A FF FF
で返ってくる。

これをLSBファーストに書き直すと、
FF 41 5A FF FF

ノーマルパッドは0x41が返ってくるはずなので、パッドのIDが正しく読めていることが確認できた。下は動作させたときのDATピンの波形。

Ws000091

このラズベリーに小型液晶を接続すれば、ちょっとしたゲーム機が作れそう。プレステのエミュレータをインストールすれば本当にミニ版PSが作れる。

注意: トラブルシュートおさらい。

・SPI通信の結果が全バイトが0x00だったら、DATのプルアップを付けたか確認する。
DATだけオープンドレインなので注意。
・SPIを使うには、linuxの設定ファイルの書き換えが必要。lsmodでデバイスドライバがロードされているか確認する。
・デバイスファイルにアクセスするプログラムは、sudoがないと実行できない。さらにwiringPiライブラリを使った場合は"gpio load spi"というコマンドが必要。





電子工作 ブログランキングへ

« Raspberry PiのSPIを使う。wiringPiを使った方法。 | トップページ | ビットスワップ LSBファーストにビットの順番を入れ替える。 »

Raspberry Pi」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

« Raspberry PiのSPIを使う。wiringPiを使った方法。 | トップページ | ビットスワップ LSBファーストにビットの順番を入れ替える。 »