GxEPDDisplay.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include "GxEPDDisplay.h"
  2. #ifndef DISPLAY_ROTATION
  3. #define DISPLAY_ROTATION 3
  4. #endif
  5. bool GxEPDDisplay::begin() {
  6. display.epd2.selectSPI(SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
  7. SPI1.begin();
  8. display.init(115200, true, 2, false);
  9. display.setRotation(DISPLAY_ROTATION);
  10. setTextSize(1); // Default to size 1
  11. display.setPartialWindow(0, 0, display.width(), display.height());
  12. display.fillScreen(GxEPD_WHITE);
  13. display.display(true);
  14. #if DISP_BACKLIGHT
  15. pinMode(DISP_BACKLIGHT, OUTPUT);
  16. #endif
  17. _init = true;
  18. return true;
  19. }
  20. void GxEPDDisplay::turnOn() {
  21. if (!_init) begin();
  22. #if DISP_BACKLIGHT
  23. digitalWrite(DISP_BACKLIGHT, HIGH);
  24. #endif
  25. _isOn = true;
  26. }
  27. void GxEPDDisplay::turnOff() {
  28. #if DISP_BACKLIGHT
  29. digitalWrite(DISP_BACKLIGHT, LOW);
  30. #endif
  31. _isOn = false;
  32. }
  33. void GxEPDDisplay::clear() {
  34. display.fillScreen(GxEPD_WHITE);
  35. display.setTextColor(GxEPD_BLACK);
  36. }
  37. void GxEPDDisplay::startFrame(Color bkg) {
  38. display.fillScreen(GxEPD_WHITE);
  39. display.setTextColor(_curr_color = GxEPD_BLACK);
  40. }
  41. void GxEPDDisplay::setTextSize(int sz) {
  42. switch(sz) {
  43. case 1: // Small
  44. display.setFont(&FreeSans9pt7b);
  45. break;
  46. case 2: // Medium Bold
  47. display.setFont(&FreeSansBold12pt7b);
  48. break;
  49. case 3: // Large
  50. display.setFont(&FreeSans18pt7b);
  51. break;
  52. default:
  53. display.setFont(&FreeSans9pt7b);
  54. break;
  55. }
  56. }
  57. void GxEPDDisplay::setColor(Color c) {
  58. // colours need to be inverted for epaper displays
  59. if (c == DARK) {
  60. display.setTextColor(_curr_color = GxEPD_WHITE);
  61. } else {
  62. display.setTextColor(_curr_color = GxEPD_BLACK);
  63. }
  64. }
  65. void GxEPDDisplay::setCursor(int x, int y) {
  66. display.setCursor((x+offset_x)*scale_x, (y+offset_y)*scale_y);
  67. }
  68. void GxEPDDisplay::print(const char* str) {
  69. display.print(str);
  70. }
  71. void GxEPDDisplay::fillRect(int x, int y, int w, int h) {
  72. display.fillRect(x*scale_x, y*scale_y, w*scale_x, h*scale_y, _curr_color);
  73. }
  74. void GxEPDDisplay::drawRect(int x, int y, int w, int h) {
  75. display.drawRect(x*scale_x, y*scale_y, w*scale_x, h*scale_y, _curr_color);
  76. }
  77. void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
  78. // Calculate the base position in display coordinates
  79. uint16_t startX = x * scale_x;
  80. uint16_t startY = y * scale_y;
  81. // Width in bytes for bitmap processing
  82. uint16_t widthInBytes = (w + 7) / 8;
  83. // Process the bitmap row by row
  84. for (uint16_t by = 0; by < h; by++) {
  85. // Calculate the target y-coordinates for this logical row
  86. int y1 = startY + (int)(by * scale_y);
  87. int y2 = startY + (int)((by + 1) * scale_y);
  88. int block_h = y2 - y1;
  89. // Scan across the row bit by bit
  90. for (uint16_t bx = 0; bx < w; bx++) {
  91. // Calculate the target x-coordinates for this logical column
  92. int x1 = startX + (int)(bx * scale_x);
  93. int x2 = startX + (int)((bx + 1) * scale_x);
  94. int block_w = x2 - x1;
  95. // Get the current bit
  96. uint16_t byteOffset = (by * widthInBytes) + (bx / 8);
  97. uint8_t bitMask = 0x80 >> (bx & 7);
  98. bool bitSet = pgm_read_byte(bits + byteOffset) & bitMask;
  99. // If the bit is set, draw a block of pixels
  100. if (bitSet) {
  101. // Draw the block as a filled rectangle
  102. display.fillRect(x1, y1, block_w, block_h, _curr_color);
  103. }
  104. }
  105. }
  106. }
  107. uint16_t GxEPDDisplay::getTextWidth(const char* str) {
  108. int16_t x1, y1;
  109. uint16_t w, h;
  110. display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
  111. return ceil((w + 1) / scale_x);
  112. }
  113. void GxEPDDisplay::endFrame() {
  114. display.display(true);
  115. }