オリジナルガシャット『大乱闘スマッシュブラザーズガシャット』の仕組み

th_sb-gasaht_12

前のマリオガシャットのときは、「自分も作りたい」という方がそこそこおられたので、少し詳しめに作り方の紹介記事を書きました。今回のスマブラガシャットについては、おそらく同じようなものを作りたいという人はいないと思っていますが、今回自分が作ったものがフェイク(=動画上での音声の切り貼り)ではないですよという証明と、他の誰かが何か作りたいときのヒントにはなるかもしれないという思いで、簡単に中身の紹介をしておこうと思います。

ということで、今回は技術寄りのお話になります。

まずはハードウェアの方から。主に使用している具材は以下です。

まずは何はともあれ、外側の入れ物が必要です。スピーカーはこれに内蔵されているものをそのまま流用します。

 

ちょっとAmazonには正規品の取り扱いがなかったので、私がいつもお世話になっているスイッチサイエンスさんにリンクを貼っています。互換品でも動くのかもしれませんが、私は基本的に正規品を使用するようにしています。

マリオガシャットのときは、同じArduino Pro Miniでも、3.3V 8MHz版を使用していました。その方が3.7V出力のリチウムイオンポリマー充電池と相性が良さそうだったのでそうしていたのですが、今回新たに採用したNFCリーダー(後述)が3.3V版だとうまく動いてくれなかったので、今回は5V版を採用することになりました。

そして今回、Arduino Pro Miniは2つ使います。ダブルガシャットモチーフだから2つ使いました、というわけでは全然なく、やむなしでこうなりました。理由は後ほど。

 

マリオガシャットでも使用していたMP3プレーヤーモジュールです。もはや自分の工作ではほぼ必須の存在です。使い方につきましては、こちらをご参照ください。

 

こちらも同様に、自分の工作では必須アイテムです。

 

今回新たに使用するモジュールです。マイクロSDカードに保存した画像(bmp)を表示できるので、容量の小さいArduinoでも画像を扱えるようになります。使い方につきましては、こちらをご参照ください。

 

MP3プレーヤーと液晶ディスプレイ用に2枚必要になります。

 

こちらも今回新たに使用するモジュールです。商品名は『Felica リーダー・ライター』ですが、hirokumaさんの公開してくださっているライブラリを使用することで、NFC Type A・Bの読み書きが可能になります。使い方につきましては、こちらこちらをご参照ください。

 

上のリンクはスイッチサイエンスさんの110mAhの商品にリンクを貼っていますが、今回は消費電力が大きくなるので、ワンランク上の400mAhのバッテリーを使っています。

 

メインの具材はこんな感じです。後はこれに、プラ板やらリード線やら熱収縮チューブやら、よく工作で使う部品を使います。

 

これらの具材を、以下のように配線します。

th_sb-gasaht_18

実際に配線すると、こんな感じになります。。。

th_sb-gasaht_17

なお、3つのボタン(スイッチ)の具体的な配線についてはマリオガシャットとほぼ同様なので、そちらをご参照いただければと思います。

ちなみに、液晶ディスプレイとNFCリーダーについては、そのままではガシャットの中に収まってくれなかったので、

th_sb_gashat_31

th_sb_gashat_32

th_sb_gashat_22

 

th_sb_gashat_28

th_sb_gashat_24

th_sb_gashat_27

 こんな感じで、ギリギリまでカットしています。

 

さて、ソースコードの説明をする前に、「なぜArduinoが2つ存在しているのか?」という疑問を解決しておきたいと思います。

Arduino LCD Screenの紹介をしたときにも触れていたのですが、LCD Screenのライブラリは非常にサイズが大きく、それだけでArduinoのフラッシュメモリとRAMのほぼ半分を使用してしまいます。

一方、hirokumaさんが作成してくださったNFC用のライブラリ(ArduinoHkNfcRw)もまた、素の状態で使用すると、RAMのほぼ半分を使用してしまいます。

結果、両方のライブラリを1つのArduino内で同時に使用しようとすると、メモリがオーバーします。実際、私が最初に作ったプログラムでは、ソースをコンパイルすると

最大30,720バイトのフラッシュメモリのうち、スケッチが29,346バイト(95%)を使っています。
最大2,048バイトのRAMのうち、グローバル変数が2,105バイト(102%)を使っていて、ローカル変数で-57バイト使うことができます。

となり、完全にメモリオーバーになってしまいました。

実はNFCライブラリ(ArduinoHkNfcRw)の方は、デフォルトではNFCのType A, B, F(Felica)の三種類に対応するのようになっているので、これを一種類(amiiboに合わせてType A)に絞れば、ライブラリのサイズを小さくすることができます(RAM専有率51%→37%)。具体的には、ライブラリ内のソース”HkNfcRule.h”の以下の2行をコメントアウトすればOKです。

#define HKNFCRW_USE_NFCB
#define HKNFCRW_USE_NFCF

そうすると、

最大30,720バイトのフラッシュメモリのうち、スケッチが28,044バイト(91%)を使っています。
最大2,048バイトのRAMのうち、グローバル変数が1,830バイト(89%)を使っていて、ローカル変数で218バイト使うことができます。

スケッチが使用できるメモリが少なくなっています。動作が不安定になる可能性があります。

のように、数字上はギリギリ収まるようになるのですが、警告通り、動作が不安定になります。

自分の知識レベルでは、これ以上ライブラリの中を探ってサイズを小さくするということはできませんでした。そのため、液晶ディスプレイの表示を制御するコントローラのためだけに一台のArduinoを割り当て、そのArduinoをI2Cのスレーブとして動作させ、メインのArduinoとI2Cで通信させるという作戦をとることにしました。コストはかかりますが、これで、サイズの大きい2つのライブラリがそれぞれ別のArduinoに分かれて使用されることになり、メモリの問題は解決します。

 

というわけで、以下、2つのArduinoのソースコードについて、ポイントだけ説明します。まずは液晶ディスプレイ側のArduinoのソースコードから。

#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TFT.h>

// PIN DEFINITION FOR LCD SCREEN
#define sd_cs  4
#define lcd_cs 10
#define dc     9
#define rst    8

TFT TFTscreen = TFT(lcd_cs, dc, rst);
PImage picture;
char last_code = 'z';

void(* resetFunc) (void) = 0; 

void setup() {
  Wire.begin(8); // Address 8
  Wire.onReceive(receiveEvent);

  // SD Card Ready
  if (!SD.begin(sd_cs)) {
    return;
  }

  // LCD screen Ready
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
}

void loop() {
  delay(100);
}

void receiveEvent(int howMany){
  char code;
  while(Wire.available()){
    code = Wire.read();
  }
  if(last_code != code){
    TFTscreen.background(0,0,0);
    switch(code){
    case 'a': picture = TFTscreen.loadImage("sb.bmp"); break;
    case 'b': picture = TFTscreen.loadImage("mar0.bmp"); break;
    case 'c': picture = TFTscreen.loadImage("mar1.bmp"); break;
    case 'd': picture = TFTscreen.loadImage("mar2.bmp"); break;
    case 'e': picture = TFTscreen.loadImage("mar3.bmp"); break;
    case 'f': picture = TFTscreen.loadImage("lin0.bmp"); break;
    case 'g': picture = TFTscreen.loadImage("lin1.bmp"); break;
    case 'h': picture = TFTscreen.loadImage("lin2.bmp"); break;
    case 'i': picture = TFTscreen.loadImage("lin3.bmp"); break;
    case 'j': picture = TFTscreen.loadImage("liz0.bmp"); break;
    case 'k': picture = TFTscreen.loadImage("liz1.bmp"); break;
    case 'l': picture = TFTscreen.loadImage("liz2.bmp"); break;
    case 'm': picture = TFTscreen.loadImage("liz3.bmp"); break;
    case 'z': resetFunc(); break;
    default : picture = TFTscreen.loadImage("sb.bmp");
    }
    delay(2500);
    TFTscreen.image(picture, 0, 0);
  }
  last_code = code;

}

こちらはソースとしてはシンプルです。基本的にはI2Cのスレーブとして設定して、マスターから送られてきた文字に合わせて表示する画像データを選択し、表示させているだけです。

1つ特筆しておくべきところは、文字”z”が送られてきたときにソフトウェアリセットがかかるようにしてあることです。これは一体何のために用意しているかというと、ディスプレイ表示の安定化のためです。

原因は未だによくわかっていないのですが、ディスプレイに表示する画像の切り替えを何回か繰り返していると、数回目にはほぼ確実に画像の表示がおかしくなるという現象が発生してしまいました。この現象はディスプレイ制御用のArduinoをリセットすると解消することだけは確認できていたので、マスター側のArduinoからの指令で自由にディスプレイ制御用のArduinoをリセットできるようにしています。

リセットをかけると、どうしてもディスプレイが一瞬真っ白になってしまうので、このガシャットでは、ガシャットの挿入時(「ダブルガシャット!」の音声の後のレベルアップ待受時)に、一度リセットをかけるようにしています。このときならリセットをかけていることが外からは見えないので。

なお、液晶に表示する画像ファイル(bmp)の作り方については、こちらをご参照ください。

 

続いて、メインの方のソースコードです。1000行程度と少々長めですがご了承ください。

#include <Wire.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
#include <Adafruit_NeoPixel.h>
#include <HkNfcRw.h>
#include <HkNfcA.h>

#define BUTTON_1_PIN 4
#define BUTTON_2_PIN 6
#define BUTTON_3_PIN 8
#define LED_PIN      9

#define N_LED    1
#define N_BUTTON 3
#define BT1_ON  HIGH
#define BT1_OFF LOW
#define BT2_ON  HIGH
#define BT2_OFF LOW
#define BT3_ON  LOW
#define BT3_OFF HIGH

const uint8_t OFF_OFF_OFF[] = {BT1_OFF, BT2_OFF, BT3_OFF};
const uint8_t ON_OFF_OFF[]  = {BT1_ON,  BT2_OFF, BT3_OFF};
const uint8_t OFF_ON_OFF[]  = {BT1_OFF, BT2_ON,  BT3_OFF};
const uint8_t OFF_OFF_ON[]  = {BT1_OFF, BT2_OFF, BT3_ON };
const uint8_t ON_ON_OFF[]   = {BT1_ON,  BT2_ON,  BT3_OFF};
const uint8_t ON_OFF_ON[]   = {BT1_ON,  BT2_OFF, BT3_ON };
const uint8_t OFF_ON_ON[]   = {BT1_OFF, BT2_ON,  BT3_ON };
const uint8_t ON_ON_ON[]    = {BT1_ON,  BT2_ON,  BT3_ON };

// State定義

// 単体遊びモード
#define STANDALONE_NAME  0
#define STANDALONE_ITEM  1
#define STANDALONE_CLEAR 2
// ドライバー連動モード
#define DRIVER_OFF       0
#define DRIVER_LEVEL_UP  1
#define DRIVER_DOUBLE_UP 2
#define DRIVER_CRITICAL_STRIKE 3

// Action定義
#define GASHAT_OFF       0
#define GAME_START       1
#define DOUBLE_GASHAT    2
#define GAME_TITLE       3
#define GASHAT_OUT       4
#define GASHAT_NAME      5
#define CHARACTER_SELECT 6
#define ITEM_GET         7
#define GAME_CLEAR       8  
#define DOUBLE_GASHAT_LEVEL_UP_READY  9
#define DRIVER_CLOSE_LEVEL_UP_READY  10
#define LEVEL_UP        11
#define DRIVER_CLOSE_DOUBLE_UP_READY 12
#define DOUBLE_UP       13
#define CRITICAL_STRIKE_READY        14
#define DOUBLE_GASHAT_CRITICAL_STRIKE_READY 15
#define DRIVER_CLOSE_CRITICAL_STRIKE_READY  16
#define CRITICAL_STRIKE 17
#define DOUBLE_GASHAT_CRITICAL_STRIKE 18

const uint32_t UID_MARIO    PROGMEM = 2733260000; // 事前に調べたamiiboのUID
const uint32_t UID_LINK     PROGMEM = 3401930000; // 事前に調べたamiiboのUID
const uint32_t UID_LIZARDON PROGMEM = 1381520000; // 事前に調べたamiiboのUID

const uint8_t CHARACTER_NONE     = 255;
const uint8_t CHARACTER_MARIO    =   0;
const uint8_t CHARACTER_LINK     =   1;
const uint8_t CHARACTER_LIZARDON =   2;

#define LED_PATTERN_OFF 0
#define LED_PATTERN_GAME_START 90
const uint8_t LED_GAME_START[][3] PROGMEM = {
  {128,128,128},{255,255,255},{224,224,224},{192,192,192},{160,160,160},{128,128,128},{ 96, 96, 96},{ 64, 64, 64},{ 32, 32, 32},{  0,  0,  0},
  {128,128,128},{255,255,255},{255,255,255},{255,255,255},{160,160,160},{128,128,128},{ 96, 96, 96},{ 64, 64, 64},{ 32, 32, 32},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{232,232,232},{208,208,208},{184,184,184},{160,160,160},{136,136,136},{112,112,112},{ 88, 88, 88},{ 64, 64, 64},{ 40, 40, 40},
  { 16, 16, 16},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0}
};

#define LED_PATTERN_GASHAT_NAME 100
const uint8_t LED_GASHAT_NAME[][3] PROGMEM = {
  {255,255,255},{128,128,128},{255,255,255},{216,216,216},{176,176,176},{136,136,136},{ 96, 96, 96},{ 56, 56, 56},{ 16, 16, 16},{  0,  0,  0},
  { 48, 48, 48},{ 96, 96, 96},{144,144,144},{192,192,192},{240,240,240},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{160,160,160},{128,128,128},
  { 96, 96, 96},{ 64, 64, 64},{ 32, 32, 32},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{128,128,128},{255,255,255},{224,224,224},{192,192,192},
  {160,160,160},{128,128,128},{ 96, 96, 96},{ 64, 64, 64},{ 32, 32, 32},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {128,128,128},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{224,224,224},
  {255,255,255},{255,255,255},{224,224,224},{192,192,192},{160,160,160},{128,128,128},{ 96, 96, 96},{ 64, 64, 64},{ 32, 32, 32},{  0,  0,  0}
};

#define LED_PATTERN_CHARACTER_SELECT 20
const uint8_t LED_CHARACTER_SELECT_MARIO[][3] PROGMEM = {
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{240,  0,  0},
  {216,  0,  0},{192,  0,  0},{168,  0,  0},{144,  0,  0},{120,  0,  0},{ 96,  0,  0},{ 72,  0,  0},{ 48,  0,  0},{ 24,  0,  0},{  0,  0,  0}
};

const uint8_t LED_CHARACTER_SELECT_LINK[][3] PROGMEM = {
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,240,  0},
  {  0,216,  0},{  0,192,  0},{  0,168,  0},{  0,144,  0},{  0,120,  0},{  0, 96,  0},{  0, 72,  0},{  0, 48,  0},{  0, 24,  0},{  0,  0,  0}
};

const uint8_t LED_CHARACTER_SELECT_LIZARDON[][3] PROGMEM = {
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{240, 50,  0},
  {216, 44,  0},{192, 38,  0},{168, 34,  0},{144, 28,  0},{120, 24,  0},{ 96, 20,  0},{ 72, 14,  0},{ 48, 10,  0},{ 24,  4,  0},{  0,  0,  0}
};

#define LED_PATTERN_ITEM_GET 30
const uint8_t LED_ITEM_GET_MARIO[][3] PROGMEM = {
  { 64,  0,  0},{255,  0,  0},{ 64,  0,  0},{255,  0,  0},{ 64,  0,  0},{255,  0,  0},{ 64,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{240,  0,  0},
  {216,  0,  0},{192,  0,  0},{168,  0,  0},{144,  0,  0},{120,  0,  0},{ 96,  0,  0},{ 64,  0,  0},{ 48,  0,  0},{ 24,  0,  0},{  0,  0,  0}
};

const uint8_t LED_ITEM_GET_LINK[][3] PROGMEM = {
  {  0,255,  0},{  0, 64,  0},{  0, 64,  0},{  0,128,  0},{  0,128,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0}, 
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,216,  0},{  0,192,  0},{  0,168,  0},{  0,144,  0},{  0,120,  0},{  0, 96,  0},{  0, 72,  0},{  0, 48,  0},{  0, 24,  0},{  0,  0,  0} 
};

const uint8_t LED_ITEM_GET_LIZARDON[][3] PROGMEM = {
  {255, 52,  0},{ 64, 12,  0},{255, 52,  0},{ 64, 12,  0},{255, 52,  0},{ 64, 12,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{240, 50,  0},
  {216, 44,  0},{192, 38,  0},{168, 34,  0},{144, 28,  0},{120, 24,  0},{ 96, 20,  0},{ 72, 14,  0},{ 48, 10,  0},{ 24,  4,  0},{  0,  0,  0}
};

#define LED_PATTERN_GAME_CLEAR 120
const uint8_t LED_GAME_CLEAR_MARIO[][3] PROGMEM = {
  {255,  0,  0},{255,  0,  0},{216,  0,  0},{168,  0,  0},{120,  0,  0},{ 72,  0,  0},{ 24,  0,  0},{  0,  0,  0},{128,  0,  0},{255,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{216,  0,  0},{168,  0,  0},{120,  0,  0},{ 72,  0,  0},{ 24,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{ 24,  0,  0},{ 48,  0,  0},{ 72,  0,  0},{ 96,  0,  0},{120,  0,  0},{144,  0,  0},{168,  0,  0},{192,  0,  0},
  {216,  0,  0},{240,  0,  0},{192,  0,  0},{144,  0,  0},{ 96,  0,  0},{ 48,  0,  0},{  0,  0,  0},{ 24,  0,  0},{ 48,  0,  0},{ 72,  0,  0},
  { 96,  0,  0},{120,  0,  0},{144,  0,  0},{168,  0,  0},{192,  0,  0},{216,  0,  0},{240,  0,  0},{192,  0,  0},{144,  0,  0},{ 96,  0,  0},
  { 48,  0,  0},{  0,  0,  0},{ 24,  0,  0},{ 48,  0,  0},{ 72,  0,  0},{ 96,  0,  0},{120,  0,  0},{144,  0,  0},{168,  0,  0},{192,  0,  0},
  {216,  0,  0},{240,  0,  0},{192,  0,  0},{144,  0,  0},{ 96,  0,  0},{ 48,  0,  0},{  0,  0,  0},{ 24,  0,  0},{ 48,  0,  0},{ 72,  0,  0},
  { 96,  0,  0},{120,  0,  0},{144,  0,  0},{168,  0,  0},{192,  0,  0},{216,  0,  0},{240,  0,  0},{192,  0,  0},{144,  0,  0},{ 96,  0,  0},
  { 48,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0}
};

const uint8_t LED_GAME_CLEAR_LINK[][3] PROGMEM = {
  {  0,255,  0},{  0,255,  0},{  0,216,  0},{  0,168,  0},{  0,120,  0},{  0, 72,  0},{  0, 24,  0},{  0,  0,  0},{  0,128,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,216,  0},{  0,168,  0},{  0,120,  0},{  0, 72,  0},{  0, 24,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,216,  0},{  0,192,  0},{  0,168,  0},{  0,144,  0},{  0,120,  0},{  0, 96,  0},{  0, 72,  0},{  0, 48,  0},{  0, 24,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0}
};

const uint8_t LED_GAME_CLEAR_LIZARDON[][3] PROGMEM = {
  {255, 52,  0},{255, 52,  0},{216, 44,  0},{168, 34,  0},{120, 24,  0},{ 72, 14,  0},{ 24,  4,  0},{  0,  0,  0},{128, 26,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{216, 44,  0},{168, 34,  0},{120, 24,  0},{ 72, 14,  0},{ 24,  4,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{128, 26,  0},
  {128, 26,  0},{128, 26,  0},{128, 26,  0},{128, 26,  0},{128, 26,  0},{128, 26,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{128, 26,  0},{128, 26,  0},
  { 64, 12,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{128, 26,  0},{128, 26,  0},{ 64, 12,  0},{  0,  0,  0},{  0,  0,  0},
  {255, 52,  0},{255, 52,  0},{128, 26,  0},{128, 26,  0},{ 64, 12,  0},{  0,  0,  0},{255, 52,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},
  {  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{128, 26,  0},{128, 26,  0},{ 64, 12,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},
  {255, 52,  0},{128, 26,  0},{128, 26,  0},{ 64, 12,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{128, 26,  0},{128, 26,  0},
  { 64, 12,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{216, 44,  0},{168, 34,  0},{120, 24,  0},{ 72, 14,  0},{ 24,  4,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0}
};

#define LED_PATTERN_LEVEL_UP 150
const uint8_t LED_LEVEL_UP_MARIO[][3] PROGMEM = {
  {255,  0,  0},{128,  0,  0},{ 64,  0,  0},{255,  0,  0},{216,  0,  0},{176,  0,  0},{136,  0,  0},{ 96,  0,  0},{ 56,  0,  0},{ 40,  0,  0},
  { 16,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{128,  0,  0},{ 64,  0,  0},
  {  0,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{216,  0,  0},{192,  0,  0},{168,  0,  0},{144,  0,  0},{ 72,  0,  0},
  { 36,  0,  0},{  0,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{128,  0,  0},{128,  0,  0},{255,255,  0},{255,255,  0},{255,255,  0},
  {255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{216,216,  0},
  {192,192,  0},{168,168,  0},{144,144,  0},{120,120,  0},{ 96, 96,  0},{ 72, 72,  0},{ 48, 48,  0},{ 24, 24,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 16,  0,  0},{ 32,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 32,  0,  0},{ 16,  0,  0},{  0,  0,  0}
};

const uint8_t LED_LEVEL_UP_LINK[][3] PROGMEM = {
  {  0,255,  0},{  0,128,  0},{  0, 64,  0},{  0,255,  0},{  0,216,  0},{  0,176,  0},{  0,136,  0},{  0, 96,  0},{  0, 56,  0},{  0, 40,  0},
  {  0, 16,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,128,  0},{  0, 64,  0},
  {  0,  0,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,128,  0},{  0,216,  0},{  0,192,  0},{  0,168,  0},{  0,144,  0},{  0, 72,  0},
  {  0, 36,  0},{  0,  0,  0},{255,255,255},{ 64, 64, 64},{255,255,255},{ 64, 64, 64},{255,255,255},{ 64, 64, 64},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},
  {216,216,216},{192,192,192},{168,168,168},{144,144,144},{120,120,120},{ 96, 96, 96},{ 72, 72, 72},{ 48, 48, 48},{ 24, 24, 24},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0, 16,  0},{  0, 32,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 32,  0},{  0, 16,  0},{  0,  0,  0}
};

const uint8_t LED_LEVEL_UP_LIZARDON[][3] PROGMEM = {
  {255, 52,  0},{128, 26,  0},{ 64, 12,  0},{255, 52,  0},{216, 44,  0},{176, 36,  0},{136, 28,  0},{ 96, 20,  0},{ 56, 12,  0},{ 40,  8,  0},
  { 16,  4,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{128, 26,  0},{ 64, 12,  0},
  {  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{216, 44,  0},{192, 38,  0},{168, 34,  0},{144, 28,  0},{ 72, 14,  0},
  { 36,  8,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {216, 44,  0},{168, 34,  0},{120, 24,  0},{ 72, 14,  0},{ 24,  4,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {216, 44,  0},{192, 38,  0},{168, 34,  0},{144, 28,  0},{120, 24,  0},{ 96, 20,  0},{ 72, 14,  0},{ 48, 10,  0},{ 24,  4,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 16,  3,  0},{ 32,  6,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 32,  6,  0},{ 16,  3,  0},{  0,  0,  0}
};

#define LED_PATTERN_DOUBLE_UP 150
const uint8_t LED_DOUBLE_UP_MARIO[][3] PROGMEM = {
  {255,  0,  0},{128,  0,  0},{ 64,  0,  0},{255,  0,  0},{216,  0,  0},{176,  0,  0},{136,  0,  0},{ 96,  0,  0},{ 56,  0,  0},{ 40,  0,  0},
  { 16,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{128,  0,  0},{ 64,  0,  0},
  {  0,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{216,  0,  0},{192,  0,  0},{168,  0,  0},{144,  0,  0},{ 72,  0,  0},
  { 36,  0,  0},{  0,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{128,  0,  0},{128,  0,  0},{ 64,  0,  0},{255,  0,  0},{ 64,  0,  0},
  {255,  0,  0},{ 64,  0,  0},{255,  0,  0},{ 64,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{240,  0,  0},{216,  0,  0},{192,  0,  0},{168,  0,  0},
  {144,  0,  0},{120,  0,  0},{ 96,  0,  0},{ 64,  0,  0},{ 48,  0,  0},{ 24,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 16,  0,  0},{ 32,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 32,  0,  0},{ 16,  0,  0},{  0,  0,  0}
};

const uint8_t LED_DOUBLE_UP_LINK[][3] PROGMEM = {
  {  0,255,  0},{  0,128,  0},{  0, 64,  0},{  0,255,  0},{  0,216,  0},{  0,176,  0},{  0,136,  0},{  0, 96,  0},{  0, 56,  0},{  0, 40,  0},
  {  0, 16,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,128,  0},{  0, 64,  0},
  {  0,  0,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,216,  0},{  0,192,  0},{  0,168,  0},{  0,144,  0},{  0, 72,  0},
  {  0, 36,  0},{  0,  0,  0},{ 38,192,192},{ 44,216,216},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 44,216,216},{ 34,168,168},
  { 24,120,120},{ 14, 72, 72},{  4, 24, 24},{  0,  0,  0},{ 14, 72, 72},{ 24,120,120},{ 34,168,168},{ 44,216,216},{ 52,255,255},{ 52,255,255},
  { 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},
  { 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},
  { 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},{ 52,255,255},
  { 44,216,216},{ 38,192,192},{ 34,168,168},{ 28,144,144},{ 24,120,120},{ 20, 96, 96},{ 14, 72, 72},{ 10, 48, 48},{  4, 24, 24},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0, 16,  0},{  0, 32,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 32,  0},{  0, 16,  0},{  0,  0,  0}
};

const uint8_t LED_DOUBLE_UP_LIZARDON[][3] PROGMEM = {
  {255, 52,  0},{128, 26,  0},{ 64, 12,  0},{255, 52,  0},{216, 44,  0},{176, 36,  0},{136, 28,  0},{ 96, 20,  0},{ 56, 12,  0},{ 40,  8,  0},
  { 16,  4,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{128, 26,  0},{ 64, 12,  0},
  {  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{216, 44,  0},{192, 38,  0},{168, 34,  0},{144, 28,  0},{ 72, 14,  0},
  { 36,  8,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{216, 44,  0},{168, 34,  0},{120, 24,  0},{ 72, 14,  0},{ 24,  4,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{216, 44,  0},{192, 38,  0},{168, 34,  0},{144, 28,  0},{120, 24,  0},{ 96, 20,  0},{ 72, 14,  0},{ 48, 10,  0},{ 24,  4,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 16,  3,  0},{ 32,  6,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 32,  6,  0},{ 16,  3,  0},{  0,  0,  0}
};

#define LED_PATTERN_CRITICAL_STRIKE 200
const uint8_t LED_CRITICAL_STRIKE_MARIO[][3] PROGMEM = {
  {255,  0,  0},{128,  0,  0},{ 64,  0,  0},{255,  0,  0},{216,  0,  0},{176,  0,  0},{136,  0,  0},{ 96,  0,  0},{ 56,  0,  0},{ 40,  0,  0},
  { 16,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255,  0,  0},{255,  0,  0},{216,  0,  0},{192,  0,  0},{168,  0,  0},
  {144,  0,  0},{120,  0,  0},{ 96,  0,  0},{ 64,  0,  0},{ 48,  0,  0},{ 24,  0,  0},{255,  0,  0},{216,  0,  0},{192,  0,  0},{168,  0,  0},
  {144,  0,  0},{120,  0,  0},{ 96,  0,  0},{ 64,  0,  0},{ 48,  0,  0},{ 24,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {255,  0,  0},{216,  0,  0},{168,  0,  0},{120,  0,  0},{ 72,  0,  0},{ 24,  0,  0},{  0,  0,  0},{255,  0,  0},{128,  0,  0},{ 64,  0,  0},
  {255,  0,  0},{192,  0,  0},{144,  0,  0},{ 96,  0,  0},{ 48,  0,  0},{128,  0,  0},{128,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},{255,  0,  0},
  {216,  0,  0},{192,  0,  0},{168,  0,  0},{144,  0,  0},{120,  0,  0},{ 96,  0,  0},{ 72,  0,  0},{ 48,  0,  0},{ 24,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 16,  0,  0},{ 32,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},
  { 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 64,  0,  0},{ 32,  0,  0},{ 16,  0,  0},{  0,  0,  0}
};

const uint8_t LED_CRITICAL_STRIKE_LINK[][3] PROGMEM = {
  {  0,255,  0},{  0,128,  0},{  0, 64,  0},{  0,255,  0},{  0,216,  0},{  0,176,  0},{  0,136,  0},{  0, 96,  0},{  0, 56,  0},{  0, 40,  0},
  {  0, 16,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,255,  0},{  0,255,  0},{  0,216,  0},{  0,192,  0},{  0,168,  0},
  {  0,144,  0},{  0,120,  0},{  0, 96,  0},{  0, 64,  0},{  0, 48,  0},{  0, 24,  0},{  0,255,  0},{  0,216,  0},{  0,192,  0},{  0,168,  0},
  {  0,144,  0},{  0,120,  0},{  0, 96,  0},{  0, 64,  0},{  0, 48,  0},{  0, 24,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},{  0,255,  0},
  {  0,255,  0},{  0,216,  0},{  0,168,  0},{  0,120,  0},{  0, 72,  0},{  0, 24,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},
  {255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},
  {255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},{255,255,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 24, 24,  0},{ 48, 48,  0},{ 72, 72,  0},{ 96, 96,  0},{120,120,  0},{144,144,  0},{168,168,  0},
  {192,192,  0},{216,216,  0},{240,240,  0},{128,128,  0},{ 64, 64,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},
  {255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},
  {255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},{255,255,  0},
  {216,216,  0},{192,192,  0},{168,168,  0},{144,144,  0},{120,120,  0},{ 96, 96,  0},{ 72, 72,  0},{ 48, 48,  0},{ 24, 24,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0, 16,  0},{  0, 32,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},
  {  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 64,  0},{  0, 32,  0},{  0, 16,  0},{  0,  0,  0}
};

const uint8_t LED_CRITICAL_STRIKE_LIZARDON[][3] PROGMEM = {
  {255, 52,  0},{128, 26,  0},{ 64, 12,  0},{255, 52,  0},{216, 44,  0},{176, 36,  0},{136, 28,  0},{ 96, 20,  0},{ 56, 12,  0},{ 40,  8,  0},
  { 16,  4,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{255, 52,  0},{255, 52,  0},{216, 44,  0},{192, 38,  0},{168, 34,  0},
  {144, 28,  0},{120, 24,  0},{ 96, 20,  0},{ 64, 12,  0},{ 48, 10,  0},{ 24,  4,  0},{255, 52,  0},{216, 44,  0},{192, 38,  0},{168, 34,  0},
  {144, 28,  0},{120, 24,  0},{ 96, 20,  0},{ 64, 12,  0},{ 48, 10,  0},{ 24,  4,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},{255, 52,  0},
  {255, 52,  0},{216, 44,  0},{168, 34,  0},{120, 24,  0},{ 72, 14,  0},{ 24,  4,  0},{  0,  0,  0},{ 48, 10,  0},{ 96, 20,  0},{144, 28,  0},
  {192, 38,  0},{240, 38,  0},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{120,120,240},{ 60,108,216},{  0, 96,192},{  0, 84,168},
  {  0, 72,144},{  0, 60,120},{  0, 48, 96},{  0, 36, 72},{  0, 24, 48},{  0, 12, 24},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,128,255},{  0,128,255},{  0,128,255},{  0,108,216},{  0, 96,192},{  0, 84,168},{  0, 72,144},{  0, 60,120},{  0, 48, 96},{  0, 36, 72},
  {  0,128,255},{  0,128,255},{  0,128,255},{  0,108,216},{  0, 96,192},{  0, 84,168},{  0, 72,144},{  0, 60,120},{  0, 48, 96},{  0, 36, 72},
  {  0,128,255},{  0,128,255},{  0,128,255},{  0,108,216},{  0, 96,192},{  0, 84,168},{  0, 72,144},{  0, 60,120},{  0, 48, 96},{  0, 36, 72},
  {  0, 24, 48},{  0, 12, 24},{  0,  0,  0},{  0,128,255},{  0,128,255},{  0,128,255},{  0,108,216},{  0, 96,192},{  0, 84,168},{  0, 72,144},
  {  0, 60,120},{  0, 48, 96},{  0, 36, 72},{  0, 24, 48},{  0, 12, 24},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},
  {  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{  0,  0,  0},{ 16,  3,  0},{ 32,  6,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},
  { 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 64, 12,  0},{ 32,  6,  0},{ 16,  3,  0},{  0,  0,  0}
};

/*----------楽曲リスト----------
<共通>
1. GAME START    ... ガシャット 電源ON
2. DOUBLE GASHAT ... ダブルガシャット
3. GAME TITLE    ... ゲーム名
4. GASHAT OUT    ... ガシャット OUT
<デフォルト>
5. GASHAT NAME ... ガシャット名
<マリオ>
6.  CHARACTER SELECT ... キャラセレクト
7.  ITEM GET         ... アイテムゲット
8.  GAME CLEAR       ... ゲームクリアー
9.  LEVEL UP READY 1 ... レベルアップ 待機(ガシャットINから):地上BGM
10. LEVEL UP READY 2 ... レベルアップ 待機(ドライバーCLOSEから):地上BGM
11. LEVEL UP         ... レベルアップ:ジャンプ+コイン
12. DOUBLE UP READY  ... ダブルアップ 待機:ワールドクリアBGM
13. DOUBLE UP        ... ダブルアップ:ジャンプ+キノコ
14. CRITICAL STRIKE READY 1 ... クリティカルストライク待機(名乗りから):スターBGM
15. CRITICAL STRIKE READY 2 ... クリティカルストライク待機(ドライバーCLOSEから):スターBGM
16: CRITICAL STRIKE READY 3 ... クリティカルストライク待機(単独)
17. CRITICAL STRIKE         ... クリティカルストライク
18. CRITICAL STRIKE 2       ... クリティカルストライク(名乗りから)
<リンク>
19. CHARACTER SELECT ... キャラセレクト
20. ITEM GET         ... アイテムゲット
21. GAME CLEAR       ... ゲームクリアー
22. LEVEL UP READY 1 ... レベルアップ 待機(ガシャットINから):宝箱オープン
23. LEVEL UP READY 2 ... レベルアップ 待機(ドライバーCLOSEから):宝箱オープン
24. LEVEL UP         ... レベルアップ:アイテムゲット
25. DOUBLE UP READY  ... ダブルアップ 待機:マスターソード
26. DOUBLE UP        ... ダブルアップ:ハートの器ゲット
27. CRITICAL STRIKE READY 1 ... クリティカルストライク待機(名乗りから):メインテーマ
28. CRITICAL STRIKE READY 2 ... クリティカルストライク待機(ドライバーCLOSEから):メインテーマ
29: CRITICAL STRIKE READY 3 ... クリティカルストライク待機(単独):メインテーマ
30. CRITICAL STRIKE         ... クリティカルストライク
31. CRITICAL STRIKE 2       ... クリティカルストライク(名乗りから)
<ポケモン>
32. CHARACTER SELECT ... キャラセレクト
33. ITEM GET         ... アイテムゲット
34. GAME CLEAR       ... ゲームクリアー
35. LEVEL UP READY 1 ... レベルアップ 待機(ガシャットINから):タイトル
36. LEVEL UP READY 2 ... レベルアップ 待機(ドライバーCLOSEから):タイトル
37. LEVEL UP         ... レベルアップ:ヒトカゲ鳴き声+レベルアップ効果音
38. DOUBLE UP READY  ... ダブルアップ 待機:進化BGM
39. DOUBLE UP        ... ダブルアップ:リザードン鳴き声+進化効果音
40. CRITICAL STRIKE READY 1 ... クリティカルストライク待機(名乗りから):オープニング
41. CRITICAL STRIKE READY 2 ... クリティカルストライク待機(ドライバーCLOSEから):オープニング
42: CRITICAL STRIKE READY 3 ... クリティカルストライク待機(単独):オープニング
43. CRITICAL STRIKE         ... クリティカルストライク
44. CRITICAL STRIKE 2       ... クリティカルストライク(名乗りから)
  ----------楽曲リスト----------*/

const uint8_t character_sounds[][13] PROGMEM = {
  { 6, 7, 8, 9,10,11,12,13,14,15,16,17,18}, // Mario
  {19,20,21,22,23,24,25,26,27,28,29,30,31}, // Link
  {32,33,34,35,36,37,38,39,40,41,42,43,44}  // Lizardon
};

const char character_picts[][4] PROGMEM = {
  {'b','c','d','e'}, // Mario
  {'f','g','h','i'}, // Link
  {'j','k','l','m'}  // Lizardon
};

SoftwareSerial mySerial(2, 3); // RX, TX
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(N_LED, LED_PIN, NEO_GRB + NEO_KHZ400);

uint32_t last_uid    = 0;
uint32_t current_uid = 0;
uint8_t  uid[] = {0, 0, 0, 0, 0, 0, 0}; 
// NFCのRead間隔調整用
const uint8_t NFC_READABLE = 3;
uint8_t nfc_read_count = 0; 

uint8_t before_state[]  = {BT1_OFF, BT2_OFF, BT3_OFF};
uint8_t current_state[] = {BT1_OFF, BT2_OFF, BT3_OFF};
uint8_t current_character = CHARACTER_NONE;
uint8_t standalone_state  = STANDALONE_NAME;
uint8_t driver_state      = DRIVER_OFF;
uint8_t action = GASHAT_OFF;
uint8_t led_pattern = LED_PATTERN_OFF;
uint8_t led_count   = 0;

void setup() {
  pinMode(BUTTON_1_PIN, INPUT_PULLUP);
  pinMode(BUTTON_2_PIN, INPUT_PULLUP);
  pinMode(BUTTON_3_PIN, INPUT_PULLUP);

  Wire.begin();

  // NFC Reader Ready
  bool ret = HkNfcRw::open();
  while (!ret) {}

  // MP3 Player Ready
  mySerial.begin (9600);
  mp3_set_serial (mySerial);  //set softwareSerial for DFPlayer-mini mp3 module 
  mp3_set_volume (25);

  // RGB LED Ready
  pixels.begin();
  pixels.show();

  delay(3000);
  action = set_action(GAME_START);
}

boolean temp_flag = true;
void loop() {
  //////////////////// NFCの処理 ///////////////////////
  if(driver_state == DRIVER_OFF){
    if(nfc_read_count == NFC_READABLE){
      nfc_read_count = 0;
      HkNfcRw::Type type = HkNfcRw::detect(true, false, false);
      if(type == HkNfcRw::NFC_A) {
        // Type A タグが見つかったとき    
        if(HkNfcRw::getNfcId(uid)){      
          current_uid = uid[6];
          for(int i=5; i>=0; i--){
            current_uid <<= 8; current_uid |= uid[i];
          }

          // UIDが変わった時のみ処理
          if(last_uid != current_uid){    
            if(current_uid == UID_MARIO){
              current_character = CHARACTER_MARIO;   
            }else if(current_uid == UID_LINK){
              current_character = CHARACTER_LINK;
            }else if(current_uid == UID_LIZARDON){
              current_character = CHARACTER_LIZARDON;
            }   

            action = set_action(CHARACTER_SELECT);
            show_image(pgm_read_byte(&character_picts[current_character][0]));
            standalone_state = STANDALONE_ITEM;

            last_uid = current_uid;
          }
        }else{
          //Serial.println(F("Failed to get UID."));
        }
      } else {
        // Type A タグが見つからなかったとき
      }
    }else{
      nfc_read_count++;
    }
  }

  //////////////////// スイッチの処理 ///////////////////////
  current_state[0] = digitalRead(BUTTON_1_PIN);
  current_state[1] = digitalRead(BUTTON_2_PIN);
  current_state[2] = digitalRead(BUTTON_3_PIN);

  if(memcmp(before_state, OFF_OFF_OFF, N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      ;
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_LEVEL_UP_READY);
      }
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_CRITICAL_STRIKE_READY);
      }
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      switch(standalone_state){
      case STANDALONE_NAME:
        if(current_character == CHARACTER_NONE){
          action = set_action(GASHAT_NAME);
        }else{
          action = set_action(CHARACTER_SELECT);
          standalone_state = STANDALONE_ITEM;
        }
        break;
      case STANDALONE_ITEM:
        action = set_action(ITEM_GET);
        standalone_state = STANDALONE_CLEAR;
        break;
      case STANDALONE_CLEAR:
        action = set_action(GAME_CLEAR);
        standalone_state = STANDALONE_NAME;
        break;
      default:
        ;
      }
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      action = set_action(DOUBLE_GASHAT);  
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_LEVEL_UP_READY); 
      }
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_CRITICAL_STRIKE); 
      }
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_CRITICAL_STRIKE_READY); 
      }
    }
  }else if(memcmp(before_state, ON_OFF_OFF, N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT); 
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      ;
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      ;
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        switch(driver_state){
        case DRIVER_OFF:
         action = set_action(LEVEL_UP);
         driver_state = DRIVER_LEVEL_UP;
         break;
        case DRIVER_LEVEL_UP:
         action = set_action(DOUBLE_UP);
         driver_state = DRIVER_DOUBLE_UP;
         break;
        case DRIVER_DOUBLE_UP:
        case DRIVER_CRITICAL_STRIKE:
         action = set_action(CRITICAL_STRIKE);
         driver_state = DRIVER_CRITICAL_STRIKE;
         break;
        default:
          ;
        }
      }      
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        switch(driver_state){
        case DRIVER_OFF:
         action = set_action(LEVEL_UP);
         driver_state = DRIVER_LEVEL_UP;
         break;
        case DRIVER_LEVEL_UP:
         action = set_action(DOUBLE_UP);
         driver_state = DRIVER_DOUBLE_UP;
         break;
        case DRIVER_DOUBLE_UP:
        case DRIVER_CRITICAL_STRIKE:
         action = set_action(CRITICAL_STRIKE);
         driver_state = DRIVER_CRITICAL_STRIKE;
         break;
        default:
          ;
        }
      }   
    } 
  }else if(memcmp(before_state, OFF_ON_OFF, N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT); 
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      ;
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      ;
    }
  }else if(memcmp(before_state, OFF_OFF_ON, N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      ;  
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_LEVEL_UP_READY);
      }  
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_CRITICAL_STRIKE); 
      }
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(DOUBLE_GASHAT_CRITICAL_STRIKE_READY); 
      }
    } 
  }else if(memcmp(before_state, ON_ON_OFF,  N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        switch(driver_state){
        case DRIVER_OFF:
         action = set_action(DRIVER_CLOSE_LEVEL_UP_READY);
         break;
        case DRIVER_LEVEL_UP:
         action = set_action(DRIVER_CLOSE_DOUBLE_UP_READY);
         break;
        case DRIVER_DOUBLE_UP:
        case DRIVER_CRITICAL_STRIKE:
         action = set_action(DRIVER_CLOSE_CRITICAL_STRIKE_READY);
         break;
        default:
          ;
        }
      }
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      action = set_action(GAME_TITLE);
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        action = set_action(CRITICAL_STRIKE_READY); 
      }  
    }  
  }else if(memcmp(before_state, ON_OFF_ON,  N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);  
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      if(current_character != CHARACTER_NONE){
        switch(driver_state){
        case DRIVER_OFF:
         action = set_action(LEVEL_UP);
         driver_state = DRIVER_LEVEL_UP;
         break;
        case DRIVER_LEVEL_UP:
         action = set_action(DOUBLE_UP);
         driver_state = DRIVER_DOUBLE_UP;
         break;
        case DRIVER_DOUBLE_UP:
        case DRIVER_CRITICAL_STRIKE:
         action = set_action(CRITICAL_STRIKE);
         driver_state = DRIVER_CRITICAL_STRIKE;
         break;
        default:
          ;
        }
      } 
    } 
  }else if(memcmp(before_state, OFF_ON_ON,  N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);   
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      ;   
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      ;
    } 
  }else if(memcmp(before_state, ON_ON_ON,   N_BUTTON) == 0){
    if(memcmp(current_state, OFF_OFF_OFF, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);  
    }else if(memcmp(current_state, ON_OFF_OFF, N_BUTTON) == 0){
      ;
    }else if(memcmp(current_state, OFF_ON_OFF, N_BUTTON) == 0){
      action = set_action(GAME_TITLE); 
    }else if(memcmp(current_state, OFF_OFF_ON, N_BUTTON) == 0){
      action = set_action(GASHAT_OUT);   
    }else if(memcmp(current_state, ON_ON_OFF,  N_BUTTON) == 0){
      ;  
    }else if(memcmp(current_state, ON_OFF_ON,  N_BUTTON) == 0){
      ; 
    }else if(memcmp(current_state, OFF_ON_ON,  N_BUTTON) == 0){
      action = set_action(GAME_TITLE);  
    }else if(memcmp(current_state, ON_ON_ON,   N_BUTTON) == 0){
      ;   
    } 
  }

  flash_led(action);

  before_state[0] = current_state[0];
  before_state[1] = current_state[1];
  before_state[2] = current_state[2];

  delay(100);
}

void show_image(char code){
  Wire.beginTransmission(8);
  Wire.write(code);
  Wire.endTransmission();
}

uint8_t set_action(uint8_t action){
  // 音声再生
  switch(action){
  case GASHAT_OFF:
    break;
  case GAME_START:
  case DOUBLE_GASHAT:
  case GAME_TITLE:
  case GASHAT_OUT:
  case GASHAT_NAME:
    mp3_play(action);
    break;
  default:
    uint8_t music_index = 0;
    switch(action){
    case CHARACTER_SELECT: music_index = 0; break;
    case ITEM_GET:         music_index = 1; break;
    case GAME_CLEAR:       music_index = 2; break;
    case DOUBLE_GASHAT_LEVEL_UP_READY: music_index = 3; break;
    case DRIVER_CLOSE_LEVEL_UP_READY:  music_index = 4; break;
    case LEVEL_UP:         music_index = 5; break;
    case DRIVER_CLOSE_DOUBLE_UP_READY: music_index = 6; break;
    case DOUBLE_UP:        music_index = 7; break;
    case CRITICAL_STRIKE_READY:        music_index = 8; break;
    case DOUBLE_GASHAT_CRITICAL_STRIKE_READY: music_index =  9; break;
    case DRIVER_CLOSE_CRITICAL_STRIKE_READY:  music_index = 10; break;
    case CRITICAL_STRIKE:  music_index = 11; break;
    case DOUBLE_GASHAT_CRITICAL_STRIKE: music_index = 12; break;
    default: music_index = 0;
    }
    mp3_play(pgm_read_byte(&character_sounds[current_character][music_index]));
  }

  // LED発光パターン変更
  switch(action){
  case GASHAT_OFF:
  case DOUBLE_GASHAT:
  case GAME_TITLE:
  case GASHAT_OUT:
  case DOUBLE_GASHAT_LEVEL_UP_READY:
  case DRIVER_CLOSE_LEVEL_UP_READY:
  case DRIVER_CLOSE_DOUBLE_UP_READY:
  case CRITICAL_STRIKE_READY:
  case DOUBLE_GASHAT_CRITICAL_STRIKE_READY:
  case DRIVER_CLOSE_CRITICAL_STRIKE_READY:
  case DOUBLE_GASHAT_CRITICAL_STRIKE:
                         led_pattern = LED_PATTERN_OFF;              break;
  case GAME_START:       led_pattern = LED_PATTERN_GAME_START;       break;
  case GASHAT_NAME:      led_pattern = LED_PATTERN_GASHAT_NAME;      break;
  case CHARACTER_SELECT: led_pattern = LED_PATTERN_CHARACTER_SELECT; break;
  case ITEM_GET:         led_pattern = LED_PATTERN_ITEM_GET;         break;
  case GAME_CLEAR:       led_pattern = LED_PATTERN_GAME_CLEAR;       break;
  case LEVEL_UP:         led_pattern = LED_PATTERN_LEVEL_UP;         break;
  case DOUBLE_UP:        led_pattern = LED_PATTERN_DOUBLE_UP;        break;
  case CRITICAL_STRIKE:  led_pattern = LED_PATTERN_CRITICAL_STRIKE;  break;
  default:               led_pattern = LED_PATTERN_OFF;
  } 
  led_count = 0;

  // スクリーン表示
  switch(action){
  case GASHAT_OFF:
    break;
  case GAME_START:
    show_image('a'); 
    break;
  case DOUBLE_GASHAT:
  case GAME_TITLE:
  case GASHAT_NAME:
  case CHARACTER_SELECT:
  case ITEM_GET:
  case GAME_CLEAR:
  case LEVEL_UP:
  case DOUBLE_UP:
  case CRITICAL_STRIKE:
  case DOUBLE_GASHAT_CRITICAL_STRIKE:
    break;
  default:
    uint8_t pict_index = 0;
    switch(action){
      case GASHAT_OUT: pict_index = 0; break;
      case DOUBLE_GASHAT_LEVEL_UP_READY:
      case DRIVER_CLOSE_LEVEL_UP_READY:
        show_image('z'); // LCD Reset
        delay(3000);
        pict_index = 1; break;
      case DRIVER_CLOSE_DOUBLE_UP_READY: pict_index = 2; break;
      case CRITICAL_STRIKE_READY:
      case DOUBLE_GASHAT_CRITICAL_STRIKE_READY:
      case DRIVER_CLOSE_CRITICAL_STRIKE_READY: pict_index = 3; break;
      default: pict_index = 0;
    }
    show_image(pgm_read_byte(&character_picts[current_character][pict_index]));
  }

  if(action == GASHAT_OUT){
    driver_state = DRIVER_OFF;     
  }

  return action;
}

void flash_led(uint8_t action){

  switch(action){

  case GAME_START:
    pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_GAME_START[led_count][0])),
                                         pgm_read_byte(&(LED_GAME_START[led_count][1])),
                                         pgm_read_byte(&(LED_GAME_START[led_count][2]))));
    break;  
  case GASHAT_NAME:
    pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_GASHAT_NAME[led_count][0])),
                                         pgm_read_byte(&(LED_GASHAT_NAME[led_count][1])),
                                         pgm_read_byte(&(LED_GASHAT_NAME[led_count][2]))));
    break;
  case CHARACTER_SELECT:
    switch(current_character){
      case CHARACTER_MARIO:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_CHARACTER_SELECT_MARIO[led_count][0])),
                                               pgm_read_byte(&(LED_CHARACTER_SELECT_MARIO[led_count][1])),
                                               pgm_read_byte(&(LED_CHARACTER_SELECT_MARIO[led_count][2]))));
          break;
      case CHARACTER_LINK:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_CHARACTER_SELECT_LINK[led_count][0])),
                                               pgm_read_byte(&(LED_CHARACTER_SELECT_LINK[led_count][1])),
                                               pgm_read_byte(&(LED_CHARACTER_SELECT_LINK[led_count][2]))));
          break; 
      case CHARACTER_LIZARDON:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_CHARACTER_SELECT_LIZARDON[led_count][0])),
                                               pgm_read_byte(&(LED_CHARACTER_SELECT_LIZARDON[led_count][1])),
                                               pgm_read_byte(&(LED_CHARACTER_SELECT_LIZARDON[led_count][2]))));
          break; 
    }
    break;

  case ITEM_GET:
    switch(current_character){
      case CHARACTER_MARIO:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_ITEM_GET_MARIO[led_count][0])),
                                               pgm_read_byte(&(LED_ITEM_GET_MARIO[led_count][1])),
                                               pgm_read_byte(&(LED_ITEM_GET_MARIO[led_count][2]))));
          break;
      case CHARACTER_LINK:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_ITEM_GET_LINK[led_count][0])),
                                               pgm_read_byte(&(LED_ITEM_GET_LINK[led_count][1])),
                                               pgm_read_byte(&(LED_ITEM_GET_LINK[led_count][2]))));
          break; 
      case CHARACTER_LIZARDON:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_ITEM_GET_LIZARDON[led_count][0])),
                                               pgm_read_byte(&(LED_ITEM_GET_LIZARDON[led_count][1])),
                                               pgm_read_byte(&(LED_ITEM_GET_LIZARDON[led_count][2]))));
          break; 
    }
    break;

  case GAME_CLEAR:
    switch(current_character){
      case CHARACTER_MARIO:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_GAME_CLEAR_MARIO[led_count][0])),
                                               pgm_read_byte(&(LED_GAME_CLEAR_MARIO[led_count][1])),
                                               pgm_read_byte(&(LED_GAME_CLEAR_MARIO[led_count][2]))));
          break;
      case CHARACTER_LINK:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_GAME_CLEAR_LINK[led_count][0])),
                                               pgm_read_byte(&(LED_GAME_CLEAR_LINK[led_count][1])),
                                               pgm_read_byte(&(LED_GAME_CLEAR_LINK[led_count][2]))));
          break; 
      case CHARACTER_LIZARDON:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_GAME_CLEAR_LIZARDON[led_count][0])),
                                               pgm_read_byte(&(LED_GAME_CLEAR_LIZARDON[led_count][1])),
                                               pgm_read_byte(&(LED_GAME_CLEAR_LIZARDON[led_count][2]))));
          break; 
    }
    break;

  case LEVEL_UP:
    switch(current_character){
      case CHARACTER_MARIO:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_LEVEL_UP_MARIO[led_count][0])),
                                               pgm_read_byte(&(LED_LEVEL_UP_MARIO[led_count][1])),
                                               pgm_read_byte(&(LED_LEVEL_UP_MARIO[led_count][2]))));
          break;
      case CHARACTER_LINK:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_LEVEL_UP_LINK[led_count][0])),
                                               pgm_read_byte(&(LED_LEVEL_UP_LINK[led_count][1])),
                                               pgm_read_byte(&(LED_LEVEL_UP_LINK[led_count][2]))));
          break; 
      case CHARACTER_LIZARDON:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_LEVEL_UP_LIZARDON[led_count][0])),
                                               pgm_read_byte(&(LED_LEVEL_UP_LIZARDON[led_count][1])),
                                               pgm_read_byte(&(LED_LEVEL_UP_LIZARDON[led_count][2]))));
          break; 
    }
    break;

  case DOUBLE_UP:
    switch(current_character){
      case CHARACTER_MARIO:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_DOUBLE_UP_MARIO[led_count][0])),
                                               pgm_read_byte(&(LED_DOUBLE_UP_MARIO[led_count][1])),
                                               pgm_read_byte(&(LED_DOUBLE_UP_MARIO[led_count][2]))));
          break;
      case CHARACTER_LINK:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_DOUBLE_UP_LINK[led_count][0])),
                                               pgm_read_byte(&(LED_DOUBLE_UP_LINK[led_count][1])),
                                               pgm_read_byte(&(LED_DOUBLE_UP_LINK[led_count][2]))));
          break; 
      case CHARACTER_LIZARDON:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_DOUBLE_UP_LIZARDON[led_count][0])),
                                               pgm_read_byte(&(LED_DOUBLE_UP_LIZARDON[led_count][1])),
                                               pgm_read_byte(&(LED_DOUBLE_UP_LIZARDON[led_count][2]))));
          break; 
    }
    break;

  case CRITICAL_STRIKE:
    switch(current_character){
      case CHARACTER_MARIO:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_CRITICAL_STRIKE_MARIO[led_count][0])),
                                               pgm_read_byte(&(LED_CRITICAL_STRIKE_MARIO[led_count][1])),
                                               pgm_read_byte(&(LED_CRITICAL_STRIKE_MARIO[led_count][2]))));
          break;
      case CHARACTER_LINK:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_CRITICAL_STRIKE_LINK[led_count][0])),
                                               pgm_read_byte(&(LED_CRITICAL_STRIKE_LINK[led_count][1])),
                                               pgm_read_byte(&(LED_CRITICAL_STRIKE_LINK[led_count][2]))));
          break; 
      case CHARACTER_LIZARDON:
          pixels.setPixelColor(0, pixels.Color(pgm_read_byte(&(LED_CRITICAL_STRIKE_LIZARDON[led_count][0])),
                                               pgm_read_byte(&(LED_CRITICAL_STRIKE_LIZARDON[led_count][1])),
                                               pgm_read_byte(&(LED_CRITICAL_STRIKE_LIZARDON[led_count][2]))));
          break; 
    }
    break;

  default:
    pixels.setPixelColor(0, pixels.Color(0,0,0));
  }

  if(led_count < led_pattern){
    led_count++;
  }else{
    pixels.setPixelColor(0, pixels.Color(0,0,0));
  }

  pixels.show();
}

基本構造はマリオガシャットのソースコードと同じですが、色々追加・修正が加わっています。以下、特にポイントになるところだけピックアップします。

64〜66行目

ここで、自分の持っているamiiboのNFCチップのUIDを記載しています。UIDの調べ方はこちらをご参照ください。

73〜360行目

各キャラの各状態でのLEDの発光パターンを、0.1秒間隔でRGB指定しています。この”0.1秒”という値は、774行目の”delay(100)”の指定によるものです。

362〜418行目

各キャラ・各状態で再生する音声の番号を指定しています。MP3プレーヤー(DFPlayer Mini)の扱い方については、こちらをご参照ください。

420〜424行目

ここで指定している文字と、先の”SmashBrosGashatScreen.ino”の43〜59行目のswitch文の文字が対応しています。

432〜433行目

あんまり早い間隔(0.1秒感覚)でNFCタグの検出を行うと、タグの検出がうまくできなかったので、NFC_READABLEの値で「何回ループしたときに検出を行うか」を指定しています。

511〜766行目

ボタンの押し方による状態遷移については、以前にマイティブラザーズXXガシャットを分析したときに得られた状態遷移図を参考に記述しています。

今回使用している液晶ディスプレイでは、表示画像の切り替えに1〜2秒程度かかってしまうので、画像の切り替えはできるだけ、画面が見えなくなるドライバークローズのときに行うようにしています。

 

ソースコードのポイントはだいたいこんな感じです。ソース自体は比較的長いですが、だいたいは同じようなことを何度も書いているところが多いので、骨子だけ見れば、そこまで複雑なコードではないと思います。

 

実際に作成する際には、以下のような感じでプロトタイプを作って、ソースコードに調整を加えて完成させてから、諸々ガシャット内部に部品を組み付けていくと良いと思います。

 

このときはまだLEDの発光パターンが未調整ですが、およそどんな感じで動いているかがわかると思います。

 

最後に、「このガシャットは何キャラ分まで対応できるのか?」をちょっと考えてみたいと思います。

今回のソースコードで、一番キャラ増加による影響を受ける箇所は、73〜360行目のLED発光パターンのところです。一人追加するごとに、2010 Byteを消費することになります。PROGMEM指定により、ここの記述はフラッシュメモリに割り当てられるので、ここのLED発光パターンの記述がフラッシュメモリを食い尽くすまではキャラの増加が可能です。

上記の”SmashBrosGashatMain.ino”の時点で、フラッシュメモリの使用率は19,324/30,720 Byteで、62%です。何%までであれば安定動作するかは調べていないのですが、仮に80%までに抑えるとすれば、使用できるメモリは24,576 Byteまでです。ということは、あと5,252 Byte使用できることになるので、あと2名は余裕で追加可能です。

もちろん、これはLEDの発光パターンを0.1秒間隔で細かく指定したい場合の話です。極論、キャラごとにLEDは点けっぱなしということであれば、発光パターンを記述する必要がないので、余裕でスマブラの全キャラに対応できると思います。

 

というわけで、スマブラガシャットの中身を、簡単にですがご紹介しました。自分としてはガシャット作りはもうお腹いっぱいな感じですので、今後はまたRaspberry Piを使った工作とかに戻ろうかなーと思っている次第です。