M5StackでBMコントローラーを動かしてみる

整理をしていたら懐かしいコントローラーがでてきたので、動かしてみました。

## ハード作成
プレステのコントローラーを接続するためのコネクタを作成します。

今回は、以下のソケットを使用しています。

https://ja.aliexpress.com/item/32822179485.html

### 配線
ソケットとM5Stack Core2との配線はこんな感じにします。

![配線図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189829/f92a1852-30f5-30fc-f1b2-63af4c7d9ac9.png)


上記のソケットだと、8番は端子がありません。
3番は、振動用の電源で、7~9Vの入力が必要ですので、今回は使っていません。
1番と、6番は、1kΩのプルアップ抵抗を入れてます。

1. Data
1. Command
1. Vibration
1. GND
1. 3.3V
1. Attention
1. Clock
1. Unkown
1. Acknowledge

### くみ上げるとこんな感じ
不格好ですが、配線するとこんな感じです。
ソケットは、グルーガンで固定しています。

![DSC_2388.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189829/c8b4ff91-0f85-2ef9-e391-78b37fa83dd2.jpeg)


## ソフトウェア
今回使用するライブラリはこちら。

https://github.com/madsci1016/Arduino-PS2X/

### ちょっと修正
このライブラリそのまま使用すると動作しないので、少し修正します。

#### ESP32環境向けの修正

`PS2X_lib.h`と、`PS2X_lib.cpp`で以下の`ESP8266`と指定されている部分に、`ESP32`を追加します。
 
```cpp:変更前
#ifdef ESP8266
```

```cpp:変更後
#if defined (ESP8266) || defined(ESP32)
```

#### アナログ接続時の処理を追加
このライブラリは、アナログでの通信が前提となっているようです。
デジタルで動作する機器（今回だとBMコントローラー）の場合、取得データの確認処理に時間がかかる現象が発生していました。
そこで、デジタル機器の場合は、チェックを無効にする処理を追加します（一応動いてます）

通信に関して詳しく調べたい方はこちらをどうぞ

https://store.curiousinventor.com/guides/PS2#hardware


データのチェックで、デジタル(0x40)の場合も、終了対象とする処理を追加します。
[変更箇所](https://github.com/madsci1016/Arduino-PS2X/blob/master/PS2X_lib/PS2X_lib.cpp#L122)


```cpp:PS2X_lib.cpp（122行目）
if ((PS2data[1] & 0xf0) == 0x70 || (PS2data[1] & 0xf0) == 0x40)
  break;
```


次に、アナログではない場合、取得の速度調整する処理があるので、デジタルの場合は、無効にします。
[変更箇所](https://github.com/madsci1016/Arduino-PS2X/blob/master/PS2X_lib/PS2X_lib.cpp#L131)

```cpp:PS2X_lib.cpp（131行目）
if ((PS2data[1] & 0xf0) != 0x70 && (PS2data[1] & 0xf0) != 0x40) {
    if (read_delay < 10)
        read_delay++;	// see if this helps out...
}
```

関数の戻り判定にも追加します。
[変更箇所](https://github.com/madsci1016/Arduino-PS2X/blob/master/PS2X_lib/PS2X_lib.cpp#L161)

```cpp:PS2X_lib.cpp（161行目）
 return ((PS2data[1] & 0xf0) == 0x70 || (PS2data[1] & 0xf0) == 0x40);
```

## PS2X_Libについて

### ボタンの取得

`read_gamepad`で、現在のボタンの情報を取得します。
※上記のデジタル対応をしないと、500msくらい処理時間がかかります。。

```cpp:PS2X_lib.h
void read_gamepad();
```

各ボタンの状態を取得する方法は4種類あります。

```cpp:PS2X_lib.h
// 現在ボタンの状況を取得することができます。
boolean Button(uint16_t);

// ボタンの状態が変化したかどうかを取得することができます。
boolean NewButtonState(unsigned int);

// ボタンが押されたかどうかを取得することができます。
boolean ButtonPressed(unsigned int); 

// ボタンが離されたかどうかを取得することができます。
boolean ButtonReleased(unsigned int);
```

引数は、確認したいボタンの種類です

```cpp:PS2X_lib.h
#define PSAB_PAD_RIGHT    9
#define PSAB_PAD_UP      11
#define PSAB_PAD_DOWN    12
#define PSAB_PAD_LEFT    10
#define PSAB_L2          19
#define PSAB_R2          20
#define PSAB_L1          17
#define PSAB_R1          18
#define PSAB_GREEN       13
#define PSAB_RED         14
#define PSAB_BLUE        15
#define PSAB_PINK        16
#define PSAB_TRIANGLE    13
#define PSAB_CIRCLE      14
#define PSAB_CROSS       15
#define PSAB_SQUARE      16
```

### サンプルを動かす

PSX2Libの[サンプル](https://github.com/madsci1016/Arduino-PS2X/blob/master/PS2X_lib/examples/PS2X_Example/PS2X_Example.ino)を修正して、動作を見てみます。
GPIOを、M5Stack Core2用に変更します。

```cpp:PS2X_Example.ino(9行目)
#define PS2_DAT        27    
#define PS2_CMD        19
#define PS2_SEL        32
#define PS2_CLK        33
```

動かすと、こんな感じでログが出力されます。
BMコントローラーを動かしているので、`Unknown Controller Type`と出力されてますが、動作はします。
![ログ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189829/529133c4-8d56-0f01-5b49-fd7586f5a995.png)


## 活用してみる

### BMコントローラの配置
BMコントローラの配置はこんな感じです
ターンテーブル部分は、右周りで、上ボタン、左回りで下ボタン入力として認識されます。
![配置](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189829/675fae8b-d788-6f5a-2af8-d522e7604ee3.png)

1. L1ボタン
1. R1ボタン
1. □ボタン
1. ×ボタン
1. 〇ボタン
1. 右回りが上ボタン、左回りが下ボタン
1. SELECTボタン
1. STARTボタン

### toioと連携

折角なのでSONYさんのtoioを動かしてみました。

操作は、6番のターンテーブルを右に回すと前進、左に回すと後進です。
1番のボタンを押すと、左に、2番のボタンを押すと右に曲がります。
3~5番のボタンは、曲がるときに角度が変化し、すべて押すとスピンします。

操作するとこんな感じに。
※【ご注意】Twitterで投稿した使用ライブラリが違ってました。。

https://twitter.com/masaya3/status/1409746540663508998

## まとめ
プレステ用のソケットを手に入れることができれば、あとは簡単にできるかなと思います。
今回は、BMコントローラーを使いましたが、ほかにもあるので機会があれば活用してみようと思います。