#include "badge/display.h" #include "badge/log.h" #include #include // #include #include #include "badge/config.h" #include "badge/util.h" #if UVOK_EPAP_DISPLAY == DISPLAY_WAVESHARE_219_YBW // HINT: Update the library code, set budy timeout to 30 or 60 seconds! // Small color GxEPD2_3C display(GxEPD2_213_Z19c(22, 21, 17, 16)); #elif UVOK_EPAP_DISPLAY == DISPLAY_WAVESHARE_290_BW // larger b/w // or T5 // GxEPD2_BW display(GxEPD2_290_T5D(22, 21, 17, 16)); GxEPD2_BW display(GxEPD2_290_M06(22, 21, 17, 16)); #elif UVOK_EPAP_DISPLAY == DISPLAY_ELECROW_290_BW /* #define SCK 12 #define MOSI 11 #define RES 47 #define DC 46 #define CS 45 #define BUSY 48 */ GxEPD2_BW display(GxEPD2_290_T94(45, 46, 47, 48)); #else #error "define display" #endif static uint8_t displayed = 0; #include "cheebox.xbm" #include "chleepy.xbm" #include "hug.xbm" #include "hungry.xbm" #include "qr.xbm" #include "uvok.xbm" #include "sneppump.xbm" void de::uvok::badge::display_init(void) { LOG_F("Init display...\n"); #if UVOK_EPAP_DISPLAY == DISPLAY_ELECROW_290_BW // Turn on once, let controller handle the rest, lest I want to do re-init... pinMode(7, OUTPUT); // Set pin 7 as output mode digitalWrite(7, HIGH); // Set pin 7 to high level to turn on the screen power display.init(115200, true); #else display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse #endif display.hibernate(); LOG_F("Display done.\n"); } void de::uvok::badge::display_demo(void) { #define TEXT_BORDER 10 // display.clearScreen(); static const char s_hungry[] = "hungry"; display.setRotation(1); display.setTextColor(GxEPD_BLACK); int16_t tbx, tby; uint16_t tbw, tbh; display.setFont(&FreeMonoBold9pt7b); display.getTextBounds(s_hungry, 0, 0, &tbx, &tby, &tbw, &tbh); // center the bounding box by transposition of the origin: uint16_t x = display.width() - tbw - TEXT_BORDER - tbx; uint16_t y = ((display.height() - tbh) / 2) - tby; display.setFullWindow(); display.firstPage(); do { display.drawXBitmap(0, 0, (unsigned char *)chleepy_bits, chleepy_width, chleepy_height, GxEPD_BLACK); display.getTextBounds(s_hungry, x, y, &tbx, &tby, &tbw, &tbh); display.fillRect(tbx - TEXT_BORDER, tby - TEXT_BORDER, tbw + 2 * TEXT_BORDER, tbh + 2 * TEXT_BORDER, GxEPD_WHITE); display.setCursor(x, y); display.print(s_hungry); } while (display.nextPage()); display.hibernate(); #undef TEXT_BORDER } #define IMAGE_DATA(name, text) {name##_bits, name##_width, name##_height, text} const struct { // I always thought making the struct const makes all membery const, yet I still get warnings... const char *bits; const int width; const int height; const char *text; } imgs[] = { #include "./images.cfg" }; const int de::uvok::badge::image_count = (ARRAY_LENGTH(imgs)); typedef enum { DISPLAY_PREVIEW, DISPLAY_FULL } display_mode_t; static void displayDo(display_mode_t mode) { static bool is_initial = true; if (is_initial) { mode = DISPLAY_FULL; is_initial = false; } LOG_F("Print image %d in full mode? %d\n", displayed, mode); display.setRotation(3); display.setTextColor(GxEPD_BLACK); display.setFont(&FreeSansBold12pt7b); const char *display_text = imgs[displayed].text; int16_t tbx, tby; uint16_t tbw, tbh; display.getTextBounds(display_text, 0, 0, &tbx, &tby, &tbw, &tbh); constexpr int TEXT_BORDER = 10; const uint16_t x = display.width() - tbw - TEXT_BORDER - tbx; const uint16_t y = ((display.height() - tbh) / 2) - tby; // re-calculate right-centered display.getTextBounds(display_text, x, y, &tbx, &tby, &tbw, &tbh); display.firstPage(); do { if (mode == DISPLAY_FULL) { display.setFullWindow(); display.drawXBitmap(0, 0, (unsigned char *)imgs[displayed].bits, imgs[displayed].width, imgs[displayed].height, GxEPD_BLACK); } else { display.setPartialWindow(tbx - TEXT_BORDER, tby - TEXT_BORDER, tbw + 2 * TEXT_BORDER, tbh + 2 * TEXT_BORDER); } display.fillRect(tbx - TEXT_BORDER, tby - TEXT_BORDER, tbw + 2 * TEXT_BORDER, tbh + 2 * TEXT_BORDER, GxEPD_WHITE); display.setCursor(x, y); display.print(display_text); } while (display.nextPage()); display.hibernate(); } uint8_t de::uvok::badge::display_prev(void) { displayed--; if (displayed >= image_count) displayed = image_count - 1; displayDo(DISPLAY_PREVIEW); return displayed; } uint8_t de::uvok::badge::display_next(void) { displayed = (displayed + 1) % image_count; displayDo(DISPLAY_PREVIEW); return displayed; } uint8_t de::uvok::badge::display_refresh(void) { displayDo(DISPLAY_FULL); return displayed; } void de::uvok::badge::display_direct(uint8_t num) { LOG_F("Display direct\n"); if (num >= image_count) return; displayed = num; displayDo(DISPLAY_FULL); } /* // -> #include "output_h4x4a.xbm" #include "output_o8x8.xbm" */