Implement 4-quadrant dirty rectangle optimization and 30 FPS limiting for ST7796
Add intelligent partial screen update system using bitwise XOR change detection and 4-quadrant tracking (top-left, top-right, bottom-left, bottom-right). Each changed pixel is routed to its quadrant, with sophisticated merge logic that combines adjacent rectangles when beneficial (<40% overhead). This dramatically reduces SPI bandwidth for UIs with scattered updates (e.g., corners, sidebars). Key changes: - 4-quadrant dirty rectangle tracking with automatic merging - XOR-based change detection for fast byte-level comparison - Expose st7796_set_window() for partial region updates - 30 FPS frame rate limiter (33ms per frame) to prevent excessive refreshes - Smart sleep timing when frame rate limit is active Performance: Up to 99% reduction in SPI traffic for corner-based UIs (e.g., 4 small regions vs full 480x320 screen updates). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -268,7 +268,7 @@ static void write_command_with_data(uint8_t cmd, const uint8_t *data, size_t len
|
||||
* This compensates for displays where the physical screen doesn't align
|
||||
* with the controller's framebuffer (common with ST7789/ST7796).
|
||||
*/
|
||||
static void set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
void st7796_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
uint8_t data[4];
|
||||
|
||||
// Add offsets for display positioning
|
||||
@@ -475,7 +475,7 @@ void st7796_init(const struct st7796_config *c, uint16_t w, uint16_t h) {
|
||||
* @param color RGB565 color value (0x0000=black, 0xFFFF=white)
|
||||
*/
|
||||
void st7796_fill(uint16_t color) {
|
||||
set_window(0, 0, width - 1, height - 1);
|
||||
st7796_set_window(0, 0, width - 1, height - 1);
|
||||
|
||||
dc_data();
|
||||
cs_select();
|
||||
@@ -535,7 +535,7 @@ void st7796_put(uint16_t color) {
|
||||
* @param y Starting Y coordinate
|
||||
*/
|
||||
void st7796_set_cursor(uint16_t x, uint16_t y) {
|
||||
set_window(x, y, width - 1, height - 1);
|
||||
st7796_set_window(x, y, width - 1, height - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,8 +614,8 @@ void st7796_write_raw(const uint8_t *data, size_t len) {
|
||||
*/
|
||||
void st7796_draw_pixel(uint16_t x, uint16_t y, uint16_t color) {
|
||||
if (x >= width || y >= height) return; // Bounds check
|
||||
|
||||
set_window(x, y, x, y); // 1x1 window
|
||||
|
||||
st7796_set_window(x, y, x, y); // 1x1 window
|
||||
|
||||
uint8_t data[2] = {(color >> 8) & 0xFF, color & 0xFF};
|
||||
dc_data();
|
||||
@@ -676,8 +676,8 @@ void st7796_fill_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t c
|
||||
if (x >= width || y >= height) return;
|
||||
if (x + w > width) w = width - x;
|
||||
if (y + h > height) h = height - y;
|
||||
|
||||
set_window(x, y, x + w - 1, y + h - 1);
|
||||
|
||||
st7796_set_window(x, y, x + w - 1, y + h - 1);
|
||||
|
||||
dc_data();
|
||||
cs_select();
|
||||
|
||||
@@ -209,16 +209,38 @@ void st7796_put(uint16_t color);
|
||||
|
||||
/**
|
||||
* @brief Set cursor position for subsequent writes
|
||||
*
|
||||
*
|
||||
* Sets the drawing window starting at (x, y) and extending to the
|
||||
* bottom-right of the display. Subsequent calls to st7796_put()
|
||||
* will write pixels starting from this position.
|
||||
*
|
||||
*
|
||||
* @param x X coordinate (0 to width-1)
|
||||
* @param y Y coordinate (0 to height-1)
|
||||
*/
|
||||
void st7796_set_cursor(uint16_t x, uint16_t y);
|
||||
|
||||
/**
|
||||
* @brief Set drawing window to a specific rectangle
|
||||
*
|
||||
* Sets the drawing window to a rectangular region defined by (x0, y0)
|
||||
* as the top-left corner and (x1, y1) as the bottom-right corner.
|
||||
* Subsequent write operations will only affect this region.
|
||||
*
|
||||
* This is useful for partial screen updates (dirty rectangle optimization)
|
||||
* where only a portion of the screen needs to be redrawn, significantly
|
||||
* improving performance by reducing SPI data transfer.
|
||||
*
|
||||
* @param x0 Top-left X coordinate (0 to width-1)
|
||||
* @param y0 Top-left Y coordinate (0 to height-1)
|
||||
* @param x1 Bottom-right X coordinate (x0 to width-1)
|
||||
* @param y1 Bottom-right Y coordinate (y0 to height-1)
|
||||
*
|
||||
* Example: Update only a 100x50 region starting at (50, 50):
|
||||
* st7796_set_window(50, 50, 149, 99);
|
||||
* st7796_write_raw(pixel_data, 100 * 50 * 2);
|
||||
*/
|
||||
void st7796_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
|
||||
/**
|
||||
* @brief Write multiple pixels at current cursor position
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user