【M5Stack FACES】GameBoyカバーのボタン入力を得る

2020年1月14日

スポンサーリンク

新年1つ目の通常投稿は『M5Stack』を触ってみます。
以前、M5Stack FACESにテトリスを入れたのですが、GameBoyカバーのボタンが機能していなかったので、そのボタン対応をして行きたいと思いますよ。
と言っても、ピンポイントな情報が上手く探し出せなかったので、若干手探りでの進行になります。
とりあえず今回は、ボタンの入力を得られるところまで進めたいと思います。

スポンサーリンク

まずは情報収集

何をするにも、まずは公式情報を見ないと始まらなかったりするんですが…
M5Stack FACESの公式情報があやふやになってません?
一応、GitHubのm5stackの中を色々と見てみたんですけど、何が正しい情報なのかよく分からなかった。
m5stack/m5-docs/blob/master/docs/ja/core/face_kit とか
m5stack/m5-docs/blob/master/docs/ja/base/face_base とか
なんか、それっぽい気がするんだけど、画像とかリンク切れてるし!
微妙に欲しい情報(PIN配置とか回路図とか、サンプルコードとか)が見つけられないし!
あとは、SWITCH SCIENCEの販売サイトの各種資料とか。。。
m5stack/M5Stack/blob/master/src/M5Faces.cpp は少し参考になるかな?
でも、これだ!と言う情報を見つけられんかった( > _ < )

最終的にはスケッチ例が一番だった

と、他にも色々それっぽいのを漁ってみたんですが、最終的には…
Arduinoのサンプルスケッチ
[ファイル]->[スケッチ例]->[M5Stack]->[Modules]->[FACES]->[I2C_Keybord]
に行き着きました。
以下は、そのサンプルのコード全文です。

#include <M5Stack.h>

#define KEYBOARD_I2C_ADDR     0X08
#define KEYBOARD_INT          5

void setup()
{
  M5.begin();
  Wire.begin();
  M5.Lcd.setTextFont(2);
  M5.Lcd.println("FACES Keyboard I2C Read Example");
  pinMode(KEYBOARD_INT, INPUT_PULLUP);
}

void loop()
{
  if(digitalRead(KEYBOARD_INT) == LOW) {
    Wire.requestFrom(KEYBOARD_I2C_ADDR, 1);  // request 1 byte from keyboard
    while (Wire.available()) { 
      uint8_t key_val = Wire.read();                  // receive a byte as character
      if(key_val != 0) {
        if(key_val >= 0x20 && key_val < 0x7F) { // ASCII String
          Serial.print((char)key_val);
          M5.Lcd.print((char)key_val);
        } else {
          Serial.printf("0x%02X ",key_val);
          M5.Lcd.printf("0x%02X ",key_val);
        }
      }
    }
  }
}

これをそのまま動かすだけで、GameBoyカバーのボタン入力が反応します。

とりあえず動かしてみる

何はともあれ、動かしてみましょう。
起動すると、初期表示で

FACES Keyboard I2C Read Example
0xFF

と表示されます。
…何も押してないのに "0xFF" が表示されるのはそう言う仕様かな?
あとは、ボタンを押すたびに、押されたボタンに対応するコードが表示されて行きます。
とりあえず、例でAボタンを押すと

FACES Keyboard I2C Read Example
0xFF 0xEF

と表示されて、 "0xEF"が取得できます。
Aボタンを離すと"0xFF"が再度取得されます。
恐らく、ボタンの変化がある度に値が取得されるのだと思います。
他のボタンも色々押すと、どんどん値が取れて面白いですよ。

色々とボタンを押してみた
色々とボタンを押してみるとこんな感じ

ボタン対応表

一通り触ってみると、ボタンの対応が見えてきました。
→:F7 (0bit目)
←:FB (1bit目)
↓:FD (2bit目)
↑:FE (3bit目)
START:7F(4bit目)
SELECT:BF(5bit目)
B:DF (6bit目)
A:EF (7bit目)
このキー入力の対応を、テトリスのコードに埋め込めば、何とか動かすことができるはず!

結局どうやっているの?

実際にどうやって値を取得しているのかと言うと…
setup関数内の

Wire.begin();

で、Wireライブラリを初期化してI2Cを利用できる様にしています。
そして、loop関数内の

Wire.requestFrom(KEYBOARD_I2C_ADDR, 1);
while (Wire.available()) { 
   uint8_t key_val = Wire.read();
   ...
}

でI2C(0x08アドレス)から1バイトの値を読み出します。
このコードをテトリスのコードに上手く埋め込めば使える様になるはず!!!

次回は実際にテトリスのコードを変えるよ

今回は、GameBoyカバーでの押下ボタンと取得値の関係性と、
入力値の取得コードを探し出すところまでできました。
これが分かれば、何とかなるはず!
と言う事で、次回は実際にテトリスのコードに手を入れて、GameBoyっぽく操作できる様にしていこうと思います。

乞うご期待!

(おまけ)デフォルトでインストールされているのは、Nintendo エミュレータだった…

前回のM5Stackの投稿で”マリオ(っぽいもの)で遊びたかった”と書いたのですが、
今回色々と調べていたところ、デフォルトでインストールされているのは"Nintendoエミュレータ"であることが分かりました。
そして、同時にマリオ(っぽいもの)のROMが入っているみたいです。
実際にソースコードがあるのかと思っていたのですが…違ったんですね。

今回の対応のついでに、実際に公開されているエミュレータも入れてみたのですけど…
遊べはするけど、処理が重かったりサウンドの音割れが酷かったりして、あまり快適じゃなかったです。
もう少し、最適化されているのかと思ったんですけど、違いましたね。
ちょっと残念でした。

スポンサーリンク