Seeeduino Xiao SAMD21 and Waveshare 4.2 inch E-ink display not working

The code compiles for me as well but similar to what I mentioned before, I cannot connect to the board while the display is attached to it after the compiled code is uploaded.
As I mentioned here:

Hi there,
So got it working here…I’m not using the SD card btw… wiring is a bit SKetch but hay it’s late. :stuck_out_tongue: :v:
Runs on Battery too!

A couple observations, I using an Xiao Nrf52840 Sense UPLOADING the Xiao must be in bootloader mode with drive present.
I’m using the Crystalfontz.com LIB Worked right away.

#include <epd4in2.h>
#include <epdif.h>
#include <epdpaint.h>
#include <fonts.h>
#include <imagedata.h>

//=============================================================================
// "Arduino" example program for Crystalfontz ePaper.
//
// This project is for the CFAP122250A2-0213 :
//
//   https://www.crystalfontz.com/product/CFAP122250A2-0213
//
// It was written against a Seeduino v4.2 @3.3v. An Arduino UNO modified to
// operate at 3.3v should also work.
//-----------------------------------------------------------------------------
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>
//=============================================================================
// Connecting the Arduino to the display
//
// ARDUINO |Adapter |Wire Color |Function
// --------+--------+-----------+--------------------
// D3      |17      |Green      |Busy Line
// D4      |18      |Brown      |Reset Line
// D5      |15      |Purple     |Data/Command Line
// D10     |16      |Blue       |Chip Select Line
// D11     |14      |White      |MOSI
// D13     |13      |Orange     |Clock
// 3.3V    |5       |Red        |Power
// GND     |3       |Black      |Ground
//
// Short the following pins on the adapter board:
// BS2  -> GND
// RESE -> 2.2ohms
//=============================================================================
//Connecting the Arduino to the SD card
//A CFA10112 micro SD card adapter can be used: https://www.crystalfontz.com/product/cfa10112
//
// ARDUINO  |Wire Color |Function
// ---------+-----------+--------------------
// D8       |Blue       |CS
// D11      |Green      |MOSI
// D12      |Purple     |MISO
// D13      |Brown      |CLK
//
//
//=============================================================================
// Creating image data arrays
//
// Bmp_to_epaper is code that will aid in creating bitmaps necessary from .bmp files.
// The code can be downloaded from the Crystalfontz website: https://www.Crystalfontz.com
// or it can be downloaded from github: https://github.com/crystalfontz/bmp_to_epaper
//=============================================================================

// The display is SPI, include the library header.
#include <SPI.h>
#include <SD.h>
//#include <avr/io.h>

// Include the images. These images were prepared with "bmp_to_epaper" which
// is available on the Crystalfontz site.
#include "Images_for_CFAP122250A20213.h"

#define ePaper_RST_0 (digitalWrite(EPD_RESET, LOW))
#define ePaper_RST_1 (digitalWrite(EPD_RESET, HIGH))
#define ePaper_CS_0 (digitalWrite(EPD_CS, LOW))
#define ePaper_CS_1 (digitalWrite(EPD_CS, HIGH))
#define ePaper_DC_0 (digitalWrite(EPD_DC, LOW))
#define ePaper_DC_1 (digitalWrite(EPD_DC, HIGH))

#define EPD_BUSY 3
#define EPD_RESET 4
#define EPD_DC 5
#define EPD_CS 10
#define SD_CS 8

#define VRES 300
#define HRES 400

#define WAIT_BUSY while (0 != digitalRead(EPD_BUSY))

//=============================================================================
//this function will take in a byte and send it to the display with the
//command bit low for command transmission
void writeCMD(uint8_t command)
{
  ePaper_DC_0;
  ePaper_CS_0;
  SPI.transfer(command);
  ePaper_CS_1;
}

//this function will take in a byte and send it to the display with the
//command bit high for data transmission
void writeData(uint8_t data)
{
  ePaper_DC_1;
  ePaper_CS_0;
  SPI.transfer(data);
  ePaper_CS_1;
}

//===========================================================================
void fullUpdate(void)
{
  //
  writeCMD(0x22);
  writeData(0xf7);
  writeCMD(0x20);
}

void partialUpdate(void)
{
  //
  writeCMD(0x22);
  writeData(0xff);
  writeCMD(0x20);
}

//===========================================================================
void setup(void)
{
  //Debug port / Arduino Serial Monitor (optional)
  Serial.begin(9600);
  delay (1000);
  Serial.println("setup started");
  // Configure the pin directions
  pinMode(EPD_CS, OUTPUT);
  pinMode(EPD_RESET, OUTPUT);
  pinMode(EPD_DC, OUTPUT);
  pinMode(EPD_BUSY, INPUT);
  pinMode(SD_CS, OUTPUT);

  digitalWrite(SD_CS, LOW);

  if (!SD.begin(SD_CS))
  {
    Serial.println("SD could not initialize");
  }
  //Set up SPI interface
  SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
  SPI.begin();

  initEPD();
  Serial.println("setup complete");
}

//================================================================================
void initEPD()
{

  //-----------------------------------------------------------------------------
  //more detail on the following commands and additional commands not used here
  //can be found on the CFAP176264A0-0270 datasheet on the Crystalfontz website
  //-----------------------------------------------------------------------------

  //reset driver
  ePaper_RST_0;
  delay(40);
  ePaper_RST_1;
  delay(40);

  //Software Reset
  WAIT_BUSY;
  writeCMD(0x12);
  WAIT_BUSY;

  //Get out of deep sleep if we're there already
  writeCMD(0x10);
  writeData(0x00);

  //Driver Output Control
  writeCMD(0x01);
  writeData(0xf9);
  writeData(0x00);
  writeData(0x00);

  //Data Entry mode setting
  writeCMD(0x11);
  writeData(0x01);

  //Set RAM X - address Start / End position
  writeCMD(0x44);
  writeData(0x00);
  writeData(0x0F);

  //Set RAM Y - address Start / End position
  writeCMD(0x45);
  writeData(0xF9);
  writeData(0x00);
  writeData(0x00);
  writeData(0x00);

  //Border Waveform Control
  writeCMD(0x3C);
  writeData(0x05);

  //Display Update Control 1
  writeCMD(0x21);
  writeData(0x00);
  writeData(0x80);

  //Temperature Sensor Control
  writeCMD(0x18);
  writeData(0x80);

  // Set RAM X and RAM Y address counter
  writeCMD(0x4E);
  writeData(0x00);
  writeCMD(0x4F);
  writeData(0xF9);
  writeData(0x00);
  WAIT_BUSY;
}

//================================================================================
void partialUpdateSolid(uint8_t x1, uint8_t y1, uint16_t x2, uint16_t y2, uint8_t color)
{

  //Border Waveform Control
  writeCMD(0x3C);
  writeData(0x80);

  //Set RAM X - address Start / End position
  writeCMD(0x44);
  writeData(x1);
  writeData(x2);

  //Set RAM Y - address Start / End position
  writeCMD(0x45);
  writeData(y1 & 0xff);
  writeData(y1 >> 8);
  writeData(y2 & 0xff);
  writeData(y2 >> 8);

  // Set RAM X and RAM Y address counter
  writeCMD(0x4E);
  writeData(x1);
  writeCMD(0x4F);
  writeData(y1 & 0xff);
  writeData(y1 >> 8);

  writeCMD(0x24);
  int i;
  int h;
  for (h = 0; h < y2 - y1; h++)
  {
    for (i = 0; i < (x2 - x1) / 8; i++)
    {
      writeData(color);
    }
  }

  //partial refresh of the same area as the partial update
  partialUpdate();
  WAIT_BUSY;
  initEPD();
}

//================================================================================
void setBaseMap(const uint8_t *holder)
{
  writeCMD(0x24); //Write Black and White image to RAM
  for (int i = 0; i < MONO_ARRAY_SIZE; i++)
  {
    writeData(pgm_read_byte(&holder[i]));
  }

  writeCMD(0x26); //Write Black and White image to RAM
  for (int i = 0; i < MONO_ARRAY_SIZE; i++)
  {
    writeData(pgm_read_byte(&holder[i]));
  }
  fullUpdate();
}

//================================================================================
void partialUpdateCharacters(const uint8_t *holder)
{

  //x1 must be divisible by 8
  uint16_t x1 = 0;
  uint16_t y1 = 100;
  uint16_t x2 = x1 + (64 / 8) - 1;
  uint16_t y2 = y1 + (58) - 1;

  //reset driver
  ePaper_RST_0;
  delay(40);
  ePaper_RST_1;
  delay(40);

  //Border Waveform Control
  writeCMD(0x3C);
  writeData(0x80);

  //Set RAM X - address Start / End position
  writeCMD(0x44);
  writeData(x1);
  writeData(x2);

  //Set RAM Y - address Start / End position
  writeCMD(0x45);
  writeData(y1 & 0xff);
  writeData(y1 >> 8);
  writeData(y2 & 0xff);
  writeData(y2 >> 8);

  // Set RAM X and RAM Y address counter
  writeCMD(0x4E);
  writeData(x1);
  writeCMD(0x4F);
  writeData(y1 & 0xff);
  writeData(y1 >> 8);

  writeCMD(0x24);
  int i;
  int h;
  for (h = 0; h <= y2 - y1; h++)
  {
    for (i = 0; i < (x2 - x1 + 1); i++)
    {
      writeData(~pgm_read_byte(&holder[i + h * 8]));
    }
  }

  //partial refresh of the same area as the partial update
  partialUpdate();
  WAIT_BUSY;
}

//================================================================================
void show_BMPs_in_root(void)
{
  File
      root_dir;
  root_dir = SD.open("/");
  if (0 == root_dir)
  {
    Serial.println("show_BMPs_in_root: Can't open \"root\"");
    return;
  }

  File
      bmp_file;

  while (1)
  {
    bmp_file = root_dir.openNextFile();
    Serial.println(bmp_file);
    if (0 == bmp_file)
    {
      // no more files, break out of while()
      // root_dir will be closed below.
      break;
    }
    //Skip directories (what about volume name?)
    if (0 == bmp_file.isDirectory())
    {
      //The file name must include ".BMP"
      if (0 != strstr(bmp_file.name(), ".BMP"))
      {
        Serial.println(bmp_file.name());
        //The BMP must be exactly 36918 long
        //(this is correct for182x96, 24-bit)
        uint32_t size = bmp_file.size();

        Serial.println(size);
        if ((uint32_t)HRES * VRES * 3 + 50 <= size <= (uint32_t)HRES * VRES * 3 + 60)
        {
          Serial.println("in final loop");

          //Make sure the display is not busy before starting a new command.
          WAIT_BUSY;

          //Select the controller

          writeCMD(0x13);
          //Jump over BMP header
          bmp_file.seek(54);
          //grab one row of pixels from the SD card at a time
          static uint8_t one_line[HRES / 2 * 3];
          for (int line = 0; line < VRES * 2; line++)
          {

            //Set the LCD to the left of this line. BMPs store data
            //to have the image drawn from the other end, uncomment the line below

            //read a line from the SD card
            bmp_file.read(one_line, HRES / 2 * 3);

            //send the line to the display
            send_pixels_BW(HRES / 2 * 3, one_line);
          }

          Serial.println("refreshing......");
          //Write the command: Display Refresh (DRF)
          fullUpdate();
          //Make sure the display is not busy before starting a new command.
          WAIT_BUSY;

          Serial.print(" complete");
          //Give a bit to let them see it
          delay(3000);
        }
      }
    }
    //Release the BMP file handle
    bmp_file.close();
  }
  //Release the root directory file handle
  root_dir.close();
}

//================================================================================
void Load_Flash_Image_To_Display_RAM_RLE(uint16_t width_pixels,
                                         uint16_t height_pixels,
                                         const uint8_t *BW_image)
{
  //Index into *image, that works with pgm_read_byte()
  uint8_t count = 0;

  //Get width_bytes from width_pixel, rounding up
  uint8_t
      width_bytes;
  width_bytes = (width_pixels + 7) >> 3;

  //Make sure the display is not busy before starting a new command.
  WAIT_BUSY;

  //Select the controller
  ePaper_CS_0;

  //Aim at the command register
  ePaper_DC_0;

  // Write RAM (Black White) / RAM 0x24
  // After this command, data entries will be
  // written into the BW RAM until another
  // command is written. Address pointers will
  // advance accordingly
  SPI.transfer(0x24);
  //Pump out the data.
  ePaper_DC_1;
  count = 0;
  for (int i = 0; i < MONO_ARRAY_SIZE; i = i + 2)
  {
    count = pgm_read_byte(&BW_image[i]);
    for (uint8_t j = 0; j < count; j++)
      SPI.transfer(pgm_read_byte(&BW_image[i + 1]));
  }

  fullUpdate();

  //Deslect the controller
  ePaper_CS_1;
}

//================================================================================
void Load_Flash_Image_To_Display_RAM(uint16_t width_pixels,
                                     uint16_t height_pixels,
                                     const uint8_t *BW_image)
{
  //Index into *image, that works with pgm_read_byte()
  uint8_t count = 0;

  //Get width_bytes from width_pixel, rounding up
  uint8_t
      width_bytes;
  width_bytes = (width_pixels + 7) >> 3;

  //Make sure the display is not busy before starting a new command.
  WAIT_BUSY;

  //Select the controller
  ePaper_CS_0;

  //Aim at the command register
  ePaper_DC_0;
  // Write RAM (Black White) / RAM 0x24
  // After this command, data entries will be
  // written into the BW RAM until another
  // command is written. Address pointers will
  // advance accordingly
  SPI.transfer(0x24);
  //Pump out the data.
  ePaper_DC_1;
  count = 0;
  for (int i = 0; i < MONO_ARRAY_SIZE; i++)
  {
    SPI.transfer(pgm_read_byte(&BW_image[i]));
  }

  fullUpdate();

  //Deslect the controller
  ePaper_CS_1;
}

//================================================================================
void send_pixels_BW(uint16_t byteCount, uint8_t *dataPtr)
{
  uint8_t data;
  uint8_t red;
  uint8_t green;
  uint8_t blue;
  while (byteCount != 0)
  {
    uint8_t data = 0;
    red = *dataPtr;
    dataPtr++;
    byteCount--;
    green = *dataPtr;
    dataPtr++;
    byteCount--;
    blue = *dataPtr;
    dataPtr++;
    byteCount--;

    if (150 > ((red * .21) + (green * .72) + (blue * .07)))
    {
      data = data | 0x01;
    }

    for (uint8_t i = 0; i < 7; i++)
    {
      red = *dataPtr;
      dataPtr++;
      byteCount--;
      green = *dataPtr;
      dataPtr++;
      byteCount--;
      blue = *dataPtr;
      dataPtr++;
      byteCount--;
      data = data << 1;
      if (127 > ((red * .21) + (green * .72) + (blue * .07)))
      {
        data = data | 0x01;
      }
      else
      {
        data = data & 0xFE;
      }
    }
    writeData(data);
  }
}

void outDeepSleep()
{
  //Software Reset
  WAIT_BUSY;

  writeCMD(0x12);
  WAIT_BUSY;

  writeCMD(0x10);
  writeData(0x00);
}

void deepSleep()
{
  writeCMD(0x10);
  writeData(0x01);
}

//=============================================================================
#define SHUTDOWN_BETWEEN_UPDATES (0)
#define waittime 5000
#define splashscreen 1
#define partialUpdate 1
#define showBMPs 0
#define black 1
#define white 1
void loop()
{
  Serial.println("top of loop");

#if splashscreen
  initEPD();

  //load an image to the display
  Load_Flash_Image_To_Display_RAM(HRES, VRES, Mono_1BPP);

  Serial.print("refreshing . . . ");
  WAIT_BUSY;

  Serial.println("refresh complete");
  //for maximum power conservation, power off the EPD
  delay(waittime);

#endif
#if partialUpdate

  initEPD();
  setBaseMap(Mono_1BPP);
  WAIT_BUSY;
  delay(100);

  partialUpdateCharacters(Mono_Letter_C);
  partialUpdateCharacters(Mono_Letter_F);
  partialUpdateCharacters(Mono_Letter_A);
  partialUpdateCharacters(Mono_Letter_P);
  delay(waittime);
#endif

#if showBMPs
  //BMPs are inverted
  initEPD();

  Epaper_Write_Command(0x01); //Driver output control
  Epaper_Write_Data(0xF9);
  Epaper_Write_Data(0x00);
  Epaper_Write_Data(0x01);
  show_BMPs_in_root();
  delay(waittime);

  //flip the display back to normal
  Epaper_Write_Command(0x01); //Driver output control
  Epaper_Write_Data(0xF9);
  Epaper_Write_Data(0x00);
  Epaper_Write_Data(0x00);

#endif

#if black
  initEPD();

  //Make sure the display is not busy before starting a new command.
  WAIT_BUSY;

  //Select the controller
  ePaper_CS_0;

  //Aim at the command register
  ePaper_DC_0;
  // Write RAM (Black White) / RAM 0x24
  // After this command, data entries will be
  // written into the BW RAM until another
  // command is written. Address pointers will
  // advance accordingly
  SPI.transfer(0x24);
  //Pump out the data.
  ePaper_DC_1;
  for (int i = 0; i < MONO_ARRAY_SIZE; i++)
  {
    SPI.transfer(0xff);
  }

  fullUpdate();

  //Deslect the controller
  ePaper_CS_1;

  delay(waittime);
#endif

#if white
  initEPD();
  //Make sure the display is not busy before starting a new command.
  WAIT_BUSY;

  //Select the controller
  ePaper_CS_0;

  //Aim at the command register
  ePaper_DC_0;
  // Write RAM (Black White) / RAM 0x24
  // After this command, data entries will be
  // written into the BW RAM until another
  // command is written. Address pointers will
  // advance accordingly
  SPI.transfer(0x24);
  //Pump out the data.
  ePaper_DC_1;
  for (int i = 0; i < MONO_ARRAY_SIZE; i++)
  {
    SPI.transfer(0x00);
  }

  fullUpdate();

  //Deslect the controller
  ePaper_CS_1;

  delay(waittime);
#endif

}
//=============================================================================

here is the compiler output

FQBN: Seeeduino:nrf52:xiaonRF52840Sense
Using board 'xiaonRF52840Sense' from platform in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1
Using core 'nRF5' from platform in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1


Linking everything together...
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\tools\\arm-none-eabi-gcc\\9-2019q4/bin/arm-none-eabi-gcc" "-LC:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\hardware\\nrf52\\1.1.1/tools/adafruit-nrfutil/win32/adafruit-nrfutil.exe" dfu genpkg --dev-type 0x0052 --sd-req 0x0123 --application "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.hex" "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.zip"
Zip created at C:\Users\Dude\AppData\Local\Temp\arduino\sketches\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.zip

Using library epd4in2 at version 1.0 in folder: D:\Arduino_projects\libraries\epd4in2-demo 
Using library SPI at version 1.0 in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1\libraries\SPI 
Using library SD at version 1.2.4 in folder: C:\Users\Dude\AppData\Local\Arduino15\libraries\SD 
Using library Adafruit TinyUSB Library at version 1.7.0 in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\nrf52\1.1.1\libraries\Adafruit_TinyUSB_Arduino 
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\tools\\arm-none-eabi-gcc\\9-2019q4/bin/arm-none-eabi-size" -A "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\5F57683B010A56727E94AB4AF4618B60/CFAP122250A20213.ino.elf"
Sketch uses 58220 bytes (7%) of program storage space. Maximum is 811008 bytes.
Global variables use 7912 bytes (3%) of dynamic memory, leaving 229656 bytes for local variables. Maximum is 237568 bytes.

Serial output looks like this.

SD could not initialize
setup complete
top of loop
refreshing . . . refresh complete
top of loop
refreshing . . . refresh complete
top of loop
refreshing . . . refresh complete
top of loop
refreshing . . . refresh complete

HTH
GL :slight_smile: PJ

Nice Display for sure.! :sunglasses: :+1:

That’s neat but I’m using the Xiao SAMD21 board.
Not sure about the code compatibility

Hi there,

e-Paper  Xiao Nrf52840 Sense	
SIGNAL(color)   NAME    PIN  PORT
--------------------------------------
BUSY Purp	D3           4	  P0.29
RST	White   D4  (SDA)    5    P0.05
DC	Green	D5  (SCL)    6	  P0.04
CS	Orange	D7  (RXD)    8	  P1.12
CLK	Yellow	D8  (SCLK)   9	  P1.13
DIN	BLUE	D10 (MOSI)  11	  P1.15

GND	BROWN	GND	    13
VCC	GRAY	3V3 	    12

So, Yes solid , FAST display, super low power too and beside the Crystal Fonts Demo, I was able to also use the LINK on the 4.2" Seeed sales page Example code for the “Good Display” brand and once I set the correct pins it worked AOK.


This is to show they are ALL the same as far as E-paper goes. Waveshare makes the display “code compatibility” :face_with_peeking_eye: will only come down to 2 things
Memory & Pin configuration. So maybe start with the Examples on the Sales pages and Post your progress. Seems as if you’re not having enough ram? 32K isn’t allot.
HTH
GL :slight_smile: PJ :vulcan_salute:

FWIW there are a multitude of LIBRARY’s as well as examples that work GDEY042T81,GDEW042T2 4.2" b/w , CFAP122250A20213 & CFAP400300A0-420

Small update: I got the 4.2-inch e-paper display to work with the Xiao samd21 but only about 50% of the time which is a bit strange. What I mean by 50% is that if you unplug the power supply to the Xiao and plug it back in sometimes the display works and other times it doesn’t. This is a rough approximation. However, it only works when supplied by the Xiao’s 5V pin, not 3.3V. With 3.3V it doesn’t ever function.
Interestingly, I got the Xiao to work flawlessly with the Waveshare 2.9-inch and 1.54-inch e-paper displays. Also only while supplied with 5V.

#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold9pt7b.h>

// Pin configuration for Seeeduino Xiao SAMD21
// Display    Xiao pin #
//   BUSY  ->  1
//   RST   ->  2
//   DC    ->  3
//   CS    ->  4
//   CLK   ->  8
//   DIN   ->  10
//   GND   ->  GND
//   VCC   ->  5V
#define EPD_CS    D4
#define EPD_DC    D3
#define EPD_RST   D2
#define EPD_BUSY  D1

// 4.2 inch e-paper
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));

// 2.9 inch e-paper
// GxEPD2_BW<GxEPD2_290_T94_V2, GxEPD2_290_T94_V2::HEIGHT> display(GxEPD2_290_T94_V2(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));

// 1.54 inch e-paper
// GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));

void setup() {
  Serial.begin(9600);
  display.init();
  display.setRotation(1);  
}

void loop() {
  display.fillScreen(GxEPD_WHITE);
  display.setTextColor(GxEPD_BLACK);
  display.setFont(&FreeMonoBold9pt7b);

  display.setCursor(10, 50);
  display.print("Hello, World!");
  display.display();
  delay(1000);

  display.fillScreen(GxEPD_WHITE);
  display.display();
  delay(1000);
}