diff --git a/Makefile b/Makefile index 8e29944..c00d65f 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ size: $(TARGET).elf # Build the display library lib/libssd1306/bld/libssd1306.a: - $(MAKE) -C lib/libssd1306/ -f Makefile.avr MCU=atmega328p + $(MAKE) -C lib/libssd1306/src/ -f Makefile.avr MCU=atmega328p $(TARGET).elf: $(OBJECTS) lib/libssd1306/bld/libssd1306.a | $(BUILD_DIR) $(LD) $(CFLAGS) $(LFLAGS) -o $@ $^ lib/libssd1306/bld/libssd1306.a diff --git a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o index 669f4b2..eccac94 100644 Binary files a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o and b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c.o differ diff --git a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_embedded.o b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_embedded.o index df7463c..b4fa735 100644 Binary files a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_embedded.o and b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_embedded.o differ diff --git a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o index f6ab8fb..58668b7 100644 Binary files a/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o and b/lib/libssd1306/bld/intf/i2c/ssd1306_i2c_twi.o differ diff --git a/lib/libssd1306/bld/intf/spi/ssd1306_spi.o b/lib/libssd1306/bld/intf/spi/ssd1306_spi.o index f454425..bbd402a 100644 Binary files a/lib/libssd1306/bld/intf/spi/ssd1306_spi.o and b/lib/libssd1306/bld/intf/spi/ssd1306_spi.o differ diff --git a/lib/libssd1306/bld/intf/spi/ssd1306_spi_avr.o b/lib/libssd1306/bld/intf/spi/ssd1306_spi_avr.o index d2fa08d..b68e8c6 100644 Binary files a/lib/libssd1306/bld/intf/spi/ssd1306_spi_avr.o and b/lib/libssd1306/bld/intf/spi/ssd1306_spi_avr.o differ diff --git a/lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o b/lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o index 89428c3..08caa11 100644 Binary files a/lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o and b/lib/libssd1306/bld/intf/spi/ssd1306_spi_usi.o differ diff --git a/lib/libssd1306/bld/intf/ssd1306_interface.o b/lib/libssd1306/bld/intf/ssd1306_interface.o index 4e81420..c4ead0d 100644 Binary files a/lib/libssd1306/bld/intf/ssd1306_interface.o and b/lib/libssd1306/bld/intf/ssd1306_interface.o differ diff --git a/lib/libssd1306/bld/intf/uart/ssd1306_uart_builtin.o b/lib/libssd1306/bld/intf/uart/ssd1306_uart_builtin.o index fdbdc96..5ef8e99 100644 Binary files a/lib/libssd1306/bld/intf/uart/ssd1306_uart_builtin.o and b/lib/libssd1306/bld/intf/uart/ssd1306_uart_builtin.o differ diff --git a/lib/libssd1306/bld/intf/vga/atmega328p/vga128x64.o b/lib/libssd1306/bld/intf/vga/atmega328p/vga128x64.o index e7da81c..d33afde 100644 Binary files a/lib/libssd1306/bld/intf/vga/atmega328p/vga128x64.o and b/lib/libssd1306/bld/intf/vga/atmega328p/vga128x64.o differ diff --git a/lib/libssd1306/bld/intf/vga/atmega328p/vga96x40.o b/lib/libssd1306/bld/intf/vga/atmega328p/vga96x40.o index d276c97..98a4cd7 100644 Binary files a/lib/libssd1306/bld/intf/vga/atmega328p/vga96x40.o and b/lib/libssd1306/bld/intf/vga/atmega328p/vga96x40.o differ diff --git a/lib/libssd1306/bld/intf/vga/esp32/CompositeOutput.o b/lib/libssd1306/bld/intf/vga/esp32/CompositeOutput.o index 11b90f5..8d3dac4 100644 Binary files a/lib/libssd1306/bld/intf/vga/esp32/CompositeOutput.o and b/lib/libssd1306/bld/intf/vga/esp32/CompositeOutput.o differ diff --git a/lib/libssd1306/bld/intf/vga/esp32/vga128x64.o b/lib/libssd1306/bld/intf/vga/esp32/vga128x64.o index 02ca036..df50295 100644 Binary files a/lib/libssd1306/bld/intf/vga/esp32/vga128x64.o and b/lib/libssd1306/bld/intf/vga/esp32/vga128x64.o differ diff --git a/lib/libssd1306/bld/intf/vga/vga.o b/lib/libssd1306/bld/intf/vga/vga.o index a2744dd..4be526c 100644 Binary files a/lib/libssd1306/bld/intf/vga/vga.o and b/lib/libssd1306/bld/intf/vga/vga.o differ diff --git a/lib/libssd1306/bld/lcd/lcd_common.o b/lib/libssd1306/bld/lcd/lcd_common.o index 48cf048..cb064f3 100644 Binary files a/lib/libssd1306/bld/lcd/lcd_common.o and b/lib/libssd1306/bld/lcd/lcd_common.o differ diff --git a/lib/libssd1306/bld/lcd/lcd_il9163.o b/lib/libssd1306/bld/lcd/lcd_il9163.o index 8ab3724..5e0f171 100644 Binary files a/lib/libssd1306/bld/lcd/lcd_il9163.o and b/lib/libssd1306/bld/lcd/lcd_il9163.o differ diff --git a/lib/libssd1306/bld/lcd/lcd_ili9341.o b/lib/libssd1306/bld/lcd/lcd_ili9341.o index f99a00c..013e123 100644 Binary files a/lib/libssd1306/bld/lcd/lcd_ili9341.o and b/lib/libssd1306/bld/lcd/lcd_ili9341.o differ diff --git a/lib/libssd1306/bld/lcd/lcd_pcd8544.o b/lib/libssd1306/bld/lcd/lcd_pcd8544.o index 78c145c..04170be 100644 Binary files a/lib/libssd1306/bld/lcd/lcd_pcd8544.o and b/lib/libssd1306/bld/lcd/lcd_pcd8544.o differ diff --git a/lib/libssd1306/bld/lcd/oled_sh1106.o b/lib/libssd1306/bld/lcd/oled_sh1106.o index d9d1e39..5eaa95c 100644 Binary files a/lib/libssd1306/bld/lcd/oled_sh1106.o and b/lib/libssd1306/bld/lcd/oled_sh1106.o differ diff --git a/lib/libssd1306/bld/lcd/oled_ssd1306.o b/lib/libssd1306/bld/lcd/oled_ssd1306.o index b425ac7..2eaf510 100644 Binary files a/lib/libssd1306/bld/lcd/oled_ssd1306.o and b/lib/libssd1306/bld/lcd/oled_ssd1306.o differ diff --git a/lib/libssd1306/bld/lcd/oled_ssd1325.o b/lib/libssd1306/bld/lcd/oled_ssd1325.o index 5799f31..8d1811e 100644 Binary files a/lib/libssd1306/bld/lcd/oled_ssd1325.o and b/lib/libssd1306/bld/lcd/oled_ssd1325.o differ diff --git a/lib/libssd1306/bld/lcd/oled_ssd1327.o b/lib/libssd1306/bld/lcd/oled_ssd1327.o index 7365e98..f788ca3 100644 Binary files a/lib/libssd1306/bld/lcd/oled_ssd1327.o and b/lib/libssd1306/bld/lcd/oled_ssd1327.o differ diff --git a/lib/libssd1306/bld/lcd/oled_ssd1331.o b/lib/libssd1306/bld/lcd/oled_ssd1331.o index 5337946..9ae92ba 100644 Binary files a/lib/libssd1306/bld/lcd/oled_ssd1331.o and b/lib/libssd1306/bld/lcd/oled_ssd1331.o differ diff --git a/lib/libssd1306/bld/lcd/oled_ssd1351.o b/lib/libssd1306/bld/lcd/oled_ssd1351.o index 71577ed..ce44d6c 100644 Binary files a/lib/libssd1306/bld/lcd/oled_ssd1351.o and b/lib/libssd1306/bld/lcd/oled_ssd1351.o differ diff --git a/lib/libssd1306/bld/lcd/oled_template.o b/lib/libssd1306/bld/lcd/oled_template.o index 24886e4..70f7d28 100644 Binary files a/lib/libssd1306/bld/lcd/oled_template.o and b/lib/libssd1306/bld/lcd/oled_template.o differ diff --git a/lib/libssd1306/bld/lcd/vga_monitor.o b/lib/libssd1306/bld/lcd/vga_monitor.o index a008545..11d65c4 100644 Binary files a/lib/libssd1306/bld/lcd/vga_monitor.o and b/lib/libssd1306/bld/lcd/vga_monitor.o differ diff --git a/lib/libssd1306/bld/libssd1306.a b/lib/libssd1306/bld/libssd1306.a index c11f680..390ee8c 100644 Binary files a/lib/libssd1306/bld/libssd1306.a and b/lib/libssd1306/bld/libssd1306.a differ diff --git a/lib/libssd1306/bld/nano_engine/canvas.o b/lib/libssd1306/bld/nano_engine/canvas.o index 054cbf3..287bcfe 100644 Binary files a/lib/libssd1306/bld/nano_engine/canvas.o and b/lib/libssd1306/bld/nano_engine/canvas.o differ diff --git a/lib/libssd1306/bld/nano_engine/core.o b/lib/libssd1306/bld/nano_engine/core.o index 3f9cba1..4f3b639 100644 Binary files a/lib/libssd1306/bld/nano_engine/core.o and b/lib/libssd1306/bld/nano_engine/core.o differ diff --git a/lib/libssd1306/bld/nano_gfx.o b/lib/libssd1306/bld/nano_gfx.o index 8ce4e4b..74b3d3f 100644 Binary files a/lib/libssd1306/bld/nano_gfx.o and b/lib/libssd1306/bld/nano_gfx.o differ diff --git a/lib/libssd1306/bld/sprite_pool.o b/lib/libssd1306/bld/sprite_pool.o index a7402b8..a5baef9 100644 Binary files a/lib/libssd1306/bld/sprite_pool.o and b/lib/libssd1306/bld/sprite_pool.o differ diff --git a/lib/libssd1306/bld/ssd1306_16bit.o b/lib/libssd1306/bld/ssd1306_16bit.o index 434b94d..fb71b2f 100644 Binary files a/lib/libssd1306/bld/ssd1306_16bit.o and b/lib/libssd1306/bld/ssd1306_16bit.o differ diff --git a/lib/libssd1306/bld/ssd1306_1bit.o b/lib/libssd1306/bld/ssd1306_1bit.o index 58a2c52..204a916 100644 Binary files a/lib/libssd1306/bld/ssd1306_1bit.o and b/lib/libssd1306/bld/ssd1306_1bit.o differ diff --git a/lib/libssd1306/bld/ssd1306_8bit.o b/lib/libssd1306/bld/ssd1306_8bit.o index b8d6660..2de1323 100644 Binary files a/lib/libssd1306/bld/ssd1306_8bit.o and b/lib/libssd1306/bld/ssd1306_8bit.o differ diff --git a/lib/libssd1306/bld/ssd1306_console.o b/lib/libssd1306/bld/ssd1306_console.o index 2d26c39..f58c527 100644 Binary files a/lib/libssd1306/bld/ssd1306_console.o and b/lib/libssd1306/bld/ssd1306_console.o differ diff --git a/lib/libssd1306/bld/ssd1306_fonts.o b/lib/libssd1306/bld/ssd1306_fonts.o index ae5f3b4..3b750ec 100644 Binary files a/lib/libssd1306/bld/ssd1306_fonts.o and b/lib/libssd1306/bld/ssd1306_fonts.o differ diff --git a/lib/libssd1306/bld/ssd1306_generic.o b/lib/libssd1306/bld/ssd1306_generic.o index e716c3b..a73b702 100644 Binary files a/lib/libssd1306/bld/ssd1306_generic.o and b/lib/libssd1306/bld/ssd1306_generic.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/arduino/platform.o b/lib/libssd1306/bld/ssd1306_hal/arduino/platform.o index 57986e1..9364dfb 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/arduino/platform.o and b/lib/libssd1306/bld/ssd1306_hal/arduino/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/avr/platform.o b/lib/libssd1306/bld/ssd1306_hal/avr/platform.o index 53f2b0f..7549972 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/avr/platform.o and b/lib/libssd1306/bld/ssd1306_hal/avr/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/energia/platform.o b/lib/libssd1306/bld/ssd1306_hal/energia/platform.o index 9500e5d..43d36ce 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/energia/platform.o and b/lib/libssd1306/bld/ssd1306_hal/energia/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/linux/platform.o b/lib/libssd1306/bld/ssd1306_hal/linux/platform.o index 970a36e..85b2edb 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/linux/platform.o and b/lib/libssd1306/bld/ssd1306_hal/linux/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/mingw/platform.o b/lib/libssd1306/bld/ssd1306_hal/mingw/platform.o index 8d7da5d..ae4ae3f 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/mingw/platform.o and b/lib/libssd1306/bld/ssd1306_hal/mingw/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/stm32/platform.o b/lib/libssd1306/bld/ssd1306_hal/stm32/platform.o index f657f0d..526734e 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/stm32/platform.o and b/lib/libssd1306/bld/ssd1306_hal/stm32/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_hal/template/platform.o b/lib/libssd1306/bld/ssd1306_hal/template/platform.o index 7b559ec..bf25833 100644 Binary files a/lib/libssd1306/bld/ssd1306_hal/template/platform.o and b/lib/libssd1306/bld/ssd1306_hal/template/platform.o differ diff --git a/lib/libssd1306/bld/ssd1306_menu.o b/lib/libssd1306/bld/ssd1306_menu.o index 8303a4f..0ef29f4 100644 Binary files a/lib/libssd1306/bld/ssd1306_menu.o and b/lib/libssd1306/bld/ssd1306_menu.o differ diff --git a/lib/libssd1306/bld/ssd1306_uart.o b/lib/libssd1306/bld/ssd1306_uart.o index dd4a820..2522aa7 100644 Binary files a/lib/libssd1306/bld/ssd1306_uart.o and b/lib/libssd1306/bld/ssd1306_uart.o differ diff --git a/src/framebuffer.c b/src/framebuffer.c index 74bf27c..37bdb9b 100644 --- a/src/framebuffer.c +++ b/src/framebuffer.c @@ -4,138 +4,134 @@ #include "framebuffer.h" -#define MIN(a,b) ((a)>(b)?(b):(a)) -#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a, b) ((a)>(b)?(b):(a)) +#define MAX(a, b) ((a)>(b)?(a):(b)) #include uint8_t fb[(FBH / 8) * FBW]; /** Fill with a vertical pattern, 1 byte */ -void fb_fill(uint8_t pattern) { +void fb_fill(uint8_t pattern) +{ memset(fb, pattern, sizeof(fb)); } -void fb_clear() { - fb_fill(0); +static void draw_mask(fbsize_t idx, uint8_t mask, uint8_t color) +{ + if (color != 0) { + fb[idx] |= mask; + } else { + fb[idx] &= ~mask; + } } -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); +void fb_px(fbpos_t x, fbpos_t y, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + const fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; + draw_mask(cell, 1 << rowrem, color); +} + +uint8_t fb_getpx(fbpos_t x, fbpos_t y) +{ + if (x >= FBW || y >= FBH) { return 0; } + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + const fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; + if (fb[cell] & (1 << rowrem)) { + return 0xFF; } else { - fb[cell] &= ~(1 << rowrem); + return 0x00; } } -void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color) { - if (x >= FBW || y >= FBH) return; +void fb_hline(fbpos_t x, fbpos_t y, fbpos_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); - } + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; + for (uint8_t i = 0; i < w; i++) { + draw_mask(cell, 1 << rowrem, color); cell++; } } -void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color) { - if (x >= FBW || y >= FBH) return; +void fb_vline(fbpos_t x, fbpos_t y, fbpos_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; + const fbpos_t row = y / 8; + const fbpos_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; - } + const uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - h - rowrem)); + draw_mask(cell, mask, color); return; } else { // First - uint8_t mask = (0xFF << rowrem); - if (color) { - fb[cell] |= mask; - } else { - fb[cell] &= ~mask; - } - h -= rowrem; + draw_mask(cell, 0xFF << rowrem, color); + h -= (rowrem == 0 ? 8 : (8 - 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; + const fbpos_t whole_cells = h / 8; + if (whole_cells > 0) { + h -= whole_cells * 8; + for (fbpos_t i = 0; i < whole_cells; i++) { + cell += FBW; + draw_mask(cell, 0xFF, color); } } // last - mask = (0xFF >> (8-h)); - if (color) { - fb[cell] |= mask; - } else { - fb[cell] &= ~mask; - } + cell += FBW; + draw_mask(cell, 0xFF >> (8 - h), color); } } -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; +void fb_rect(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } + w = MIN(FBW - x, w); + h = MIN(FBH - y, h); + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; - if (rowrem + h <= 8) { + if (w == 1 && h == 1) { + fb_px(x, y, color); + } else if (w == 1) { + fb_vline(x, y, h, color); + } else if (h == 1) { + fb_hline(x, y, w, color); + } else if (rowrem + h <= 8) { // all within one cell - uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - (h - rowrem))); + 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; - } + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, mask, color); } 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; - } + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, mask, color); } 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; + const fbpos_t whole_cells = h / 8; + if (whole_cells > 0) { + h -= whole_cells * 8; + for (fbpos_t j = 0; j < whole_cells; j++) { + cell += FBW; + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, 0xFF, color); } } } @@ -143,109 +139,64 @@ void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { 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; - } + mask = (0xFF >> (8 - h)); + for (fbpos_t i = 0; i < w; i++) { + draw_mask(cell + i, mask, color); } } } -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; +void fb_frame(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t thickness, uint8_t color) +{ + if (thickness == 0) { + return; + } else if (thickness == 1) { + fb_hline(x, y, w, color); + fb_vline(x, y, h, color); + fb_hline(x, y + h - 1, w, color); + fb_vline(x + w - 1, y, h, color); + } else { + fb_rect(x, y, w, thickness, color); + fb_rect(x, y + h - thickness, w, thickness, color); + fb_rect(x, y + thickness, thickness, h - 2 * thickness, color); + fb_rect(x + w - thickness, y + thickness, thickness, h - 2 * thickness, color); + } +} + +void fb_bitmap(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, const uint8_t *map, uint8_t color) +{ + if (x >= FBW || y >= FBH) { return; } + const fbpos_t w0 = w; 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; + const fbpos_t row = y / 8; + const fbpos_t rowrem = y % 8; + fbsize_t cell = (fbsize_t) x + (fbsize_t) row * FBW; if (rowrem + h <= 8) { - for(uint8_t i = 0; i < w; i++) { + for (fbpos_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; - } + const uint8_t mask = (map[i] & (0xFF >> (8 - h))) << rowrem; + draw_mask(cell + i, mask, color); } return; - } else if (rowrem == 0) { - // Optimization - uint8_t mapc0 = 0; - - // 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; - mapc0 += w0; - for(uint8_t i = 0; i < w; i++) { - uint8_t mask = map[i + mapc0]; - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } - } - } - - // last - mapc0 += w0; - cell += FBW; - - // last - for(uint8_t i = 0; i < w; i++) { - uint8_t mask = map[i + mapc0] & (0xFF >> (8-h)); - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } - } - } else { - uint8_t mapc0 = 0; + fbsize_t mapc0 = 0; + // Draw the bitmap slice-by-slice based on how rows of the bitmap intersect with rows of the canvas. + // This could be optimized to walk each row of the canvas only once, but the code would get bigger. while (h > 0) { - // First - for (uint8_t i = 0; i < w; i++) { - uint8_t mask = (map[i + mapc0] & (0xFF >> rowrem)) << rowrem; - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; - } + for (fbpos_t i = 0; i < w; i++) { + const uint8_t mask = (map[i + mapc0] & (0xFF >> rowrem)) << rowrem; + draw_mask(cell + i, mask, color); } - //mapc0 += w0; cell += FBW; - // leftover of the first row in map - - // last - for (uint8_t i = 0; i < w; i++) { - uint8_t mask = (map[i + mapc0] & (0xFF << (8 - rowrem))) >> (8 - rowrem); - if (color) { - fb[cell + i] |= mask; - } else { - fb[cell + i] &= ~mask; + if (rowrem != 0) { + for (fbpos_t i = 0; i < w; i++) { + const uint8_t mask = (map[i + mapc0] & (0xFF << (8 - rowrem))) >> (8 - rowrem); + draw_mask(cell + i, mask, color); } } @@ -259,3 +210,73 @@ void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, u } } + +enum SevenSegBars { + T = 1, RT = 2, RB = 4, B = 8, LB = 16, LT = 32, M = 64 +}; + +static const uint8_t PROGMEM seven[] = { + [0] = T | RT | RB | B | LB | LT, + [1] = RT | RB, + [2] = T | RT | M | LB | B, + [3] = T | RT | M | RB | B, + [4] = RT | RB | M | LT, + [5] = T | LT | M | RB | B, + [6] = T | LT | LB | B | RB | M, + [7] = T | RT | RB, + [8] = T | LT | RT | LB | RB | B | M, + [9] = T | LT | RT | RB | B | M, +}; + +fbpos_t fb_7seg_dig(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t digit, uint8_t color) +{ + const uint8_t mask = digit > 9 ? 0 : pgm_read_byte(&seven[digit]); + const fbpos_t wi = w - th * 2; + const fbpos_t hi = (h - th * 3) / 2; + + bool bcolor = !color; // changed for XOR + + fb_rect(x + th, + y, + wi, + th, bcolor ^ (bool) (mask & T)); + + fb_rect(x + th, + y + th + hi, + wi, + th, bcolor ^ (bool) (mask & M)); + + fb_rect(x + th, + y + th * 2 + hi * 2, + wi, + th, bcolor ^ (bool) (mask & B)); + + fb_rect(x, + y + th, + th, + hi, bcolor ^ (bool) (mask & LT)); + + fb_rect(x + th + wi, + y + hi + th, + th, + hi, bcolor ^ (bool) (mask & LB)); + + fb_rect(x + th + wi, + y + th, + th, + hi, bcolor ^ (bool) (mask & RT)); + + fb_rect(x + th + wi, + y + th * 2 + hi, + th, + hi, bcolor ^ (bool) (mask & RB)); + + return w; +} + +fbpos_t fb_7seg_period(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t color) +{ + const fbpos_t hi = (h - th * 3) / 2; + fb_rect(x, y + hi * 2 + th * 2, th, th, color); + return th; +} diff --git a/src/framebuffer.h b/src/framebuffer.h index b0dcb44..c0cb1f4 100644 --- a/src/framebuffer.h +++ b/src/framebuffer.h @@ -13,6 +13,9 @@ #define FBSET 0xFF #define FBCLEAR 0x00 +typedef uint16_t fbsize_t; +typedef uint8_t fbpos_t; + /// Framebuffer backing array. /// /// The format is the native format for SSD1306: array of bytes representing pixels in 8 rows at once, LSB is the topmost row. @@ -26,16 +29,62 @@ /// and more bytes continue rows 8-15 and so on extern uint8_t fb[(FBH / 8) * FBW]; +/// Fill the entire screen with a byte pattern. +/// Use 0xFF or 0x00 for a solid fill. Other patterns may be used to create horizontal stripes. 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); + +/// Clear the display (fill with 0x00) +static inline void fb_clear(void) +{ + fb_fill(0); +} + +/// Set a single pixel +void fb_px(fbpos_t x, fbpos_t y, uint8_t color); + +/// Get pixel color +uint8_t fb_getpx(fbpos_t x, fbpos_t y); + +/// Draw a horizontal line +void fb_hline(fbpos_t x, fbpos_t y, fbpos_t w, uint8_t color); + +/// Draw a vertical line +void fb_vline(fbpos_t x, fbpos_t y, fbpos_t h, uint8_t color); + +/// Draw a filled rect +void fb_rect(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, uint8_t color); + +/// Draw a frame (unfilled rect) +void fb_frame(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t thickness, uint8_t color); + +/// Draw a bitmap +void fb_bitmap(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, const uint8_t *map, uint8_t color); + +/// Draw a 7-segment digit. Returns its width (without spacing) +/// +/// \param x - pos X (left top) +/// \param y - pos Y (left top) +/// \param w - full digit width +/// \param h - full digit height; will be adjusted down if needed +/// \param th - thickness +/// \param digit - digit 0-9 +/// \return width taken +fbpos_t fb_7seg_dig(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t digit, uint8_t color); + +/// Draw a 7-segment period. Returns its width (without spacing). +/// Digit height is (w * 2 - th) +/// +/// \param x - pos X (digit left top) +/// \param y - pos Y (digit left top) +/// \param w - full digit width +/// \param h - full digit height; will be adjusted down if needed +/// \param th - thickness +/// \return width taken +fbpos_t fb_7seg_period(fbpos_t x, fbpos_t y, fbpos_t w, fbpos_t h, fbpos_t th, uint8_t color); /// Output the framebuffer array `fb` to the display device. +/// +/// The user must implement this extern void fb_blit(void); - #endif //FRAMEBUFFER_H diff --git a/src/framebuffer_config.h b/src/framebuffer_config.h index 56f495e..fec08c7 100644 --- a/src/framebuffer_config.h +++ b/src/framebuffer_config.h @@ -4,4 +4,10 @@ #define FBW 128 #define FBH 32 +#include +/* +#define PROGMEM +#define pgm_read_byte(adr) (*adr) +*/ + #endif /* FRAMEBUFFER_CONFIG_H */