GxEPD2 How to declare/initialize in my own .cpp/.h

Hi

I'm less experienced in writing C++ code. To keep my code clean I wanted to encapsulate the ePaper API in my own .cpp/.h file.

Because of GxEPD2_3C doesn't have a default constructor I don't know how to declare the display variable in my header file. Since C++ doesn't allow declaration without initialization I tried to initialize it in a dummy way and override it later.

What I tried is using a point instead: GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display
But know I have to treat with the variable deletion and use of -> instead of . to reference class members. If this is the way to go, then it is...
But, going this way results in mirrored output. If I print display.print("Hello"); then the out put is mirrored (letter order is reversed and letter itself is mirrored). I guess this is due to a byte-order issue.

What I have so far without the pointer stuff:

sketch.ino

#include "EPaper.h"

DisplayPins displayPins = {
    15, // CS
    27, // DC
    26, // RST
    25, // BUSY
    13, // SCK
    12, // MISO
    14 // MOSI
};

EPaper epaper = EPaper(displayPins);

void setup() {
    while (!epaper.setup()) {
        Serial.println("E-Paper display not ready");
        delay(1000);
    }
    epaper.test();
}

void loop() {
}

EPaper.h

#ifndef EPAPER_H
#define EPAPER_H

#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include "bitmaps/Bitmaps3c200x200.h" // 1.54" b/w/r

typedef struct {
    int cs;
    int dc;
    int rst;
    int busy;
    int sck;
    int miso;
    int mosi;
} DisplayPins;

class EPaper
{
    public:
        const bool hasDeepSleepSupport = true;

        EPaper(DisplayPins displayPins);

        bool setup(void);
        void test(void);
        void clear(uint16_t color);

    private:
        DisplayPins displayPins;
        GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display; // Doesn't work, no default constructor

};
#endif

EPaper.cpp

#include "EPaper.h"

EPaper::EPaper(DisplayPins pins) {
    displayPins = pins;
    display(GxEPD2_154c(displayPins.cs, displayPins.dc, displayPins.rst, displayPins.busy)); // Doesn't work
}

bool EPaper::setup(void) {
    display.init(115200);
    SPI.end();
    SPI.begin(EPaper::displayPins.sck, EPaper::displayPins.miso, EPaper::displayPins.mosi, EPaper::displayPins.cs);

    return true;
}

void EPaper::test(void) {   
    display.setRotation(1);
    display.setFont(&FreeMonoBold9pt7b);
    display.setTextColor(GxEPD_BLACK);
    display.setFullWindow();
    
    display.firstPage();
    do {
        display.fillScreen(GxEPD_WHITE);
        display.setCursor(50, 50);
        
        display.print("Test");
    } while (display.nextPage());
}

Thank you for pointing me into the right direction.
Cheers Danny

@dannyyy,

welcome to the forum. Maybe you should start with reading General Guidance and How to use the Forum and Learn How To Use The Forum.

Unfortunately I am not clever enough to understand what you want to do, maybe because you don't explain why you want to do what you want to do.

I'm less experienced in writing C++ code.

Maybe you should start with something easier.

Jean-Marc

@ZingJM

I barely doubt you read a single line of my code. Otherwise it should be obviouse, which two lines are wrong and I need some help for.

To your next question why. The ePaper example code is more than a mess. Honestly no one want to have that kind of code in its .ino file. Therefor I wanted to abstract the whole ePaper library once more to have clean interfaces and as lose coupling as possible. My main programm shouldn't change if I decide to use another display library.

Nevertheless I try to rephrase my question.
The following code produces the output depicted in the following image.
Exptected: Imgur: The magic of the Internet
Actual: Imgur: The magic of the Internet

Question 1: Is this intended to be like that?
Question 2: If yes, how can I solve it?

class EPaper
{
    public:
        const bool hasDeepSleepSupport = true;

        EPaper(DisplayPins displayPins);

        bool setup(void);
        void test(void);
        void clear(uint16_t color);

    private:
        DisplayPins displayPins;
        GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> *display; // <------

};
#include "EPaper.h"

EPaper::EPaper(DisplayPins pins) {
    displayPins = pins;
    display = new GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT>(GxEPD2_154c(displayPins.cs, displayPins.dc, displayPins.rst, displayPins.busy));
}

bool EPaper::setup(void) {
    display->init(115200);
    SPI.end();
    SPI.begin(EPaper::displayPins.sck, EPaper::displayPins.miso, EPaper::displayPins.mosi, EPaper::displayPins.cs);

    return true;
}

void EPaper::test(void) {   
    display->setRotation(1);
    display->setFont(&FreeMonoBold9pt7b);
    display->setTextColor(GxEPD_BLACK);
    display->setFullWindow();
    
    display->firstPage();
    do {
        display->fillScreen(GxEPD_WHITE);
        display->setCursor(50, 50);
        
        display->print("Hello World"); // <----- Output is mirrored
    } while (display->nextPage());
}

Maybe adding this mirror function in setup will help. Try true and false as parameters.

@dannyyy,

thank you for the explanation. I wish you Good Luck.

Jean-Marc

bodmer:
Maybe adding this mirror function in setup will help. Try true and false as parameters.

@bodmer
Thank you. This did the trick.
I initialy tried it with "mirror(true)", but I had to set it to "mirror(false)".
The mentioned solution using a pointer to reference the dispay object works like a charm.

@ZinggJM
Btw your core library is awesome. I only complaint about the examples, for a real project this need in my opinion another layer of abstraction. At that moment I was criticizing on that part and I cannot deny, your answer was in my kind also disrespectful. I appoligize if you felt being attacked by my words.

Cheers
Danny

Glad to here it worked. I have not used the library so the suggestion was just a guess.

I understand that you wish to clean up the examples configuration setting but typically there is just one option you need and the rest can be deleted.

The flexibility of these libraries means there are lots of configuration options. For example, look at this "Hello World" sketch. The main code is just a few lines but there are 174 lines before that which are configuration options...