M5Stack PaperS3 improvements and other bug fixes (#512)
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
#include <Tactility/hal/touch/TouchDevice.h>
|
||||
|
||||
#include <epd_highlevel.h>
|
||||
#include <epdiy.h>
|
||||
#include <lvgl.h>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
class EpdiyDisplay final : public tt::hal::display::DisplayDevice {
|
||||
|
||||
public:
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
|
||||
Configuration(
|
||||
const EpdBoardDefinition* board,
|
||||
const EpdDisplay_t* display,
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> touch = nullptr,
|
||||
enum EpdInitOptions initOptions = EPD_OPTIONS_DEFAULT,
|
||||
const EpdWaveform* waveform = EPD_BUILTIN_WAVEFORM,
|
||||
int defaultTemperature = 25,
|
||||
enum EpdDrawMode defaultDrawMode = MODE_GL16,
|
||||
bool fullRefresh = false,
|
||||
enum EpdRotation rotation = EPD_ROT_LANDSCAPE
|
||||
) : board(board),
|
||||
display(display),
|
||||
touch(std::move(touch)),
|
||||
initOptions(initOptions),
|
||||
waveform(waveform),
|
||||
defaultTemperature(defaultTemperature),
|
||||
defaultDrawMode(defaultDrawMode),
|
||||
fullRefresh(fullRefresh),
|
||||
rotation(rotation) {
|
||||
check(board != nullptr);
|
||||
check(display != nullptr);
|
||||
}
|
||||
|
||||
const EpdBoardDefinition* board;
|
||||
const EpdDisplay_t* display;
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> touch;
|
||||
enum EpdInitOptions initOptions;
|
||||
const EpdWaveform* waveform;
|
||||
int defaultTemperature;
|
||||
enum EpdDrawMode defaultDrawMode;
|
||||
bool fullRefresh;
|
||||
enum EpdRotation rotation;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr<Configuration> configuration;
|
||||
lv_display_t* _Nullable lvglDisplay = nullptr;
|
||||
EpdiyHighlevelState highlevelState = {};
|
||||
uint8_t* framebuffer = nullptr;
|
||||
uint8_t* lvglDrawBuffer = nullptr;
|
||||
uint8_t* packedBuffer = nullptr; // Pre-allocated 4-bit packed pixel buffer for flushInternal
|
||||
bool initialized = false;
|
||||
bool powered = false;
|
||||
|
||||
// epd_hl_init() sets an internal already_initialized flag and has no matching deinit.
|
||||
// We track first-time init statically and keep the HL state alive across stop()/start() cycles.
|
||||
static bool s_hlInitialized;
|
||||
static EpdiyHighlevelState s_hlState;
|
||||
|
||||
static void flushCallback(lv_display_t* display, const lv_area_t* area, uint8_t* pixelMap);
|
||||
void flushInternal(const lv_area_t* area, uint8_t* pixelMap, bool isLast);
|
||||
|
||||
static void rotationEventCallback(lv_event_t* event);
|
||||
void handleRotationChange(lv_display_rotation_t rotation);
|
||||
|
||||
// Rotation mapping helpers
|
||||
static lv_display_rotation_t epdRotationToLvgl(enum EpdRotation epdRotation);
|
||||
static enum EpdRotation lvglRotationToEpd(lv_display_rotation_t lvglRotation);
|
||||
|
||||
public:
|
||||
|
||||
explicit EpdiyDisplay(std::unique_ptr<Configuration> inConfiguration);
|
||||
|
||||
~EpdiyDisplay() override;
|
||||
|
||||
std::string getName() const override { return "EPDiy"; }
|
||||
|
||||
std::string getDescription() const override {
|
||||
return "E-Ink display powered by EPDiy library";
|
||||
}
|
||||
|
||||
// Device lifecycle
|
||||
bool start() override;
|
||||
bool stop() override;
|
||||
|
||||
// Power control
|
||||
void setPowerOn(bool turnOn) override;
|
||||
bool isPoweredOn() const override { return powered; }
|
||||
bool supportsPowerControl() const override { return true; }
|
||||
|
||||
// Touch device
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable getTouchDevice() override {
|
||||
return configuration->touch;
|
||||
}
|
||||
|
||||
// LVGL support
|
||||
bool supportsLvgl() const override { return true; }
|
||||
bool startLvgl() override;
|
||||
bool stopLvgl() override;
|
||||
lv_display_t* _Nullable getLvglDisplay() const override { return lvglDisplay; }
|
||||
|
||||
// DisplayDriver (not supported for EPD)
|
||||
bool supportsDisplayDriver() const override { return false; }
|
||||
std::shared_ptr<tt::hal::display::DisplayDriver> _Nullable getDisplayDriver() override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// EPD specific functions
|
||||
|
||||
/**
|
||||
* Get a reference to the framebuffer
|
||||
*/
|
||||
uint8_t* getFramebuffer() {
|
||||
return epd_hl_get_framebuffer(&highlevelState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the screen by flashing it
|
||||
*/
|
||||
void clearScreen();
|
||||
|
||||
/**
|
||||
* Clear an area by flashing it
|
||||
*/
|
||||
void clearArea(EpdRect area);
|
||||
|
||||
/**
|
||||
* Manually trigger a screen update
|
||||
* @param mode The draw mode to use (defaults to configuration default)
|
||||
* @param temperature Temperature in °C (defaults to configuration default)
|
||||
*/
|
||||
enum EpdDrawError updateScreen(
|
||||
enum EpdDrawMode mode = MODE_UNKNOWN_WAVEFORM,
|
||||
int temperature = -1
|
||||
);
|
||||
|
||||
/**
|
||||
* Update a specific area of the screen
|
||||
* @param area The area to update
|
||||
* @param mode The draw mode to use (defaults to configuration default)
|
||||
* @param temperature Temperature in °C (defaults to configuration default)
|
||||
*/
|
||||
enum EpdDrawError updateArea(
|
||||
EpdRect area,
|
||||
enum EpdDrawMode mode = MODE_UNKNOWN_WAVEFORM,
|
||||
int temperature = -1
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the display to all white
|
||||
*/
|
||||
void setAllWhite();
|
||||
};
|
||||
Reference in New Issue
Block a user