~ruther/qmk_firmware

d8e100ae3cc38a63889c5933cecc13b0a58f9277 — Chris Salch 1 year, 10 months ago b9d6bfe
Allow force flush of oled display (#20953)

Co-authored-by: Drashna Jaelre <drashna@live.com>
Co-authored-by: Ryan <fauxpark@gmail.com>
3 files changed, 64 insertions(+), 16 deletions(-)

M docs/feature_oled_driver.md
M drivers/oled/oled_driver.c
M drivers/oled/oled_driver.h
M docs/feature_oled_driver.md => docs/feature_oled_driver.md +50 -6
@@ 166,6 166,42 @@ bool oled_task_user(void) {
#endif
```

Render a message before booting into bootloader mode.
```c
void oled_render_boot(bool bootloader) {
    oled_clear();
    for (int i = 0; i < 16; i++) {
        oled_set_cursor(0, i);
        if (bootloader) {
            oled_write_P(PSTR("Awaiting New Firmware "), false);
        } else {
            oled_write_P(PSTR("Rebooting "), false);
        }
    }

    oled_render_dirty(true);
}

bool reboot = false;

bool uint16_t keycode, keyrecord_t *record) {
    if (record->event.pressed) {
  
        // Display a special message prior to rebooting...
        if (keycode == QK_BOOT) {
           reboot = true;
        }
    }

    return true;
}

void shutdown_user(void) {
    oled_render_boot(reboot);
}

```

## Basic Configuration

These configuration options should be placed in `config.h`. Example:


@@ 275,7 311,7 @@ Rotation on SH1106 and SH1107 is noticeably less efficient than on SSD1306, beca
## OLED API

```c
// OLED rotation enum values are flags
// OLED Rotation enum values are flags
typedef enum {
    OLED_ROTATION_0   = 0,
    OLED_ROTATION_90  = 1,


@@ 283,7 319,7 @@ typedef enum {
    OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180
} oled_rotation_t;

// Initialize the OLED display, rotating the rendered output based on the define passed in.
// Initialize the oled display, rotating the rendered output based on the define passed in.
// Returns true if the OLED was initialized successfully
bool oled_init(oled_rotation_t rotation);



@@ 301,8 337,12 @@ bool oled_send_data(const uint8_t *data, uint16_t size);
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
void oled_clear(void);

// Renders the dirty chunks of the buffer to OLED display
void oled_render(void);
// Alias to oled_render_dirty to avoid a change in api.
#define oled_render() oled_render_dirty(false)

// Renders all dirty blocks to the display at one time or a subset depending on the value of
// all.
void oled_render_dirty(bool all);

// Moves cursor to character position indicated by column and line, wraps if out of bounds
// Max column denoted by 'oled_max_chars()' and max lines by 'oled_max_lines()' functions


@@ 333,8 373,6 @@ void oled_write_ln(const char *data, bool invert);

// Pans the buffer to the right (or left by passing true) by moving contents of the buffer
// Useful for moving the screen in preparation for new drawing
// oled_scroll_left or oled_scroll_right should be preferred for all cases of moving a static
// image such as a logo or to avoid burn-in as it's much, much less cpu intensive
void oled_pan(bool left);

// Returns a pointer to the requested start index in the buffer plus remaining


@@ 351,6 389,7 @@ void oled_write_raw_byte(const char data, uint16_t index);
// Coordinates start at top-left and go right and down for positive x and y
void oled_write_pixel(uint8_t x, uint8_t y, bool on);

#if defined(__AVR__)
// Writes a PROGMEM string to the buffer at current cursor position
// Advances the cursor while writing, inverts the pixels if true
// Remapped to call 'void oled_write(const char *data, bool invert);' on ARM


@@ 364,6 403,11 @@ void oled_write_ln_P(const char *data, bool invert);

// Writes a PROGMEM string to the buffer at current cursor position
void oled_write_raw_P(const char *data, uint16_t size);
#else
#    define oled_write_P(data, invert) oled_write(data, invert)
#    define oled_write_ln_P(data, invert) oled_write_ln(data, invert)
#    define oled_write_raw_P(data, size) oled_write_raw(data, size)
#endif // defined(__AVR__)

// Can be used to manually turn on the screen if it is off
// Returns true if the screen was on or turns on

M drivers/oled/oled_driver.c => drivers/oled/oled_driver.c +2 -2
@@ 448,7 448,7 @@ static void rotate_90(const uint8_t *src, uint8_t *dest) {
    }
}

void oled_render(void) {
void oled_render_dirty(bool all) {
    // Do we have work to do?
    oled_dirty &= OLED_ALL_BLOCKS_MASK;
    if (!oled_dirty || !oled_initialized || oled_scrolling) {


@@ 460,7 460,7 @@ void oled_render(void) {

    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)
    while (oled_dirty && (num_processed++ < OLED_UPDATE_PROCESS_LIMIT || all)) { // render all dirty blocks (up to the configured limit)
        // Find next dirty block
        while (!(oled_dirty & ((OLED_BLOCK_TYPE)1 << update_start))) {
            ++update_start;

M drivers/oled/oled_driver.h => drivers/oled/oled_driver.h +12 -8
@@ 353,20 353,24 @@ oled_rotation_t oled_init_user(oled_rotation_t rotation);
// Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
void oled_clear(void);

// Renders the dirty chunks of the buffer to oled display
void oled_render(void);
// Alias to oled_render_dirty to avoid a change in api.
#define oled_render() oled_render_dirty(false)

// Renders all dirty blocks to the display at one time or a subset depending on the value of
// all.
void oled_render_dirty(bool all);

// Moves cursor to character position indicated by column and line, wraps if out of bounds
// Max column denoted by 'oled_max_chars()' and max lines by 'oled_max_lines()' functions
void oled_set_cursor(uint8_t col, uint8_t line);

// Advances the cursor to the next page, writing ' ' if true
// Wraps to the begining when out of bounds
// Wraps to the beginning when out of bounds
void oled_advance_page(bool clearPageRemainder);

// Moves the cursor forward 1 character length
// Advance page if there is not enough room for the next character
// Wraps to the begining when out of bounds
// Wraps to the beginning when out of bounds
void oled_advance_char(void);

// Writes a single character to the buffer at current cursor position


@@ 433,10 437,10 @@ bool oled_off(void);
// not
bool is_oled_on(void);

// Sets the brightness of the display
// Sets the brightness level of the display
uint8_t oled_set_brightness(uint8_t level);

// Gets the current brightness of the display
// Gets the current brightness level of the display
uint8_t oled_get_brightness(void);

// Basically it's oled_render, but with timeout management and oled_task_user calling!


@@ 458,12 462,12 @@ void oled_scroll_set_area(uint8_t start_line, uint8_t end_line);
// 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256
void oled_scroll_set_speed(uint8_t speed);

// Scrolls the entire display right
// Begin scrolling the entire display right
// Returns true if the screen was scrolling or starts scrolling
// NOTE: display contents cannot be changed while scrolling
bool oled_scroll_right(void);

// Scrolls the entire display left
// Begin scrolling the entire display left
// Returns true if the screen was scrolling or starts scrolling
// NOTE: display contents cannot be changed while scrolling
bool oled_scroll_left(void);