diff --git a/lib/GfxRenderer/GfxRenderer.cpp b/lib/GfxRenderer/GfxRenderer.cpp index 08420bf9..fb54d803 100644 --- a/lib/GfxRenderer/GfxRenderer.cpp +++ b/lib/GfxRenderer/GfxRenderer.cpp @@ -10,19 +10,19 @@ void GfxRenderer::rotateCoordinates(const int x, const int y, int* rotatedX, int // Logical portrait (480x800) → panel (800x480) // Rotation: 90 degrees clockwise *rotatedX = y; - *rotatedY = EInkDisplay::DISPLAY_HEIGHT - 1 - x; + *rotatedY = HalDisplay::DISPLAY_HEIGHT - 1 - x; break; } case LandscapeClockwise: { // Logical landscape (800x480) rotated 180 degrees (swap top/bottom and left/right) - *rotatedX = EInkDisplay::DISPLAY_WIDTH - 1 - x; - *rotatedY = EInkDisplay::DISPLAY_HEIGHT - 1 - y; + *rotatedX = HalDisplay::DISPLAY_WIDTH - 1 - x; + *rotatedY = HalDisplay::DISPLAY_HEIGHT - 1 - y; break; } case PortraitInverted: { // Logical portrait (480x800) → panel (800x480) // Rotation: 90 degrees counter-clockwise - *rotatedX = EInkDisplay::DISPLAY_WIDTH - 1 - y; + *rotatedX = HalDisplay::DISPLAY_WIDTH - 1 - y; *rotatedY = x; break; } @@ -49,14 +49,14 @@ void GfxRenderer::drawPixel(const int x, const int y, const bool state) const { rotateCoordinates(x, y, &rotatedX, &rotatedY); // Bounds checking against physical panel dimensions - if (rotatedX < 0 || rotatedX >= EInkDisplay::DISPLAY_WIDTH || rotatedY < 0 || - rotatedY >= EInkDisplay::DISPLAY_HEIGHT) { + if (rotatedX < 0 || rotatedX >= HalDisplay::DISPLAY_WIDTH || rotatedY < 0 || + rotatedY >= HalDisplay::DISPLAY_HEIGHT) { Serial.printf("[%lu] [GFX] !! Outside range (%d, %d) -> (%d, %d)\n", millis(), x, y, rotatedX, rotatedY); return; } // Calculate byte position and bit position - const uint16_t byteIndex = rotatedY * EInkDisplay::DISPLAY_WIDTH_BYTES + (rotatedX / 8); + const uint16_t byteIndex = rotatedY * HalDisplay::DISPLAY_WIDTH_BYTES + (rotatedX / 8); const uint8_t bitPosition = 7 - (rotatedX % 8); // MSB first if (state) { @@ -392,12 +392,12 @@ void GfxRenderer::invertScreen() const { Serial.printf("[%lu] [GFX] !! No framebuffer in invertScreen\n", millis()); return; } - for (int i = 0; i < EInkDisplay::BUFFER_SIZE; i++) { + for (int i = 0; i < HalDisplay::BUFFER_SIZE; i++) { buffer[i] = ~buffer[i]; } } -void GfxRenderer::displayBuffer(const EInkDisplay::RefreshMode refreshMode) const { +void GfxRenderer::displayBuffer(const HalDisplay::RefreshMode refreshMode) const { einkDisplay.displayBuffer(refreshMode); } @@ -418,13 +418,13 @@ int GfxRenderer::getScreenWidth() const { case Portrait: case PortraitInverted: // 480px wide in portrait logical coordinates - return EInkDisplay::DISPLAY_HEIGHT; + return HalDisplay::DISPLAY_HEIGHT; case LandscapeClockwise: case LandscapeCounterClockwise: // 800px wide in landscape logical coordinates - return EInkDisplay::DISPLAY_WIDTH; + return HalDisplay::DISPLAY_WIDTH; } - return EInkDisplay::DISPLAY_HEIGHT; + return HalDisplay::DISPLAY_HEIGHT; } int GfxRenderer::getScreenHeight() const { @@ -432,13 +432,13 @@ int GfxRenderer::getScreenHeight() const { case Portrait: case PortraitInverted: // 800px tall in portrait logical coordinates - return EInkDisplay::DISPLAY_WIDTH; + return HalDisplay::DISPLAY_WIDTH; case LandscapeClockwise: case LandscapeCounterClockwise: // 480px tall in landscape logical coordinates - return EInkDisplay::DISPLAY_HEIGHT; + return HalDisplay::DISPLAY_HEIGHT; } - return EInkDisplay::DISPLAY_WIDTH; + return HalDisplay::DISPLAY_WIDTH; } int GfxRenderer::getSpaceWidth(const int fontId) const { @@ -640,9 +640,7 @@ void GfxRenderer::drawTextRotated90CW(const int fontId, const int x, const int y uint8_t* GfxRenderer::getFrameBuffer() const { return einkDisplay.getFrameBuffer(); } -size_t GfxRenderer::getBufferSize() { return EInkDisplay::BUFFER_SIZE; } - -void GfxRenderer::grayscaleRevert() const { einkDisplay.grayscaleRevert(); } +size_t GfxRenderer::getBufferSize() { return HalDisplay::BUFFER_SIZE; } void GfxRenderer::copyGrayscaleLsbBuffers() const { einkDisplay.copyGrayscaleLsbBuffers(einkDisplay.getFrameBuffer()); } diff --git a/lib/GfxRenderer/GfxRenderer.h b/lib/GfxRenderer/GfxRenderer.h index b1fea69b..6e836354 100644 --- a/lib/GfxRenderer/GfxRenderer.h +++ b/lib/GfxRenderer/GfxRenderer.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -21,11 +21,11 @@ class GfxRenderer { private: static constexpr size_t BW_BUFFER_CHUNK_SIZE = 8000; // 8KB chunks to allow for non-contiguous memory - static constexpr size_t BW_BUFFER_NUM_CHUNKS = EInkDisplay::BUFFER_SIZE / BW_BUFFER_CHUNK_SIZE; - static_assert(BW_BUFFER_CHUNK_SIZE * BW_BUFFER_NUM_CHUNKS == EInkDisplay::BUFFER_SIZE, + static constexpr size_t BW_BUFFER_NUM_CHUNKS = HalDisplay::BUFFER_SIZE / BW_BUFFER_CHUNK_SIZE; + static_assert(BW_BUFFER_CHUNK_SIZE * BW_BUFFER_NUM_CHUNKS == HalDisplay::BUFFER_SIZE, "BW buffer chunking does not line up with display buffer size"); - EInkDisplay& einkDisplay; + HalDisplay& einkDisplay; RenderMode renderMode; Orientation orientation; uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr}; @@ -36,7 +36,7 @@ class GfxRenderer { void rotateCoordinates(int x, int y, int* rotatedX, int* rotatedY) const; public: - explicit GfxRenderer(EInkDisplay& einkDisplay) : einkDisplay(einkDisplay), renderMode(BW), orientation(Portrait) {} + explicit GfxRenderer(HalDisplay& einkDisplay) : einkDisplay(einkDisplay), renderMode(BW), orientation(Portrait) {} ~GfxRenderer() { freeBwBufferChunks(); } static constexpr int VIEWABLE_MARGIN_TOP = 9; @@ -54,7 +54,7 @@ class GfxRenderer { // Screen ops int getScreenWidth() const; int getScreenHeight() const; - void displayBuffer(EInkDisplay::RefreshMode refreshMode = EInkDisplay::FAST_REFRESH) const; + void displayBuffer(HalDisplay::RefreshMode refreshMode = HalDisplay::FAST_REFRESH) const; // EXPERIMENTAL: Windowed update - display only a rectangular region void displayWindow(int x, int y, int width, int height) const; void invertScreen() const; @@ -106,6 +106,6 @@ class GfxRenderer { // Low level functions uint8_t* getFrameBuffer() const; static size_t getBufferSize(); - void grayscaleRevert() const; + // void grayscaleRevert() const; // unused void getOrientedViewableTRBL(int* outTop, int* outRight, int* outBottom, int* outLeft) const; }; diff --git a/lib/hal/HalDisplay.cpp b/lib/hal/HalDisplay.cpp new file mode 100644 index 00000000..28bcfa64 --- /dev/null +++ b/lib/hal/HalDisplay.cpp @@ -0,0 +1,212 @@ +#include +#include + +std::string base64_encode(char* buf, unsigned int bufLen); + +HalDisplay::HalDisplay(int8_t sclk, int8_t mosi, int8_t cs, int8_t dc, int8_t rst, int8_t busy) : einkDisplay(sclk, mosi, cs, dc, rst, busy) { + if (is_emulated) { + emuFramebuffer0 = new uint8_t[BUFFER_SIZE]; + } +} + +HalDisplay::~HalDisplay() { + if (emuFramebuffer0) { + delete[] emuFramebuffer0; + emuFramebuffer0 = nullptr; + } +} + +void HalDisplay::begin() { + if (!is_emulated) { + einkDisplay.begin(); + } else { + Serial.printf("[%lu] [ ] Emulated display initialized\n", millis()); + // no-op + } +} + +void HalDisplay::clearScreen(uint8_t color) const { + if (!is_emulated) { + einkDisplay.clearScreen(color); + } else { + Serial.printf("[%lu] [ ] Emulated clear screen with color 0x%02X\n", millis(), color); + memset(emuFramebuffer0, color, BUFFER_SIZE); + } +} + +void HalDisplay::drawImage(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool fromProgmem) const { + if (!is_emulated) { + einkDisplay.drawImage(imageData, x, y, w, h, fromProgmem); + } else { + Serial.printf("[%lu] [ ] Emulated draw image at (%u, %u) with size %ux%u\n", millis(), x, y, w, h); + + // Calculate bytes per line for the image + const uint16_t imageWidthBytes = w / 8; + + // Copy image data to frame buffer + for (uint16_t row = 0; row < h; row++) { + const uint16_t destY = y + row; + if (destY >= DISPLAY_HEIGHT) + break; + + const uint16_t destOffset = destY * DISPLAY_WIDTH_BYTES + (x / 8); + const uint16_t srcOffset = row * imageWidthBytes; + + for (uint16_t col = 0; col < imageWidthBytes; col++) { + if ((x / 8 + col) >= DISPLAY_WIDTH_BYTES) + break; + + if (fromProgmem) { + emuFramebuffer0[destOffset + col] = pgm_read_byte(&imageData[srcOffset + col]); + } else { + emuFramebuffer0[destOffset + col] = imageData[srcOffset + col]; + } + } + } + } +} + +void HalDisplay::displayBuffer(RefreshMode mode) { + if (!is_emulated) { + einkDisplay.displayBuffer(mode); + } else { + Serial.printf("[%lu] [ ] Emulated display buffer with mode %d\n", millis(), static_cast(mode)); + std::string b64 = base64_encode(reinterpret_cast(emuFramebuffer0), BUFFER_SIZE); + Serial.printf("$$DATA:DISPLAY:{\"mode\":%d,\"buffer\":\"", static_cast(mode)); + Serial.print(b64.c_str()); + Serial.print("\"}$$\n"); + } +} + +void HalDisplay::refreshDisplay(RefreshMode mode, bool turnOffScreen) { + if (!is_emulated) { + einkDisplay.refreshDisplay(mode, turnOffScreen); + } else { + Serial.printf("[%lu] [ ] Emulated refresh display with mode %d, turnOffScreen %d\n", millis(), static_cast(mode), turnOffScreen); + // emulated delay + if (mode == RefreshMode::FAST_REFRESH) { + delay(50); + } else if (mode == RefreshMode::HALF_REFRESH) { + delay(800); + } else if (mode == RefreshMode::FULL_REFRESH) { + delay(1500); + } + } +} + +void HalDisplay::deepSleep() { + if (!is_emulated) { + einkDisplay.deepSleep(); + } else { + Serial.printf("[%lu] [ ] Emulated deep sleep\n", millis()); + // no-op + } +} + +uint8_t* HalDisplay::getFrameBuffer() const { + if (!is_emulated) { + return einkDisplay.getFrameBuffer(); + } else { + return emuFramebuffer0; + } +} + +void HalDisplay::copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t* msbBuffer) { + if (!is_emulated) { + einkDisplay.copyGrayscaleBuffers(lsbBuffer, msbBuffer); + } else { + Serial.printf("[%lu] [ ] Emulated copy grayscale buffers\n", millis()); + // TODO: not sure what this does + } +} + +void HalDisplay::copyGrayscaleLsbBuffers(const uint8_t* lsbBuffer) { + if (!is_emulated) { + einkDisplay.copyGrayscaleLsbBuffers(lsbBuffer); + } else { + Serial.printf("[%lu] [ ] Emulated copy grayscale LSB buffers\n", millis()); + // TODO: not sure what this does + } +} + +void HalDisplay::copyGrayscaleMsbBuffers(const uint8_t* msbBuffer) { + if (!is_emulated) { + einkDisplay.copyGrayscaleMsbBuffers(msbBuffer); + } else { + Serial.printf("[%lu] [ ] Emulated copy grayscale MSB buffers\n", millis()); + // TODO: not sure what this does + } +} + +void HalDisplay::cleanupGrayscaleBuffers(const uint8_t* bwBuffer) { + if (!is_emulated) { + einkDisplay.cleanupGrayscaleBuffers(bwBuffer); + } else { + Serial.printf("[%lu] [ ] Emulated cleanup grayscale buffers\n", millis()); + // TODO: not sure what this does + } +} + +void HalDisplay::displayGrayBuffer() { + if (!is_emulated) { + einkDisplay.displayGrayBuffer(); + } else { + Serial.printf("[%lu] [ ] Emulated display gray buffer\n", millis()); + // TODO: not sure what this does + } +} + +// +// Base64 utilities +// + +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +static inline bool is_base64(char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64_encode(char* buf, unsigned int bufLen) { + std::string ret; + ret.reserve(bufLen * 4 / 3 + 4); // reserve enough space + int i = 0; + int j = 0; + char char_array_3[3]; + char char_array_4[4]; + + while (bufLen--) { + char_array_3[i++] = *(buf++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i < 4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) { + for(j = i; j < 3; j++) { + char_array_3[j] = '\0'; + } + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + } + + return ret; +} diff --git a/lib/hal/HalDisplay.h b/lib/hal/HalDisplay.h new file mode 100644 index 00000000..3c2bcc1a --- /dev/null +++ b/lib/hal/HalDisplay.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include +#include + +class HalDisplay { + public: + // Constructor with pin configuration + HalDisplay(int8_t sclk, int8_t mosi, int8_t cs, int8_t dc, int8_t rst, int8_t busy); + + // Destructor + ~HalDisplay(); + + // Refresh modes (guarded to avoid redefinition in test builds) + using RefreshMode = EInkDisplay::RefreshMode; + static constexpr EInkDisplay::RefreshMode FULL_REFRESH = EInkDisplay::FULL_REFRESH; + static constexpr EInkDisplay::RefreshMode HALF_REFRESH = EInkDisplay::HALF_REFRESH; + static constexpr EInkDisplay::RefreshMode FAST_REFRESH = EInkDisplay::FAST_REFRESH; + + // Initialize the display hardware and driver + void begin(); + + // Display dimensions + static constexpr uint16_t DISPLAY_WIDTH = 800; + static constexpr uint16_t DISPLAY_HEIGHT = 480; + static constexpr uint16_t DISPLAY_WIDTH_BYTES = DISPLAY_WIDTH / 8; + static constexpr uint32_t BUFFER_SIZE = DISPLAY_WIDTH_BYTES * DISPLAY_HEIGHT; + + // Frame buffer operations + void clearScreen(uint8_t color = 0xFF) const; + void drawImage(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool fromProgmem = false) const; + + void displayBuffer(RefreshMode mode = RefreshMode::FAST_REFRESH); + void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); + + // Power management + void deepSleep(); + + // Access to frame buffer + uint8_t* getFrameBuffer() const; + + void copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t* msbBuffer); + void copyGrayscaleLsbBuffers(const uint8_t* lsbBuffer); + void copyGrayscaleMsbBuffers(const uint8_t* msbBuffer); + void cleanupGrayscaleBuffers(const uint8_t* bwBuffer); + + void displayGrayBuffer(); + + private: + bool is_emulated = CROSSPOINT_EMULATED; + + // real display implementation + EInkDisplay einkDisplay; + + // emulated display implementation + uint8_t* emuFramebuffer0 = nullptr; +}; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index c0d6844f..7e291782 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -133,7 +133,7 @@ void SleepActivity::renderDefaultSleepScreen() const { renderer.invertScreen(); } - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); } void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const { @@ -180,7 +180,7 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const { Serial.printf("[%lu] [SLP] drawing to %d x %d\n", millis(), x, y); renderer.clearScreen(); renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight, cropX, cropY); - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); if (bitmap.hasGreyscale()) { bitmap.rewindToData(); @@ -270,5 +270,5 @@ void SleepActivity::renderCoverSleepScreen() const { void SleepActivity::renderBlankSleepScreen() const { renderer.clearScreen(); - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); } diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 6ff39c5e..0743df71 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -322,7 +322,7 @@ void EpubReaderActivity::renderScreen() { auto progressCallback = [this, barX, barY, barWidth, barHeight](int progress) { const int fillWidth = (barWidth - 2) * progress / 100; renderer.fillRect(barX + 1, barY + 1, fillWidth, barHeight - 2, true); - renderer.displayBuffer(EInkDisplay::FAST_REFRESH); + renderer.displayBuffer(HalDisplay::FAST_REFRESH); }; if (!section->createSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(), @@ -392,7 +392,7 @@ void EpubReaderActivity::renderContents(std::unique_ptr page, const int or page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop); renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); if (pagesUntilFullRefresh <= 1) { - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); pagesUntilFullRefresh = SETTINGS.getRefreshFrequency(); } else { renderer.displayBuffer(); diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index db725320..7c3ea29f 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -237,7 +237,7 @@ void TxtReaderActivity::buildPageIndex() { // Fill progress bar const int fillWidth = (barWidth - 2) * progressPercent / 100; renderer.fillRect(barX + 1, barY + 1, fillWidth, barHeight - 2, true); - renderer.displayBuffer(EInkDisplay::FAST_REFRESH); + renderer.displayBuffer(HalDisplay::FAST_REFRESH); } // Yield to other tasks periodically @@ -465,7 +465,7 @@ void TxtReaderActivity::renderPage() { renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft); if (pagesUntilFullRefresh <= 1) { - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); pagesUntilFullRefresh = SETTINGS.getRefreshFrequency(); } else { renderer.displayBuffer(); diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 0a58d7b3..4aba7e66 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -269,7 +269,7 @@ void XtcReaderActivity::renderPage() { // Display BW with conditional refresh based on pagesUntilFullRefresh if (pagesUntilFullRefresh <= 1) { - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); pagesUntilFullRefresh = SETTINGS.getRefreshFrequency(); } else { renderer.displayBuffer(); @@ -349,7 +349,7 @@ void XtcReaderActivity::renderPage() { // Display with appropriate refresh if (pagesUntilFullRefresh <= 1) { - renderer.displayBuffer(EInkDisplay::HALF_REFRESH); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); pagesUntilFullRefresh = SETTINGS.getRefreshFrequency(); } else { renderer.displayBuffer(); diff --git a/src/activities/util/FullScreenMessageActivity.h b/src/activities/util/FullScreenMessageActivity.h index 3e975c91..b6cf8bed 100644 --- a/src/activities/util/FullScreenMessageActivity.h +++ b/src/activities/util/FullScreenMessageActivity.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include @@ -10,12 +10,12 @@ class FullScreenMessageActivity final : public Activity { std::string text; EpdFontFamily::Style style; - EInkDisplay::RefreshMode refreshMode; + HalDisplay::RefreshMode refreshMode; public: explicit FullScreenMessageActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string text, const EpdFontFamily::Style style = EpdFontFamily::REGULAR, - const EInkDisplay::RefreshMode refreshMode = EInkDisplay::FAST_REFRESH) + const HalDisplay::RefreshMode refreshMode = HalDisplay::FAST_REFRESH) : Activity("FullScreenMessage", renderer, mappedInput), text(std::move(text)), style(style), diff --git a/src/main.cpp b/src/main.cpp index f848c8a2..63ada0b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -39,7 +39,7 @@ #define SD_SPI_MISO 7 -EInkDisplay einkDisplay(EPD_SCLK, EPD_MOSI, EPD_CS, EPD_DC, EPD_RST, EPD_BUSY); +HalDisplay einkDisplay(EPD_SCLK, EPD_MOSI, EPD_CS, EPD_DC, EPD_RST, EPD_BUSY); InputManager inputManager; MappedInputManager mappedInputManager(inputManager); GfxRenderer renderer(einkDisplay);