// // Created by MightyPork on 2022/11/12. // #include "user_interface.h" #include "framebuffer.h" #include "ssd1306.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 >> (8 - (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 -= 8 - 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; } } } cell += FBW; // 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_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color) { if (x >= FBW || y >= FBH) return; const uint8_t w0 = w; const uint8_t h0 = h; 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) { for(uint8_t i = 0; i < w; i++) { // all within one cell uint8_t mask = (map[i] & (0xFF >> (8-h))) << rowrem; if (color) { fb[cell + i] |= mask; } else { fb[cell + i] &= ~mask; } } return; } else if (rowrem == 0) { // Optimization // First for(uint8_t i = 0; i < w; i++) { uint8_t mask = map[i]; if (color) { fb[cell + i] |= mask; } else { fb[cell + i] &= ~mask; } } h -= 8; // Middle 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++) { uint8_t mask = map[i + (j+1)*w0]; if (color) { fb[cell + i] |= mask; } else { fb[cell + i] &= ~mask; } } } // last cell += FBW; // last for(uint8_t i = 0; i < w; i++) { uint8_t mask = map[i + (whole_cells+1)*w0] & (0xFF >> (8-h)); if (color) { fb[cell + i] |= mask; } else { fb[cell + i] &= ~mask; } } } else { // TODO wild combination, unaligned multi-row } } void fb_blit() { ssd1306_drawBuffer(0, 0, FBW, FBH, fb); }