refactoring

This commit is contained in:
Jorj Bauer 2022-01-30 20:26:12 -05:00
parent 0f4e4be73c
commit 0a2fb1aeee
19 changed files with 299 additions and 504 deletions

View File

@ -8,9 +8,9 @@ CXXFLAGS=-Wall -I/usr/include/SDL2 -I .. -I . -I apple -I nix -I sdl -I/usr/loca
TSRC=cpu.cpp util/testharness.cpp
COMMONSRCS=cpu.cpp apple/appledisplay.cpp apple/applekeyboard.cpp apple/applemmu.cpp apple/applevm.cpp apple/diskii.cpp apple/nibutil.cpp LRingBuffer.cpp globals.cpp apple/parallelcard.cpp apple/fx80.cpp lcg.cpp apple/hd32.cpp images.cpp apple/appleui.cpp vmram.cpp bios.cpp apple/noslotclock.cpp apple/woz.cpp apple/crc32.c apple/woz-serializer.cpp apple/mouse.c
COMMONSRCS=cpu.cpp apple/appledisplay.cpp apple/applekeyboard.cpp apple/applemmu.cpp apple/applevm.cpp apple/diskii.cpp apple/nibutil.cpp LRingBuffer.cpp globals.cpp apple/parallelcard.cpp apple/fx80.cpp lcg.cpp apple/hd32.cpp images.cpp apple/appleui.cpp vmram.cpp bios.cpp apple/noslotclock.cpp apple/woz.cpp apple/crc32.c apple/woz-serializer.cpp apple/mouse.c physicaldisplay.cpp
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o LRingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o images.o apple/appleui.o vmram.o bios.o apple/noslotclock.o apple/woz.o apple/crc32.o apple/woz-serializer.o apple/mouse.o
COMMONOBJS=cpu.o apple/appledisplay.o apple/applekeyboard.o apple/applemmu.o apple/applevm.o apple/diskii.o apple/nibutil.o LRingBuffer.o globals.o apple/parallelcard.o apple/fx80.o lcg.o apple/hd32.o images.o apple/appleui.o vmram.o bios.o apple/noslotclock.o apple/woz.o apple/crc32.o apple/woz-serializer.o apple/mouse.o physicaldisplay.o
FBSRCS=linuxfb/linux-speaker.cpp linuxfb/fb-display.cpp linuxfb/linux-keyboard.cpp linuxfb/fb-paddles.cpp nix/nix-filemanager.cpp linuxfb/aiie.cpp linuxfb/linux-printer.cpp nix/nix-clock.cpp nix/nix-prefs.cpp

View File

@ -42,8 +42,6 @@
#define drawApplePixel(c,x,y) { g_display->cacheDoubleWidePixel(x,y,c); }
#define draw2Pixels(cA, cB, x, y) { g_display->cache2DoubleWidePixels(x,y,cA, cB); }
#define DrawLoresPixelAt(c, x, y) { \
uint8_t pixel = c & 0x0F; \
for (uint8_t y2 = 0; y2<4; y2++) { \

View File

@ -101,7 +101,7 @@ void AppleUI::drawBatteryStatus(uint8_t percent)
b = (float)b * alpha + (bgb * (1.0 - alpha));
uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
g_display->drawUIPixel(x+xoff, y+yoff, color16);
g_display->drawPixel(x+xoff, y+yoff, color16);
}
}
}
@ -126,9 +126,9 @@ void AppleUI::blit()
// 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);
g_display->drawPixel(x + LED_X, y + LED1_Y, driveActivity[0] ? 0xFA00 : 0x0000);
g_display->drawUIPixel(x + LED_X, y + LED2_Y, driveActivity[1] ? 0xFA00 : 0x0000);
g_display->drawPixel(x + LED_X, y + LED2_Y, driveActivity[1] ? 0xFA00 : 0x0000);
}
}
*/

View File

@ -137,12 +137,12 @@ void BIOS::DrawMenuBar()
for (int i=0; i<NUM_TITLES; i++) {
for (int x=0; x<titleWidths[i] + 2*XPADDING; x++) {
g_display->drawUIPixel(xpos+x, 0, 0xFFFF);
g_display->drawUIPixel(xpos+x, LINEHEIGHT, 0xFFFF);
g_display->drawPixel(xpos+x, 0, 0xFFFF);
g_display->drawPixel(xpos+x, LINEHEIGHT, 0xFFFF);
}
for (int y=0; y<=LINEHEIGHT; y++) {
g_display->drawUIPixel(xpos, y, 0xFFFF);
g_display->drawUIPixel(xpos + titleWidths[i] + 2*XPADDING, y, 0xFFFF);
g_display->drawPixel(xpos, y, 0xFFFF);
g_display->drawPixel(xpos + titleWidths[i] + 2*XPADDING, y, 0xFFFF);
}
xpos += XPADDING;
@ -551,7 +551,7 @@ uint16_t BIOS::AboutScreenHandler(bool needsRedraw, bool performAction)
// Draw a black area where we're going to "boot" a fake //e for the about screen. Don't put the whole graphic around it so it's obvious it's not a //e.
for (uint8_t y=12; y<12+192; y++) {
for (uint16_t x=20; x<280+20; x++) {
g_display->drawUIPixel( x, y, 0x0000 );
g_display->drawPixel( x, y, 0x0000 );
}
}
/*
@ -682,26 +682,26 @@ uint16_t BIOS::PaddlesScreenHandler(bool needsRedraw, bool performAction)
// Draw the target for the paddle position
for (uint16_t y=10; y<=110; y++) {
for (uint16_t x=160; x<=260; x++) {
g_display->drawUIPixel(x, y, 0x0000);
g_display->drawUIPixel(x, 10, 0xFFFF);
g_display->drawUIPixel(x, 110, 0xFFFF);
g_display->drawPixel(x, y, 0x0000);
g_display->drawPixel(x, 10, 0xFFFF);
g_display->drawPixel(x, 110, 0xFFFF);
}
g_display->drawUIPixel(160, y, 0xFFFF);
g_display->drawUIPixel(260, y, 0xFFFF);
g_display->drawPixel(160, y, 0xFFFF);
g_display->drawPixel(260, y, 0xFFFF);
}
for (uint16_t y=57; y<=63; y++) {
g_display->drawUIPixel(207,y,0xFFFF);
g_display->drawUIPixel(213,y,0xFFFF);
g_display->drawPixel(207,y,0xFFFF);
g_display->drawPixel(213,y,0xFFFF);
}
for (uint16_t x=207; x<=213; x++) {
g_display->drawUIPixel(x,57,0xFFFF);
g_display->drawUIPixel(x,63,0xFFFF);
g_display->drawPixel(x,57,0xFFFF);
g_display->drawPixel(x,63,0xFFFF);
}
float drawX = ((float)lastPaddleX/255.0)*100.0;
float drawY = ((float)lastPaddleY/255.0)*100.0;
g_display->drawUIPixel(160+drawX, 10+drawY, 0xFFFF);
g_display->drawPixel(160+drawX, 10+drawY, 0xFFFF);
g_display->flush();
@ -1050,7 +1050,7 @@ void BIOS::DrawHardwareMenu()
uint16_t volCutoff = 300.0 * (float)((float) g_volume / 15.0);
for (uint8_t y=234; y<=235; y++) {
for (uint16_t x = 0; x< 300; x++) {
g_display->drawUIPixel( x, y, x <= volCutoff ? 0xFFFF : 0x0010 );
g_display->drawPixel( x, y, x <= volCutoff ? 0xFFFF : 0x0010 );
}
}
}
@ -1159,7 +1159,7 @@ uint16_t BIOS::DrawDiskNames(uint8_t page, int8_t selection, const char *filter)
g_display->drawString(M_NORMAL, 0, 0, title);
for (int x=0; x<strlen(title)*8; x++) {
g_display->drawUIPixel(x, LINEHEIGHT-1, 0xFFFF);
g_display->drawPixel(x, LINEHEIGHT-1, 0xFFFF);
}
uint8_t vpos = FILEMENUSTARTAT;

96
physicaldisplay.cpp Normal file
View File

@ -0,0 +1,96 @@
#include "physicaldisplay.h"
#include "globals.h"
#include "applevm.h"
#include "appleui.h"
#include "font.h"
const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
0xC006, // 1 magenta
0x0010, // 2 dark blue
0xA1B5, // 3 purple
0x0480, // 4 dark green
0x6B4D, // 5 dark grey
0x1B9F, // 6 med blue
0x0DFD, // 7 light blue
0x92A5, // 8 brown
0xF8C5, // 9 orange
0x9555, // 10 light gray
0xFCF2, // 11 pink
0x07E0, // 12 green
0xFFE0, // 13 yellow
0x87F0, // 14 aqua
0xFFFF // 15 white
};
void PhysicalDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
{
int8_t xsize = 8,
ysize = 0x07;
uint16_t offPixel, onPixel;
switch (mode) {
case M_NORMAL:
onPixel = 0xFFFF;
offPixel = 0x0010;
break;
case M_SELECTED:
onPixel = 0x0000;
offPixel = 0xFFFF;
break;
case M_DISABLED:
default:
onPixel = 0x7BEF;
offPixel = 0x0000;
break;
case M_SELECTDISABLED:
onPixel = 0x7BEF;
offPixel = 0xFFE0;
break;
case M_PLAIN:
onPixel = 0xFFFF;
offPixel = 0x0000;
break;
}
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++) {
if (*ch & (1 << (x_off))) {
drawPixel(x+x_off, y+y_off, onPixel);
} else {
drawPixel(x+x_off, y+y_off, onPixel);
}
}
ch++;
}
}
void PhysicalDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str)
{
int8_t xsize = 8; // width of a char in this font
for (int8_t i=0; i<strlen(str); i++) {
drawCharacter(mode, x, y, str[i]);
x += xsize;
if (x >= (320-xsize)/2) break; // FIXME this is a
// pre-scaled number, b/c
// drawCharacter is
// scaling. Klutzy. It's
// also using the ILI
// constant; what about
// the RA8875?
}
}
void PhysicalDisplay::redraw()
{
if (g_ui) {
g_ui->drawStaticUIElement(UIeOverlay);
if (g_vm) {
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
}
}
}

View File

@ -10,31 +10,27 @@ class PhysicalDisplay {
PhysicalDisplay() { overlayMessage[0] = '\0'; }
virtual ~PhysicalDisplay() {};
virtual void flush() = 0; // flush any pending drawings
virtual void redraw() = 0; // total redraw, assuming nothing
virtual void redraw(); // total redraw, assuming nothing
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 flush() = 0;
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;
virtual void drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str) = 0;
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 debugMsg(const char *msg) { strncpy(overlayMessage, msg, sizeof(overlayMessage));overlayMessage[strlen(overlayMessage)] = 0; }
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color) = 0;
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b) = 0;
virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color) = 0;
virtual void clrScr(uint8_t coloridx) = 0;
// methods to draw in to the buffer - not directly to the screen.
// First, methods that expect *us* to pixel-double the width...
virtual void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color) = 0;
virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB) = 0;
// Then the direct-pixel methods
virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color) = 0;

View File

@ -227,9 +227,8 @@ struct timespec runDisplay(struct timespec now)
g_ui->blit();
g_vm->vmdisplay->lockDisplay();
if (g_vm->vmdisplay->needsRedraw()) {
AiieRect what = g_vm->vmdisplay->getDirtyRect();
g_vm->vmdisplay->didRedraw();
g_display->blit(what);
g_display->blit();
}
g_vm->vmdisplay->unlockDisplay();

View File

@ -7,13 +7,6 @@
#include "applevm.h"
#include "apple/appleui.h"
// FIXME should be able to omit this include and rely on the xterns, which
// would prove it's linking properly
#include "apple/font.h"
extern const unsigned char ucase_glyphs[512];
extern const unsigned char lcase_glyphs[256];
extern const unsigned char mousetext_glyphs[256];
extern const unsigned char interface_glyphs[256];
#include "images.h"
@ -94,19 +87,6 @@ void SDLDisplay::flush()
SDL_RenderPresent(renderer);
}
void SDLDisplay::redraw()
{
// primarily for the device, where it's in and out of the
// bios. Draws the background image.
g_ui->drawStaticUIElement(UIeOverlay);
if (g_vm && g_ui) {
// determine whether or not a disk is inserted & redraw each drive
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
}
}
void SDLDisplay::drawUIImage(uint8_t imageIdx)
{
switch (imageIdx) {
@ -163,34 +143,16 @@ void SDLDisplay::blit()
SDL_RenderPresent(renderer);
}
// Blit the videoBuffer to the display device, in the rect given
void SDLDisplay::blit(AiieRect r)
{
blit();
/*
if (overlayMessage[0]) {
drawString(M_SELECTDISABLED, 1, 240 - 16 - 12, overlayMessage);
}
SDL_RenderPresent(renderer);
*/
}
inline void putpixel(SDL_Renderer *renderer, int x, int y, uint8_t r, uint8_t g, uint8_t b)
{
SDL_SetRenderDrawColor(renderer, r, g, b, 255);
SDL_RenderDrawPoint(renderer, x, y);
}
void SDLDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color)
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
{
if (x >= SDL_WIDTH || y >= SDL_HEIGHT) return; // make sure it's onscreen
videoBuffer[y][x] = color16To32(color);
}
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
{
uint8_t
r = (color & 0xF800) >> 8,
g = (color & 0x7E0) >> 3,
@ -204,69 +166,9 @@ void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
void SDLDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
{
for (int yoff=0; yoff<2; yoff++) {
putpixel(renderer, x, (y*2)+yoff, r, g, b);
}
}
void SDLDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
{
int8_t xsize = 8,
ysize = 0x07;
uint16_t offPixel, onPixel;
switch (mode) {
case M_NORMAL:
onPixel = 0xFFFF;
offPixel = 0x0010;
break;
case M_SELECTED:
onPixel = 0x0000;
offPixel = 0xFFFF;
break;
case M_DISABLED:
default:
onPixel = 0x7BEF;
offPixel = 0x0000;
break;
case M_SELECTDISABLED:
onPixel = 0x7BEF;
offPixel = 0xFFE0;
break;
case M_PLAIN:
onPixel = 0xFFFF;
offPixel = 0x0000;
break;
}
// scale up the font
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++) {
if (*ch & (1 << (x_off))) {
for (int8_t ys=0; ys<2; ys++) {
for (int8_t xs=0; xs<2; xs++) {
drawUIPixel((x + x_off)*2+xs, (y+y_off)*2 + ys, onPixel);
}
}
} else {
for (int8_t ys=0; ys<2; ys++) {
for (int8_t xs=0; xs<2; xs++) {
drawUIPixel((x + x_off)*2+xs, (y+y_off)*2 + ys, offPixel);
}
}
}
if (x < SDL_WIDTH && y < SDL_HEIGHT) {
putpixel(renderer, x, (y*2)+yoff, r, g, b);
}
ch++;
}
}
void SDLDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str)
{
int8_t xsize = 8; // width of a char in this font
for (int8_t i=0; i<strlen(str); i++) {
drawCharacter(mode, x, y, str[i]);
x += xsize;
}
}
@ -311,16 +213,6 @@ void SDLDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedCol
}
}
void SDLDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorB, uint8_t colorA)
{
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
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]);
}
}
}
void SDLDisplay::windowResized(uint32_t w, uint32_t h)
{
// Preserve the aspect ratio

View File

@ -17,8 +17,6 @@ class SDLDisplay : public PhysicalDisplay {
virtual ~SDLDisplay();
virtual void blit();
virtual void blit(AiieRect r);
virtual void redraw();
virtual void flush();
@ -28,16 +26,11 @@ class SDLDisplay : public PhysicalDisplay {
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color);
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color);
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 clrScr(uint8_t coloridx);
virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color);
virtual void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color);
void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint32_t packedColor);
virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB);
void windowResized(uint32_t w, uint32_t h);

View File

@ -1,8 +1,15 @@
#include "ILI9341_wrap.h"
#include "images.h"
#include "globals.h"
#include "appledisplay.h"
#define _332To565(c) ((((c) & 0xe0) << 8) | (((c) & 0x1c) << 6) | ((c) & 0x03))
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;
frame_buffer = NULL;
_cs = cs_pin;
_dc = dc_pin;
@ -33,27 +40,68 @@ 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);
if (tft) {
tft->fillScreen(ILI9341_BLACK);
this->frame_buffer = (uint16_t *)frame_buffer;
tft->setFrameBuffer((uint16_t *)frame_buffer);
tft->useFrameBuffer(true);
}
}
bool ILI9341_Wrap::asyncUpdateActive()
{
return tft->asyncUpdateActive();
return tft ? tft->asyncUpdateActive() : false;
}
bool ILI9341_Wrap::updateScreenAsync(bool update_cont)
{
return tft->updateScreenAsync(update_cont);
return tft ? tft->updateScreenAsync(update_cont) : false;
}
void ILI9341_Wrap::drawPixel(int16_t x, int16_t y, uint16_t color)
{
tft->drawPixel(x, y, color);
frame_buffer[y*ILI9341_WIDTH+x] = color;
}
void ILI9341_Wrap::drawPixel(int16_t x, int16_t y, uint8_t color)
{
frame_buffer[y*ILI9341_WIDTH+x] = _332To565(color);
}
// 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
void ILI9341_Wrap::cacheApplePixel(uint16_t x, uint16_t y, uint16_t color)
{
if (x&1) {
uint16_t origColor =frame_buffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH+(x>>1)+SCREENINSET_9341_X];
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, color);
uint16_t luminance = luminanceFromRGB(_565toR(blendedColor),
_565toG(blendedColor),
_565toB(blendedColor));
cacheDoubleWideApplePixel(x>>1,y,(uint16_t)((luminance >= g_luminanceCutoff) ? 0xFFFF : 0x0000));
} else {
cacheDoubleWideApplePixel(x>>1, y, color);
}
} else {
// All of the even pixels get drawn...
cacheDoubleWideApplePixel(x>>1, y, color);
}
}
void ILI9341_Wrap::cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16)
{
frame_buffer[(y+SCREENINSET_9341_Y)*ILI9341_WIDTH + (x) + SCREENINSET_9341_X] = color16;
}
uint32_t ILI9341_Wrap::frameCount()
{
return tft->frameCount();
return tft ? tft->frameCount() : 0;
}

View File

@ -27,11 +27,17 @@ class ILI9341_Wrap : public BaseDisplay {
virtual bool updateScreenAsync(bool update_cont = false);
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual void drawPixel(int16_t x, int16_t y, uint8_t color);
virtual void cacheApplePixel(uint16_t x, uint16_t y, uint16_t color);
virtual void ILI9341_Wrap::cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16);
virtual uint32_t frameCount();
private:
ILI9341_t3n *tft;
uint8_t _cs, _dc, _rst, _mosi, _sck, _miso;
uint16_t *frame_buffer;
};

View File

@ -1,6 +1,8 @@
#include "RA8875_t4.h"
#include "RA8875_registers.h"
#include "images.h"
// Discussion about DMA channels: http://forum.pjrc.com/threads/25778-Could-there-be-something-like-an-ISR-template-function/page3
// Thread discussing the way to get started: https://forum.pjrc.com/threads/63353-Teensy-4-1-How-to-start-using-DMA
// Thread of someone writing an LCD interface: https://forum.pjrc.com/threads/67247-Teensy-4-0-DMA-SPI
@ -401,6 +403,31 @@ void RA8875_t4::drawPixel(int16_t x, int16_t y, uint16_t color)
_pfbtft[y*RA8875_WIDTH+x] = _color16To8bpp(color);
}
void RA8875_t4::drawPixel(int16_t x, int16_t y, uint8_t color)
{
// FIXME: bounds checking
_pfbtft[y*RA8875_WIDTH+x] = color;
}
void RA8875_t4::cacheApplePixel(uint16_t x, uint16_t y, uint16_t color)
{
// The 8875 display doubles vertically
uint c8 = _565To332(color);
for (int yoff=0; yoff<2; yoff++) {
_pfbtft[((y*2)+SCREENINSET_8875_Y+yoff) * RA8875_WIDTH +x+SCREENINSET_8875_X] = c8;
}
}
void RA8875_t4::cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16)
{
// The RA8875 doubles Apple's pixels.
for (int yoff=0; yoff<2; yoff++) {
for (int xoff=0; xoff<2; xoff++) {
_pfbtft[((y*2)+SCREENINSET_8875_Y+yoff)*RA8875_WIDTH+(x*2)+SCREENINSET_8875_X+xoff] = _565To332(color16);
}
}
}
uint32_t RA8875_t4::frameCount()
{
return _dma_frame_count;

View File

@ -37,6 +37,11 @@ class RA8875_t4 : public BaseDisplay {
virtual bool updateScreenAsync(bool update_cont = false);
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual void drawPixel(int16_t x, int16_t y, uint8_t color);
virtual void cacheApplePixel(uint16_t x, uint16_t y, uint16_t color16);
virtual void cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16);
virtual uint32_t frameCount();
uint8_t color16To8bpp(uint16_t color) __attribute__((always_inline)) {

42
teensy/basedisplay.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef __BASE_DISPLAY_H
#define __BASE_DISPLAY_H
const uint16_t loresPixelColors[16];
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
#define _565toG(c) ( ((c) & 0x07E0) >> 3 )
#define _565toB(c) ( ((c) & 0x001F) << 3 )
#define RGBto332(r,g,b) ((((r) & 0xE0)) | (((g) & 0xE0) >> 3) | ((b) >> 6))
#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))
#define _332To565(c) ((((c) & 0xe0) << 8) | (((c) & 0x1c) << 6) | ((c) & 0x03))
#define blendColors(a,b) RGBto565( (_565toR(a) + _565toR(b))/2, (_565toG(a) + _565toG(b))/2, (_565toB(a) + _565toB(b))/2 )
class BaseDisplay {
public:
BaseDisplay(uint8_t cs_pin, uint8_t rst_pin, uint8_t mosi_pin, uint8_t sck_pin, uint8_t miso_pin, uint8_t dc_pin=255) {};
~BaseDisplay() {};
virtual void begin(uint32_t spi_clock=30000000u, uint32_t spi_clock_read=2000000) = 0;
virtual void fillWindow(uint16_t color = 0x0000) = 0;
virtual void setFrameBuffer(uint8_t *frame_buffer) = 0;
virtual bool asyncUpdateActive();
virtual bool updateScreenAsync(bool update_cont = false) = 0;
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
virtual void drawPixel(int16_t x, int16_t y, uint8_t color) = 0;
// Apple interface methods
virtual void cacheApplePixel(uint16_t x, uint16_t y, uint16_t color) = 0;
virtual void cacheDoubleWideApplePixel(uint16_t x, uint16_t y, uint16_t color16) = 0;
virtual uint32_t frameCount() = 0;
};
#endif

1
teensy/physicaldisplay.cpp Symbolic link
View File

@ -0,0 +1 @@
../physicaldisplay.cpp

View File

@ -1,72 +0,0 @@
/*
* https://forum.pjrc.com/threads/186-Teensy-3-fault-handler-demonstration?highlight=crash+handler
*
* call this from setup():
* enableFaultHandler();
*
* On crash you see something like:
* !!!! Crashed at pc=0x490, lr=0x55B.
*
* which you can interpret thusly:
* $ arm-none-eabi-addr2line -s -f -C -e main.elf 0x490 0x55B
* Print:: println(char const*)
* Print.h:47
* main
* main_crash.cpp:86
*/
#define SCB_SHCSR_USGFAULTENA (uint32_t)1<<18
#define SCB_SHCSR_BUSFAULTENA (uint32_t)1<<17
#define SCB_SHCSR_MEMFAULTENA (uint32_t)1<<16
#define SCB_SHPR1_USGFAULTPRI *(volatile uint8_t *)0xE000ED20
#define SCB_SHPR1_BUSFAULTPRI *(volatile uint8_t *)0xE000ED19
#define SCB_SHPR1_MEMFAULTPRI *(volatile uint8_t *)0xE000ED18
// enable bus, usage, and mem fault handlers.
void enableFaultHandler()
{
SCB_SHCSR |= SCB_SHCSR_BUSFAULTENA | SCB_SHCSR_USGFAULTENA | SCB_SHCSR_MEMFAULTENA;
}
extern "C" {
void __attribute__((naked)) _fault_isr () {
uint32_t* sp=0;
// this is from "Definitive Guide to the Cortex M3" pg 423
asm volatile ( "TST LR, #0x4\n\t" // Test EXC_RETURN number in LR bit 2
"ITE EQ\n\t" // if zero (equal) then
"MRSEQ %0, MSP\n\t" // Main Stack was used, put MSP in sp
"MRSNE %0, PSP\n\t" // else Process stack was used, put PSP in sp
: "=r" (sp) : : "cc");
Serial.print("!!!! Crashed at pc=0x");
Serial.print(sp[6], 16);
Serial.print(", lr=0x");
Serial.print(sp[5], 16);
Serial.println(".");
Serial.flush();
// allow USB interrupts to preempt us:
SCB_SHPR1_BUSFAULTPRI = (uint8_t)255;
SCB_SHPR1_USGFAULTPRI = (uint8_t)255;
SCB_SHPR1_MEMFAULTPRI = (uint8_t)255;
while (1) {
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);
asm volatile (
"WFI" // Wait For Interrupt.
);
}
}
}
void hard_fault_isr(void) __attribute__ ((alias("_fault_isr")));
void memmanage_fault_isr(void) __attribute__ ((alias("_fault_isr")));
void bus_fault_isr(void) __attribute__ ((alias("_fault_isr")));
void usage_fault_isr(void) __attribute__ ((alias("_fault_isr")));

View File

@ -4,13 +4,6 @@
#include "iocompat.h"
#include "appleui.h"
// FIXME should be able to omit this include and rely on the xterns, which
// would prove it's linking properly
#include "font.h"
extern const unsigned char ucase_glyphs[512];
extern const unsigned char lcase_glyphs[256];
extern const unsigned char mousetext_glyphs[256];
extern const unsigned char interface_glyphs[256];
#include "globals.h"
#include "applevm.h"
@ -20,14 +13,8 @@ extern const unsigned char interface_glyphs[256];
#include "images.h"
// 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.
uint8_t *dmaBuffer = NULL;
uint16_t *dmaBuffer16 = NULL;
#include <SPI.h>
@ -38,42 +25,8 @@ uint16_t *dmaBuffer16 = NULL; // At runtime, this points to dmaBuffer.
#define PIN_MISO 1
#define PIN_SCK 27
// RGB map of each of the lowres colors
const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
0xC006, // 1 magenta
0x0010, // 2 dark blue
0xA1B5, // 3 purple
0x0480, // 4 dark green
0x6B4D, // 5 dark grey
0x1B9F, // 6 med blue
0x0DFD, // 7 light blue
0x92A5, // 8 brown
0xF8C5, // 9 orange
0x9555, // 10 light gray
0xFCF2, // 11 pink
0x07E0, // 12 green
0xFFE0, // 13 yellow
0x87F0, // 14 aqua
0xFFFF // 15 white
};
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
#define _565toG(c) ( ((c) & 0x07E0) >> 3 )
#define _565toB(c) ( ((c) & 0x001F) << 3 )
#define RGBto332(r,g,b) ((((r) & 0xE0)) | (((g) & 0xE0) >> 3) | ((b) >> 6))
#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))
#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;
@ -86,10 +39,12 @@ TeensyDisplay::TeensyDisplay()
digitalWrite(11, HIGH); // turn on pull-up
if (digitalRead(11)) {
// Default: use older, small ILI display if pin 11 is not connected to ground
// Default: use older, smaller but faster, ILI display if pin 11 is not connected to ground
Serial.println(" using ILI9341 display");
dmaBuffer16 = (uint16_t *)malloc((320*240)*2+32); // malloc() happens in the DMAMEM area (RAM2) FIXME *** CONSTANTS -- and does the +32 align properly?
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);
@ -100,11 +55,14 @@ TeensyDisplay::TeensyDisplay()
getImageInfoAndData(IMG_9341_APPLEBATTERY, &appleImageWidth, &appleImageHeight, &appleImage);
tft->begin(50000000u);
tft->setFrameBuffer((uint8_t *)dmaBuffer16);
} else {
// If someone grounded pin 11, then use the new RA8875 display
Serial.println(" using RA8875 display");
dmaBuffer = (uint8_t *)malloc(800*480+32); // malloc() happens in the DMAMEM area (RAM2) FIXME *** CONSTANTS -- and does the +32 align properly?
tft = new RA8875_t4(PIN_CS, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
use8875 = true;
// Load the 8875 images
getImageInfoAndData(IMG_8875_SHELL, &shellWidth, &shellHeight, &shellImage);
@ -118,32 +76,21 @@ TeensyDisplay::TeensyDisplay()
// 60MHz: unexpected palatte shifts & (may be audio overruns, needs checking since bumping up buffer sizes) 17 FPS
// And I can't get the SPI bus working at 80MHz or higher. Not sure why yet...
tft->begin(57500000);
tft->setFrameBuffer((uint8_t *)dmaBuffer);
}
tft->setFrameBuffer((uint8_t *)dmaBuffer);
Serial.print("before ");
Serial.println((uint32_t)tft);
Serial.print("after ");
Serial.println((uint32_t)tft);
tft->fillWindow();
Serial.println("finished filling");
}
TeensyDisplay::~TeensyDisplay()
{
}
void TeensyDisplay::flush()
{
}
void TeensyDisplay::redraw()
{
if (g_ui) {
g_ui->drawStaticUIElement(UIeOverlay);
if (g_vm) {
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
}
}
}
// Take one of the abstracted image constants, figure out which one it
// is based on the current display, and display it via
// drawImageOfSizeAt.
@ -185,17 +132,16 @@ void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
uint16_t v = pgm_read_byte(p++);
v <<= 8;
v |= pgm_read_byte(p++);
if (use8875) {
dmaBuffer[(y+wherey)*RA8875_WIDTH + x+wherex] = _565To332(v);
} else {
dmaBuffer16[(y+wherey)*ILI9341_WIDTH + x+wherex] = v;
}
tft->drawPixel(x+wherex, y+wherey, v);
}
}
}
void TeensyDisplay::blit()
{
if (!tft)
return;
// Start updates, if they're not running already
if (!tft->asyncUpdateActive())
tft->updateScreenAsync(true);
@ -214,186 +160,32 @@ void TeensyDisplay::blit()
}
}
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 (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 (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;
}
tft->drawPixel(x,y,color);
}
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
{
uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
drawPixel(x,y,color16);
}
void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint16_t y, char c)
{
int8_t xsize = 8,
ysize = 0x07;
uint16_t offPixel, onPixel;
switch (mode) {
case M_NORMAL:
onPixel = 0xFFFF;
offPixel = 0x0010;
break;
case M_SELECTED:
onPixel = 0x0000;
offPixel = 0xFFFF;
break;
case M_DISABLED:
default:
onPixel = 0x7BEF;
offPixel = 0x0000;
break;
case M_SELECTDISABLED:
onPixel = 0x7BEF;
offPixel = 0xFFE0;
break;
case M_PLAIN:
onPixel = 0xFFFF;
offPixel = 0x0000;
break;
}
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++) {
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++;
}
}
void TeensyDisplay::drawString(uint8_t mode, uint16_t x, uint16_t y, const char *str)
{
int8_t xsize = 8; // width of a char in this font
for (int8_t i=0; i<strlen(str); i++) {
drawCharacter(mode, x, y, str[i]);
x += xsize;
if (x >= (RA8875_WIDTH-xsize)/2) break; // FIXME this is a pre-scaled number, b/c drawCharacter is scaling. Klutzy.
}
tft->drawPixel(x,y,color16);
}
void TeensyDisplay::clrScr(uint8_t coloridx)
{
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;
}
}
}
}
uint16_t color16 = loresPixelColors[coloridx];
tft->fillWindow(color16);
}
void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t 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);
}
}
tft->cacheApplePixel(x,y,loresPixelColors[color]);
}
void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint16_t 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;
}
tft->cacheDoubleWideApplePixel(x, y, color16);
}
// "DoubleWide" means "please double the X because I'm in low-res
@ -402,38 +194,14 @@ void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
{
uint16_t color16;
color16 = loresPixelColors[(( color & 0x0F ) )];
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;
}
}
// This exists for 4bpp optimization. We could totally call
// cacheDoubleWidePixel twice, but the (x&1) pfutzing is messy if
// we're just storing both halves anyway...
void TeensyDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y,
uint8_t colorA, uint8_t 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;
}
tft->cacheDoubleWideApplePixel(x, y, color16);
}
uint32_t TeensyDisplay::frameCount()
{
if (!tft)
return 0;
return tft->frameCount();
}

View File

@ -17,36 +17,27 @@ class TeensyDisplay : public PhysicalDisplay {
virtual ~TeensyDisplay();
virtual void blit();
virtual void blit(AiieRect r);
virtual void redraw();
virtual void flush() { };
virtual void clrScr(uint8_t coloridx);
virtual void flush();
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);
virtual void cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color);
virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB);
virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color);
uint32_t frameCount();
private:
virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color);
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color);
bool needsRedraw;
bool driveIndicator[2];
bool driveIndicatorDirty;
private:
bool use8875;
const uint8_t *shellImage;
const uint16_t shellWidth, shellHeight;
const uint8_t *d1OpenImage;
@ -56,6 +47,8 @@ private:
const uint8_t *d2ClosedImage;
const uint8_t *appleImage;
const uint16_t appleImageWidth, appleImageHeight;
BaseDisplay *tft;
};
#endif

View File

@ -32,7 +32,6 @@
#define BATTERYSELECT 21 // digital select that turns on the power reading ckt
#include "globals.h"
#include "teensy-crash.h"
BIOS bios;
@ -166,6 +165,10 @@ void setup()
delay(2000);
#endif
delay(200); // let the power settle & serial to get its bearings
if (CrashReport) {
Serial.print(CrashReport);
delay(5000);
}
pinMode(DEBUGPIN, OUTPUT); // for debugging
pinMode(BATTERYSELECT, OUTPUT);