Tasmota/lib/libesp32_epdiy/src/epd_driver/include/epd_driver.h
2021-04-03 17:41:35 +02:00

472 lines
15 KiB
C
Executable File

/**
* @file epd_driver.h
* A driver library for drawing to an EPD.
*/
#ifdef __cplusplus
extern "C" {
#endif
#define CONFIG_EPD_DISPLAY_TYPE_ED047TC1
#define CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
#pragma once
#include "esp_attr.h"
#include "epd_internals.h"
#include <stdbool.h>
#include <stdint.h>
/// An area on the display.
typedef struct {
/// Horizontal position.
int x;
/// Vertical position.
int y;
/// Area / image width, must be positive.
int width;
/// Area / image height, must be positive.
int height;
} EpdRect;
/// Possible failures when drawing.
enum EpdDrawError {
EPD_DRAW_SUCCESS = 0x0,
/// No valid framebuffer packing mode was specified.
EPD_DRAW_INVALID_PACKING_MODE = 0x1,
/// No lookup table implementation for this mode / packing.
EPD_DRAW_LOOKUP_NOT_IMPLEMENTED = 0x2,
/// The string to draw is invalid.
EPD_DRAW_STRING_INVALID = 0x4,
/// The string was not empty, but no characters where drawable.
EPD_DRAW_NO_DRAWABLE_CHARACTERS = 0x8,
/// Allocation failed
EPD_DRAW_FAILED_ALLOC = 0x10,
/// A glyph could not be drawn, and not fallback was present.
EPD_DRAW_GLYPH_FALLBACK_FAILED = 0x20,
/// The specified crop area is invalid.
EPD_DRAW_INVALID_CROP = 0x40,
/// No such mode is available with the current waveform.
EPD_DRAW_MODE_NOT_FOUND = 0x80,
/// The waveform info file contains no applicable temperature range.
EPD_DRAW_NO_PHASES_AVAILABLE = 0x100,
/// An invalid combination of font flags was used.
EPD_DRAW_INVALID_FONT_FLAGS = 0x200,
};
/// Global EPD driver options.
enum EpdInitOptions {
/// Use the default options.
EPD_OPTIONS_DEFAULT = 0,
/// Use a small look-up table of 1024 bytes.
/// The EPD driver will use less space, but performance may be worse.
EPD_LUT_1K = 1,
/// Use a 64K lookup table. (default)
/// Best performance, but permanently occupies a 64k block of internal memory.
EPD_LUT_64K = 2,
/// Use a small feed queue of 8 display lines.
/// This uses less memory, but may impact performance.
EPD_FEED_QUEUE_8 = 4,
/// Use a feed queue of 32 display lines. (default)
/// Best performance, but larger memory footprint.
EPD_FEED_QUEUE_32 = 8,
};
/// The image drawing mode.
enum EpdDrawMode {
/// An init waveform.
/// This is currently unused, use `epd_clear()` instead.
MODE_INIT = 0x0,
/// Direct Update: Go from any color to black for white only.
MODE_DU = 0x1,
/// Go from any grayscale value to another with a flashing update.
MODE_GC16 = 0x2,
/// Faster version of `MODE_GC16`.
/// Not available with default epdiy waveforms.
MODE_GC16_FAST = 0x3,
/// Animation Mode: Fast, monochrom updates.
/// Not available with default epdiy waveforms.
MODE_A2 = 0x4,
/// Go from any grayscale value to another with a non-flashing update.
MODE_GL16 = 0x5,
/// Faster version of `MODE_GL16`.
/// Not available with default epdiy waveforms.
MODE_GL16_FAST = 0x6,
/// A 4-grayscale version of `MODE_DU`.
/// Not available with default epdiy waveforms.
MODE_DU4 = 0x7,
/// Arbitrary transitions for 4 grayscale values.
/// Not available with default epdiy waveforms.
MODE_GL4 = 0xA,
/// Not available with default epdiy waveforms.
MODE_GL16_INV = 0xB,
/// Go from a white screen to arbitrary grayscale, quickly.
/// Exclusively available with epdiy waveforms.
MODE_EPDIY_WHITE_TO_GL16 = 0x10,
/// Go from a black screen to arbitrary grayscale, quickly.
/// Exclusively available with epdiy waveforms.
MODE_EPDIY_BLACK_TO_GL16 = 0x11,
/// Monochrome mode. Only supported with 1bpp buffers.
MODE_EPDIY_MONOCHROME = 0x20,
MODE_UNKNOWN_WAVEFORM = 0x3F,
// Framebuffer packing modes
/// 1 bit-per-pixel framebuffer with 0 = black, 1 = white.
/// MSB is left is the leftmost pixel, LSB the rightmost pixel.
MODE_PACKING_8PPB = 0x40,
/// 4 bit-per pixel framebuffer with 0x0 = black, 0xF = white.
/// The upper nibble corresponds to the left pixel.
/// A byte cannot wrap over multiple rows, images of uneven width
/// must add a padding nibble per line.
MODE_PACKING_2PPB = 0x80,
/// A difference image with one pixel per byte.
/// The upper nibble marks the "from" color,
/// the lower nibble the "to" color.
MODE_PACKING_1PPB_DIFFERENCE = 0x100,
// reserver for 4PPB mode
/// Assert that the display has a uniform color, e.g. after initialization.
/// If `MODE_PACKING_2PPB` is specified, a optimized output calculation can be used.
/// Draw on a white background
PREVIOUSLY_WHITE = 0x200,
/// See `PREVIOUSLY_WHITE`.
/// Draw on a black background
PREVIOUSLY_BLACK = 0x400,
};
/// The default draw mode (non-flashy refresh, whith previously white screen).
#define EPD_MODE_DEFAULT (MODE_GL16 | PREVIOUSLY_WHITE)
/// Font drawing flags
enum EpdFontFlags {
/// Draw a background.
///
/// Take the background into account
/// when calculating the size.
EPD_DRAW_BACKGROUND = 0x1,
/// Left-Align lines
EPD_DRAW_ALIGN_LEFT = 0x2,
/// Right-align lines
EPD_DRAW_ALIGN_RIGHT = 0x4,
/// Center-align lines
EPD_DRAW_ALIGN_CENTER = 0x8,
};
/// Font properties.
typedef struct {
/// Foreground color
uint8_t fg_color : 4;
/// Background color
uint8_t bg_color : 4;
/// Use the glyph for this codepoint for missing glyphs.
uint32_t fallback_glyph;
/// Additional flags, reserved for future use
enum EpdFontFlags flags;
} EpdFontProperties;
/** Initialize the ePaper display */
void epd_init(enum EpdInitOptions options);
/** Deinit the ePaper display */
void epd_deinit();
/** Enable display power supply. */
void epd_poweron();
/** Disable display power supply. */
void epd_poweroff();
/** Clear the whole screen by flashing it. */
void epd_clear();
/**
* Clear an area by flashing it.
*
* @param area: The area to clear.
*/
void epd_clear_area(EpdRect area);
/**
* Clear an area by flashing it.
*
* @param area: The area to clear.
* @param cycles: The number of black-to-white clear cycles.
* @param cycle_time: Length of a cycle. Default: 50 (us).
*/
void epd_clear_area_cycles(EpdRect area, int cycles, int cycle_time);
/**
* @returns Rectancle representing the whole screen area.
*/
EpdRect epd_full_screen();
/**
* Draw a picture to a given framebuffer.
*
* @param image_area: The area to copy to. `width` and `height` of the area
* must correspond to the image dimensions in pixels.
* @param image_data: The image data, as a buffer of 4 bit wide brightness
* values. Pixel data is packed (two pixels per byte). A byte cannot wrap over
* multiple rows, images of uneven width must add a padding nibble per line.
* @param framebuffer: The framebuffer object,
* which must be `EPD_WIDTH / 2 * EPD_HEIGHT` large.
*/
void epd_copy_to_framebuffer(EpdRect image_area, const uint8_t *image_data,
uint8_t *framebuffer);
/**
* Draw a pixel a given framebuffer.
*
* @param x: Horizontal position in pixels.
* @param y: Vertical position in pixels.
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_draw_pixel(int x, int y, uint8_t color, uint8_t *framebuffer);
/**
* Draw a horizontal line to a given framebuffer.
*
* @param x: Horizontal start position in pixels.
* @param y: Vertical start position in pixels.
* @param length: Length of the line in pixels.
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
* which must be `EPD_WIDTH / 2 * EPD_HEIGHT` bytes large.
*/
void epd_draw_hline(int x, int y, int length, uint8_t color,
uint8_t *framebuffer);
/**
* Draw a horizontal line to a given framebuffer.
*
* @param x: Horizontal start position in pixels.
* @param y: Vertical start position in pixels.
* @param length: Length of the line in pixels.
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
* which must be `EPD_WIDTH / 2 * EPD_HEIGHT` bytes large.
*/
void epd_draw_vline(int x, int y, int length, uint8_t color,
uint8_t *framebuffer);
void epd_fill_circle_helper(int x0, int y0, int r, int corners, int delta,
uint8_t color, uint8_t *framebuffer);
/**
* Draw a circle with given center and radius
*
* @param x: Center-point x coordinate
* @param y: Center-point y coordinate
* @param r: Radius of the circle in pixels
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_draw_circle(int x, int y, int r, uint8_t color, uint8_t *framebuffer);
/**
* Draw a circle with fill with given center and radius
*
* @param x: Center-point x coordinate
* @param y: Center-point y coordinate
* @param r: Radius of the circle in pixels
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_fill_circle(int x, int y, int r, uint8_t color, uint8_t *framebuffer);
/**
* Draw a rectanle with no fill color
*
* @param rect: The rectangle to draw.
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_draw_rect(EpdRect rect, uint8_t color, uint8_t *framebuffer);
/**
* Draw a rectanle with fill color
*
* @param rect: The rectangle to fill.
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_fill_rect(EpdRect rect, uint8_t color, uint8_t *framebuffer);
/**
* Draw a line
*
* @param x0 Start point x coordinate
* @param y0 Start point y coordinate
* @param x1 End point x coordinate
* @param y1 End point y coordinate
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_draw_line(int x0, int y0, int x1, int y1, uint8_t color,
uint8_t *framebuffer);
/**
* Draw a triangle with no fill color
*
* @param x0 Vertex #0 x coordinate
* @param y0 Vertex #0 y coordinate
* @param x1 Vertex #1 x coordinate
* @param y1 Vertex #1 y coordinate
* @param x2 Vertex #2 x coordinate
* @param y2 Vertex #2 y coordinate
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
uint8_t color, uint8_t *framebuffer);
/**
* Draw a triangle with color-fill
*
* @param x0 Vertex #0 x coordinate
* @param y0 Vertex #0 y coordinate
* @param x1 Vertex #1 x coordinate
* @param y1 Vertex #1 y coordinate
* @param x2 Vertex #2 x coordinate
* @param y2 Vertex #2 y coordinate
* @param color: The gray value of the line (0-255);
* @param framebuffer: The framebuffer to draw to,
*/
void epd_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
uint8_t color, uint8_t *framebuffer);
/**
* Get the current ambient temperature in °C, if supported by the board.
* Requires the display to be powered on.
*/
float epd_ambient_temperature();
/**
* The default font properties.
*/
EpdFontProperties epd_font_properties_default();
/*!
* Get the text bounds for string, when drawn at (x, y).
* Set font properties to NULL to use the defaults.
*/
void epd_get_text_bounds(const EpdFont *font, const char *string,
const int *x, const int *y,
int *x1, int *y1, int *w, int *h,
const EpdFontProperties *props);
/**
* Write text to the EPD.
*/
enum EpdDrawError epd_write_string(const EpdFont *font, const char *string, int *cursor_x,
int *cursor_y, uint8_t *framebuffer,
const EpdFontProperties *properties);
/**
* Write a (multi-line) string to the EPD.
*/
enum EpdDrawError epd_write_default(const EpdFont *font, const char *string, int *cursor_x,
int *cursor_y, uint8_t *framebuffer);
/**
* Get the font glyph for a unicode code point.
*/
const EpdGlyph* epd_get_glyph(const EpdFont *font, uint32_t code_point);
/**
* Darken / lighten an area for a given time.
*
* @param area: The area to darken / lighten.
* @param time: The time in us to apply voltage to each pixel.
* @param color: 1: lighten, 0: darken.
*/
void epd_push_pixels(EpdRect area, short time, int color);
/**
* Base function for drawing an image on the screen.
* If It is very customizable, and the documentation below should be studied carefully.
* For simple applications, use the epdiy highlevel api in "epd_higlevel.h".
*
* @param area: The area of the screen to draw to.
* This can be imagined as shifting the origin of the frame buffer.
* @param data: A full framebuffer of display data.
* It's structure depends on the chosen `mode`.
* @param crop_to: Only draw a part of the frame buffer.
* Set to `epd_full_screen()` to draw the full buffer.
* @param mode: Specifies the Waveform used, the framebuffer format
* and additional information, like if the display is cleared.
* @param temperature: The temperature of the display in °C.
* Currently, this is unused by the default waveforms at can be
* set to room temperature, e.g. 20-25°C.
* @param drawn_lines: If not NULL, an array of at least the height of the
* image. Every line where the corresponding value in `lines` is `false` will be
* skipped.
* @param waveform: The waveform information to use for drawing.
* If you don't have special waveforms, use `EPD_BUILTIN_WAVEFORM`.
* @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
*/
enum EpdDrawError IRAM_ATTR epd_draw_base(EpdRect area,
const uint8_t *data,
EpdRect crop_to,
enum EpdDrawMode mode,
int temperature,
const bool *drawn_lines,
const EpdWaveform *waveform);
/**
* Calculate a `MODE_PACKING_1PPB_DIFFERENCE` difference image
* from two `MODE_PACKING_2PPB` (4 bit-per-pixel) buffers.
* If you're using the epdiy highlevel api, this is handled by the update functions.
*
* @param to: The goal image as 4-bpp (`MODE_PACKING_2PPB`) framebuffer.
* @param from: The previous image as 4-bpp (`MODE_PACKING_2PPB`) framebuffer.
* @param crop_to: Only calculate the difference for a crop of the input framebuffers.
* The `interlaced` will not be modified outside the crop area.
* @param interlaced: The resulting difference image in `MODE_PACKING_1PPB_DIFFERENCE` format.
* @param dirty_lines: An array of at least `EPD_HEIGHT`.
* The positions corresponding to lines where `to` and `from` differ
* are set to `true`, otherwise to `false`.
* @param previously_white: If not NULL, it is set to `true`
* if the considered crop of the `from`-image is completely white.
* @param previously_black: If not NULL, it is set to `true`
* if the considered crop of the `from`-image is completely black.
* @returns The smallest rectangle containing all changed pixels.
*/
EpdRect epd_difference_image_cropped(
const uint8_t* to,
const uint8_t* from,
EpdRect crop_to,
uint8_t* interlaced,
bool* dirty_lines,
bool* previously_white,
bool* previously_black
);
/**
* Simplified version of `epd_difference_image_cropped()`, which considers the
* whole display frame buffer.
*
* See `epd_difference_image_cropped() for details.`
*/
EpdRect epd_difference_image(const uint8_t* to, const uint8_t* from, uint8_t* interlaced, bool* dirty_lines);
#ifdef __cplusplus
}
#endif