mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-04-18 09:25:06 +00:00
164 lines
5.0 KiB
C++
164 lines
5.0 KiB
C++
#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();
|
|
};
|