Skip to content

Instantly share code, notes, and snippets.

@ztaylor54
Last active December 21, 2022 20:03
Show Gist options
  • Save ztaylor54/b89ca29823a8a83be5c1662d23a76f24 to your computer and use it in GitHub Desktop.
Save ztaylor54/b89ca29823a8a83be5c1662d23a76f24 to your computer and use it in GitHub Desktop.
Waveshare Three Color 2.9inch E-Ink Display Module (B - V3) Example Code with GxEPD2
/**
* @file ws2in9b_v3.h
* @author Zachary Taylor (@ztaylor54)
* @brief Driver for Waveshare 2.9in 3-color e-paper display, type 'B' V3
* @version 0.1
* @date 2022-12-21
*
* @copyright GNU GPLv3
*
*/
#pragma once
// GxEPD2 settings
#define ENABLE_GxEPD2_GFX 0
#define USE_HSPI_FOR_EPD
// display module pins
#define EPD_BUSY 40 /**< Busy status output, low active */
#define EPD_RST 39 /**< External reset, low active */
#define EPD_DC 38 /**< Data / Command selection (high for data, low for command) */
#define EPD_CS 37 /**< SPI chip selection, low active */
#define EPD_CLK 36 /**< SPI SCK pin */
#define EPD_DIN 35 /**< SPI MOSI pin */
// spi bus pins
#define SPI_SS EPD_CS
#define SPI_SCK EPD_CLK
#define SPI_MOSI EPD_DIN
#define SPI_MISO 12 /**< Unused, but you need to set it to something */
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY)); /**< display driver: GDEW029Z10 128x296, UC8151 (IL0373) */
SPIClass hspi(HSPI);
void ws2in9b_v3_init() {
log_i("ws2in9b_v3 init");
hspi.begin(SPI_SCK, SPI_MISO, SPI_MOSI, SPI_SS);
display.epd2.selectSPI(hspi, SPISettings(4000000, MSBFIRST, SPI_MODE0));
display.init(115200);
}
/**
* @file ws2in9b_v3_example.ino
* @author Zachary Taylor (@ztaylor54)
* @brief Example sketch for Waveshare 2.9in 3-color e-paper display, type 'B' V3
* @version 0.1
* @date 2022-12-21
*
* @copyright GNU GPLv3
*
*/
#include "ws2in9b_v3.h"
void setup()
{
log_i("setup");
ws2in9b_v3_init(); // init epd display
// first update should be full refresh
helloWorldForDummies();
delay(1000);
log_i("setup done, hibernating display");
display.hibernate();
}
void loop()
{
// nothing to see here
}
void helloWorldForDummies()
{
log_i("helloWorld");
const char text[] = "Hello World!";
// most e-papers have width < height (portrait) as native orientation, especially the small ones
// in GxEPD2 rotation 0 is used for native orientation (most TFT libraries use 0 fix for portrait orientation)
// set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
display.setRotation(1);
// select a suitable font in Adafruit_GFX
display.setFont(&FreeMonoBold9pt7b);
// on e-papers black on white is more pleasant to read
display.setTextColor(GxEPD_BLACK);
// Adafruit_GFX has a handy method getTextBounds() to determine the boundary box for a text for the actual font
int16_t tbx, tby;
uint16_t tbw, tbh; // boundary box window
display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh); // it works for origin 0, 0, fortunately (negative tby!)
// center bounding box by transposition of origin:
uint16_t x = ((display.width() - tbw) / 2) - tbx;
uint16_t y = ((display.height() - tbh) / 2) - tby;
// full window mode is the initial mode, set it anyway
display.setFullWindow();
// here we use paged drawing, even if the processor has enough RAM for full buffer
// so this can be used with any supported processor board.
// the cost in code overhead and execution time penalty is marginal
// tell the graphics class to use paged drawing mode
display.firstPage();
do
{
// this part of code is executed multiple times, as many as needed,
// in case of full buffer it is executed once
// IMPORTANT: each iteration needs to draw the same, to avoid strange effects
// use a copy of values that might change, don't read e.g. from analog or pins in the loop!
display.fillScreen(GxEPD_WHITE); // set the background to white (fill the buffer with value for white)
display.setCursor(x, y); // set the postition to start printing text
display.print(text); // print some text
// end of part executed multiple times
}
// tell the graphics class to transfer the buffer content (page) to the controller buffer
// the graphics class will command the controller to refresh to the screen when the last page has been transferred
// returns true if more pages need be drawn and transferred
// returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
// returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
// (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
while (display.nextPage());
log_i("helloWorld done");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment