diff options
Diffstat (limited to 'drivers/oled/ssd1306_sh1106.c')
| -rw-r--r-- | drivers/oled/ssd1306_sh1106.c | 91 | 
1 files changed, 45 insertions, 46 deletions
| diff --git a/drivers/oled/ssd1306_sh1106.c b/drivers/oled/ssd1306_sh1106.c index 30cfeb5648..342920572e 100644 --- a/drivers/oled/ssd1306_sh1106.c +++ b/drivers/oled/ssd1306_sh1106.c @@ -291,65 +291,64 @@ 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; +    uint8_t num_processed = 0; +    while (oled_dirty && num_processed++ < OLED_UPDATE_PROCESS_LIMIT) { // render all dirty blocks (up to the configured limit) +        // 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) { | 
