diff --git a/src/framebuffer.c b/src/framebuffer.c new file mode 100644 index 0000000..5edbb17 --- /dev/null +++ b/src/framebuffer.c @@ -0,0 +1,232 @@ +// +// 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); +} diff --git a/src/framebuffer.h b/src/framebuffer.h new file mode 100644 index 0000000..b9fdacf --- /dev/null +++ b/src/framebuffer.h @@ -0,0 +1,20 @@ +// +// Created by MightyPork on 2022/11/12. +// + +#ifndef FRAMEBUFFER_H +#define FRAMEBUFFER_H + +#include +#include + +void fb_fill(uint8_t pattern); +void fb_clear(void); +void fb_px(uint8_t x, uint8_t y, uint8_t color); +void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color); +void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color); +void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color); +void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color); +void fb_blit(void); + +#endif //FRAMEBUFFER_H diff --git a/src/graphic_loading.c b/src/graphic_loading.c index 0a65aaa..bb7d17e 100644 --- a/src/graphic_loading.c +++ b/src/graphic_loading.c @@ -6,174 +6,103 @@ #include #include "ssd1306.h" #include "user_interface.h" +#include "framebuffer.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 show_loading_screen(uint8_t progress_percent, bool clear) { + // HACKS - GUI dev here -void fb_clear() { - fb_fill(0); -} + fb_clear(); + fb_blit(); -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); - } -} + const uint8_t icon[14] = { + 0b11000011, + 0b01100110, + 0b01111110, + 0b00111100, + 0b00011000, + 0b00111100, + 0b01111110, + 0b11111111, + 0b11111111, + 0b11111011, + 0b11111111, + 0b01111110, + 0b00111100, + 0b00011000, + }; -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++; - } -} +#define ZIR_W 12 +#define ZIR_H 3 + const uint8_t zirafa[ZIR_H * ZIR_W] = { + // levo + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, // vrsek + 0b00011000, + 0b00011111, + 0b11111000, + 0b00011111, + 0b00001000, + + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + + 0b00010000, + 0b00001000, + 0b11111000, + 0b00011000, + 0b11111000, // spodek + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011111, + 0b11111000, + 0b00000000, -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; + int a = 10; + int b = 40; + for (;;) { + fb_bitmap(a, 0, ZIR_W, ZIR_H*8, zirafa, 0); + fb_bitmap(b, 16, 14, 8, icon, 0); + a++; + b++; + if(a>127) { + a = 0; } - } -} -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; - } - } + if(b>127) { + b = 0; } + fb_bitmap(a, 0, ZIR_W, ZIR_H*8, zirafa, 1); + fb_bitmap(b, 16, 14, 8, icon, 1); - 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; - } - } + fb_blit(); + _delay_ms(100); } -} -void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color) { - // TODO -} -void fb_blit() { - ssd1306_drawBuffer(0, 0, FBW, FBH, fb); -} -void show_loading_screen(uint8_t progress_percent, bool clear) -{ - // HACKS - GUI dev here + for(;;) {} - fb_clear(); - fb_blit(); + // #if 0 int a = 0, b = 0, ai = 1, bi = 1; @@ -220,8 +149,6 @@ void show_loading_screen(uint8_t progress_percent, bool clear) } #endif - for(;;) {} - if (clear) { ssd1306_clearScreen(); diff --git a/src/main.c b/src/main.c index 82501c1..70ee058 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,9 @@ void __attribute__((noreturn)) main() init_user_interface(); show_loading_screen(0, true); + while(1){} + +#if 0 init_timebase(); init_radiation(); @@ -48,6 +51,8 @@ void __attribute__((noreturn)) main() shutdown_due_to_weak_battery(); } } + +#endif }