Introduction ~~~~~~~~~~~~ Many serial displays are refreshed in chunks using a byte stream. Setting a single pixel is expensive or even impossible. Rendr8 provides a byte oriented, render callback based API for efficiently update a part of the screen or the whole screen. The basic concept is that the main loop calls a partial or full refresh of the screen using the gendriver, which then builds the byte stream required for the refresh. Where the byte stream includes actual display data, an user provided rendr8 function is called back with the x and y coordinates. This function is expected to return the next 8 bits of screen data. Rendr8 callback ~~~~~~~~~~~~~~~ static inline unsigned char r8(void *r8ctx, unsigned char x, unsigned char y); Any time screen data needs to be rendered, the rendr8 function specified at instantiation is called back with the starting coordinates x;y. The function renders and returns the next 8 horizontal (x++) pixels from x;y. Screen update ~~~~~~~~~~~~~ The screen is updated upon user call to one of the functions below. void ID_update_all(void): redraws the whole screen at once void ID_init_chunk(unsigned coordtype *x, unsigned coordtype *y): Reset x and y before starting a full redraw in chunked mode. unsigned char ID_update_chunk(unsigned coordtype *x, unsigned coordtype *y): Redraws the next chunk from x;y, incrementing x and y as needed. Coordtype is an integral type specific to the given driver (typically unsigned char or unsigned short int). Returns 1 if this was the last chunk for a full screen, 0 otherwise. After returning 1, there's no need to call ID_init_chunk() before starting the next frame. Chunked update is useful for async apps where communicating to the display should be "non-blocking". Chunk size is configured instantiaton-time, but may have a driver-specific minimum value or the driver may round it up or down to specific values. This which may differ depending on some settings (e.g. landscape vs. portrait). The driver .h should explain details in comment. Example ~~~~~~~ The following code is rendering a chess-board pattern on ssd1306, assuming i2c with port0 is already set up: static inline unsigned char my_rnd(void *rctx, unsigned char x, unsigned char y) { return y % 2 ? 0x55 : 0xAA; } static const gdrv_ssd1306_cfg_t disp0cfg = {0, 2*8+1}; gdrv_create_ssd1306(disp0, disp0cfg, i2c_write, i2c_flush, &port0, my_rnd, 0) void main() { disp0_init(); disp0_set_contrast(255); disp0_update_all(); }