From 0a2fb1aeee35c8aa618bc33cecee876b0805b991 Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Sun, 30 Jan 2022 20:26:12 -0500 Subject: [PATCH] refactoring --- Makefile | 4 +- apple/appledisplay.cpp | 2 - apple/appleui.cpp | 6 +- bios.cpp | 34 ++--- physicaldisplay.cpp | 96 ++++++++++++ physicaldisplay.h | 12 +- sdl/aiie.cpp | 3 +- sdl/sdl-display.cpp | 114 +-------------- sdl/sdl-display.h | 7 - teensy/ILI9341_wrap.cpp | 62 +++++++- teensy/ILI9341_wrap.h | 6 + teensy/RA8875_t4.cpp | 27 ++++ teensy/RA8875_t4.h | 5 + teensy/basedisplay.h | 42 ++++++ teensy/physicaldisplay.cpp | 1 + teensy/teensy-crash.h | 72 --------- teensy/teensy-display.cpp | 292 ++++--------------------------------- teensy/teensy-display.h | 13 +- teensy/teensy.ino | 5 +- 19 files changed, 299 insertions(+), 504 deletions(-) create mode 100644 physicaldisplay.cpp create mode 100644 teensy/basedisplay.h create mode 120000 teensy/physicaldisplay.cpp delete mode 100644 teensy/teensy-crash.h diff --git a/Makefile b/Makefile index c054178..e8e56f0 100755 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/apple/appledisplay.cpp b/apple/appledisplay.cpp index ef0896a..145f05b 100644 --- a/apple/appledisplay.cpp +++ b/apple/appledisplay.cpp @@ -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++) { \ diff --git a/apple/appleui.cpp b/apple/appleui.cpp index 3c596a5..a54a253 100644 --- a/apple/appleui.cpp +++ b/apple/appleui.cpp @@ -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; ydrawUIPixel(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); } } */ diff --git a/bios.cpp b/bios.cpp index 8a11064..3e2af1a 100644 --- a/bios.cpp +++ b/bios.cpp @@ -137,12 +137,12 @@ void BIOS::DrawMenuBar() for (int i=0; idrawUIPixel(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; xdrawUIPixel(x, LINEHEIGHT-1, 0xFFFF); + g_display->drawPixel(x, LINEHEIGHT-1, 0xFFFF); } uint8_t vpos = FILEMENUSTARTAT; diff --git a/physicaldisplay.cpp b/physicaldisplay.cpp new file mode 100644 index 0000000..520d820 --- /dev/null +++ b/physicaldisplay.cpp @@ -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= (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'); + } + } +} diff --git a/physicaldisplay.h b/physicaldisplay.h index e08e853..79c419e 100644 --- a/physicaldisplay.h +++ b/physicaldisplay.h @@ -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; diff --git a/sdl/aiie.cpp b/sdl/aiie.cpp index 4126cc2..c030f3c 100644 --- a/sdl/aiie.cpp +++ b/sdl/aiie.cpp @@ -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(); diff --git a/sdl/sdl-display.cpp b/sdl/sdl-display.cpp index 7e5a664..f67f670 100644 --- a/sdl/sdl-display.cpp +++ b/sdl/sdl-display.cpp @@ -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; isetFrameBuffer((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; } diff --git a/teensy/ILI9341_wrap.h b/teensy/ILI9341_wrap.h index 8fc1baf..54e9ed8 100644 --- a/teensy/ILI9341_wrap.h +++ b/teensy/ILI9341_wrap.h @@ -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; }; diff --git a/teensy/RA8875_t4.cpp b/teensy/RA8875_t4.cpp index e1a8e1b..0f797bf 100644 --- a/teensy/RA8875_t4.cpp +++ b/teensy/RA8875_t4.cpp @@ -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; diff --git a/teensy/RA8875_t4.h b/teensy/RA8875_t4.h index 73d0046..95b503c 100644 --- a/teensy/RA8875_t4.h +++ b/teensy/RA8875_t4.h @@ -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)) { diff --git a/teensy/basedisplay.h b/teensy/basedisplay.h new file mode 100644 index 0000000..e107f84 --- /dev/null +++ b/teensy/basedisplay.h @@ -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 diff --git a/teensy/physicaldisplay.cpp b/teensy/physicaldisplay.cpp new file mode 120000 index 0000000..c6566a2 --- /dev/null +++ b/teensy/physicaldisplay.cpp @@ -0,0 +1 @@ +../physicaldisplay.cpp \ No newline at end of file diff --git a/teensy/teensy-crash.h b/teensy/teensy-crash.h deleted file mode 100644 index fab4026..0000000 --- a/teensy/teensy-crash.h +++ /dev/null @@ -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"))); diff --git a/teensy/teensy-display.cpp b/teensy/teensy-display.cpp index 38723c5..c24f200 100644 --- a/teensy/teensy-display.cpp +++ b/teensy/teensy-display.cpp @@ -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 @@ -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= (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; yfillWindow(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(); } diff --git a/teensy/teensy-display.h b/teensy/teensy-display.h index c01c003..9011072 100644 --- a/teensy/teensy-display.h +++ b/teensy/teensy-display.h @@ -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 diff --git a/teensy/teensy.ino b/teensy/teensy.ino index ede0d21..8a55035 100644 --- a/teensy/teensy.ino +++ b/teensy/teensy.ino @@ -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);