From 4c1d8a0eb33e5738f305191dfb7a56f8b0275827 Mon Sep 17 00:00:00 2001 From: Richard Nash Date: Sun, 13 Nov 2022 10:49:59 -0500 Subject: Fix oled_render to render all dirty blocks. (#18887) --- drivers/oled/ssd1306_sh1106.c | 90 +++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 46 deletions(-) (limited to 'drivers/oled') diff --git a/drivers/oled/ssd1306_sh1106.c b/drivers/oled/ssd1306_sh1106.c index 30cfeb5648..9fc8c2d2ad 100644 --- a/drivers/oled/ssd1306_sh1106.c +++ b/drivers/oled/ssd1306_sh1106.c @@ -291,65 +291,63 @@ static void rotate_90(const uint8_t *src, uint8_t *dest) { } void oled_render(void) { - if (!oled_initialized) { - return; - } - // Do we have work to do? oled_dirty &= OLED_ALL_BLOCKS_MASK; - if (!oled_dirty || oled_scrolling) { + if (!oled_dirty || !oled_initialized || oled_scrolling) { return; } - // Find first dirty block - uint8_t update_start = 0; - while (!(oled_dirty & ((OLED_BLOCK_TYPE)1 << update_start))) { - ++update_start; - } - - // Set column & page position - static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1}; - if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { - calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start - } else { - calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start - } - - // Send column & page position - if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) { - print("oled_render offset command failed\n"); - return; - } + // Turn on display if it is off + oled_on(); - if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { - // Send render data chunk as is - if (I2C_WRITE_REG(I2C_DATA, &oled_buffer[OLED_BLOCK_SIZE * update_start], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { - print("oled_render data failed\n"); - return; + uint8_t update_start = 0; + while (oled_dirty) { // render all dirty blocks + // Find next dirty block + while (!(oled_dirty & ((OLED_BLOCK_TYPE)1 << update_start))) { + ++update_start; } - } else { - // Rotate the render chunks - const static uint8_t source_map[] = OLED_SOURCE_MAP; - const static uint8_t target_map[] = OLED_TARGET_MAP; - - static uint8_t temp_buffer[OLED_BLOCK_SIZE]; - memset(temp_buffer, 0, sizeof(temp_buffer)); - for (uint8_t i = 0; i < sizeof(source_map); ++i) { - rotate_90(&oled_buffer[OLED_BLOCK_SIZE * update_start + source_map[i]], &temp_buffer[target_map[i]]); + + // Set column & page position + static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1}; + if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { + calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start + } else { + calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start } - // Send render data chunk after rotating - if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { - print("oled_render90 data failed\n"); + // Send column & page position + if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) { + print("oled_render offset command failed\n"); return; } - } - // Turn on display if it is off - oled_on(); + if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { + // Send render data chunk as is + if (I2C_WRITE_REG(I2C_DATA, &oled_buffer[OLED_BLOCK_SIZE * update_start], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { + print("oled_render data failed\n"); + return; + } + } else { + // Rotate the render chunks + const static uint8_t source_map[] = OLED_SOURCE_MAP; + const static uint8_t target_map[] = OLED_TARGET_MAP; + + static uint8_t temp_buffer[OLED_BLOCK_SIZE]; + memset(temp_buffer, 0, sizeof(temp_buffer)); + for (uint8_t i = 0; i < sizeof(source_map); ++i) { + rotate_90(&oled_buffer[OLED_BLOCK_SIZE * update_start + source_map[i]], &temp_buffer[target_map[i]]); + } - // Clear dirty flag - oled_dirty &= ~((OLED_BLOCK_TYPE)1 << update_start); + // Send render data chunk after rotating + if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { + print("oled_render90 data failed\n"); + return; + } + } + + // Clear dirty flag of just rendered block + oled_dirty &= ~((OLED_BLOCK_TYPE)1 << update_start); + } } void oled_set_cursor(uint8_t col, uint8_t line) { -- cgit v1.2.3