Skip to content

Commit

Permalink
Add a method to read the OLED display buffer from user space (#8777)
Browse files Browse the repository at this point in the history
* Adding extern and declaration

* Change to mediated buffer read

* Adding raw byte read

* Restore write raw... D'Oh

* Working struct return

* Pack that struct

* Remove conditional packing and add example to docs

* Cleanup tab/spaces

* Update docs/feature_oled_driver.md

Prettify formatting

* Update drivers/oled/oled_driver.h

Prettify formatting
  • Loading branch information
brickbots authored and noroadsleft committed Aug 29, 2020
1 parent 92385b3 commit fa6cf85
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
41 changes: 41 additions & 0 deletions docs/feature_oled_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,43 @@ static void render_logo(void) {
}
```
## Buffer Read Example
For some purposes, you may need to read the current state of the OLED display
buffer. The `oled_read_raw` function can be used to safely read bytes from the
buffer.
In this example, calling `fade_display` in the `oled_task_user` function will
slowly fade away whatever is on the screen by turning random pixels black over
time.
```c
//Setup some mask which can be or'd with bytes to turn off pixels
const uint8_t single_bit_masks[8] = {127, 191, 223, 239, 247, 251, 253, 254};
static void fade_display(void) {
//Define the reader structure
oled_buffer_reader_t reader;
uint8_t buff_char;
if (random() % 30 == 0) {
srand(timer_read());
// Fetch a pointer for the buffer byte at index 0. The return structure
// will have the pointer and the number of bytes remaining from this
// index position if we want to perform a sequential read by
// incrementing the buffer pointer
reader = oled_read_raw(0);
//Loop over the remaining buffer and erase pixels as we go
for (uint16_t i = 0; i < reader.remaining_element_count; i++) {
//Get the actual byte in the buffer by dereferencing the pointer
buff_char = *reader.current_element;
if (buff_char != 0) {
oled_write_raw_byte(buff_char & single_bit_masks[rand() % 8], i);
}
//increment the pointer to fetch a new byte during the next loop
reader.current_element++;
}
}
}
```

## Other Examples

In split keyboards, it is very common to have two OLED displays that each render different content and are oriented or flipped differently. You can do this by switching which content to render by using the return value from `is_keyboard_master()` or `is_keyboard_left()` found in `split_util.h`, e.g:
Expand Down Expand Up @@ -238,6 +275,10 @@ void oled_write_P(const char *data, bool invert);
// Remapped to call 'void oled_write_ln(const char *data, bool invert);' on ARM
void oled_write_ln_P(const char *data, bool invert);

// Returns a pointer to the requested start index in the buffer plus remaining
// buffer length as struct
oled_buffer_reader_t oled_read_raw(uint16_t start_index);

// Writes a string to the buffer at current cursor position
void oled_write_raw(const char *data, uint16_t size);

Expand Down
8 changes: 8 additions & 0 deletions drivers/oled/oled_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,14 @@ void oled_pan(bool left) {
oled_dirty = ~((OLED_BLOCK_TYPE)0);
}

oled_buffer_reader_t oled_read_raw(uint16_t start_index) {
if (start_index > OLED_MATRIX_SIZE) start_index = OLED_MATRIX_SIZE;
oled_buffer_reader_t ret_reader;
ret_reader.current_element = &oled_buffer[start_index];
ret_reader.remaining_element_count = OLED_MATRIX_SIZE - start_index;
return ret_reader;
}

void oled_write_raw_byte(const char data, uint16_t index) {
if (index > OLED_MATRIX_SIZE) index = OLED_MATRIX_SIZE;
if (oled_buffer[index] == data) return;
Expand Down
9 changes: 9 additions & 0 deletions drivers/oled/oled_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define OLED_I2C_TIMEOUT 100
#endif

typedef struct __attribute__((__packed__)) {
uint8_t *current_element;
uint16_t remaining_element_count;
} oled_buffer_reader_t;

// OLED Rotation enum values are flags
typedef enum {
OLED_ROTATION_0 = 0,
Expand Down Expand Up @@ -207,6 +212,10 @@ 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
void oled_pan(bool left);

// Returns a pointer to the requested start index in the buffer plus remaining
// buffer length as struct
oled_buffer_reader_t oled_read_raw(uint16_t start_index);

void oled_write_raw(const char *data, uint16_t size);
void oled_write_raw_byte(const char data, uint16_t index);

Expand Down

0 comments on commit fa6cf85

Please sign in to comment.