diff --git a/src/graphic_loading.c b/src/graphic_loading.c index cf80812..430755e 100644 --- a/src/graphic_loading.c +++ b/src/graphic_loading.c @@ -7,9 +7,192 @@ #include "ssd1306.h" #include "user_interface.h" +/* Tiny framebuffer */ +#define FBW DISPLAY_W +#define FBH DISPLAY_H + +#define MIN(a,b) ((a)>(b)?(b):(a)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + +static uint8_t fb[(FBH/8)*FBW]; + +/** Fill with a vertical pattern, 1 byte */ +void fb_fill(uint8_t pattern) { + memset(fb, pattern, sizeof(fb)); +} + +void fb_clear() { + fb_fill(0); +} + +void fb_px(uint8_t x, uint8_t y, uint8_t color) { + if (x >= FBW || y >= FBH) return; + const uint8_t row = y / 8; + const uint8_t rowrem = y % 8; + const uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; + if (color) { + fb[cell] |= (1 << rowrem); + } else { + fb[cell] &= ~(1 << rowrem); + } +} + +void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color) { + if (x >= FBW || y >= FBH) return; + w = MIN(FBW - x, w); + const uint8_t row = y / 8; + const uint8_t rowrem = y % 8; + uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; + for(uint8_t i = 0; i < w; i++) { + if (color) { + fb[cell] |= (1 << rowrem); + } else { + fb[cell] &= ~(1 << rowrem); + } + cell++; + } +} + +void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color) { + if (x >= FBW || y >= FBH) return; + h = MIN(FBH - y - 1, h); + const uint8_t row = y / 8; + const uint8_t rowrem = y % 8; + uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; + + if (rowrem + h < 8) { + // all within one cell + uint8_t mask = (0xFF << rowrem) & (0xFF >> (h-rowrem)); + if (color) { + fb[cell] |= mask; + } else { + fb[cell] &= ~mask; + } + return; + } else { + // First + uint8_t mask = (0xFF << rowrem); + if (color) { + fb[cell] |= mask; + } else { + fb[cell] &= ~mask; + } + h -= rowrem; + + uint8_t whole_cells = h / 8; + h -= whole_cells * 8; + for(uint8_t i = 0; i < whole_cells; i++) { + cell += FBW; + if (color) { + fb[cell] = 0xFF; + } else { + fb[cell] = 0; + } + } + + // last + mask = (0xFF >> (8-h)); + if (color) { + fb[cell] |= mask; + } else { + fb[cell] &= ~mask; + } + } +} + +void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { + if (x >= FBW || y >= FBH) return; + w = MIN(FBW - x - 1, w); + h = MIN(FBH - y - 1, h); + const uint8_t row = y / 8; + const uint8_t rowrem = y % 8; + uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; + + if (rowrem + h < 8) { + // all within one cell + uint8_t mask = (0xFF << rowrem) & (0xFF >> (h-rowrem)); + + for(uint8_t i = 0; i < w; i++) { + if (color) { + fb[cell + i] |= mask; + } else { + fb[cell + i] &= ~mask; + } + } + return; + } else { + // First + uint8_t mask = (0xFF << rowrem); + for(uint8_t i = 0; i < w; i++) { + if (color) { + fb[cell + i] |= mask; + } else { + fb[cell + i] &= ~mask; + } + } + h -= rowrem; + + uint8_t whole_cells = h / 8; + h -= whole_cells * 8; + for(uint8_t j = 0; j < whole_cells; j++) { + cell += FBW; + for(uint8_t i = 0; i < w; i++) { + if (color) { + fb[cell + i] = 0xFF; + } else { + fb[cell + i] = 0; + } + } + } + + // last + mask = (0xFF >> (8-h)); + for(uint8_t i = 0; i < w; i++) { + if (color) { + fb[cell + i] |= mask; + } else { + fb[cell + i] &= ~mask; + } + } + } +} + +void fb_blit() { + ssd1306_drawBuffer(0, 0, FBW, FBH, fb); +} + void show_loading_screen(uint8_t progress_percent, bool clear) { + // HACKS - GUI dev here + + fb_clear(); + fb_blit(); +// +// fb_hline(3, 3, 30, 1); +// fb_hline(3, 15, 35, 1); +// fb_hline(3, 30, 40, 1); +// +// fb_vline(5, 0, 15, 1); +// fb_vline(6, 0, 32, 0); + + fb_rect(10, 10, 30, 3, 1); + fb_rect(40, 13, 3, 10, 1); +// +// fb_rect(0, 0, 10, 10, 1); +// +// fb_rect(7, 20, 20, 1, 1); +// fb_rect(7, 23, 20, 3, 1); + + //fb_rect(15, 0, 5, 20, 0); + + fb_blit(); + + + + for(;;){} + + if (clear) { ssd1306_clearScreen(); }