A lightweight, hardware-optimized graphics and text library written from scratch for the RISC-V LP Core (ULP) coprocessor inside ESP32-C6 and ESP32-C5 SoC.
This library enables the Low-Power (LP) core to completely offload monochrome OLED display rendering via the hardware LP_I2C peripheral. The High-Performance (HP) main core can remain in Deep Sleep or execute independent high-load tasks (such as Wi-Fi 6 or BLE communication) without interrupting the display output.
Left: Rendering performance test (stress test GFX) |Right: GFX and text static demo on ESP32-C6 LP 20MHz
- RAM Footprint: The library standalone footprint is only 2.5 KB to 4 KB of LP SRAM (including the framebuffer). With full system drivers, ULP bootloader components, and stack allocation, real runtime consumption scales to ~6 KB to 8 KB out of the 16 KB total available. Completely static allocation.
- Performance: Capable of rendering complex scenes (tested with 150 bounding/colliding objects at 100% LP Core load.
- Auto-Platform Pin Mapping: Target I2C pins are handled automatically at compile-time based on the selected target framework (GPIO 6/7 for ESP32-C6; GPIO 2/3 for ESP32-C5). No manual pin configuration is required in the codebase.
- Hardware Time-Tracking: Implements a precise microsecond timer (
oled_lp_get_time_us) with hardware clock-tick calibration and overflow protection, compensating for the lack ofesp_timeron the LP Core.
- Core Control: Framerate configuration (1β30 FPS), power state toggling (sleep/wake), contrast adjustment, 180Β° display rotation, and inversion.
- Geometry Engine: Standard primitives including pixels, lines (1 to 4 pixels thick), rectangles, frames, circles, and capsules with adjustable corner radius.
- Advanced Rendering: Built-in chess-pattern fill mode for efficient semi-transparent overlays and shading on monochrome matrices.
- Text Engine: Fast 5x7 ASCII font rendering with fast scaling (1x to 4x) and 180Β° string mirroring.
- Framework Version: Developed and fully tested on the official ESP-IDF
masterbranch (v6.0.DEV state as of July 1, 2026).
SSD1306_OLED_RISC-V_LP-Core/
βββ LICENSE # License MIT
βββ CMakeLists.txt # Top-level project CMake
βββ README.md # Documentation
βββ assets/ # Media files (Images & GIF)
βββ main/
β βββ CMakeLists.txt # Component build script with ULP integration
β βββ lp_core_ssd1306.c # Main HP Core initialization application
β βββ ulp/
β βββ main.c # Entry point for the LP Core application
β βββ ssd1306_lp.c # Library implementation
β βββ ssd1306_lp.h # Library header
To integrate this library into any existing ESP-IDF v6.0+ project, follow these steps:
Place ssd1306_lp.c and ssd1306_lp.h directly into your component's ulp/ directory.
Modify your main/CMakeLists.txt to include the ulp and esp_driver_i2c requirements, and register the source files inside the ulp_embed_binary function as shown below:
# Set usual component variables
set(app_sources "lp_core_ssd1306.c")
idf_component_register(SRCS \${app_sources}
REQUIRES ulp esp_driver_i2c
WHOLE_ARCHIVE)
# ULP source registration
set(ulp_app_name ulp_\${COMPONENT_NAME})
set(ulp_sources
"ulp/main.c"
"ulp/ssd1306_lp.c" # <-- Add library source file here
)
set(ulp_exp_dep_srcs \${app_sources})
ulp_embed_binary(\${ulp_app_name} "\${ulp_sources}" "\${ulp_exp_dep_srcs}")Before building, you must explicitly enable the LP Core coprocessor and allocate enough memory for the combined driver and application footprint:
- Run
idf.py menuconfig - Navigate to:
Component configβ‘οΈUltra Low Power (ULP) Co-processor - Enable
Enable Ultra Low Power (ULP) Coprocessor - Set
ULP Co-processor typetoLP Core RISC-V - Change
ULP memory size (bytes)to a minimum of 8192 (10240 or 12288 is recommended if you plan to add more custom user logic).
Include the header file inside your LP Core source code (ulp/main.c):
#include "ssd1306_lp.h"void oled_lp_init(void);β Initialize display, calibrate timer, start at 24 FPS by default.void oled_lp_deinit(void);β Deinitialize: turn off matrix, clear buffer, disable charge pump.void oled_lp_time_init(void);β Hardware measurement of LP Core frequency (ticks per 1 Β΅s).uint64_t oled_lp_get_time_us(void);β Time in Β΅s with overflow protection and auto-recalibration.void oled_lp_set_fps(uint8_t fps);β Set target frame rate (1..30 FPS).
void oled_lp_power_on(void);β Quick wake from sleep (turn on matrix).void oled_lp_power_off(void);β Quick sleep mode (turn off matrix for power saving).void oled_lp_set_contrast(uint8_t contrast);β Matrix brightness (0x00 .. 0xFF).void oled_lp_set_inversion(bool invert);β Screen color inversion (true = inverted).void oled_lp_set_rotation_180(bool rotate);β Rotate display 180 degrees.
void oled_lp_clear_buffer(void);β Clear local RAM buffer (1024 bytes) to zero.bool oled_lp_is_dirty(void);β Check if the buffer has changed since last transmission.void oled_lp_refresh_once(void);β Force transmit buffer to I2C bus regardless of FPS.bool oled_lp_refresh_sync(void);β Send frame based on FPS schedule (if buffer is "dirty"). Returns true on send.
void oled_lp_draw_pixel(uint8_t x, uint8_t y, bool set);β Pixel (set: true = on, false = off).void oled_lp_draw_frame(void);β Draw 1-pixel outline border around the screen.void oled_lp_draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t thickness);β Line (thickness 1..4).void oled_lp_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t t, bool solid, bool chess);β Rectangle (w-width, h-height, r-corner radius, t-border thickness, solid-fill, chess-checkerboard fill).void oled_lp_draw_string(uint8_t x, uint8_t y, const char* str, uint8_t scale, bool flip_180);β Text (5x7 ASCII font). scale-multiplier (1..4x), flip_180-mirror string horizontally/vertically.
This library relies strictly on the hardware LP_I2C peripheral architecture implemented in the ESP32-C6 and ESP32-C5 series. Due to architectural differences and specific hardware behavior of the RTC I2C controller on the ESP32-S3 SoC, this codebase is fundamentally incompatible with the ESP32-S3 ULP RISC-V coprocessor and cannot be run on it.
This project is licensed under the MIT License. You are free to use, modify, and distribute this software in both commercial and open-source applications without restriction. Thanks

