Created
August 9, 2026 18:29
-
-
Save maxgerhardt/dbf3864310a1b0cb0d22f8afda16c9c3 to your computer and use it in GitHub Desktop.
u8g2 + epaper reference ESP-IDF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include "u8g2.h" | |
| #include "epd_gdey042t81.h" | |
| #define SCREEN_WIDTH 400 | |
| #define SCREEN_HEIGHT 300 | |
| #define BYTES_PER_ROW (SCREEN_WIDTH / 8) | |
| #define FRAMEBUFFER_SIZE (BYTES_PER_ROW * SCREEN_HEIGHT) | |
| #define TILE_HEIGHT ((SCREEN_HEIGHT + 7) / 8) | |
| static u8g2_t u8g2; | |
| /* | |
| * This is BOTH: | |
| * | |
| * - u8g2's drawing framebuffer | |
| * - the framebuffer passed to epd_display() | |
| * | |
| * No second framebuffer and no conversion. | |
| */ | |
| static uint8_t framebuffer[FRAMEBUFFER_SIZE]; | |
| /* | |
| * u8g2 needs display geometry. | |
| * | |
| * tile_width = 400 / 8 = 50 bytes per row | |
| * tile_height = ceil(300 / 8) = 38 | |
| * | |
| * pixel_width = 400 | |
| * pixel_height = 300 | |
| */ | |
| static const u8x8_display_info_t display_info = { | |
| .chip_enable_level = 0, | |
| .chip_disable_level = 1, | |
| .post_chip_enable_wait_ns = 0, | |
| .pre_chip_disable_wait_ns = 0, | |
| .reset_pulse_width_ms = 0, | |
| .post_reset_wait_ms = 0, | |
| .sda_setup_time_ns = 0, | |
| .sck_pulse_width_ns = 0, | |
| .sck_clock_hz = 0, | |
| .spi_mode = 0, | |
| .i2c_bus_clock_100kHz = 0, | |
| .data_setup_time_ns = 0, | |
| .write_pulse_width_ns = 0, | |
| .tile_width = SCREEN_WIDTH / 8, | |
| .tile_height = TILE_HEIGHT, | |
| .default_x_offset = 0, | |
| .flipmode_x_offset = 0, | |
| .pixel_width = SCREEN_WIDTH, | |
| .pixel_height = SCREEN_HEIGHT, | |
| }; | |
| /* | |
| * u8g2 doesn't send anything to a physical display. | |
| * | |
| * We only use this callback to provide the display geometry. | |
| */ | |
| static uint8_t display_callback(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) | |
| { | |
| (void)arg_int; | |
| (void)arg_ptr; | |
| if (msg == U8X8_MSG_DISPLAY_SETUP_MEMORY) | |
| u8x8->display_info = &display_info; | |
| return 1; | |
| } | |
| /* | |
| * Initialize u8g2 as a framebuffer-only renderer. | |
| */ | |
| static void graphics_init(void) | |
| { | |
| u8g2_SetupDisplay( | |
| &u8g2, | |
| display_callback, | |
| u8x8_dummy_cb, | |
| u8x8_dummy_cb, | |
| u8x8_dummy_cb | |
| ); | |
| /* | |
| * IMPORTANT: | |
| * | |
| * horizontal_right_lsb gives us: | |
| * | |
| * framebuffer[y * 50 + x / 8] | |
| * | |
| * with: | |
| * | |
| * x=0 -> bit 7 | |
| * x=1 -> bit 6 | |
| * ... | |
| * x=7 -> bit 0 | |
| * | |
| * This is exactly the format expected by epd_gdey042t81.c. | |
| */ | |
| u8g2_SetupBuffer( | |
| &u8g2, | |
| framebuffer, | |
| TILE_HEIGHT, | |
| u8g2_ll_hvline_horizontal_right_lsb, | |
| U8G2_R0 | |
| ); | |
| } | |
| /* | |
| * Draw our screen. | |
| */ | |
| static void render_screen(void) | |
| { | |
| u8g2_ClearBuffer(&u8g2); | |
| u8g2_SetDrawColor(&u8g2, 1); | |
| u8g2_SetFont(&u8g2, u8g2_font_helvB24_tf); | |
| u8g2_DrawStr(&u8g2, 20, 45, "Hello e-paper!"); | |
| u8g2_SetFont(&u8g2, u8g2_font_helvB14_tf); | |
| u8g2_DrawStr(&u8g2, 20, 75, "u8g2 + GDEY042T81"); | |
| u8g2_DrawFrame( | |
| &u8g2, | |
| 10, | |
| 100, | |
| SCREEN_WIDTH - 20, | |
| 100 | |
| ); | |
| u8g2_DrawLine( | |
| &u8g2, | |
| 20, | |
| 220, | |
| SCREEN_WIDTH - 20, | |
| 220 | |
| ); | |
| u8g2_DrawDisc( | |
| &u8g2, | |
| SCREEN_WIDTH / 2, | |
| 260, | |
| 25, | |
| U8G2_DRAW_ALL | |
| ); | |
| } | |
| /* | |
| * Full display update. | |
| * | |
| * framebuffer is already in exactly the format expected by | |
| * epd_display(). | |
| */ | |
| static void display_full(void) | |
| { | |
| epd_display(framebuffer); | |
| } | |
| /* | |
| * Fast full display update. | |
| */ | |
| static void display_full_fast(void) | |
| { | |
| epd_display_fast(framebuffer); | |
| } | |
| /* | |
| * Establish the framebuffer as the partial-refresh base image. | |
| */ | |
| static void display_set_basemap(void) | |
| { | |
| epd_set_basemap(framebuffer); | |
| } | |
| void app_main(void) | |
| { | |
| printf("Starting graphics renderer\n"); | |
| printf("Screen: %d x %d\n", SCREEN_WIDTH, SCREEN_HEIGHT); | |
| printf("Bytes/row: %d\n", BYTES_PER_ROW); | |
| printf("Framebuffer: %d bytes\n", FRAMEBUFFER_SIZE); | |
| /* | |
| * Initialize the GDEY042T81. | |
| * | |
| * This also initializes the SPI interface. | |
| */ | |
| epd_init_fast(); | |
| /* | |
| * Initialize u8g2. | |
| * | |
| * No u8g2 display hardware is involved. | |
| */ | |
| graphics_init(); | |
| /* | |
| * Draw into framebuffer[]. | |
| */ | |
| render_screen(); | |
| /* | |
| * framebuffer[] is directly passed to the e-paper driver. | |
| */ | |
| display_full_fast(); | |
| /* | |
| * Or: | |
| * | |
| * display_full(); | |
| * | |
| * Or establish this image as the partial-refresh base: | |
| * | |
| * display_set_basemap(); | |
| */ | |
| /* | |
| * The pointer returned by u8g2 is the same buffer. | |
| */ | |
| uint8_t *fb = u8g2_GetBufferPtr(&u8g2); | |
| printf("u8g2 framebuffer: %p\n", (void *)fb); | |
| printf("our framebuffer: %p\n", (void *)framebuffer); | |
| while (1) | |
| vTaskDelay(pdMS_TO_TICKS(1000)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment