Archive for 5月 2018
NES GAME with M5STACK
M5STACK で NES GAME を 動かしてみました。 2018.05.07
Mac ( マック) での方法を記載します。
FACES を購入しますと マリオ風のゲームがインストールされています。
ゲームは エミュレーターで動いています。
NES EMULATOR と GAME の ソースは
m5stack/M5Stack-nesemu にあります。 M5Stack-nesemu-master を DL し、 中にある firmware.zip を解凍します。 4つのファイルを転送すると動きます。 1. bootloader.bin 2. partitions.bin 3. nesemu.bin 4. SuperMario4.nes |
m5stack/M5Stack-nesemu:(SuperMario4.nes) をインストールする方法。
_ デスクトップに rom フォルダーを作成し bootloader.bin, partitions.bin,
_ nesemu.bin, SuperMario4.nes を入れておきます。
以下の4つを Terminalへ入力します。
1. esptool.py –port /dev/tty.SLAB_USBtoUART write_flash 0x1000 ~/Desktop/rom/bootloader.bin
2. esptool.py –port /dev/tty.SLAB_USBtoUART write_flash 0x8000 ~/Desktop/rom/partitions.bin
3. esptool.py –port /dev/tty.SLAB_USBtoUART write_flash 0x10000 ~/Desktop/rom/nesemu.bin
4. esptool.py –port /dev/tty.SLAB_USBtoUART write_flash 0x100000 ~/Desktop/rom/SuperMario4.nes
M5Stack-nesemu には、Controller、ROM,Copyright について書かれており
通常 FACES GAME Controller で操作できますが 他に NES, Playstation 1, 2
controller の接続方法が書かれています。(CLK=14,DAT=27,ATT=16,CMD=2)
Terminal入力の説明:
esptool.py –port /dev/tty.SLAB_USBtoUART write_flash 0x100000 ~/Desktop/rom/galaxian.nes
1. Python 2.7 又は Python 3.4以上がシステムにインストールされている事。
2. esptool.py:esptool.py がマックにある事が条件です。
_ 無い場合: esptool.py の Read.me に書かれています。
_ Terminal に 「pip install esptool」 を入力しますと動きます。
_ パーミッションエラーの場合は 「sudo pip install esptool 」を入力します。
3. –port /dev/tty.SLAB_USBtoUART:接続したM5STACKの USBの名前です。
_ 異なる USB デバイスの場合は 接続する USBの名前にします。
_ USBの名前の確認は Terminal に ls -l /dev/tty.*
を入力しますと
_ usb デバイス名が表示されます。 ( /dev/tty.SLAB_USBtoUART )
crw-rw-rw- 1 root wheel 19, 8 5 7 05:18 /dev/tty.SLAB_USBtoUART
4. write_flash:M5STACK の FLASH Memory へ書き込みます。
_ memo : 読み込みの場合は read_flash になります。
5. 0x100000:16進の100000番地に書き込みます。
6. ~/Desktop:デスクトップの場所です。他に書類の場所は Document です。
7. /rom:rom というフォルダーを作り nes ROM データーを入れておきます。
8. /galaxian.nes:galaxian の ROM DATA です。
MEMO:データーを読み込む方法:
_ write_flash を read_flash にし 読み込む長さを追加します。
例:esptool.py –port /dev/tty.SLAB_USBtoUART read_flash 0x1000 0x0010 ~/Desktop/data.bin
_ read_flash 開始番地 (0x000000) 長さ(0x0010 : 16byte)
使用方法は M5Stack Community の M5Stack Russia:
_ Урок 13. FACES. Запуск игр от Dendy (NES) に記載されています。
_ 内容を お読み下さい。( 参考になる 検索先が書かれています ) 。
データーの構成:以下の4つで構成されています。
_ M5Stack-nesemu-master の中にある firmware.zip を解凍した
_ ものと同じで 0x100000 は ゲームのデーター です。
0x1000 bootloader.bin 0x8000 partitions.bin 0x10000 nesemu.bin 0x100000 Baltron.nes
配置:それぞれの bin は バイナリー表示の番地へ配置されます。
例:0x1000 bootloader.bin:bootloader.bin は 0x1000番地へ配置されます。
注意:書き込み番地を間違えますと 動かなくなるかもしれません。
_ 各自の責任で行ってください。
解説は ESP32 DOWNLOAD TOOL を使用し Windows の方法が書かれています。
ここでは Mac ( マック) での方法を解説します。
使用環境は iMac 27 MacOS Sierra を使用。古いOSでは出来ない場合があります。
Mac の Terminal (ターミナル) を使用する方法です。
Terminal は アプリケーション フォルダー / ユーティリティフォルダーにあります。
ゲームのデーター「galaxian.nes」(購入したデーター等) を用意します。
Desktop に rom フォルダーを作り、この中に「galaxian.nes」を入れます。
FACES (又は M5STACK ) と マックを USB接続します。
Terminal を起動し、以下の様に入力(1行です) しますと
esptool.py –port /dev/tty.SLAB_USBtoUART write_flash 0x100000 ~/Desktop/rom/galaxian.nes
esptool.py v2.2 Connecting........_____....._____. Detecting chip type... ESP32 Chip is ESP32D0WDQ6 (revision 1) Uploading stub... Running stub... Stub running... Configuring flash size... Auto-detected Flash size: 4MB Compressed 40976 bytes to 10231... Wrote 40976 bytes (10231 compressed) at 0x00100000 in 0.9 seconds (effective 363.9 kbit/s)... Hash of data verified. Leaving... Hard resetting...
と表示され「galaxian」が動きます。
Windows の方法:MY氏から方法を教えて頂きました。感謝致します。
_ Windowsの場合は、以下の内容を “flash.cmd” という名前で各FWファイルを
_ 同じ場所に保存し、同じフォルダに “esptool.exe”を置けば、あとは NES
_ ファイルをドラッグ ドロップすると書き込めます。
—–
@echo off
SET COM_PORT=COM3
SET NES_IMAGE=%1
esptool.exe –chip esp32 –port %COM_PORT% –baud 921600 –before default_reset –after hard_reset write_flash -z –flash_mode dio –flash_freq 40m –flash_size detect 0x1000 bootloader.bin 0x10000 nesemu.bin 0x8000 partitions.bin 0x100000 %NES_IMAGE%
—–
自作データー集:
NES ROM は 購入した物や 怪しい所とか 幾つか方法があります。
ゲームを自作したデーターが公開されてます。
1. NES研究室 – 自作ゲーム
_ 「tkrpg100」、「tkshoot100」があります。
2. ど~もeagle0wlです:正規公開されているゲーム専用機のROMイメージ
_ 「2048」、「ブレイドバスター」があります。
3. 野うさぎ亭 – NESプログラミング
_ 「RevolvingGems」があります。
感想:
Terminal 操作:解りにくさや 難さがありますが 今回の方法で 出来ると
_ 便利かと思います。
自作ゲーム: asm で書かれており 開発時の熱意を感じます。
期待する機能:M5Stack-SD-Updater の様に SD に NES-EMU, NES DATA を
_ 入れ M5STACK のメニューリストから LOAD 出来ると便利かと思います。
_ 私の力量では無理ですので どなたか よろしくお願い致します。
掘り出し物:ファミコン時代にゲームを遊び、購入したゲームのROMを
_ 読み出して勉強した人もいるかと思います。M5STACKで再び再現でき
_ 保存したデーターが生き返る事になったかと思います。
_ NES EMULATOR を公開された M5STACK TEAM に感謝致します。
M5STACK WiFiScan
ESP8266 WiFi Scan を M5STACK に移植しました。 2018.05.03
ORIGINALは oaquimorg/esp8266_wifi_scan です。
joaquim.org : joaquimorg氏の記事:ESP8266 WiFi Scan
joaquimorg氏 に感謝致します。
オリジナルのディスプレーは 2.4 inch 320×240 です。
M5STACK も 320×200 ですが 2.0 inch の為 文字が小さく見づらいですが 良しとします。
Free_Fonts.h は M5STACK Library の中にあります。
SD にアプリを入れて起動する為に SD Update のスケッチが入っています。
スケッチ:WiFiScan:
_ WiFiScan のフォルダーの構成は以下の3つです。
_ icons.h は esp8266_wifi_scan から使用すると良いです。
_ WiFiScan Folder : [ WiFiScan.ino, icons.h, Free_Fonts.h ]
// Scan WiFi networks. (c)joaquim.org // https://github.com/joaquimorg/ESP8266/tree/master/esp8266_wifi_scan // https://www.joaquim.org/esp8266-wifi-scan/ // Github:https://macsbug.wordpress.com/2018/05/03/m5stack-wifiscan/ #include "WiFi.h" #include <M5Stack.h> #include "M5StackUpdater.h" // SD Update #include "icons.h" //#include "Free_Fonts.h" typedef struct { String SSID; uint8_t encryptionType,Active,Update; int32_t RSSI,Channel; } NetInfo; NetInfo networkInfo[30]; typedef struct { int32_t Total,RSSI; }ChannelInfo; ChannelInfo totalChannel[14],totalChannelOld[14]; #define TEXT_SIZE 10 int initclear = 1; void setup() { Serial.begin(115200);delay(500); M5.begin(); Wire.begin(); if(digitalRead(BUTTON_A_PIN) == 0){ // SD Update updateFromFS(SD); ESP.restart(); // SD Update } // SD Update M5.Lcd.setTextColor(TFT_BLACK, TFT_WHITE); M5.Lcd.fillScreen(TFT_WHITE); //M5.Lcd.setFreeFont(FSSB12); //M5.Lcd.setFreeFont(FSS9); M5.Lcd.fillScreen(ILI9341_BLACK); M5.Lcd.drawBitmap(110, 10, wifiBitmap, 100, 70, ILI9341_WHITE); //M5.Lcd.setFont(&FreeMono9pt7b); M5.Lcd.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); M5.Lcd.setCursor(105, 100); M5.Lcd.print("Wifi Scan"); M5.Lcd.setTextColor(ILI9341_GREEN, ILI9341_BLACK); M5.Lcd.setCursor(95, 130); M5.Lcd.print("joaquim.org"); //M5.Lcd.displayUpdate(); M5.Lcd.setTextColor(ILI9341_WHITE, ILI9341_BLACK); Serial.println("esp8266 Wifi Scan ... "); // Set WiFi to station mode and disconnect from an AP if it was previously connected WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(5000); Serial.println("running... "); //M5.Lcd.fillScreen(ILI9341_BLACK); M5.Lcd.setCursor(75, 200); M5.Lcd.println("Scanning WiFi..."); //M5.Lcd.displayUpdate(); memset( networkInfo, 0x0, sizeof(networkInfo) ); memset( totalChannel, 0x0, sizeof(totalChannel) ); memset( totalChannelOld, 0x0, sizeof(totalChannelOld) ); M5.Lcd.setTextSize(1); } void showScreen1( int num ) { int pos = 0, col = 0, total = 0; for (int i = 0; i < num; ++i) { if (networkInfo[i].Active == 1) { M5.Lcd.fillRect(col, 2 + (TEXT_SIZE * pos),160,TEXT_SIZE,BLACK); M5.Lcd.setCursor(col, 2 + (TEXT_SIZE * pos)); /*if (networkInfo[i].encryptionType == ENC_TYPE_NONE) { M5.Lcd.drawBitmap(col,(TEXT_SIZE * pos),unlockBitmap10,10,10,GREEN); } else { M5.Lcd.drawBitmap(col,(TEXT_SIZE * pos),lockBitmap10,10,10,RED); }*/ M5.Lcd.setCursor(col + 14, 2 + (TEXT_SIZE * pos)); M5.Lcd.setTextColor(ILI9341_WHITE, ILI9341_BLACK); if (networkInfo[i].RSSI <= -80) { M5.Lcd.setTextColor(ILI9341_RED, ILI9341_BLACK); } else if (networkInfo[i].RSSI >= -80 && networkInfo[i].RSSI < -70){ M5.Lcd.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); } else { M5.Lcd.setTextColor(ILI9341_GREEN, ILI9341_BLACK); } M5.Lcd.print(networkInfo[i].SSID); //Serial.print(networkInfo[i].SSID);Serial.print(" : "); //Serial.println(networkInfo[i].RSSI);*/ //M5.Lcd.fillRect(0, (TEXT_SIZE * pos), 240, TEXT_SIZE, ILI9341_BLACK); /*if (networkInfo[i].RSSI <= -80) { M5.Lcd.drawBitmap(120,20 + (TEXT_SIZE * pos),level1Bitmap, 8, 8,RED); } else if (networkInfo[i].RSSI >= -80 && networkInfo[i].RSSI < -70){ M5.Lcd.drawBitmap(120,20 + (TEXT_SIZE * pos),level2Bitmap,8,8,YELLOW); } else { M5.Lcd.drawBitmap(120,20 + (TEXT_SIZE * pos),level3Bitmap,8,8,GREEN); }*/ pos++; total++; if ( total > 21) break; if ( total == 11 ) { col = 160; pos = 0; } } } } void BubbleSort(NetInfo netInfo[], int numLength) { uint8_t i, j, flag = 1; // set flag to 1 to start first pass NetInfo temp; // holding variable for (i = 1; (i <= numLength) && flag; i++){ flag = 0; for (j = 0; j < (numLength - 1);j++){// ascending order simply changes to if (abs(netInfo[j + 1].RSSI) < abs(netInfo[j].RSSI)){ temp = netInfo[j]; // swap elements netInfo[j] = netInfo[j + 1]; netInfo[j + 1] = temp; flag = 1; // indicates that a swap occurred. } } } return; //arrays are passed to functions by address; nothing is returned } void addToArray( NetInfo netInfo ) { uint8_t total = 0; for (int i = 0; i < 30; ++i) { if (networkInfo[i].Active == 1 && (networkInfo[i].SSID == netInfo.SSID)){ networkInfo[i] = netInfo; //Serial.print("Found :" + netInfo.SSID + " ");Serial.println(i); return; } } for (int i = 0; i < 30; ++i) { /*Serial.print(i);Serial.print(" "); Serial.print(networkInfo[i].Active); Serial.println(" " + networkInfo[i].SSID + " ");*/ if ( networkInfo[i].Active == 1 ) { total++; } } if ( total < 30 ) { networkInfo[total] = netInfo; //Serial.print("New :" + netInfo.SSID + " ");Serial.println(total); } } void drawGraphScreen() { M5.Lcd.drawRect(1, 120, 319, 105, ILI9341_DARKGREY); M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK); M5.Lcd.drawString("01 02 03 04 05 06 07 08 09 10 11 12 13 14",50,210); M5.Lcd.drawFastHLine(40, 205, 265, ILI9341_ORANGE); M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK); M5.Lcd.drawString("-99", 15, 195); M5.Lcd.drawString("-80", 15, 185); M5.Lcd.drawString("-70", 15, 175); M5.Lcd.drawString("-60", 15, 165); M5.Lcd.drawString("-50", 15, 155); M5.Lcd.drawString("-40", 15, 145); M5.Lcd.drawString("-30", 15, 135); M5.Lcd.drawString("-20", 15, 125); M5.Lcd.drawFastVLine(40, 125, 80, ILI9341_ORANGE); } void drawGraph() { for (int i = 0; i < 14; ++i) { M5.Lcd.drawFastVLine(55 + (i * 18), 125, 75, ILI9341_BLACK); if ( totalChannelOld[i].Total > 0) { M5.Lcd.setTextColor(ILI9341_WHITE, ILI9341_BLACK); M5.Lcd.setCursor(60 + (i * 18), 200 - totalChannelOld[i].RSSI); M5.Lcd.print(" "); } if ( totalChannel[i].Total > 0) { M5.Lcd.setTextColor(ILI9341_WHITE, ILI9341_BLACK); M5.Lcd.setCursor(60 + (i * 18), 200 - totalChannel[i].RSSI); M5.Lcd.print(totalChannel[i].Total); M5.Lcd.drawFastVLine(55 + (i * 18), 200 - totalChannel[i].RSSI, totalChannel[i].RSSI, ILI9341_GREEN); } totalChannelOld[i] = totalChannel[i]; } } void loop() { int n = WiFi.scanNetworks(); int m = n; NetInfo netInfo; for (int i = 0; i < 30; ++i) { networkInfo[i].Update = 0; } for (int i = 0; i < 14; ++i) { totalChannel[i].Total = 0; totalChannel[i].RSSI = 0; } if ( initclear == 1 ) { initclear = 0; M5.Lcd.fillScreen(ILI9341_BLACK); drawGraphScreen(); } if (n == 0) { //M5.Lcd.setTextSize(2); M5.Lcd.fillScreen(ILI9341_BLACK); M5.Lcd.setTextColor(ILI9341_BLUE, ILI9341_BLACK); M5.Lcd.setCursor(0, 10); M5.Lcd.println();M5.Lcd.println(); M5.Lcd.print("No networks found...");M5.Lcd.println(); M5.Lcd.println("Scanning..."); //M5.Lcd.setTextSize(1); } else { if ( m > 30 ) m = 30; for (int i = 0; i < m; ++i) { netInfo.SSID = WiFi.SSID(i); netInfo.encryptionType = WiFi.encryptionType(i); netInfo.RSSI = WiFi.RSSI(i); netInfo.Channel = WiFi.channel(i); netInfo.Active = 1; netInfo.Update = 1; addToArray(netInfo); totalChannel[netInfo.Channel - 1].Total = totalChannel[netInfo.Channel - 1].Total + 1; if ((netInfo.RSSI + 100) > totalChannel[netInfo.Channel - 1].RSSI){ totalChannel[netInfo.Channel - 1].RSSI = (netInfo.RSSI + 100); } } for (int i = 0; i < 30; ++i) { if ( networkInfo[i].Update == 0 ) { networkInfo[i].SSID = ""; networkInfo[i].RSSI = 255; networkInfo[i].Active = 0; } } BubbleSort(networkInfo, 30); M5.Lcd.setCursor(5, 230); M5.Lcd.setTextColor(ILI9341_CYAN, ILI9341_BLACK); M5.Lcd.print(n); M5.Lcd.setTextColor(ILI9341_WHITE, ILI9341_BLACK); M5.Lcd.print(" networks found"); //M5.Lcd.fillRect(0, 20, 240, 320, ILI9341_BLACK); showScreen1(30); drawGraph(); } }
//icons.h const unsigned char wifiBitmap [] PROGMEM = { 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, 31, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 255, 255, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 255, 255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 1, 255, 255, 255, 255, 192, 0, 0, 0, 0, 0, 0, 0, 3, 255, 255, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 15, 255, 255, 255, 255, 248, 0, 0, 0, 0, 0, 0, 0, 15, 255, 255, 255, 255, 252, 0, 0, 0, 0, 0, 0, 7, 255, 255, 255, 255, 255, 255, 248, 0, 0, 0, 0, 0, 127, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 192, 0, 0, 0, 3, 255, 255, 255, 255, 255, 255, 255, 255, 224, 0, 0, 0, 7, 255, 255, 255, 255, 255, 128, 0, 1, 240, 0, 0, 0, 7, 255, 255, 255, 255, 255, 0, 0, 0, 120, 0, 0, 0, 15, 255, 255, 255, 255, 254, 0, 0, 0, 60, 0, 0, 0, 31, 255,255, 255, 255, 252, 0, 0, 0, 28, 0, 0, 0, 31, 255,255, 255, 255, 248, 0, 0, 0, 30, 0, 0, 0, 63, 255,255, 255, 31, 240, 0, 0, 30, 14, 0, 0, 0, 63, 7, 7, 6, 15, 240, 255, 255, 62, 14, 0, 0, 0, 63, 7, 7, 6, 15, 224, 255, 255, 62, 7, 0, 0, 0, 127, 7, 7, 14, 15, 224, 255, 255, 62, 7, 0, 0, 0, 127, 135, 7, 15, 31, 224, 255, 255, 30, 7, 0, 0, 0, 127, 135, 7, 15, 255, 224, 255, 255, 0, 3, 0, 0, 0, 127, 134, 6, 15, 255, 224, 252, 0, 30, 3, 0, 0, 0, 127, 130, 2, 14, 31, 224, 252, 0, 62, 3, 0, 0, 0, 127, 130, 2, 30, 31, 224, 252, 0, 62, 3, 0, 0, 0, 127, 194, 34, 30, 31, 224, 252, 0, 62, 3, 0, 0, 0, 127, 194, 34, 30, 31, 224, 255, 254, 62, 3, 0, 0, 0, 127, 194, 34, 30, 31, 224, 255, 254, 62, 3, 0, 0, 0, 127, 194, 34, 30, 31, 224, 255, 254, 62, 3, 0, 0, 0, 127, 192, 32, 62, 31, 224, 255, 254, 62, 3, 0, 0, 0, 127, 224, 32, 62, 31, 224, 255, 254, 62, 3, 0, 0, 0, 127, 224, 96, 62, 31, 224, 255, 254, 62, 3, 0, 0, 0, 127, 224, 112, 62, 31, 224, 252, 0, 62, 3, 0, 0, 0, 127, 224, 112, 62, 31, 224, 252, 0, 62, 3, 0, 0, 0, 127, 224, 112, 126, 31, 224, 252, 0, 62, 3, 0, 0, 0, 127, 240, 112, 126, 31, 192, 252, 0, 62, 7, 0, 0, 0, 127, 240, 240, 126, 31, 192, 252, 0, 62, 7, 0, 0, 0, 63, 255, 255, 255, 255, 192, 248, 0, 62, 7, 0, 0, 0, 63, 255, 255, 255, 255, 192, 0, 0, 0, 14, 0, 0, 0, 63, 255, 255, 255, 255, 128, 0, 0, 0, 14, 0, 0, 0, 31, 255, 255, 255, 255, 128, 0, 0, 0, 30, 0, 0, 0, 31, 255, 255, 255, 255, 0, 0, 0, 0, 28, 0, 0, 0, 15, 255, 255, 255, 255, 0, 0, 0, 0, 56, 0, 0, 0, 7, 255, 255, 255, 254, 0, 0, 0, 0, 248, 0, 0, 0, 7, 255, 255, 255, 252, 0, 0, 0, 1, 240, 0, 0, 0, 1, 255, 255, 255, 255, 255, 255, 255, 255, 224, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 192, 0, 0, 0, 0, 63, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 7, 255, 255, 255, 255, 255, 255, 240, 0, 0, 0, 0, 0, 0, 7, 255, 255, 255, 255, 248, 0, 0, 0, 0, 0, 0, 0, 3, 255, 255, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 3, 255, 255, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 1, 255, 255, 255, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 0, 63, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 255, 255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 248, 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 unsigned char battBitmap10 [] PROGMEM = { 0, 0, 0, 0, 0, 0, 127, 255, 0, 127, 193, 192, 127, 129, 192, 127, 1, 192, 126, 1, 192, 127, 255, 0, 0, 0, 0, 0, 0, 0 }; const unsigned char lockBitmap10 [] PROGMEM = { 0, 0, 30, 0, 51, 0, 33, 0, 33, 0, 127, 128, 115, 128, 115, 128, 63, 0, 0, 0 }; const unsigned char unlockBitmap10 [] PROGMEM = { 0, 0, 30, 0, 51, 0, 1, 0, 1, 0, 127, 128, 127, 128, 127, 128, 63, 0, 0, 0 }; const unsigned char level1Bitmap [] PROGMEM = { 7, 128, 63, 240, 240, 60, 199, 140, 31, 224, 48, 48, 7, 128, 12, 192, 0, 0, 3, 0, 3, 0 }; const unsigned char level2Bitmap [] PROGMEM = { 0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0xd8, 0x00 }; const unsigned char level3Bitmap [] PROGMEM = { 0x00, 0x03, 0x03, 0x1b, 0x1b, 0xdb, 0xdb, 0x00 }; const unsigned char openBitmap [] PROGMEM = { 0x00, 0x18, 0x24, 0x42, 0x42, 0x24, 0x18, 0x00 }; const unsigned char closeBitmap [] PROGMEM = { 0x00, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x00 };