diff --git a/bootloader/bootloader-display.c b/bootloader/bootloader-display.c index 8c13116d78e937292ce8499c7014dce19b536f07..d04db551d6833aca9391cd5aad80139792ecfdf4 100644 --- a/bootloader/bootloader-display.c +++ b/bootloader/bootloader-display.c @@ -6,31 +6,18 @@ #include "gfx.h" #include "display.h" -/* - * "Decompress" splash-screen image. The algorithm works as follows: - * - * Each byte encodes up to 127 pixels in either white or black. The most - * significant bit determines the color, the remaining 7 bits determine the - * amount. - */ static void bootloader_display_splash(void) { - int idx = 0; - - Color white = gfx_color(&display_screen, WHITE); - Color black = gfx_color(&display_screen, BLACK); - for (int i = 0; i < sizeof(splash); i++) { - Color color = (splash[i] & 0x80) ? white : black; - uint8_t length = splash[i] & 0x7f; - - for (int j = 0; j < length; j++) { - uint16_t x = idx % 160; - uint16_t y = idx / 160; - gfx_setpixel(&display_screen, x, y, color); - idx++; - } - } - + gfx_copy_region( + &display_screen, + 0, + 0, + 160, + 80, + GFX_RLE_MONO, + sizeof(splash), + (const void *)(splash) + ); gfx_update(&display_screen); } diff --git a/epicardium/main.c b/epicardium/main.c index 3d40ceb8ecbcbf09418b74a0c54adc8b3e7b1780..95319203b53b33b0c099d0b7ecaa50f3ea3e50d8 100644 --- a/epicardium/main.c +++ b/epicardium/main.c @@ -34,8 +34,15 @@ int main(void) mxc_delay(500000); epic_disp_clear(0x0000); if (strcmp(CARD10_VERSION, "v1.11") == 0) { - gfx_copy_region_raw( - &display_screen, 0, 0, 160, 80, 2, version_splash + gfx_copy_region( + &display_screen, + 0, + 0, + 160, + 80, + GFX_RAW, + sizeof(version_splash), + version_splash ); } else { const int off = (160 - (int)strlen(version_buf) * 14) / 2; diff --git a/hw-tests/dual-core/main.c b/hw-tests/dual-core/main.c index 60636833753d48b3812833266f01876297037a1d..30026b8051f1e64f775dbcee8df46fd7b1d8615b 100644 --- a/hw-tests/dual-core/main.c +++ b/hw-tests/dual-core/main.c @@ -3,27 +3,34 @@ ******************************************************************************/ /***** Includes *****/ -#include "pmic.h" -#include "leds.h" #include "card10.h" +#include "leds.h" +#include "pmic.h" -#include "gfx.h" #include "display.h" +#include "gfx.h" #include "tmr_utils.h" -#include <stdio.h> +#include <Heart.h> #include <stdint.h> +#include <stdio.h> #include <string.h> -#include <Heart.h> int main(void) { card10_init(); card10_diag(); - gfx_copy_region_raw( - &display_screen, 0, 0, 160, 80, 2, (const void *)(Heart) + gfx_copy_region( + &display_screen, + 0, + 0, + 160, + 80, + GFX_RAW, + sizeof(Heart), + (const void *)(Heart) ); gfx_update(&display_screen); diff --git a/hw-tests/hello-world/main.c b/hw-tests/hello-world/main.c index 87fdab3ba7d8bf33eea462ce5b71d0bf1eacbd5e..5f2a82aad5b14a52cfa94ee3e3f6acf891a3dfa3 100644 --- a/hw-tests/hello-world/main.c +++ b/hw-tests/hello-world/main.c @@ -30,8 +30,15 @@ int main(void) card10_init(); card10_diag(); - gfx_copy_region_raw( - &display_screen, 0, 0, 160, 80, 2, (const void *)(Heart) + gfx_copy_region( + &display_screen, + 0, + 0, + 160, + 80, + GFX_RAW, + sizeof(Heart), + (const void *)(Heart) ); gfx_update(&display_screen); diff --git a/hw-tests/ips/main.c b/hw-tests/ips/main.c index 6aa51eae2c518e69219f7e16af89e39b33a4cb24..b638a7832310f0d681c57f979001b595fe1e140c 100644 --- a/hw-tests/ips/main.c +++ b/hw-tests/ips/main.c @@ -37,22 +37,24 @@ int main(void) gfx_line(&display_screen, 100, 10, 70, 40, 2, yellow); gfx_circle(&display_screen, 85, 25, 22, 2, green); - gfx_copy_region_raw( + gfx_copy_region( &display_screen, 120, 0, 40, 40, - 2, + GFX_RAW, + 40 * 40 * 2, (const void *)(gImage_40X40) ); - gfx_copy_region_raw( + gfx_copy_region( &display_screen, 0, 0, 160, 80, - 2, + GFX_RAW, + 160 * 80 * 2, (const void *)(gImage_160X80) ); gfx_update(&display_screen); diff --git a/lib/gfx/gfx.c b/lib/gfx/gfx.c index 49b8d3a8d618bf49c1ed849f49c97316b9210496..8e6c6115ce28b399f85fe3d8f33737553a2d4de4 100644 --- a/lib/gfx/gfx.c +++ b/lib/gfx/gfx.c @@ -273,15 +273,17 @@ Color gfx_color(struct gfx_region *reg, enum gfx_color color) return gfx_color_rgb(reg, c->r, c->g, c->b); } -void gfx_copy_region_raw( +static void gfx_copy_region_raw( struct gfx_region *reg, int x, int y, int w, int h, - size_t bpp, + size_t size, const void *p ) { + size_t bpp = size / (w * h); + for (int y_ = 0; y_ < h; y_++) { for (int x_ = 0; x_ < w; x_++) { Color c; @@ -299,6 +301,96 @@ void gfx_copy_region_raw( } } +static void gfx_copy_region_mono( + struct gfx_region *reg, + int x, + int y, + int w, + int h, + size_t size, + const void *p +) { + const char *bp = p; + int bit = 0; + Color white = gfx_color(reg, WHITE); + Color black = gfx_color(reg, BLACK); + + for (int y_ = 0; y_ < h; y_++) { + for (int x_ = 0; x_ < w; x_++) { + int value = *bp & (1 << bit); + if (++bit >= 8) { + bp++; + bit %= 8; + + if ((const void *)(bp) >= (p + size)) + return; + } + + Color c = value ? white : black; + gfx_setpixel(reg, x + x_, y + y_, c); + } + } +} + +/* + * "Decompress" the image. The algorithm works as follows: + * + * Each byte encodes up to 127 pixels in either white or black. The most + * significant bit determines the color, the remaining 7 bits determine the + * amount. + */ +static void gfx_copy_region_rle_mono( + struct gfx_region *reg, + int x, + int y, + int w, + int h, + size_t size, + const void *p +) { + const char *data = p; + int idx = 0; + Color white = gfx_color(reg, WHITE); + Color black = gfx_color(reg, BLACK); + + for (int i = 0; i < size; i++) { + Color color = (data[i] & 0x80) ? white : black; + uint8_t length = data[i] & 0x7f; + + for (int j = 0; j < length; j++) { + uint16_t x = idx % w; + uint16_t y = idx / w; + gfx_setpixel(reg, x, y, color); + idx++; + } + } +} + +void gfx_copy_region( + struct gfx_region *reg, + int x, + int y, + int w, + int h, + enum gfx_encoding encoding, + size_t size, + const void *p +) { + switch (encoding) { + case GFX_RAW: + gfx_copy_region_raw(reg, x, y, w, h, size, p); + break; + case GFX_MONO: + gfx_copy_region_mono(reg, x, y, w, h, size, p); + break; + case GFX_RLE_MONO: + gfx_copy_region_rle_mono(reg, x, y, w, h, size, p); + break; + default: + break; + } +} + void gfx_copy_raw(struct gfx_region *reg, const void *p, size_t size) { fb_copy_raw(reg->fb, p, size); diff --git a/lib/gfx/gfx.h b/lib/gfx/gfx.h index 0f64a429b59170182077b7d01e2d1cd027743974..4c9a16e508fef1ac4d7346d7adeeee62d71d5c1f 100644 --- a/lib/gfx/gfx.h +++ b/lib/gfx/gfx.h @@ -43,6 +43,12 @@ enum gfx_color { COLORS }; +enum gfx_encoding { + GFX_RAW, + GFX_MONO, + GFX_RLE_MONO +}; + struct gfx_color_rgb { uint8_t r; uint8_t g; @@ -51,8 +57,9 @@ struct gfx_color_rgb { Color gfx_color(struct gfx_region *reg, enum gfx_color color); -void gfx_copy_region_raw(struct gfx_region *reg, int x, int y, int w, int h, - size_t bpp, const void *p); +void gfx_copy_region(struct gfx_region *reg, int x, int y, int w, int h, + enum gfx_encoding encoding, size_t size, + const void *p); void gfx_copy_raw(struct gfx_region *reg, const void *p, size_t size); #endif