abstracting displays

This commit is contained in:
Jorj Bauer 2022-01-26 13:49:28 -05:00
parent a7f6307174
commit ab888aea88
18 changed files with 29971 additions and 119 deletions

View File

@ -1,12 +1,9 @@
#include "appleui.h"
#include "vm.h" // for DISPLAYHEIGHT. Probably not the most sensible.
#include "images.h"
#include "vm.h"
#include "images.h" // for the image abstraction constants
#include "globals.h"
// FIXME: abstract and standardize the sizes, onscreen locations, and
// underlying bitmap types
AppleUI::AppleUI()
{
redrawFrame = false;
@ -48,8 +45,7 @@ void AppleUI::drawPercentageUIElement(uint8_t element, uint8_t percent)
if (element != UIePowerPercentage) {
return;
}
// Temporarily disabled; the API for this needs updating for resolution-independent display coordinates
// drawBatteryStatus(percent);
drawBatteryStatus(percent);
}
void AppleUI::drawBatteryStatus(uint8_t percent)
@ -62,7 +58,7 @@ void AppleUI::drawBatteryStatus(uint8_t percent)
// the area around the apple is 12 wide; it's exactly 11 high the
// color is 210/202/159
static const uint8_t *img = NULL;
static uint8_t *img = NULL;
static uint16_t h,w;
if (!img) {
if (!getImageInfoAndData(IMG_APPLEBATTERY, &w, &h, &img)) {
@ -112,48 +108,22 @@ void AppleUI::drawBatteryStatus(uint8_t percent)
void AppleUI::blit()
{
static const uint8_t *bg_img = NULL;
static uint16_t bg_h,bg_w;
if (!bg_img) {
if (!getImageInfoAndData(IMG_SHELL, &bg_w, &bg_h, &bg_img))
return;
}
if (redrawFrame) {
redrawFrame = false;
g_display->drawImageOfSizeAt(bg_img, bg_w, bg_h, 0, 0);
g_display->drawUIImage(IMG_SHELL);
}
if (redrawDriveLatches) {
redrawDriveLatches = false;
static const uint8_t *d1open_img = NULL;
static const uint8_t *d1closed_img = NULL;
static const uint16_t d1_w, d1_h;
static const uint8_t *d2open_img = NULL;
static const uint8_t *d2closed_img = NULL;
static const uint16_t d2_w, d2_h;
if (!d1open_img && !getImageInfoAndData(IMG_D1OPEN, &d1_w, &d1_h, &d1open_img))
return;
if (!d1closed_img && !getImageInfoAndData(IMG_D1CLOSED, &d1_w, &d1_h, &d1closed_img))
return;
if (!d2open_img && !getImageInfoAndData(IMG_D2OPEN, &d2_w, &d2_h, &d2open_img))
return;
if (!d2closed_img && !getImageInfoAndData(IMG_D2CLOSED, &d2_w, &d2_h, &d2closed_img))
return;
// assumes all the latch images are the same width/height
g_display->drawImageOfSizeAt(driveInserted[0] ? d1closed_img : d1open_img, d1_w, d1_h, LATCH_X, LATCH1_Y);
g_display->drawImageOfSizeAt(driveInserted[1] ? d2closed_img : d2open_img, d2_w, d2_h, LATCH_X, LATCH1_Y);
g_display->drawUIImage(driveInserted[0] ? IMG_D1CLOSED : IMG_D1OPEN);
g_display->drawUIImage(driveInserted[1] ? IMG_D2CLOSED : IMG_D2OPEN);
}
if (redrawDriveActivity) {
redrawDriveActivity = false;
/*
// FIXME make these bitmaps so the size/location are abstracted
for (int y=0; y<LED_HEIGHT; y++) {
for (int x=0; x<LED_WIDTH; x++) {
g_display->drawUIPixel(x + LED_X, y + LED1_Y, driveActivity[0] ? 0xFA00 : 0x0000);
@ -161,6 +131,7 @@ void AppleUI::blit()
g_display->drawUIPixel(x + LED_X, y + LED2_Y, driveActivity[1] ? 0xFA00 : 0x0000);
}
}
*/
}
}

57
image-9341-applebitmap.h Normal file
View File

@ -0,0 +1,57 @@
const uint8_t img_9341_applebitmap[] PROGMEM = {
0xA7, 0xD7, 0x98, 0x00, 0x87, 0xCC, 0x72, 0x00,
0x7B, 0xC1, 0x65, 0x00, 0x9D, 0xD0, 0x8D, 0x00,
0xBF, 0xE0, 0xB7, 0x00, 0x81, 0xC9, 0x6A, 0x6F,
0x68, 0xC0, 0x4B, 0xC0, 0x95, 0xCF, 0x83, 0x05,
0x96, 0xCE, 0x84, 0x00, 0x95, 0xCE, 0x83, 0x00,
0xA7, 0xD6, 0x98, 0x00, 0x88, 0xCC, 0x73, 0x00,
0x7E, 0xC2, 0x69, 0x00, 0x8E, 0xCA, 0x7B, 0x00,
0x96, 0xD0, 0x84, 0x42, 0x59, 0xBB, 0x38, 0xFF,
0x7D, 0xC6, 0x65, 0x81, 0x95, 0xCE, 0x84, 0x00,
0x8C, 0xCD, 0x77, 0x00, 0xCC, 0xE7, 0xC3, 0x00,
0xA6, 0xD8, 0x9D, 0x00, 0x7F, 0xCB, 0x6E, 0x1C,
0x6D, 0xC0, 0x59, 0x67, 0x73, 0xC3, 0x5F, 0x4E,
0x7A, 0xC8, 0x68, 0x70, 0x66, 0xC2, 0x4F, 0xA1,
0x73, 0xC3, 0x60, 0x61, 0x70, 0xC2, 0x5D, 0x60,
0x80, 0xCB, 0x6D, 0x15, 0xDB, 0xEF, 0xD5, 0x00,
0xA7, 0xD1, 0x81, 0x32, 0x72, 0xBD, 0x3A, 0xE7,
0x6D, 0xBC, 0x34, 0xFF, 0x6E, 0xBC, 0x35, 0xFF,
0x73, 0xBE, 0x3C, 0xED, 0x72, 0xBD, 0x3B, 0xE6,
0x6D, 0xBC, 0x35, 0xFF, 0x6C, 0xBB, 0x31, 0xFF,
0x70, 0xBF, 0x3F, 0xCF, 0xD5, 0xEE, 0xD4, 0x0C,
0xF5, 0xC0, 0x19, 0xB9, 0xF7, 0xBB, 0x00, 0xFF,
0xF7, 0xBC, 0x03, 0xFF, 0xF7, 0xBC, 0x03, 0xFF,
0xF7, 0xBC, 0x02, 0xFF, 0xF7, 0xBC, 0x02, 0xFF,
0xF7, 0xBC, 0x03, 0xFF, 0xF9, 0xBB, 0x00, 0xFF,
0xE4, 0xC6, 0x42, 0x67, 0xE2, 0xE8, 0xBF, 0x00,
0xFC, 0x99, 0x02, 0xE9, 0xFD, 0x99, 0x00, 0xFF,
0xFD, 0x99, 0x00, 0xFF, 0xFD, 0x99, 0x00, 0xFF,
0xFD, 0x99, 0x00, 0xFF, 0xFD, 0x99, 0x00, 0xFF,
0xFD, 0x98, 0x00, 0xFF, 0xFD, 0x9D, 0x09, 0xE9,
0xFB, 0xB6, 0x5A, 0x11, 0xF9, 0xB5, 0x5C, 0x00,
0xF2, 0x6D, 0x10, 0xE6, 0xF2, 0x6B, 0x0E, 0xFF,
0xF2, 0x6B, 0x0E, 0xFF, 0xF2, 0x6B, 0x0E, 0xFF,
0xF2, 0x6B, 0x0E, 0xFF, 0xF2, 0x6B, 0x0E, 0xFF,
0xF2, 0x6A, 0x0D, 0xFF, 0xF2, 0x6D, 0x13, 0xF4,
0xF0, 0x8E, 0x53, 0x23, 0xF5, 0xB8, 0x92, 0x00,
0xE1, 0x46, 0x4D, 0xBD, 0xE0, 0x32, 0x39, 0xFF,
0xE0, 0x35, 0x3C, 0xFF, 0xE0, 0x35, 0x3C, 0xFF,
0xE0, 0x35, 0x3C, 0xFF, 0xE0, 0x35, 0x3C, 0xFF,
0xE0, 0x35, 0x3C, 0xFF, 0xE0, 0x33, 0x3A, 0xFF,
0xE0, 0x3F, 0x45, 0xAF, 0xEF, 0xA6, 0xAA, 0x15,
0xBE, 0x67, 0x9F, 0x64, 0xA9, 0x2F, 0x83, 0xFF,
0xAD, 0x32, 0x85, 0xFF, 0xAD, 0x32, 0x85, 0xFF,
0xAD, 0x32, 0x85, 0xFF, 0xAD, 0x32, 0x85, 0xFF,
0xAD, 0x32, 0x85, 0xFF, 0xAD, 0x32, 0x85, 0xFF,
0xA6, 0x29, 0x7E, 0xFF, 0xCF, 0x8D, 0xBA, 0x52,
0x8E, 0x9F, 0xD2, 0x06, 0x5F, 0x71, 0xC0, 0xC4,
0x48, 0x66, 0xBC, 0xFF, 0x4C, 0x68, 0xBD, 0xFF,
0x49, 0x67, 0xBD, 0xFF, 0x49, 0x67, 0xBD, 0xFF,
0x4B, 0x68, 0xBD, 0xFF, 0x46, 0x65, 0xBC, 0xFF,
0x68, 0x77, 0xC2, 0xAE, 0x97, 0xA5, 0xD3, 0x00,
0x62, 0xC7, 0xEE, 0x00, 0x42, 0xC0, 0xEC, 0x23,
0x01, 0xA6, 0xE4, 0xC8, 0x01, 0xA4, 0xE4, 0xDB,
0x12, 0xAA, 0xE3, 0x90, 0x11, 0xAA, 0xE3, 0x93,
0x00, 0xA4, 0xE4, 0xE0, 0x06, 0xA8, 0xE5, 0xBA,
0x5C, 0xC8, 0xEC, 0x15, 0x77, 0xCC, 0xEC, 0x00
};

28802
image-9341-bg.h Normal file

File diff suppressed because it is too large Load Diff

651
image-9341-drivelatches.h Normal file
View File

@ -0,0 +1,651 @@
const uint8_t image_9341_driveclosed[] PROGMEM = {
0xCF, 0xC1, 0x97, 0xB4, 0xA4, 0x84, 0xAE, 0x9D,
0x7E, 0xAF, 0x9F, 0x7F, 0xB1, 0xA1, 0x81, 0xB1,
0xA1, 0x81, 0xB1, 0xA1, 0x80, 0xB0, 0xA0, 0x7E,
0xB1, 0xA1, 0x7F, 0xB1, 0xA1, 0x7F, 0xB1, 0xA2,
0x80, 0xB2, 0xA3, 0x80, 0xB1, 0xA2, 0x80, 0xB1,
0xA2, 0x80, 0xB1, 0xA2, 0x80, 0xB0, 0xA2, 0x7F,
0xB1, 0xA3, 0x80, 0xB1, 0xA3, 0x81, 0xB3, 0xA3,
0x80, 0xB1, 0xA2, 0x7E, 0xB0, 0xA0, 0x7D, 0xB3,
0xA3, 0x7F, 0xB4, 0xA4, 0x80, 0xB3, 0xA4, 0x7F,
0xB4, 0xA5, 0x7E, 0xB6, 0xA7, 0x81, 0xB7, 0xA8,
0x82, 0xB9, 0xA9, 0x83, 0xB8, 0xA9, 0x83, 0xB7,
0xA8, 0x84, 0xB9, 0xA9, 0x87, 0xBA, 0xAA, 0x88,
0xBB, 0xAB, 0x89, 0xBA, 0xAA, 0x88, 0xBC, 0xAC,
0x8A, 0xBE, 0xAF, 0x88, 0xBE, 0xAF, 0x88, 0xBD,
0xAE, 0x87, 0xBD, 0xAD, 0x87, 0xC0, 0xB1, 0x8A,
0xC5, 0xB6, 0x8D, 0xC7, 0xB8, 0x8C, 0xD9, 0xCA,
0x9F, 0xC5, 0xB5, 0x8F, 0x82, 0x71, 0x59, 0x7B,
0x6B, 0x51, 0x91, 0x81, 0x66, 0x8C, 0x7C, 0x61,
0x8C, 0x7C, 0x60, 0x8C, 0x7B, 0x5F, 0x8E, 0x7C,
0x62, 0x8F, 0x7D, 0x63, 0x8E, 0x7D, 0x62, 0x8E,
0x7D, 0x62, 0x8C, 0x7A, 0x60, 0x89, 0x7B, 0x5F,
0x8A, 0x7C, 0x60, 0x8B, 0x7C, 0x60, 0x8A, 0x7B,
0x5F, 0x8C, 0x7C, 0x61, 0x8B, 0x7A, 0x5F, 0x8A,
0x7A, 0x5F, 0x8B, 0x7B, 0x60, 0x8B, 0x7B, 0x60,
0x8B, 0x7B, 0x60, 0x8B, 0x7B, 0x5F, 0x8A, 0x7A,
0x5E, 0x8B, 0x79, 0x5D, 0x8A, 0x79, 0x5D, 0x8B,
0x7A, 0x5E, 0x8C, 0x7A, 0x5F, 0x8C, 0x7A, 0x5F,
0x8C, 0x7C, 0x60, 0x8C, 0x7D, 0x61, 0x8D, 0x7D,
0x61, 0x8C, 0x7C, 0x61, 0x8E, 0x7E, 0x62, 0x8E,
0x7E, 0x63, 0x8D, 0x7C, 0x5D, 0x8E, 0x7F, 0x5F,
0x8E, 0x7F, 0x5F, 0x8B, 0x7D, 0x5E, 0x7D, 0x6E,
0x54, 0x7E, 0x70, 0x56, 0xAB, 0x9B, 0x78, 0xD9,
0xCA, 0x9F, 0xC6, 0xB6, 0x91, 0x75, 0x65, 0x4D,
0x99, 0x89, 0x76, 0xA9, 0x98, 0x7C, 0xA9, 0x98,
0x7C, 0xA6, 0x95, 0x79, 0xA5, 0x94, 0x78, 0xA4,
0x93, 0x77, 0xA4, 0x93, 0x77, 0xA5, 0x92, 0x78,
0xA5, 0x90, 0x79, 0xA3, 0x91, 0x79, 0xA1, 0x90,
0x78, 0xA2, 0x93, 0x79, 0xA0, 0x92, 0x78, 0xA0,
0x92, 0x78, 0x9F, 0x91, 0x75, 0xA1, 0x93, 0x76,
0xA1, 0x93, 0x74, 0xA1, 0x93, 0x73, 0xA1, 0x93,
0x73, 0xA2, 0x94, 0x76, 0xA1, 0x92, 0x75, 0xA0,
0x92, 0x75, 0xA1, 0x92, 0x75, 0xA1, 0x93, 0x75,
0xA1, 0x93, 0x76, 0xA2, 0x93, 0x76, 0xA2, 0x93,
0x76, 0xA2, 0x93, 0x76, 0xA1, 0x93, 0x75, 0xA1,
0x93, 0x75, 0xA4, 0x93, 0x75, 0xA3, 0x92, 0x75,
0xA4, 0x93, 0x77, 0xA2, 0x91, 0x77, 0xA1, 0x90,
0x77, 0xA0, 0x8F, 0x76, 0x9B, 0x90, 0x72, 0x96,
0x88, 0x6E, 0x67, 0x59, 0x40, 0xB2, 0xA2, 0x82,
0xD9, 0xCA, 0x9F, 0xC2, 0xB3, 0x8D, 0x76, 0x66,
0x4D, 0x9E, 0x8D, 0x78, 0xAB, 0x9A, 0x7A, 0xAB,
0x9A, 0x7A, 0xA7, 0x96, 0x78, 0xA4, 0x94, 0x75,
0xA4, 0x93, 0x75, 0xA4, 0x93, 0x75, 0xA7, 0x94,
0x78, 0xA8, 0x94, 0x7A, 0xA3, 0x93, 0x77, 0xA3,
0x93, 0x77, 0xA5, 0x96, 0x79, 0xA0, 0x92, 0x76,
0xA0, 0x91, 0x75, 0xA2, 0x93, 0x75, 0xA3, 0x94,
0x76, 0xA3, 0x94, 0x75, 0xA3, 0x94, 0x73, 0xA3,
0x94, 0x73, 0xA2, 0x93, 0x74, 0xA3, 0x94, 0x74,
0xA2, 0x93, 0x74, 0xA4, 0x95, 0x76, 0xA4, 0x94,
0x75, 0xA3, 0x94, 0x74, 0xA3, 0x94, 0x75, 0xA3,
0x94, 0x75, 0xA3, 0x94, 0x74, 0xA3, 0x94, 0x75,
0xA3, 0x94, 0x75, 0xA4, 0x93, 0x75, 0xA4, 0x93,
0x75, 0xA6, 0x95, 0x77, 0xA3, 0x92, 0x76, 0xA1,
0x91, 0x76, 0xA0, 0x90, 0x75, 0x9C, 0x90, 0x70,
0x97, 0x8A, 0x6F, 0x6B, 0x5C, 0x42, 0xB2, 0xA2,
0x81, 0xD9, 0xCA, 0x9F, 0xC3, 0xB3, 0x8D, 0x79,
0x69, 0x4F, 0xA0, 0x91, 0x78, 0xAA, 0x99, 0x78,
0xAA, 0x99, 0x78, 0xA7, 0x97, 0x77, 0xA4, 0x95,
0x74, 0xA5, 0x95, 0x74, 0xA4, 0x94, 0x73, 0xA7,
0x94, 0x75, 0xA7, 0x95, 0x77, 0xA4, 0x94, 0x75,
0xA3, 0x94, 0x74, 0xA4, 0x96, 0x76, 0xA1, 0x94,
0x74, 0xA4, 0x94, 0x77, 0xA4, 0x93, 0x76, 0xA4,
0x94, 0x75, 0xA4, 0x95, 0x74, 0xA3, 0x94, 0x72,
0xA4, 0x94, 0x73, 0xA4, 0x95, 0x74, 0xA4, 0x94,
0x73, 0xA4, 0x94, 0x73, 0xA2, 0x93, 0x72, 0xA3,
0x93, 0x73, 0xA3, 0x94, 0x73, 0xA4, 0x95, 0x74,
0xA2, 0x93, 0x72, 0xA2, 0x93, 0x73, 0xA4, 0x94,
0x73, 0xA3, 0x94, 0x73, 0xA4, 0x94, 0x74, 0xA4,
0x94, 0x74, 0xA4, 0x92, 0x75, 0xA3, 0x92, 0x75,
0xA2, 0x91, 0x75, 0xA0, 0x91, 0x74, 0x9C, 0x90,
0x6F, 0x9A, 0x8C, 0x70, 0x6F, 0x60, 0x47, 0xB2,
0xA2, 0x80, 0xD9, 0xCA, 0x9F, 0xC0, 0xB1, 0x8A,
0x77, 0x67, 0x4B, 0xA2, 0x93, 0x78, 0xAA, 0x9A,
0x78, 0xAA, 0x9A, 0x78, 0xA9, 0x99, 0x78, 0xA7,
0x97, 0x76, 0xA7, 0x97, 0x76, 0xA8, 0x98, 0x76,
0xA9, 0x96, 0x76, 0xA6, 0x94, 0x73, 0xA5, 0x96,
0x74, 0xA5, 0x97, 0x75, 0xA5, 0x98, 0x76, 0xA4,
0x97, 0x75, 0xA7, 0x95, 0x77, 0xA8, 0x96, 0x77,
0xA7, 0x95, 0x75, 0xA5, 0x93, 0x72, 0xA8, 0x96,
0x74, 0xA7, 0x96, 0x74, 0xA8, 0x96, 0x76, 0xA8,
0x96, 0x76, 0xA7, 0x95, 0x75, 0xA7, 0x95, 0x74,
0xA7, 0x96, 0x76, 0xA7, 0x97, 0x77, 0xA8, 0x9A,
0x79, 0xA6, 0x97, 0x76, 0xA5, 0x97, 0x76, 0xA6,
0x97, 0x76, 0xA5, 0x97, 0x75, 0xA5, 0x95, 0x74,
0xA5, 0x95, 0x73, 0xA3, 0x92, 0x73, 0xA2, 0x92,
0x74, 0xA4, 0x93, 0x77, 0xA3, 0x94, 0x75, 0x9C,
0x92, 0x6E, 0x9B, 0x8E, 0x71, 0x73, 0x65, 0x4B,
0xB4, 0xA5, 0x81, 0xD9, 0xCA, 0x9F, 0xBF, 0xB0,
0x89, 0x79, 0x69, 0x4C, 0xAC, 0x9C, 0x7F, 0xB1,
0xA1, 0x7F, 0xB1, 0xA1, 0x7F, 0xB0, 0xA0, 0x7F,
0xB2, 0xA2, 0x80, 0xB2, 0xA2, 0x81, 0xB3, 0xA3,
0x82, 0xB5, 0xA2, 0x80, 0xB3, 0xA1, 0x7F, 0xB2,
0xA1, 0x7F, 0xB3, 0xA4, 0x80, 0xB0, 0xA2, 0x7E,
0xAF, 0xA0, 0x7D, 0xB1, 0x9D, 0x7E, 0xB1, 0x9E,
0x7D, 0xAF, 0x9B, 0x7B, 0xB0, 0x9D, 0x7C, 0xB2,
0x9F, 0x7C, 0xB0, 0x9D, 0x7B, 0xB0, 0x9C, 0x7B,
0xB0, 0x9D, 0x7C, 0xB1, 0x9D, 0x7D, 0xB3, 0xA0,
0x7F, 0xB3, 0x9F, 0x7F, 0xAE, 0x9F, 0x7C, 0xAF,
0xA1, 0x7E, 0xB0, 0xA2, 0x7E, 0xB0, 0xA2, 0x7E,
0xB0, 0xA2, 0x7F, 0xB0, 0xA2, 0x7E, 0xB1, 0xA0,
0x7E, 0xB3, 0xA3, 0x81, 0xB3, 0xA2, 0x82, 0xB2,
0xA0, 0x82, 0xB0, 0x9E, 0x82, 0xAB, 0x9C, 0x7C,
0xA4, 0x98, 0x73, 0xA3, 0x94, 0x75, 0x7A, 0x6A,
0x50, 0xB4, 0xA6, 0x83, 0xD9, 0xCA, 0x9F, 0xA4,
0x94, 0x70, 0x70, 0x5F, 0x43, 0xC6, 0xB6, 0x94,
0xC1, 0xB2, 0x8F, 0xC1, 0xB2, 0x8F, 0xC3, 0xB3,
0x90, 0xC4, 0xB4, 0x92, 0xC4, 0xB4, 0x91, 0xC4,
0xB4, 0x91, 0xC4, 0xB2, 0x8D, 0xC3, 0xB1, 0x8C,
0xC3, 0xB1, 0x8C, 0xC3, 0xB1, 0x8C, 0xC3, 0xB0,
0x8C, 0xC4, 0xB2, 0x8D, 0xC4, 0xB1, 0x8D, 0xC3,
0xB0, 0x8B, 0xC3, 0xB0, 0x8B, 0xC3, 0xB0, 0x8C,
0xC3, 0xB0, 0x8B, 0xC2, 0xAF, 0x8D, 0xC1, 0xAD,
0x8C, 0xC2, 0xAF, 0x8E, 0xC3, 0xB0, 0x8F, 0xC3,
0xAF, 0x8E, 0xC3, 0xAF, 0x8E, 0xC1, 0xB0, 0x8B,
0xC1, 0xB1, 0x8A, 0xC1, 0xB0, 0x8A, 0xC1, 0xB0,
0x8A, 0xC2, 0xB2, 0x8B, 0xC3, 0xB2, 0x8C, 0xC4,
0xB1, 0x8C, 0xC4, 0xB1, 0x8E, 0xC4, 0xB1, 0x8F,
0xC4, 0xB0, 0x91, 0xC3, 0xAF, 0x91, 0xC0, 0xAD,
0x8D, 0xBD, 0xA9, 0x84, 0xBA, 0xA8, 0x82, 0x81,
0x6E, 0x53, 0xB1, 0xA1, 0x80, 0xD9, 0xCA, 0x9F,
0xA3, 0x94, 0x6D, 0x69, 0x58, 0x3B, 0xBF, 0xB0,
0x89, 0xBE, 0xAF, 0x87, 0xBE, 0xAF, 0x87, 0xBF,
0xAF, 0x87, 0xBF, 0xB0, 0x88, 0xBF, 0xB0, 0x87,
0xBF, 0xB0, 0x87, 0xBF, 0xAF, 0x88, 0xBE, 0xAF,
0x88, 0xBF, 0xAF, 0x88, 0xBF, 0xAF, 0x88, 0xBE,
0xAE, 0x87, 0xC0, 0xAF, 0x89, 0xC1, 0xAF, 0x89,
0xC0, 0xAE, 0x88, 0xC0, 0xAE, 0x87, 0xBF, 0xAD,
0x87, 0xBF, 0xAD, 0x87, 0xC0, 0xAE, 0x8A, 0xBF,
0xAC, 0x89, 0xC2, 0xAF, 0x8B, 0xC1, 0xAF, 0x8B,
0xBF, 0xAD, 0x89, 0xC1, 0xAE, 0x8B, 0xC2, 0xAF,
0x88, 0xC1, 0xAF, 0x86, 0xC0, 0xAD, 0x85, 0xC0,
0xAD, 0x85, 0xC1, 0xAE, 0x87, 0xC0, 0xAD, 0x86,
0xBE, 0xAC, 0x84, 0xC0, 0xAE, 0x87, 0xBF, 0xAD,
0x88, 0xBF, 0xAD, 0x89, 0xBE, 0xAC, 0x89, 0xBF,
0xAC, 0x89, 0xBE, 0xAB, 0x86, 0xBE, 0xAD, 0x88,
0x79, 0x67, 0x4C, 0xC0, 0xB1, 0x8B, 0xB0, 0xA1,
0x76, 0xC7, 0xB8, 0x90, 0x6F, 0x5F, 0x41, 0xBB,
0xAC, 0x81, 0xBC, 0xAD, 0x82, 0xBC, 0xAD, 0x82,
0xBC, 0xAD, 0x82, 0xBC, 0xAD, 0x82, 0xBD, 0xAE,
0x82, 0xBD, 0xAF, 0x84, 0xBD, 0xAF, 0x88, 0xBD,
0xAE, 0x88, 0xBB, 0xAD, 0x86, 0xBA, 0xAC, 0x85,
0xBA, 0xAB, 0x85, 0xBC, 0xAC, 0x86, 0xBD, 0xAB,
0x86, 0xBC, 0xAB, 0x85, 0xBE, 0xAC, 0x87, 0xBE,
0xAD, 0x87, 0xBD, 0xAC, 0x87, 0xBD, 0xAB, 0x85,
0xBD, 0xAB, 0x85, 0xBC, 0xAB, 0x84, 0xBB, 0xAB,
0x84, 0xBC, 0xAB, 0x84, 0xBC, 0xAC, 0x85, 0xC1,
0xAD, 0x85, 0xBD, 0xA9, 0x81, 0xBC, 0xA8, 0x80,
0xBE, 0xAB, 0x84, 0xBF, 0xAB, 0x84, 0xBE, 0xAC,
0x84, 0xBC, 0xAB, 0x83, 0xBC, 0xAC, 0x83, 0xBD,
0xAC, 0x83, 0xBB, 0xAA, 0x82, 0xBC, 0xAC, 0x84,
0xBC, 0xAC, 0x84, 0xBC, 0xAB, 0x85, 0xBB, 0xAA,
0x84, 0x6E, 0x5D, 0x42, 0xCE, 0xBE, 0x97, 0xDC,
0xCF, 0x9D, 0xD3, 0xC4, 0x9B, 0x79, 0x69, 0x4B,
0xC2, 0xB2, 0x89, 0xC7, 0xB8, 0x8E, 0xC7, 0xB8,
0x8E, 0xC7, 0xB8, 0x8E, 0xC5, 0xB6, 0x8D, 0xC4,
0xB4, 0x8A, 0xBB, 0xAC, 0x85, 0xBF, 0xB0, 0x8E,
0xC4, 0xB5, 0x93, 0xC4, 0xB6, 0x94, 0xC0, 0xB1,
0x8F, 0xC0, 0xB2, 0x90, 0xBA, 0xAB, 0x89, 0xBC,
0xAC, 0x8A, 0xBA, 0xAB, 0x89, 0xB9, 0xAA, 0x88,
0xBE, 0xAE, 0x8C, 0xBD, 0xAD, 0x8B, 0xB9, 0xA9,
0x85, 0xBC, 0xAC, 0x88, 0xBC, 0xAD, 0x8A, 0xBF,
0xB0, 0x8C, 0xBF, 0xB0, 0x8C, 0xBF, 0xB0, 0x8B,
0xB8, 0xA7, 0x84, 0xB9, 0xA8, 0x86, 0xC0, 0xAE,
0x8C, 0xBC, 0xAA, 0x88, 0xBE, 0xAC, 0x8A, 0xBC,
0xAC, 0x88, 0xBC, 0xAD, 0x88, 0xBB, 0xAC, 0x87,
0xC1, 0xB2, 0x8B, 0xC1, 0xB2, 0x8A, 0xC1, 0xB2,
0x89, 0xC1, 0xB2, 0x89, 0xC0, 0xB1, 0x8B, 0xB9,
0xA9, 0x83, 0x65, 0x56, 0x3B, 0xBC, 0xAC, 0x85,
0xE5, 0xD7, 0xA4, 0xD0, 0xC1, 0x96, 0x79, 0x69,
0x4A, 0xC5, 0xB5, 0x91, 0xC8, 0xB8, 0x94, 0xC8,
0xB8, 0x94, 0xC7, 0xB7, 0x94, 0xC8, 0xB8, 0x95,
0xBC, 0xAC, 0x88, 0x99, 0x8B, 0x6A, 0xA9, 0x9B,
0x7F, 0xAF, 0xA1, 0x84, 0xA6, 0x98, 0x7B, 0x9D,
0x8F, 0x73, 0xB0, 0xA2, 0x85, 0xA5, 0x96, 0x7A,
0x9B, 0x8B, 0x6F, 0xA1, 0x91, 0x75, 0xA0, 0x91,
0x75, 0x99, 0x89, 0x6D, 0x98, 0x88, 0x6C, 0x99,
0x8A, 0x6B, 0x94, 0x85, 0x67, 0xAA, 0x9B, 0x7D,
0xA0, 0x91, 0x73, 0xAB, 0x9C, 0x7E, 0xA9, 0x99,
0x7B, 0xA1, 0x93, 0x74, 0x9F, 0x91, 0x72, 0xB1,
0xA2, 0x84, 0xA1, 0x93, 0x74, 0x9F, 0x90, 0x72,
0x99, 0x8A, 0x6B, 0x99, 0x89, 0x6A, 0xA0, 0x91,
0x70, 0xC0, 0xB3, 0x8E, 0xC5, 0xB7, 0x92, 0xC1,
0xB3, 0x8C, 0xC1, 0xB3, 0x8C, 0xBF, 0xB0, 0x8B,
0xB5, 0xA7, 0x7F, 0x60, 0x51, 0x37, 0xA4, 0x94,
0x6F, 0xDA, 0xCC, 0x9B, 0xC2, 0xB2, 0x8A, 0x71,
0x63, 0x44, 0xCC, 0xBC, 0x9A, 0xCE, 0xBE, 0x9C,
0xCE, 0xBE, 0x9C, 0xCE, 0xBE, 0x9C, 0xCF, 0xBF,
0x9C, 0xC2, 0xB2, 0x8F, 0xBB, 0xAC, 0x8D, 0xB6,
0xA8, 0x8E, 0xB0, 0xA1, 0x87, 0xA8, 0x99, 0x7F,
0xAB, 0x9D, 0x83, 0xBA, 0xAC, 0x93, 0xAE, 0x9F,
0x84, 0xB0, 0xA0, 0x85, 0xAE, 0x9E, 0x83, 0xB7,
0xA7, 0x8C, 0xAC, 0x9D, 0x82, 0xAE, 0x9F, 0x83,
0xB1, 0xA2, 0x86, 0xAC, 0x9D, 0x81, 0xB9, 0xAA,
0x8D, 0xA9, 0x9A, 0x7D, 0xB2, 0xA3, 0x86, 0xB7,
0xA8, 0x8C, 0xB1, 0xA5, 0x87, 0xA9, 0x9D, 0x7F,
0xB1, 0xA5, 0x87, 0xAC, 0xA0, 0x82, 0xAC, 0xA1,
0x83, 0xA6, 0x98, 0x7B, 0xA3, 0x93, 0x75, 0xB4,
0xA4, 0x86, 0xCD, 0xBE, 0x9E, 0xCF, 0xBF, 0x9F,
0xC8, 0xB8, 0x97, 0xC8, 0xB8, 0x97, 0xC5, 0xB6,
0x92, 0xB4, 0xA6, 0x81, 0x5D, 0x4E, 0x36, 0x98,
0x89, 0x63, 0xC6, 0xB8, 0x8B, 0xAE, 0x9F, 0x79,
0x72, 0x66, 0x49, 0xE4, 0xD3, 0xB3, 0xE5, 0xD5,
0xB4, 0xE5, 0xD5, 0xB4, 0xE6, 0xD6, 0xB5, 0xE7,
0xD7, 0xB6, 0xE6, 0xD6, 0xB5, 0xE6, 0xD6, 0xB8,
0xE4, 0xD4, 0xB8, 0xE2, 0xD2, 0xB7, 0xE0, 0xD0,
0xB6, 0xE3, 0xD3, 0xBA, 0xE4, 0xD4, 0xBD, 0xE0,
0xD1, 0xB5, 0xE2, 0xD3, 0xB6, 0xE2, 0xD3, 0xB6,
0xE1, 0xD2, 0xB5, 0xE1, 0xD2, 0xB5, 0xE1, 0xD2,
0xB5, 0xE0, 0xD1, 0xB4, 0xE0, 0xD1, 0xB4, 0xDF,
0xD0, 0xB3, 0xDF, 0xD0, 0xB3, 0xDB, 0xCC, 0xAF,
0xE1, 0xD2, 0xB6, 0xDC, 0xCF, 0xB3, 0xDC, 0xCF,
0xB3, 0xDC, 0xCF, 0xB3, 0xDE, 0xD1, 0xB5, 0xDB,
0xCF, 0xB3, 0xDF, 0xD0, 0xB3, 0xE3, 0xD2, 0xB3,
0xDE, 0xCD, 0xAF, 0xE0, 0xCF, 0xB1, 0xE5, 0xD3,
0xB6, 0xD4, 0xC3, 0xA6, 0xD4, 0xC3, 0xA6, 0xCA,
0xBC, 0x96, 0xB0, 0xA1, 0x80, 0x5E, 0x4E, 0x36,
0x9A, 0x8B, 0x64, 0xB7, 0xA9, 0x7E, 0xAC, 0x9D,
0x77, 0x7A, 0x6C, 0x50, 0xBA, 0xA8, 0x8C, 0xB9,
0xA8, 0x8B, 0xB9, 0xA8, 0x8B, 0xBB, 0xAA, 0x8D,
0xBC, 0xAB, 0x8F, 0xB9, 0xA8, 0x8B, 0xB8, 0xA8,
0x8B, 0xB7, 0xA8, 0x8B, 0x9B, 0x8C, 0x70, 0x97,
0x87, 0x6D, 0xA9, 0x99, 0x80, 0xA4, 0x94, 0x7B,
0x9C, 0x8D, 0x71, 0x9D, 0x8E, 0x71, 0xB4, 0xA5,
0x88, 0x9B, 0x8C, 0x6F, 0x91, 0x82, 0x65, 0xA6,
0x97, 0x7A, 0xA6, 0x97, 0x7A, 0x9D, 0x8E, 0x71,
0xA9, 0x9A, 0x7D, 0xA9, 0x9A, 0x7D, 0x98, 0x89,
0x6C, 0x96, 0x87, 0x6C, 0x94, 0x86, 0x6D, 0x90,
0x82, 0x68, 0x98, 0x8A, 0x70, 0x93, 0x85, 0x6B,
0xA2, 0x94, 0x7B, 0xB6, 0xA6, 0x88, 0xB6, 0xA6,
0x85, 0xB4, 0xA4, 0x83, 0xB6, 0xA6, 0x85, 0xB6,
0xA6, 0x86, 0xB4, 0xA4, 0x83, 0xB4, 0xA4, 0x83,
0xB6, 0xA8, 0x84, 0xA9, 0x9A, 0x78, 0x5F, 0x4F,
0x36, 0xA2, 0x92, 0x6D, 0xAD, 0x9E, 0x75, 0xAF,
0x9F, 0x78, 0x80, 0x73, 0x55, 0xB1, 0xA0, 0x83,
0xB2, 0xA2, 0x84, 0xB2, 0xA2, 0x84, 0xB3, 0xA2,
0x84, 0xB2, 0xA1, 0x83, 0xB0, 0x9F, 0x83, 0xB1,
0xA1, 0x82, 0xB1, 0xA2, 0x83, 0x99, 0x8A, 0x6D,
0x9E, 0x8F, 0x73, 0x94, 0x84, 0x6A, 0x91, 0x81,
0x67, 0x8F, 0x80, 0x63, 0x95, 0x86, 0x69, 0xA9,
0x9A, 0x7D, 0x93, 0x84, 0x67, 0x8A, 0x7B, 0x5E,
0x9B, 0x8C, 0x6F, 0x9B, 0x8C, 0x6F, 0x8B, 0x7C,
0x5F, 0x9A, 0x8B, 0x6E, 0x9E, 0x8F, 0x72, 0x90,
0x81, 0x64, 0x8C, 0x7D, 0x61, 0x95, 0x86, 0x6C,
0x89, 0x79, 0x5F, 0x8F, 0x7F, 0x65, 0x87, 0x78,
0x5E, 0x97, 0x87, 0x6E, 0xAE, 0x9F, 0x7F, 0xAE,
0x9E, 0x7C, 0xAE, 0x9E, 0x7D, 0xAE, 0x9E, 0x7D,
0xAD, 0x9C, 0x7B, 0xAD, 0x9D, 0x7C, 0xAD, 0x9D,
0x7C, 0xB2, 0xA3, 0x81, 0xA3, 0x94, 0x73, 0x64,
0x55, 0x38, 0xA5, 0x95, 0x72, 0xAB, 0x9C, 0x74,
0xAE, 0x9E, 0x78, 0x8A, 0x7E, 0x5C, 0xB2, 0xA2,
0x81, 0xB3, 0xA3, 0x81, 0xB3, 0xA3, 0x81, 0xB1,
0xA1, 0x7F, 0xAF, 0x9F, 0x7D, 0xAE, 0x9D, 0x7C,
0xAB, 0x9C, 0x7C, 0xAA, 0x9B, 0x7C, 0xA7, 0x98,
0x7A, 0xA7, 0x98, 0x7B, 0xA3, 0x94, 0x78, 0xA3,
0x93, 0x79, 0xA2, 0x93, 0x76, 0xA4, 0x95, 0x78,
0xA6, 0x97, 0x7A, 0xA4, 0x95, 0x78, 0xA2, 0x93,
0x76, 0xA4, 0x95, 0x78, 0xA4, 0x95, 0x78, 0xA3,
0x94, 0x77, 0xA4, 0x95, 0x78, 0xA5, 0x96, 0x79,
0xA1, 0x92, 0x75, 0xA4, 0x94, 0x76, 0xA5, 0x95,
0x76, 0xA5, 0x95, 0x76, 0xA2, 0x93, 0x74, 0xA6,
0x97, 0x77, 0xA8, 0x99, 0x7A, 0xA9, 0x99, 0x78,
0xAA, 0x9A, 0x78, 0xAB, 0x9B, 0x79, 0xAB, 0x9B,
0x79, 0xAC, 0x9C, 0x7A, 0xAB, 0x9B, 0x79, 0xAB,
0x9B, 0x79, 0xAE, 0x9F, 0x7F, 0x99, 0x8A, 0x6B,
0x69, 0x5A, 0x3B, 0xA6, 0x95, 0x74, 0xA9, 0x9A,
0x74, 0xAE, 0x9E, 0x79, 0x9F, 0x94, 0x6D, 0xD4,
0xC5, 0x9E, 0xC9, 0xBA, 0x94, 0xC9, 0xBA, 0x94,
0xC1, 0xB2, 0x8B, 0xB5, 0xA6, 0x80, 0xAB, 0x9B,
0x76, 0x9F, 0x90, 0x6F, 0x93, 0x84, 0x64, 0x8E,
0x7F, 0x60, 0x8A, 0x7B, 0x5E, 0x8B, 0x7C, 0x5F,
0x8A, 0x7B, 0x5F, 0x88, 0x79, 0x5C, 0x8A, 0x7B,
0x5E, 0x88, 0x79, 0x5C, 0x89, 0x7A, 0x5D, 0x89,
0x7A, 0x5D, 0x88, 0x79, 0x5C, 0x89, 0x7A, 0x5D,
0x89, 0x79, 0x5D, 0x8B, 0x7C, 0x5F, 0x8B, 0x7C,
0x5F, 0x8F, 0x80, 0x64, 0x94, 0x85, 0x63, 0x94,
0x85, 0x5F, 0x98, 0x89, 0x63, 0x9E, 0x8E, 0x69,
0xA2, 0x92, 0x6D, 0xA4, 0x95, 0x6F, 0xA3, 0x93,
0x70, 0xA2, 0x92, 0x70, 0xA4, 0x94, 0x72, 0xA5,
0x95, 0x73, 0xA4, 0x94, 0x72, 0xA5, 0x95, 0x73,
0xA3, 0x94, 0x75, 0x99, 0x8A, 0x6A, 0x88, 0x79,
0x58, 0x7F, 0x70, 0x4F, 0xA0, 0x90, 0x6F, 0xA8,
0x98, 0x75, 0xB8, 0xA8, 0x7E, 0xC7, 0xB9, 0x8F,
0xCA, 0xBB, 0x91, 0xE5, 0xD6, 0xAF, 0xDC, 0xCE,
0xA6, 0xD4, 0xC5, 0x9D, 0xCA, 0xBB, 0x94, 0xC2,
0xB4, 0x8C, 0xB9, 0xAA, 0x86, 0xB4, 0xA4, 0x80,
0xB0, 0xA0, 0x7C, 0xAE, 0x9F, 0x7B, 0xAC, 0x9D,
0x79, 0xAD, 0x9E, 0x7A, 0xAD, 0xA0, 0x7D, 0xAC,
0x9F, 0x7D, 0xAB, 0x9E, 0x7C, 0xAA, 0x9D, 0x7B,
0xAA, 0x9D, 0x7B, 0xAC, 0x9E, 0x7A, 0xAD, 0x9D,
0x7A, 0xAC, 0x9D, 0x79, 0xAE, 0x9E, 0x7B, 0xAF,
0x9F, 0x7C, 0xB1, 0xA1, 0x7E, 0xB2, 0xA3, 0x7D,
0xB6, 0xA7, 0x7F, 0xB7, 0xA8, 0x81, 0xBC, 0xAD,
0x85, 0xBF, 0xB0, 0x88, 0xC0, 0xB1, 0x8A, 0xBF,
0xB0, 0x8A, 0xBE, 0xAF, 0x89, 0xBE, 0xAF, 0x88,
0xBF, 0xB0, 0x89, 0xC0, 0xB0, 0x89, 0xC1, 0xB2,
0x8B, 0xC2, 0xB3, 0x8D, 0xC0, 0xB1, 0x8A, 0xBC,
0xAD, 0x87, 0xB2, 0xA3, 0x7C, 0x9D, 0x8F, 0x6A,
0xB5, 0xA5, 0x7C, 0xC9, 0xBA, 0x8F, 0xE0, 0xD1,
0xA6, 0xE5, 0xD6, 0xAB, 0xE7, 0xD8, 0xB0, 0xE4,
0xD5, 0xAC, 0xE1, 0xD2, 0xA9, 0xDE, 0xCF, 0xA6,
0xDB, 0xCC, 0xA3, 0xD6, 0xC6, 0x9E, 0xD4, 0xC5,
0x9D, 0xD3, 0xC4, 0x9B, 0xD2, 0xC3, 0x99, 0xD0,
0xC1, 0x98, 0xCF, 0xC1, 0x98, 0xCF, 0xC3, 0x9A,
0xD0, 0xC4, 0x9C, 0xCF, 0xC2, 0x9B, 0xD0, 0xC4,
0x9C, 0xCF, 0xC3, 0x9C, 0xCE, 0xC0, 0x98, 0xD1,
0xC2, 0x99, 0xCF, 0xC0, 0x98, 0xD0, 0xC1, 0x99,
0xD2, 0xC3, 0x9A, 0xD4, 0xC4, 0x9B, 0xD4, 0xC5,
0x9C, 0xD3, 0xC4, 0x9B, 0xD5, 0xC6, 0x9D, 0xD7,
0xC8, 0x9F, 0xD8, 0xC9, 0xA0, 0xD8, 0xC9, 0xA0,
0xD8, 0xC9, 0xA0, 0xD8, 0xC9, 0xA0, 0xD7, 0xC8,
0x9F, 0xD7, 0xC8, 0x9E, 0xD8, 0xC9, 0x9F, 0xD9,
0xCA, 0xA0, 0xD9, 0xC9, 0xA0, 0xD9, 0xC9, 0x9F,
0xD8, 0xC9, 0x9F, 0xD7, 0xC7, 0x9D, 0xB4, 0xA6,
0x7D, 0xC4, 0xB3, 0x88
};
const uint8_t image_9341_driveopen[] PROGMEM = {
0xCF, 0xC1, 0x97, 0xB4, 0xA4, 0x84, 0xAE, 0x9D,
0x7E, 0xAF, 0x9F, 0x7F, 0xB1, 0xA1, 0x81, 0xB1,
0xA1, 0x81, 0xB1, 0xA1, 0x80, 0xB0, 0xA0, 0x7E,
0xB1, 0xA1, 0x7F, 0xB1, 0xA1, 0x7F, 0xB1, 0xA2,
0x80, 0xB2, 0xA3, 0x80, 0xB1, 0xA2, 0x80, 0xB1,
0xA2, 0x80, 0xB1, 0xA2, 0x80, 0xB0, 0xA2, 0x7F,
0xB1, 0xA3, 0x80, 0xB1, 0xA3, 0x81, 0xB3, 0xA3,
0x80, 0xB1, 0xA2, 0x7E, 0xB0, 0xA0, 0x7D, 0xB3,
0xA3, 0x7F, 0xB4, 0xA4, 0x80, 0xB3, 0xA4, 0x7F,
0xB4, 0xA5, 0x7E, 0xB6, 0xA7, 0x81, 0xB7, 0xA8,
0x82, 0xB9, 0xA9, 0x83, 0xB8, 0xA9, 0x83, 0xB7,
0xA8, 0x84, 0xB9, 0xA9, 0x87, 0xBA, 0xAA, 0x88,
0xBB, 0xAB, 0x89, 0xBA, 0xAA, 0x88, 0xBC, 0xAC,
0x8A, 0xBE, 0xAF, 0x88, 0xBE, 0xAF, 0x88, 0xBD,
0xAE, 0x87, 0xBD, 0xAD, 0x87, 0xC0, 0xB1, 0x8A,
0xC5, 0xB6, 0x8D, 0xC7, 0xB8, 0x8C, 0xD9, 0xCA,
0x9F, 0xC5, 0xB5, 0x8F, 0x82, 0x71, 0x59, 0x7B,
0x6B, 0x51, 0x91, 0x81, 0x66, 0x8C, 0x7C, 0x61,
0x8C, 0x7C, 0x60, 0x8C, 0x7B, 0x5F, 0x8E, 0x7C,
0x62, 0x8F, 0x7D, 0x63, 0x8E, 0x7D, 0x62, 0x8E,
0x7D, 0x62, 0x8C, 0x7A, 0x60, 0x89, 0x7B, 0x5F,
0x8A, 0x7C, 0x60, 0x8B, 0x7C, 0x60, 0x8A, 0x7B,
0x5F, 0x8C, 0x7C, 0x61, 0x8B, 0x7A, 0x5F, 0x8A,
0x7A, 0x5F, 0x8B, 0x7B, 0x60, 0x8B, 0x7B, 0x60,
0x8B, 0x7B, 0x60, 0x8B, 0x7B, 0x5F, 0x8A, 0x7A,
0x5E, 0x8B, 0x79, 0x5D, 0x8A, 0x79, 0x5D, 0x8B,
0x7A, 0x5E, 0x8C, 0x7A, 0x5F, 0x8C, 0x7A, 0x5F,
0x8C, 0x7C, 0x60, 0x8C, 0x7D, 0x61, 0x8D, 0x7D,
0x61, 0x8C, 0x7C, 0x61, 0x8E, 0x7E, 0x62, 0x8E,
0x7E, 0x63, 0x8D, 0x7C, 0x5D, 0x8E, 0x7F, 0x5F,
0x8E, 0x7F, 0x5F, 0x8B, 0x7D, 0x5E, 0x7D, 0x6E,
0x54, 0x7E, 0x70, 0x56, 0xAB, 0x9B, 0x78, 0xD9,
0xCA, 0x9F, 0xC6, 0xB6, 0x91, 0x79, 0x69, 0x4B,
0xC2, 0xB2, 0x89, 0xC7, 0xB8, 0x8E, 0xC7, 0xB8,
0x8E, 0xC7, 0xB8, 0x8E, 0xC5, 0xB6, 0x8D, 0xC4,
0xB4, 0x8A, 0xBB, 0xAC, 0x85, 0xBF, 0xB0, 0x8E,
0xC4, 0xB5, 0x93, 0xC4, 0xB6, 0x94, 0xC0, 0xB1,
0x8F, 0xC0, 0xB2, 0x90, 0xBA, 0xAB, 0x89, 0xBC,
0xAC, 0x8A, 0xBA, 0xAB, 0x89, 0xB9, 0xAA, 0x88,
0xBE, 0xAE, 0x8C, 0xBD, 0xAD, 0x8B, 0xB9, 0xA9,
0x85, 0xBC, 0xAC, 0x88, 0xBC, 0xAD, 0x8A, 0xBF,
0xB0, 0x8C, 0xBF, 0xB0, 0x8C, 0xBF, 0xB0, 0x8B,
0xB8, 0xA7, 0x84, 0xB9, 0xA8, 0x86, 0xC0, 0xAE,
0x8C, 0xBC, 0xAA, 0x88, 0xBE, 0xAC, 0x8A, 0xBC,
0xAC, 0x88, 0xBC, 0xAD, 0x88, 0xBB, 0xAC, 0x87,
0xC1, 0xB2, 0x8B, 0xC1, 0xB2, 0x8A, 0xC1, 0xB2,
0x89, 0xC1, 0xB2, 0x89, 0xC0, 0xB1, 0x8B, 0xB9,
0xA9, 0x83, 0x65, 0x56, 0x3B, 0xB2, 0xA2, 0x82,
0xD9, 0xCA, 0x9F, 0xC2, 0xB3, 0x8D, 0x79, 0x69,
0x4A, 0xC5, 0xB5, 0x91, 0xC8, 0xB8, 0x94, 0xC8,
0xB8, 0x94, 0xC7, 0xB7, 0x94, 0xC8, 0xB8, 0x95,
0xBC, 0xAC, 0x88, 0x99, 0x8B, 0x6A, 0xA9, 0x9B,
0x7F, 0xAF, 0xA1, 0x84, 0xA6, 0x98, 0x7B, 0x9D,
0x8F, 0x73, 0xB0, 0xA2, 0x85, 0xA5, 0x96, 0x7A,
0x9B, 0x8B, 0x6F, 0xA1, 0x91, 0x75, 0xA0, 0x91,
0x75, 0x99, 0x89, 0x6D, 0x98, 0x88, 0x6C, 0x99,
0x8A, 0x6B, 0x94, 0x85, 0x67, 0xAA, 0x9B, 0x7D,
0xA0, 0x91, 0x73, 0xAB, 0x9C, 0x7E, 0xA9, 0x99,
0x7B, 0xA1, 0x93, 0x74, 0x9F, 0x91, 0x72, 0xB1,
0xA2, 0x84, 0xA1, 0x93, 0x74, 0x9F, 0x90, 0x72,
0x99, 0x8A, 0x6B, 0x99, 0x89, 0x6A, 0xA0, 0x91,
0x70, 0xC0, 0xB3, 0x8E, 0xC5, 0xB7, 0x92, 0xC1,
0xB3, 0x8C, 0xC1, 0xB3, 0x8C, 0xBF, 0xB0, 0x8B,
0xB5, 0xA7, 0x7F, 0x60, 0x51, 0x37, 0xB2, 0xA2,
0x81, 0xD9, 0xCA, 0x9F, 0xC3, 0xB3, 0x8D, 0x71,
0x63, 0x44, 0xCC, 0xBC, 0x9A, 0xCE, 0xBE, 0x9C,
0xCE, 0xBE, 0x9C, 0xCE, 0xBE, 0x9C, 0xCF, 0xBF,
0x9C, 0xC2, 0xB2, 0x8F, 0xBB, 0xAC, 0x8D, 0xB6,
0xA8, 0x8E, 0xB0, 0xA1, 0x87, 0xA8, 0x99, 0x7F,
0xAB, 0x9D, 0x83, 0xBA, 0xAC, 0x93, 0xAE, 0x9F,
0x84, 0xB0, 0xA0, 0x85, 0xAE, 0x9E, 0x83, 0xB7,
0xA7, 0x8C, 0xAC, 0x9D, 0x82, 0xAE, 0x9F, 0x83,
0xB1, 0xA2, 0x86, 0xAC, 0x9D, 0x81, 0xB9, 0xAA,
0x8D, 0xA9, 0x9A, 0x7D, 0xB2, 0xA3, 0x86, 0xB7,
0xA8, 0x8C, 0xB1, 0xA5, 0x87, 0xA9, 0x9D, 0x7F,
0xB1, 0xA5, 0x87, 0xAC, 0xA0, 0x82, 0xAC, 0xA1,
0x83, 0xA6, 0x98, 0x7B, 0xA3, 0x93, 0x75, 0xB4,
0xA4, 0x86, 0xCD, 0xBE, 0x9E, 0xCF, 0xBF, 0x9F,
0xC8, 0xB8, 0x97, 0xC8, 0xB8, 0x97, 0xC5, 0xB6,
0x92, 0xB4, 0xA6, 0x81, 0x5D, 0x4E, 0x36, 0xB2,
0xA2, 0x80, 0xD9, 0xCA, 0x9F, 0xC0, 0xB1, 0x8A,
0x72, 0x66, 0x49, 0xE4, 0xD3, 0xB3, 0xE5, 0xD5,
0xB4, 0xE5, 0xD5, 0xB4, 0xE6, 0xD6, 0xB5, 0xE7,
0xD7, 0xB6, 0xE6, 0xD6, 0xB5, 0xE6, 0xD6, 0xB8,
0xE4, 0xD4, 0xB8, 0xE2, 0xD2, 0xB7, 0xE0, 0xD0,
0xB6, 0xE3, 0xD3, 0xBA, 0xE4, 0xD4, 0xBD, 0xE0,
0xD1, 0xB5, 0xE2, 0xD3, 0xB6, 0xE2, 0xD3, 0xB6,
0xE1, 0xD2, 0xB5, 0xE1, 0xD2, 0xB5, 0xE1, 0xD2,
0xB5, 0xE0, 0xD1, 0xB4, 0xE0, 0xD1, 0xB4, 0xDF,
0xD0, 0xB3, 0xDF, 0xD0, 0xB3, 0xDB, 0xCC, 0xAF,
0xE1, 0xD2, 0xB6, 0xDC, 0xCF, 0xB3, 0xDC, 0xCF,
0xB3, 0xDC, 0xCF, 0xB3, 0xDE, 0xD1, 0xB5, 0xDB,
0xCF, 0xB3, 0xDF, 0xD0, 0xB3, 0xE3, 0xD2, 0xB3,
0xDE, 0xCD, 0xAF, 0xE0, 0xCF, 0xB1, 0xE5, 0xD3,
0xB6, 0xD4, 0xC3, 0xA6, 0xD4, 0xC3, 0xA6, 0xCA,
0xBC, 0x96, 0xB0, 0xA1, 0x80, 0x5E, 0x4E, 0x36,
0xB4, 0xA5, 0x81, 0xD9, 0xCA, 0x9F, 0xBF, 0xB0,
0x89, 0x7A, 0x6C, 0x50, 0xBA, 0xA8, 0x8C, 0xB9,
0xA8, 0x8B, 0xB9, 0xA8, 0x8B, 0xBB, 0xAA, 0x8D,
0xBC, 0xAB, 0x8F, 0xB9, 0xA8, 0x8B, 0xB8, 0xA8,
0x8B, 0xB7, 0xA8, 0x8B, 0x9B, 0x8C, 0x70, 0x97,
0x87, 0x6D, 0xA9, 0x99, 0x80, 0xA4, 0x94, 0x7B,
0x9C, 0x8D, 0x71, 0x9D, 0x8E, 0x71, 0xB4, 0xA5,
0x88, 0x9B, 0x8C, 0x6F, 0x91, 0x82, 0x65, 0xA6,
0x97, 0x7A, 0xA6, 0x97, 0x7A, 0x9D, 0x8E, 0x71,
0xA9, 0x9A, 0x7D, 0xA9, 0x9A, 0x7D, 0x98, 0x89,
0x6C, 0x96, 0x87, 0x6C, 0x94, 0x86, 0x6D, 0x90,
0x82, 0x68, 0x98, 0x8A, 0x70, 0x93, 0x85, 0x6B,
0xA2, 0x94, 0x7B, 0xB6, 0xA6, 0x88, 0xB6, 0xA6,
0x85, 0xB4, 0xA4, 0x83, 0xB6, 0xA6, 0x85, 0xB6,
0xA6, 0x86, 0xB4, 0xA4, 0x83, 0xB4, 0xA4, 0x83,
0xB6, 0xA8, 0x84, 0xA9, 0x9A, 0x78, 0x5F, 0x4F,
0x36, 0xB4, 0xA6, 0x83, 0xD9, 0xCA, 0x9F, 0xA4,
0x94, 0x70, 0x80, 0x73, 0x55, 0xB1, 0xA0, 0x83,
0xB2, 0xA2, 0x84, 0xB2, 0xA2, 0x84, 0xB3, 0xA2,
0x84, 0xB2, 0xA1, 0x83, 0xB0, 0x9F, 0x83, 0xB1,
0xA1, 0x82, 0xB1, 0xA2, 0x83, 0x99, 0x8A, 0x6D,
0x9E, 0x8F, 0x73, 0x94, 0x84, 0x6A, 0x91, 0x81,
0x67, 0x8F, 0x80, 0x63, 0x95, 0x86, 0x69, 0xA9,
0x9A, 0x7D, 0x93, 0x84, 0x67, 0x8A, 0x7B, 0x5E,
0x9B, 0x8C, 0x6F, 0x9B, 0x8C, 0x6F, 0x8B, 0x7C,
0x5F, 0x9A, 0x8B, 0x6E, 0x9E, 0x8F, 0x72, 0x90,
0x81, 0x64, 0x8C, 0x7D, 0x61, 0x95, 0x86, 0x6C,
0x89, 0x79, 0x5F, 0x8F, 0x7F, 0x65, 0x87, 0x78,
0x5E, 0x97, 0x87, 0x6E, 0xAE, 0x9F, 0x7F, 0xAE,
0x9E, 0x7C, 0xAE, 0x9E, 0x7D, 0xAE, 0x9E, 0x7D,
0xAD, 0x9C, 0x7B, 0xAD, 0x9D, 0x7C, 0xAD, 0x9D,
0x7C, 0xB2, 0xA3, 0x81, 0xA3, 0x94, 0x73, 0x64,
0x55, 0x38, 0xB1, 0xA1, 0x80, 0xD9, 0xCA, 0x9F,
0xA3, 0x94, 0x6D, 0x8A, 0x7E, 0x5C, 0xB2, 0xA2,
0x81, 0xB3, 0xA3, 0x81, 0xB3, 0xA3, 0x81, 0xB1,
0xA1, 0x7F, 0xAF, 0x9F, 0x7D, 0xAE, 0x9D, 0x7C,
0xAB, 0x9C, 0x7C, 0xAA, 0x9B, 0x7C, 0xA7, 0x98,
0x7A, 0xA7, 0x98, 0x7B, 0xA3, 0x94, 0x78, 0xA3,
0x93, 0x79, 0xA2, 0x93, 0x76, 0xA4, 0x95, 0x78,
0xA6, 0x97, 0x7A, 0xA4, 0x95, 0x78, 0xA2, 0x93,
0x76, 0xA4, 0x95, 0x78, 0xA4, 0x95, 0x78, 0xA3,
0x94, 0x77, 0xA4, 0x95, 0x78, 0xA5, 0x96, 0x79,
0xA1, 0x92, 0x75, 0xA4, 0x94, 0x76, 0xA5, 0x95,
0x76, 0xA5, 0x95, 0x76, 0xA2, 0x93, 0x74, 0xA6,
0x97, 0x77, 0xA8, 0x99, 0x7A, 0xA9, 0x99, 0x78,
0xAA, 0x9A, 0x78, 0xAB, 0x9B, 0x79, 0xAB, 0x9B,
0x79, 0xAC, 0x9C, 0x7A, 0xAB, 0x9B, 0x79, 0xAB,
0x9B, 0x79, 0xAE, 0x9F, 0x7F, 0x99, 0x8A, 0x6B,
0x69, 0x5A, 0x3B, 0xA5, 0x97, 0x6C, 0xA5, 0x97,
0x6C, 0xC7, 0xB8, 0x90, 0x54, 0x4E, 0x3E, 0x54,
0x4E, 0x3E, 0x55, 0x4F, 0x3E, 0x54, 0x4E, 0x3E,
0x54, 0x4E, 0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F,
0x3E, 0x54, 0x4E, 0x3E, 0x55, 0x4F, 0x3E, 0x55,
0x4F, 0x3E, 0x54, 0x4E, 0x3E, 0x54, 0x4E, 0x3E,
0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F,
0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x54,
0x4E, 0x3E, 0x55, 0x4F, 0x3E, 0x54, 0x4E, 0x3E,
0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F,
0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x55,
0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x54, 0x4E, 0x3E,
0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x54, 0x4E,
0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x55,
0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x54, 0x4E, 0x3E,
0x55, 0x4F, 0x3E, 0x55, 0x4F, 0x3E, 0x55, 0x4F,
0x3E, 0x54, 0x4E, 0x3E, 0xA4, 0x94, 0x6F, 0xD9,
0xCB, 0x9B, 0xD3, 0xC4, 0x9B, 0x64, 0x5D, 0x4A,
0x64, 0x5D, 0x4A, 0x65, 0x5E, 0x4A, 0x64, 0x5D,
0x4A, 0x64, 0x5D, 0x4A, 0x65, 0x5E, 0x4A, 0x64,
0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A,
0x64, 0x5D, 0x4A, 0x65, 0x5E, 0x4A, 0x64, 0x5D,
0x4A, 0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x64,
0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A,
0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x65, 0x5E,
0x4A, 0x65, 0x5E, 0x4A, 0x64, 0x5D, 0x4A, 0x64,
0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x65, 0x5E, 0x4A,
0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x64, 0x5D,
0x4A, 0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x65,
0x5E, 0x4A, 0x64, 0x5D, 0x4A, 0x65, 0x5E, 0x4A,
0x64, 0x5D, 0x4A, 0x64, 0x5D, 0x4A, 0x64, 0x5D,
0x4A, 0x65, 0x5E, 0x4A, 0x64, 0x5D, 0x4A, 0x65,
0x5E, 0x4A, 0x64, 0x5D, 0x4A, 0xA4, 0x94, 0x6F,
0xEE, 0xDF, 0xB4, 0xD0, 0xC1, 0x96, 0xC7, 0xB9,
0x92, 0xC7, 0xB9, 0x92, 0xC6, 0xB9, 0x91, 0xC6,
0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xC7, 0xB9, 0x92,
0xC7, 0xB9, 0x92, 0xC6, 0xB9, 0x91, 0xC6, 0xB9,
0x91, 0xC6, 0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xC6,
0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xC6, 0xB9, 0x91,
0xC6, 0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xC6, 0xB9,
0x91, 0xC6, 0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xC6,
0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xC7, 0xB9, 0x92,
0xC6, 0xB9, 0x91, 0xC7, 0xB9, 0x92, 0xC6, 0xB9,
0x91, 0xC6, 0xB9, 0x91, 0xC7, 0xB9, 0x92, 0xC7,
0xB9, 0x92, 0xC7, 0xB9, 0x92, 0xC7, 0xB9, 0x92,
0xC6, 0xB9, 0x91, 0xC7, 0xB9, 0x92, 0xC6, 0xB9,
0x91, 0xC7, 0xB9, 0x92, 0xC7, 0xB9, 0x92, 0xC6,
0xB9, 0x91, 0xC7, 0xB9, 0x92, 0xC7, 0xB9, 0x92,
0xC6, 0xB9, 0x91, 0xC6, 0xB9, 0x91, 0xA4, 0x94,
0x6F, 0xEE, 0xDF, 0xB4, 0xC2, 0xB2, 0x8A, 0xCD,
0xBF, 0x96, 0xCC, 0xBE, 0x96, 0xCD, 0xBF, 0x96,
0xCD, 0xBF, 0x96, 0xCC, 0xBE, 0x96, 0xCC, 0xBE,
0x96, 0xCC, 0xBE, 0x96, 0xCC, 0xBE, 0x96, 0xCC,
0xBE, 0x96, 0xCD, 0xBF, 0x96, 0xCC, 0xBE, 0x96,
0xCD, 0xBF, 0x96, 0xCD, 0xBF, 0x96, 0xCC, 0xBE,
0x96, 0xCC, 0xBE, 0x96, 0xCD, 0xBF, 0x96, 0xCD,
0xBF, 0x96, 0xCD, 0xBF, 0x96, 0xCD, 0xBF, 0x96,
0xCC, 0xBE, 0x96, 0xCC, 0xBE, 0x96, 0xCD, 0xBF,
0x96, 0xCD, 0xBF, 0x96, 0xCC, 0xBE, 0x96, 0xCC,
0xBE, 0x96, 0xCC, 0xBE, 0x96, 0xCD, 0xBF, 0x96,
0xCD, 0xBF, 0x96, 0xCD, 0xBF, 0x96, 0xCC, 0xBE,
0x96, 0xCC, 0xBE, 0x96, 0xCC, 0xBE, 0x96, 0xCC,
0xBE, 0x96, 0xCC, 0xBE, 0x96, 0xCC, 0xBE, 0x96,
0xCD, 0xBF, 0x96, 0xCD, 0xBF, 0x96, 0xCC, 0xBE,
0x96, 0xCD, 0xBF, 0x96, 0xCD, 0xBF, 0x96, 0x98,
0x89, 0x63, 0xEE, 0xDF, 0xB4, 0xAE, 0x9F, 0x79,
0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3,
0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1,
0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99,
0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3,
0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1,
0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99,
0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3,
0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1,
0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99,
0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3,
0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1,
0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99,
0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3,
0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1,
0xC3, 0x99, 0xD1, 0xC3, 0x99, 0xD1, 0xC3, 0x99,
0x9A, 0x8B, 0x64, 0xEE, 0xDF, 0xB4, 0xAC, 0x9D,
0x77, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5,
0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C,
0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6,
0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5,
0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C,
0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6,
0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5,
0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C,
0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6,
0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5,
0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C,
0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6,
0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5,
0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C,
0xD5, 0xC6, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5, 0xC6,
0x9C, 0xA2, 0x92, 0x6D, 0xD9, 0xCA, 0x9F, 0xAF,
0x9F, 0x78, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7,
0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7,
0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7,
0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7,
0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7,
0xC8, 0x9E, 0xA5, 0x95, 0x72, 0xD9, 0xCA, 0x9F,
0xAE, 0x9E, 0x78, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xA6, 0x95, 0x74, 0xD9, 0xCA,
0x9F, 0xAE, 0x9E, 0x79, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xDA, 0xCB, 0xA0, 0xD9, 0xCA, 0xA0,
0xD9, 0xCA, 0x9F, 0xD8, 0xC9, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9D, 0xD6, 0xC7, 0x9D, 0xD6,
0xC7, 0x9C, 0xD6, 0xC7, 0x9C, 0xD6, 0xC7, 0x9C,
0xD6, 0xC7, 0x9C, 0xD6, 0xC7, 0x9C, 0xD5, 0xC7,
0x9C, 0xD5, 0xC7, 0x9C, 0xD5, 0xC6, 0x9C, 0xD5,
0xC6, 0x9C, 0xD5, 0xC7, 0x9C, 0xD6, 0xC6, 0x9C,
0xD5, 0xC6, 0x9C, 0xD6, 0xC7, 0x9C, 0xD6, 0xC7,
0x9C, 0xD6, 0xC7, 0x9C, 0xD6, 0xC7, 0x9C, 0xD6,
0xC7, 0x9C, 0xD6, 0xC7, 0x9D, 0xD7, 0xC8, 0x9D,
0xD7, 0xC8, 0x9D, 0xD7, 0xC8, 0x9D, 0xD7, 0xC8,
0x9D, 0xD7, 0xC8, 0x9D, 0xD7, 0xC8, 0x9D, 0xD7,
0xC8, 0x9D, 0xD7, 0xC8, 0x9D, 0xD7, 0xC8, 0x9D,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9D, 0xD7, 0xC8,
0x9D, 0xD6, 0xC7, 0x9C, 0xA0, 0x90, 0x6F, 0xD9,
0xCA, 0x9F, 0xB8, 0xA8, 0x7E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9F, 0xD9, 0xCA, 0xA0, 0xD9, 0xCA,
0x9F, 0xD9, 0xCA, 0x9F, 0xD8, 0xC9, 0x9F, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC9, 0x9E, 0xD7,
0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E,
0xD7, 0xC8, 0x9E, 0xD7, 0xC8, 0x9E, 0xD7, 0xC8,
0x9E, 0xD8, 0xC9, 0x9E, 0xD7, 0xC8, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E,
0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9,
0x9E, 0xD8, 0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0xD8,
0xC9, 0x9E, 0xD8, 0xC9, 0x9E, 0x9D, 0x8F, 0x6A,
0xD9, 0xCA, 0x9F, 0xC9, 0xBA, 0x8F, 0xE0, 0xD1,
0xA6, 0xE5, 0xD6, 0xAB, 0xE7, 0xD8, 0xB0, 0xE4,
0xD5, 0xAC, 0xE1, 0xD2, 0xA9, 0xDE, 0xCF, 0xA6,
0xDB, 0xCC, 0xA3, 0xD6, 0xC6, 0x9E, 0xD4, 0xC5,
0x9D, 0xD3, 0xC4, 0x9B, 0xD2, 0xC3, 0x99, 0xD0,
0xC1, 0x98, 0xCF, 0xC1, 0x98, 0xCF, 0xC3, 0x9A,
0xD0, 0xC4, 0x9C, 0xCF, 0xC2, 0x9B, 0xD0, 0xC4,
0x9C, 0xCF, 0xC3, 0x9C, 0xCE, 0xC0, 0x98, 0xD1,
0xC2, 0x99, 0xCF, 0xC0, 0x98, 0xD0, 0xC1, 0x99,
0xD2, 0xC3, 0x9A, 0xD4, 0xC4, 0x9B, 0xCF, 0xC3,
0x9C, 0xCE, 0xC0, 0x98, 0xD1, 0xC2, 0x99, 0xCF,
0xC0, 0x98, 0xD0, 0xC1, 0x99, 0xD2, 0xC3, 0x9A,
0xD4, 0xC4, 0x9B, 0xD4, 0xC5, 0x9C, 0xD3, 0xC4,
0x9B, 0xD5, 0xC6, 0x9D, 0xD7, 0xC8, 0x9F, 0xD8,
0xC9, 0xA0, 0xD8, 0xC9, 0xA0, 0xD8, 0xC9, 0xA0,
0xD8, 0xC9, 0xA0, 0xD7, 0xC8, 0x9F, 0xB4, 0xA6,
0x7D, 0xD9, 0xCA, 0x9F
};

View File

@ -19,41 +19,64 @@
#include "image-8875-bg.h"
#include "image-8875-apple.h"
#include "image-8875-drivelatches.h"
#include "image-9341-bg.h"
#include "image-9341-drivelatches.h"
#include "image-9341-applebitmap.h"
const bool getImageInfoAndData(uint8_t imgnum, uint16_t *width, uint16_t *height, const uint8_t **dataptr)
bool getImageInfoAndData(uint8_t imgnum, uint16_t *width, uint16_t *height, uint8_t **dataptr)
{
switch (imgnum) {
case IMG_SHELL:
case IMG_8875_SHELL:
*width = 800;
*height = 480;
*dataptr = image_8875_bg;
*dataptr = (uint8_t *)image_8875_bg;
break;
case IMG_D1OPEN:
case IMG_8875_D1OPEN:
*width = 62;
*height = 11;
*dataptr = image_d1_open;
*dataptr = (uint8_t *)image_d1_open;
break;
case IMG_D1CLOSED:
case IMG_8875_D1CLOSED:
*width = 62;
*height = 11;
*dataptr = image_d1_closed;
*dataptr = (uint8_t *)image_d1_closed;
break;
case IMG_D2OPEN:
case IMG_8875_D2OPEN:
*width = 62;
*height = 11;
*dataptr = image_d2_open;
*dataptr = (uint8_t *)image_d2_open;
break;
case IMG_D2CLOSED:
case IMG_8875_D2CLOSED:
*width = 62;
*height = 11;
*dataptr = image_d2_closed;
*dataptr = (uint8_t *)image_d2_closed;
break;
case IMG_APPLEBATTERY:
case IMG_8875_APPLEBATTERY:
// FIXME
return false;
break;
case IMG_9341_SHELL:
*width = 320;
*height = 240;
*dataptr = (uint8_t *)img_9341_bg;
break;
case IMG_9341_D1OPEN: // d2 is the same constant
*width = 43;
*height = 20;
*dataptr = (uint8_t *)image_9341_driveopen;
break;
case IMG_9341_D1CLOSED: // d2 is the same constant
*width = 43;
*height = 20;
*dataptr = (uint8_t *)image_9341_driveclosed;
break;
case IMG_9341_APPLEBATTERY:
// FIXME
return false;
break;
default:
// Don't know what this one is...
return false;

View File

@ -7,16 +7,10 @@
#include <stdint.h>
#endif
#define DBITMAP_HEIGHT 480
#define DBITMAP_WIDTH 800
#define LATCH_HEIGHT 11
#define LATCH_WIDTH 62
#define LATCH_X 4
#define LATCH1_Y 67
#define LATCH2_Y 116
#define SCREENINSET_X (121)
#define SCREENINSET_Y (47)
#define SCREENINSET_8875_X (121)
#define SCREENINSET_8875_Y (47)
#define SCREENINSET_9341_X (18)
#define SCREENINSET_9341_Y (13)
// Spacing and positioning of elements within the DBITMAP, used by AppleUI
#define LED_HEIGHT 9
@ -25,6 +19,8 @@
#define LED1_Y 68
#define LED2_Y 117
// These are the ABSTRACTED constants that AppleUI uses to tell the
// display what it wants redrawn via drawUIImage(uint8_t imageIdx)
enum {
IMG_SHELL = 0, // previously displayBitmap
IMG_D1OPEN = 1,
@ -34,6 +30,23 @@ enum {
IMG_APPLEBATTERY = 5
};
const bool getImageInfoAndData(uint8_t imgnum, uint16_t *width, uint16_t *height, const uint8_t **dataptr);
// These are the DISPLAY-SPECIFIC constants that are used to retrieve
// a specific image from storage from within drawUIImage itself
enum {
IMG_8875_SHELL = 0,
IMG_8875_D1OPEN = 1,
IMG_8875_D1CLOSED = 2,
IMG_8875_D2OPEN = 3,
IMG_8875_D2CLOSED = 4,
IMG_8875_APPLEBATTERY = 5,
IMG_9341_SHELL = 6,
IMG_9341_D1OPEN = 7,
IMG_9341_D1CLOSED = 8,
IMG_9341_D2OPEN = 7, // repeat of d1; they're the same image
IMG_9341_D2CLOSED = 8,
IMG_9341_APPLEBATTERY = 9
};
bool getImageInfoAndData(uint8_t imgnum, uint16_t *width, uint16_t *height, uint8_t **dataptr);
#endif

View File

@ -15,6 +15,8 @@ class PhysicalDisplay {
virtual void blit() = 0; // blit everything to the display (including UI area)
virtual void blit(AiieRect r) = 0; // blit a piece of the VM area to the display
virtual void drawUIImage(uint8_t imageIdx) = 0;
// FIXME: drawImageOfSizeAt should probably be private now
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint16_t sizey, uint16_t wherex, uint16_t wherey) = 0;
virtual void drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c) = 0;

View File

@ -15,6 +15,8 @@ extern const unsigned char lcase_glyphs[256];
extern const unsigned char mousetext_glyphs[256];
extern const unsigned char interface_glyphs[256];
#include "images.h"
// RGB map of each of the lowres colors
const uint8_t loresPixelColors[16][3] = { { 0, 0, 0 }, // black
{ 0xAC, 0x12, 0x4C }, // magenta
@ -49,6 +51,18 @@ SDLDisplay::SDLDisplay()
{
memset(videoBuffer, 0, sizeof(videoBuffer));
shellImage = NULL;
d1OpenImage = d1ClosedImage = d2OpenImage = d2ClosedImage = NULL;
appleImage = NULL;
// Load the 9341 images
getImageInfoAndData(IMG_8875_SHELL, &shellWidth, &shellHeight, &shellImage);
getImageInfoAndData(IMG_8875_D1OPEN, &driveWidth, &driveHeight, &d1OpenImage);
getImageInfoAndData(IMG_8875_D1CLOSED, &driveWidth, &driveHeight, &d1ClosedImage);
getImageInfoAndData(IMG_8875_D2OPEN, &driveWidth, &driveHeight, &d2OpenImage);
getImageInfoAndData(IMG_8875_D2CLOSED, &driveWidth, &driveHeight, &d2ClosedImage);
getImageInfoAndData(IMG_8875_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
// FIXME: abstract constants
screen = SDL_CreateWindow("Aiie!",
SDL_WINDOWPOS_UNDEFINED,
@ -94,6 +108,30 @@ void SDLDisplay::redraw()
}
}
void SDLDisplay::drawUIImage(uint8_t imageIdx)
{
switch (imageIdx) {
case IMG_SHELL:
drawImageOfSizeAt(shellImage, shellWidth, shellHeight, 0, 0);
break;
case IMG_D1OPEN:
drawImageOfSizeAt(d1OpenImage, driveWidth, driveHeight, 4, 67);
break;
case IMG_D1CLOSED:
drawImageOfSizeAt(d1ClosedImage, driveWidth, driveHeight, 4, 67);
break;
case IMG_D2OPEN:
drawImageOfSizeAt(d2OpenImage, driveWidth, driveHeight, 4, 116);
break;
case IMG_D2CLOSED:
drawImageOfSizeAt(d2ClosedImage, driveWidth, driveHeight, 4, 116);
break;
case IMG_APPLEBATTERY:
// FIXME ***
break;
}
}
void SDLDisplay::drawImageOfSizeAt(const uint8_t *img,
uint16_t sizex, uint16_t sizey,
uint16_t wherex, uint16_t wherey)
@ -249,7 +287,7 @@ void SDLDisplay::clrScr(uint8_t coloridx)
void SDLDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
{
for (int yoff=0; yoff<2; yoff++) {
videoBuffer[(y*2)+SCREENINSET_Y+yoff][x+SCREENINSET_X] = packColor32(loresPixelColors[color]);
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][x+SCREENINSET_8875_X] = packColor32(loresPixelColors[color]);
}
}
@ -258,7 +296,7 @@ void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
{
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
videoBuffer[(y*2)+SCREENINSET_Y+yoff][(x*2)+SCREENINSET_X+xoff] = packColor32(loresPixelColors[color]);
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x*2)+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[color]);
}
}
}
@ -267,7 +305,7 @@ void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedCol
{
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
videoBuffer[(y*2)+SCREENINSET_Y+yoff][(x*2)+SCREENINSET_X+xoff] = packedColor;
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x*2)+SCREENINSET_8875_X+xoff] = packedColor;
}
}
}
@ -276,8 +314,8 @@ void SDLDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorB,
{
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
videoBuffer[(y*2)+SCREENINSET_Y+yoff][(x*2)+SCREENINSET_X+xoff] = packColor32(loresPixelColors[colorA]);
videoBuffer[(y*2)+SCREENINSET_Y+yoff][(x+1)*2+SCREENINSET_X+xoff] = packColor32(loresPixelColors[colorB]);
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x*2)+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[colorA]);
videoBuffer[(y*2)+SCREENINSET_8875_Y+yoff][(x+1)*2+SCREENINSET_8875_X+xoff] = packColor32(loresPixelColors[colorB]);
}
}
}

View File

@ -22,6 +22,7 @@ class SDLDisplay : public PhysicalDisplay {
virtual void flush();
virtual void drawUIImage(uint8_t imageIdx);
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint16_t sizey, uint16_t wherex, uint16_t wherey);
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color);
@ -46,6 +47,18 @@ class SDLDisplay : public PhysicalDisplay {
SDL_Window *screen;
SDL_Renderer *renderer;
SDL_Texture *buffer;
uint8_t *shellImage;
uint16_t shellWidth, shellHeight;
uint8_t *d1OpenImage;
uint16_t driveWidth, driveHeight; // assume all the latches are the
// same width/height no matter
// what position
uint8_t *d1ClosedImage;
uint8_t *d2OpenImage;
uint8_t *d2ClosedImage;
uint8_t *appleImage;
uint16_t appleImageWidth, appleImageHeight;
};
#endif

59
teensy/ILI9341_wrap.cpp Normal file
View File

@ -0,0 +1,59 @@
#include "ILI9341_wrap.h"
ILI9341_Wrap::ILI9341_Wrap(const uint8_t cs_pin, const uint8_t rst_pin, const uint8_t mosi_pin, const uint8_t sck_pin, const uint8_t miso_pin, const uint8_t dc_pin) : BaseDisplay(cs_pin, rst_pin, mosi_pin, sck_pin, miso_pin, dc_pin)
{
tft = NULL;
_cs = cs_pin;
_dc = dc_pin;
_rst = rst_pin;
_mosi = mosi_pin;
_sck = sck_pin;
_miso = miso_pin;
}
ILI9341_Wrap::~ILI9341_Wrap()
{
if (tft)
delete tft;
}
void ILI9341_Wrap::begin(uint32_t spi_clock=30000000u, uint32_t spi_clock_read=2000000)
{
if (!tft) {
tft = new ILI9341_t3n(_cs, _dc, _rst, _mosi, _sck, _miso);
tft->begin(spi_clock, spi_clock_read);
tft->setRotation(3);
}
}
void ILI9341_Wrap::fillWindow(uint16_t color = 0x0000)
{
}
void ILI9341_Wrap::setFrameBuffer(uint8_t *frame_buffer)
{
tft->setFrameBuffer((uint16_t *)frame_buffer);
tft->useFrameBuffer(true);
tft->fillScreen(ILI9341_BLACK);
}
bool ILI9341_Wrap::asyncUpdateActive()
{
return tft->asyncUpdateActive();
}
bool ILI9341_Wrap::updateScreenAsync(bool update_cont)
{
return tft->updateScreenAsync(update_cont);
}
void ILI9341_Wrap::drawPixel(int16_t x, int16_t y, uint16_t color)
{
tft->drawPixel(x, y, color);
}
uint32_t ILI9341_Wrap::frameCount()
{
return tft->frameCount();
}

38
teensy/ILI9341_wrap.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef __ILI9341_WRAP_H
#define __ILI9341_WRAP_H
#include <Arduino.h>
#include <SPI.h>
#include <DMAChannel.h>
#include <stdint.h>
#include <ILI9341_t3n.h>
#include "basedisplay.h"
#define ILI9341_WIDTH 320
#define ILI9341_HEIGHT 240
class ILI9341_Wrap : public BaseDisplay {
public:
ILI9341_Wrap(uint8_t cs_pin, uint8_t rst_pin, uint8_t mosi_pin, uint8_t sck_pin, uint8_t miso_pin, uint8_t dc_pin);
~ILI9341_Wrap();
virtual void begin(uint32_t spi_clock=30000000u, uint32_t spi_clock_read=2000000);
virtual void fillWindow(uint16_t color = 0x0000);
virtual void setFrameBuffer(uint8_t *frame_buffer);
virtual bool asyncUpdateActive();
virtual bool updateScreenAsync(bool update_cont = false);
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual uint32_t frameCount();
private:
ILI9341_t3n *tft;
uint8_t _cs, _dc, _rst, _mosi, _sck, _miso;
};
#endif

View File

@ -98,7 +98,7 @@
// application, so this can be pared down.
static RA8875_t4 *_dmaActiveDisplay = NULL;
RA8875_t4::RA8875_t4(const uint8_t cs_pin, const uint8_t rst_pin, const uint8_t mosi_pin, const uint8_t sck_pin, const uint8_t miso_pin)
RA8875_t4::RA8875_t4(uint8_t cs_pin, uint8_t rst_pin, uint8_t mosi_pin, uint8_t sck_pin, uint8_t miso_pin, uint8_t dc_pin) : BaseDisplay(cs_pin, rst_pin, mosi_pin, sck_pin, miso_pin, dc_pin)
{
_mosi = mosi_pin;
_miso = miso_pin;

View File

@ -6,6 +6,8 @@
#include <DMAChannel.h>
#include <stdint.h>
#include "basedisplay.h"
#define RA8875_WIDTH 800
#define RA8875_HEIGHT 480
@ -19,22 +21,23 @@ enum {
RA8875_DMA_ACTIVE=0x80
};
class RA8875_t4 {
class RA8875_t4 : public BaseDisplay {
public:
RA8875_t4(const uint8_t cs_pin, const uint8_t rst_pin, const uint8_t mosi_pin, const uint8_t sck_pin, const uint8_t miso_pin);
RA8875_t4(uint8_t cs_pin, uint8_t rst_pin, uint8_t mosi_pin, uint8_t sck_pin, uint8_t miso_pin, uint8_t dc_pin); // dc pin is unused for this display but it's needed for the ILI and base class.
~RA8875_t4();
void begin(uint32_t spi_clock=30000000u, uint32_t spi_clock_read=2000000);
virtual void begin(uint32_t spi_clock=30000000u, uint32_t spi_clock_read=2000000);
void fillWindow(uint16_t color = 0x0000);
virtual void fillWindow(uint16_t color = 0x0000);
void setFrameBuffer(uint8_t *frame_buffer);
virtual void setFrameBuffer(uint8_t *frame_buffer);
bool asyncUpdateActive();
bool updateScreenAsync(bool update_cont = false);
virtual bool asyncUpdateActive();
virtual bool updateScreenAsync(bool update_cont = false);
void drawPixel(int16_t x, int16_t y, uint16_t color);
uint32_t frameCount();
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual uint32_t frameCount();
uint8_t color16To8bpp(uint16_t color) __attribute__((always_inline)) {
return ((color & 0xe000) >> 8) | ((color & 0x700) >> 6) | ((color & 0x18) >> 3);

View File

@ -0,0 +1 @@
../image-9341-applebitmap.h

1
teensy/image-9341-bg.h Symbolic link
View File

@ -0,0 +1 @@
../image-9341-bg.h

View File

@ -0,0 +1 @@
../image-9341-drivelatches.h

View File

@ -15,13 +15,19 @@ extern const unsigned char interface_glyphs[256];
#include "globals.h"
#include "applevm.h"
#include "RA8875_t4.h"
#include "ILI9341_wrap.h"
#include "images.h"
#ifndef RA8875_HEIGHT
#define RA8875_HEIGHT 480
#endif
DMAMEM uint8_t dmaBuffer[RA8875_HEIGHT][RA8875_WIDTH] __attribute__((aligned(32)));
// We have two handles to the DMA buffer - the actual data
// (dmaBuffer), which is the larger of the two sizes at 800*480 bytes
// (=38400); or dmaBuffer16, which is the same pointer for (320*240 =
// 76800) 16-bit words (using 153600 bytes of RAM). Since the 800*480
// is larger we'll construct a buffer using that value and then use it
// either as dmaBuffer or dmaBuffer16.
DMAMEM uint8_t dmaBuffer[RA8875_HEIGHT * RA8875_WIDTH] __attribute__((aligned(32)));
uint16_t *dmaBuffer16 = NULL; // At runtime, this points to dmaBuffer.
#include <SPI.h>
// 30MHz: solid performance, 9 FPS
@ -64,16 +70,55 @@ const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
#define luminanceFromRGB(r,g,b) ( ((r)*0.2126) + ((g)*0.7152) + ((b)*0.0722) )
#define _565To332(c) ((((c) & 0xe000) >> 8) | (((c) & 0x700) >> 6) | (((c) & 0x18) >> 3))
RA8875_t4 tft = RA8875_t4(PIN_CS, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
#define blendColors(a,b) RGBto565( (_565toR(a) + _565toR(b))/2, (_565toG(a) + _565toG(b))/2, (_565toB(a) + _565toB(b))/2 )
BaseDisplay *tft = NULL;
TeensyDisplay::TeensyDisplay()
{
dmaBuffer16 = (uint16_t *)dmaBuffer;
driveIndicator[0] = driveIndicator[1] = false;
driveIndicatorDirty = true;
tft.begin(_clock);
tft.setFrameBuffer((uint8_t *)dmaBuffer);
tft.fillWindow();
shellImage = NULL;
d1OpenImage = d1ClosedImage = d2OpenImage = d2ClosedImage = NULL;
appleImage = NULL;
// FIXME abstract pin number, don't hard code it
pinMode(11, INPUT);
digitalWrite(11, HIGH); // turn on pull-up
if (digitalRead(11)) {
// Default: use older, small ILI display if pin 11 is not connected to ground
tft = new ILI9341_Wrap(PIN_CS, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO, PIN_DC);
use8875 = false;
// Load the 9341 images
getImageInfoAndData(IMG_9341_SHELL, &shellWidth, &shellHeight, &shellImage);
getImageInfoAndData(IMG_9341_D1OPEN, &driveWidth, &driveHeight, &d1OpenImage);
getImageInfoAndData(IMG_9341_D1CLOSED, &driveWidth, &driveHeight, &d1ClosedImage);
getImageInfoAndData(IMG_9341_D2OPEN, &driveWidth, &driveHeight, &d2OpenImage);
getImageInfoAndData(IMG_9341_D2CLOSED, &driveWidth, &driveHeight, &d2ClosedImage);
getImageInfoAndData(IMG_9341_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
} else {
// If someone grounded pin 11, then use the new RA8875 display
tft = new RA8875_t4(PIN_CS, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO, 255);
use8875 = true;
// Load the 8875 images
getImageInfoAndData(IMG_8875_SHELL, &shellWidth, &shellHeight, &shellImage);
getImageInfoAndData(IMG_8875_D1OPEN, &driveWidth, &driveHeight, &d1OpenImage);
getImageInfoAndData(IMG_8875_D1CLOSED, &driveWidth, &driveHeight, &d1ClosedImage);
getImageInfoAndData(IMG_8875_D2OPEN, &driveWidth, &driveHeight, &d2OpenImage);
getImageInfoAndData(IMG_8875_D2CLOSED, &driveWidth, &driveHeight, &d2ClosedImage);
getImageInfoAndData(IMG_8875_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
}
tft->begin(_clock);
tft->setFrameBuffer((uint8_t *)dmaBuffer);
tft->fillWindow();
}
TeensyDisplay::~TeensyDisplay()
@ -96,6 +141,35 @@ void TeensyDisplay::redraw()
}
}
// Take one of the abstracted image constants, figure out which one it
// is based on the current display, and display it via
// drawImageOfSizeAt.
void TeensyDisplay::drawUIImage(uint8_t imageIdx)
{
switch (imageIdx) {
case IMG_SHELL:
drawImageOfSizeAt(shellImage, shellWidth, shellHeight, 0, 0);
break;
case IMG_D1OPEN:
drawImageOfSizeAt(d1OpenImage, driveWidth, driveHeight, 55, 216);
break;
case IMG_D1CLOSED:
drawImageOfSizeAt(d1ClosedImage, driveWidth, driveHeight, 55, 216);
break;
case IMG_D2OPEN:
drawImageOfSizeAt(d2OpenImage, driveWidth, driveHeight, 189, 216);
break;
case IMG_D2CLOSED:
drawImageOfSizeAt(d2ClosedImage, driveWidth, driveHeight, 189, 216);
break;
case IMG_APPLEBATTERY:
// FIXME ***
break;
}
}
// *** this probably needs to be private now FIXME
void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
uint16_t sizex, uint16_t sizey,
uint16_t wherex, uint16_t wherey)
@ -107,7 +181,11 @@ void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
r = pgm_read_byte(&img[(y*sizex + x)*3 + 0]);
g = pgm_read_byte(&img[(y*sizex + x)*3 + 1]);
b = pgm_read_byte(&img[(y*sizex + x)*3 + 2]);
dmaBuffer[y+wherey][x+wherex] = RGBto332(r,g,b);
if (use8875) {
dmaBuffer[(y+wherey)*RA8875_WIDTH + x+wherex] = RGBto332(r,g,b);
} else {
dmaBuffer16[(y+wherey)*ILI9341_WIDTH + x+wherex] = RGBto565(r,g,b);
}
}
}
}
@ -115,8 +193,8 @@ void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
void TeensyDisplay::blit()
{
// Start updates, if they're not running already
if (!tft.asyncUpdateActive())
tft.updateScreenAsync(true);
if (!tft->asyncUpdateActive())
tft->updateScreenAsync(true);
static uint32_t ctr = 0;
@ -139,14 +217,24 @@ void TeensyDisplay::blit(AiieRect r)
// FIXME do we still need 2 different methods for drawing pixels
void TeensyDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color)
{
if (x < RA8875_WIDTH && y < RA8875_HEIGHT)
dmaBuffer[y][x] = _565To332(color);
if (use8875) {
if (x < RA8875_WIDTH && y < RA8875_HEIGHT)
dmaBuffer[y*RA8875_WIDTH+x] = _565To332(color);
} else {
if (x < ILI9341_WIDTH && y < ILI9341_HEIGHT)
dmaBuffer16[y*ILI9341_WIDTH+x] = color;
}
}
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
{
if (x < RA8875_WIDTH && y < RA8875_HEIGHT)
dmaBuffer[y][x] = _565To332(color);
if (use8875) {
if (x < RA8875_WIDTH && y < RA8875_HEIGHT)
dmaBuffer[y*RA8875_WIDTH+x] = _565To332(color);
} else {
if (x < ILI9341_WIDTH && y < ILI9341_HEIGHT)
dmaBuffer16[y*ILI9341_WIDTH+x] = color;
}
}
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
@ -189,14 +277,22 @@ void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
const unsigned char *ch = asciiToAppleGlyph(c);
for (int8_t y_off = 0; y_off <= ysize; y_off++) {
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
for (int8_t ys=0; ys<2; ys++) {
for (int8_t xs=0; xs<2; xs++) {
if (*ch & (1 << (x_off))) {
drawUIPixel((x + x_off)*2+xs, (y + y_off)*2+ys, onPixel);
} else {
drawUIPixel((x + x_off)*2+xs, (y + y_off)*2+ys, offPixel);
if (use8875) {
for (int8_t ys=0; ys<2; ys++) {
for (int8_t xs=0; xs<2; xs++) {
if (*ch & (1 << (x_off))) {
drawUIPixel((x + x_off)*2+xs, (y + y_off)*2+ys, onPixel);
} else {
drawUIPixel((x + x_off)*2+xs, (y + y_off)*2+ys, offPixel);
}
}
}
} else {
if (*ch & (1 << (x_off))) {
drawUIPixel((x + x_off), (y + y_off), onPixel);
} else {
drawUIPixel((x + x_off), (y + y_off), offPixel);
}
}
}
ch++;
@ -216,27 +312,87 @@ void TeensyDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char
void TeensyDisplay::clrScr(uint8_t coloridx)
{
uint8_t c = _565To332(loresPixelColors[coloridx]);
for (uint16_t y=0; y<RA8875_HEIGHT; y++) {
for (uint16_t x=0; x<RA8875_WIDTH; x++) {
dmaBuffer[y][x] = c;
uint16_t color16 = loresPixelColors[c_black];
if (use8875) {
uint8_t c = _565To332(color16);
for (uint16_t y=0; y<RA8875_HEIGHT; y++) {
for (uint16_t x=0; x<RA8875_WIDTH; x++) {
// This could be faster - make one line, then memcpy the line to
// the other lines? Or just use memset since it's 8bpp
dmaBuffer[y*RA8875_WIDTH+x] = c;
}
}
} else {
if (coloridx == c_black) {
memset(dmaBuffer16, 0x00, ILI9341_HEIGHT * ILI9341_WIDTH * 2);
} else if (coloridx == c_white) {
memset(dmaBuffer16, 0xFF, ILI9341_HEIGHT * ILI9341_WIDTH * 2);
} else {
if (coloridx < 16)
color16 = loresPixelColors[coloridx];
// This could be faster - make one line, then memcpy the line to
// the other lines?
for (uint16_t y=0; y<ILI9341_HEIGHT; y++) {
for (uint16_t x=0; x<ILI9341_WIDTH; x++) {
dmaBuffer16[y*ILI9341_WIDTH+x] = color16;
}
}
}
}
}
void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
{
for (int yoff=0; yoff<2; yoff++) {
dmaBuffer[(y*2)+SCREENINSET_Y+yoff][x+SCREENINSET_X] = _565To332(loresPixelColors[color]);
if (use8875) {
// The 8875 display doubles vertically
for (int yoff=0; yoff<2; yoff++) {
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff) * RA8875_WIDTH +x+SCREENINSET_8875_X] = _565To332(loresPixelColors[color]);
}
} else {
// The 9341 is half the width we need, so this jumps through hoops
// to reduce the resolution in a way that's reasonable by blending
// pixels
if (x&1) {
uint16_t origColor = dmaBuffer16[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH+(x>>1)+SCREENINSET_9341_X];
uint16_t newColor = (uint16_t) loresPixelColors[color];
if (g_displayType == m_blackAndWhite) {
// There are four reasonable decisions here: if either pixel
// *was* on, then it's on; if both pixels *were* on, then it's
// on; and if the blended value of the two pixels were on, then
// it's on; or if the blended value of the two is above some
// certain overall brightness, then it's on. This is the last of
// those - where the brightness cutoff is defined in the bios as
// g_luminanceCutoff.
uint16_t blendedColor = blendColors(origColor, newColor);
uint16_t luminance = luminanceFromRGB(_565toR(blendedColor),
_565toG(blendedColor),
_565toB(blendedColor));
cacheDoubleWidePixel(x>>1,y,(uint16_t)((luminance >= g_luminanceCutoff) ? 0xFFFF : 0x0000));
} else {
cacheDoubleWidePixel(x>>1,y,color);
// Else if it's black, we leave whatever was in the other pixel.
}
} else {
// All of the even pixels get drawn...
cacheDoubleWidePixel(x>>1,y,color);
}
}
}
void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint16_t color16)
{
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
dmaBuffer[(y*2)+SCREENINSET_Y+yoff][(x*2)+SCREENINSET_X+xoff] = _565To332(color16);
if (use8875) {
for (int yoff=0; yoff<2; yoff++) {
if (use8875) {
for (int xoff=0; xoff<2; xoff++) {
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(color16);
}
} else {
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+x+SCREENINSET_8875_X] = _565To332(color16);
}
}
} else {
dmaBuffer16[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = color16;
}
}
@ -247,10 +403,14 @@ void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
uint16_t color16;
color16 = loresPixelColors[(( color & 0x0F ) )];
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
dmaBuffer[(y*2)+SCREENINSET_Y+yoff][(x*2)+SCREENINSET_X+xoff] = _565To332(color16);
if (use8875) {
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(color16);
}
}
} else {
dmaBuffer16[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = color16;
}
}
@ -260,15 +420,20 @@ void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
void TeensyDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y,
uint8_t colorA, uint8_t colorB)
{
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
dmaBuffer[(y*2)+SCREENINSET_Y+yoff][(x*2)+SCREENINSET_X+xoff] = _565To332(colorA);
dmaBuffer[(y*2)+SCREENINSET_Y+yoff][(x+1)*2+SCREENINSET_X+xoff] = _565To332(colorB);
if (use8875) {
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(colorA);
dmaBuffer[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x+1)*2+SCREENINSET_8875_X+xoff] = _565To332(colorB);
}
}
} else {
dmaBuffer16[(y+SCREENINSET_8875_Y)*ILI9341_WIDTH + (x)+SCREENINSET_9341_X] = colorA;
dmaBuffer16[(y+SCREENINSET_8875_Y)*ILI9341_WIDTH + ((x+1))+SCREENINSET_9341_X] = colorB;
}
}
uint32_t TeensyDisplay::frameCount()
{
return tft.frameCount();
return tft->frameCount();
}

View File

@ -3,7 +3,7 @@
#include <Arduino.h>
#include <SPI.h>
#include "RA8875_t4.h"
#include "basedisplay.h"
#include "physicaldisplay.h"
@ -26,6 +26,7 @@ class TeensyDisplay : public PhysicalDisplay {
virtual void drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c);
virtual void drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str);
virtual void drawUIImage(uint8_t imageIdx);
virtual void drawImageOfSizeAt(const uint8_t *img, uint16_t sizex, uint16_t sizey, uint16_t wherex, uint16_t wherey);
void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint16_t color16);
@ -42,6 +43,19 @@ class TeensyDisplay : public PhysicalDisplay {
bool needsRedraw;
bool driveIndicator[2];
bool driveIndicatorDirty;
private:
bool use8875;
const uint8_t *shellImage;
const uint16_t shellWidth, shellHeight;
const uint8_t *d1OpenImage;
const uint16_t driveWidth, driveHeight; // assume all the latches are the same width/height no matter what position
const uint8_t *d1ClosedImage;
const uint8_t *d2OpenImage;
const uint8_t *d2ClosedImage;
const uint8_t *appleImage;
const uint16_t appleImageWidth, appleImageHeight;
};
#endif