diff --git a/apps/SOURCES b/apps/SOURCES index ccfc7fa280..0fdb6f5955 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -57,8 +57,10 @@ recorder/icons.c recorder/keyboard.c recorder/peakmeter.c recorder/widgets.c -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 recorder/backdrop.c +#endif +#ifdef HAVE_LCD_COLOR gui/color_picker.c #endif #endif diff --git a/apps/bookmark.c b/apps/bookmark.c index cb1735f3d5..e6c6261856 100644 --- a/apps/bookmark.c +++ b/apps/bookmark.c @@ -51,7 +51,7 @@ #include "splash.h" #include "yesno.h" -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif @@ -218,7 +218,7 @@ bool bookmark_autobookmark(void) str(LANG_RESUME_CONFIRM_PLAYER)}; struct text_message message={(char **)lines, 2}; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); /* switch to main backdrop as we may come from wps */ #endif gui_syncstatusbar_draw(&statusbars, false); diff --git a/apps/filetree.c b/apps/filetree.c index 9d5109ceb9..f10c02b449 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -54,7 +54,7 @@ static int boot_size = 0; static int boot_cluster; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif @@ -466,7 +466,7 @@ int ft_enter(struct tree_context* c) /* wps config file */ case TREE_ATTR_WPS: gui_syncsplash(0, true, str(LANG_WAIT)); -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 unload_wps_backdrop(); #endif wps_data_load(gui_wps[0].data, buf, true); diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 98f2c7e2ed..212f40f3c0 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -48,7 +48,7 @@ #include "bmp.h" #include "atoi.h" #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif #include "dsp.h" @@ -143,7 +143,7 @@ bool wps_data_preload_tags(struct wps_data *data, char *buf, } break; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 case 'X': /* Backdrop image - must be the same size as the LCD */ { @@ -2473,7 +2473,7 @@ bool gui_wps_display(void) if(i == 0) { #ifdef HAVE_LCD_BITMAP -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 unload_wps_backdrop(); #endif wps_data_load(gui_wps[i].data, diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 115e9f7441..482442cb53 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c @@ -54,7 +54,7 @@ #include "abrepeat.h" #include "playback.h" #include "splash.h" -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif #include "ata_idle_notify.h" @@ -104,9 +104,9 @@ long gui_wps_show(void) { gui_wps_set_margin(&gui_wps[i]); } -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_wps_backdrop(); -#endif /* HAVE_LCD_COLOR */ +#endif /* LCD_DEPTH > 1 */ #endif #ifdef AB_REPEAT_ENABLE @@ -201,12 +201,12 @@ long gui_wps_show(void) switch(button) { case ACTION_WPS_CONTEXT: -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif action_signalscreenchange(); onplay(wps_state.id3->path, TREE_ATTR_MPA, CONTEXT_WPS); -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_wps_backdrop(); #endif #ifdef HAVE_LCD_BITMAP @@ -422,13 +422,13 @@ long gui_wps_show(void) FOR_NB_SCREENS(i) gui_wps[i].display->stop_scroll(); -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif action_signalscreenchange(); if (main_menu()) return true; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_wps_backdrop(); #endif #ifdef HAVE_LCD_BITMAP @@ -443,12 +443,12 @@ long gui_wps_show(void) #ifdef HAVE_QUICKSCREEN case ACTION_WPS_QUICKSCREEN: -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif if (quick_screen_quick(button)) return SYS_USB_CONNECTED; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_wps_backdrop(); #endif #ifdef HAVE_LCD_BITMAP @@ -464,7 +464,7 @@ long gui_wps_show(void) /* screen settings */ #ifdef BUTTON_F3 case ACTION_F3: -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif if (quick_screen_f3(BUTTON_F3)) @@ -482,13 +482,13 @@ long gui_wps_show(void) /* pitch screen */ #ifdef HAVE_PITCHSCREEN case ACTION_WPS_PITCHSCREEN: -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif action_signalscreenchange(); if (1 == pitch_screen()) return SYS_USB_CONNECTED; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_wps_backdrop(); #endif restore = true; @@ -533,11 +533,11 @@ long gui_wps_show(void) break; case ACTION_WPS_ID3SCREEN: -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif browse_id3(); -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_wps_backdrop(); #endif #ifdef HAVE_LCD_BITMAP @@ -559,7 +559,7 @@ long gui_wps_show(void) case SYS_POWEROFF: bookmark_autobookmark(); -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif default_event_handler(SYS_POWEROFF); @@ -868,7 +868,7 @@ void gui_sync_wps_init(void) gui_wps_set_data(&gui_wps[i], &wps_datas[i]); gui_wps_set_statusbar(&gui_wps[i], &statusbars.statusbars[i]); } -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 unload_wps_backdrop(); #endif } diff --git a/apps/onplay.c b/apps/onplay.c index 60a737938f..59fa8caa85 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -50,7 +50,7 @@ #include "action.h" #include "splash.h" #include "yesno.h" -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif #ifdef HAVE_LCD_BITMAP @@ -493,7 +493,7 @@ static bool delete_dir(void) return delete_handler(true); } -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 static bool set_backdrop(void) { /* load the image */ @@ -837,7 +837,7 @@ int onplay(char* file, int attr, int from) struct menu_item items[12]; #endif int m, i=0, result; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 char *suffix; #endif @@ -920,7 +920,7 @@ int onplay(char* file, int attr, int from) items[i].function = delete_file; i++; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 suffix = strrchr(file, '.'); if (suffix) { diff --git a/apps/plugin.c b/apps/plugin.c index 0d9635b88e..4827476545 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -485,7 +485,7 @@ int plugin_load(const char* plugin, void* parameter) #ifdef HAVE_REMOTE_LCD int rxm, rym; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 fb_data* old_backdrop; #endif @@ -567,7 +567,7 @@ int plugin_load(const char* plugin, void* parameter) xm = lcd_getxmargin(); ym = lcd_getymargin(); lcd_setmargins(0,0); -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 old_backdrop = lcd_get_backdrop(); lcd_set_backdrop(NULL); #endif @@ -594,8 +594,8 @@ int plugin_load(const char* plugin, void* parameter) #ifdef HAVE_LCD_BITMAP #if LCD_DEPTH > 1 -#ifdef HAVE_LCD_COLOR lcd_set_backdrop(old_backdrop); +#ifdef HAVE_LCD_COLOR lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, global_settings.bg_color); #else diff --git a/apps/recorder/backdrop.c b/apps/recorder/backdrop.c index 374dba9f4b..7779792621 100644 --- a/apps/recorder/backdrop.c +++ b/apps/recorder/backdrop.c @@ -21,10 +21,20 @@ #include "config.h" #include "lcd.h" #include "backdrop.h" -#include "splash.h" /* debugging */ +#if LCD_DEPTH >= 8 fb_data main_backdrop[LCD_HEIGHT][LCD_WIDTH]; fb_data wps_backdrop[LCD_HEIGHT][LCD_WIDTH]; +#elif LCD_DEPTH == 2 +#if LCD_PIXELFORMAT == VERTICAL_PACKING +fb_data main_backdrop[(LCD_HEIGHT+3)/4][LCD_WIDTH]; +fb_data wps_backdrop[(LCD_HEIGHT+3)/4][LCD_WIDTH]; +#else +fb_data main_backdrop[LCD_HEIGHT][LCD_FBWIDTH]; +fb_data wps_backdrop[LCD_HEIGHT][LCD_FBWIDTH]; +#endif +#endif + bool main_backdrop_valid = false; bool wps_backdrop_valid = false; @@ -52,27 +62,23 @@ bool load_backdrop(char* filename, fb_data* backdrop_buffer) bool load_main_backdrop(char* filename) { main_backdrop_valid = load_backdrop(filename, &main_backdrop[0][0]); -/* gui_syncsplash(100, true, "MAIN backdrop load: %s", main_backdrop_valid ? "OK" : "FAIL");*/ return main_backdrop_valid; } bool load_wps_backdrop(char* filename) { wps_backdrop_valid = load_backdrop(filename, &wps_backdrop[0][0]); -/* gui_syncsplash(100, true, "WPS backdrop load: %s", main_backdrop_valid ? "OK" : "FAIL");*/ return wps_backdrop_valid; } void unload_main_backdrop(void) { main_backdrop_valid = false; -/* gui_syncsplash(100, true, "MAIN backdrop unload");*/ } void unload_wps_backdrop(void) { wps_backdrop_valid = false; -/* gui_syncsplash(100, true, "WPS backdrop unload");*/ } void show_main_backdrop(void) @@ -89,7 +95,6 @@ void show_wps_backdrop(void) } else { -/* gui_syncsplash(100, true, "WPS backdrop show: fallback to MAIN");*/ show_main_backdrop(); } } diff --git a/apps/recorder/backdrop.h b/apps/recorder/backdrop.h index da515af261..93373f1321 100644 --- a/apps/recorder/backdrop.h +++ b/apps/recorder/backdrop.h @@ -20,15 +20,10 @@ #ifndef _BACKDROP_H #define _BACKDROP_H -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "lcd.h" #include "bmp.h" -#include "backdrop.h" -/* -extern fb_data main_backdrop[LCD_HEIGHT][LCD_WIDTH]; -extern fb_data wps_backdrop[LCD_HEIGHT][LCD_WIDTH]; -*/ bool load_main_backdrop(char* filename); bool load_wps_backdrop(char* filename); @@ -39,6 +34,6 @@ void unload_wps_backdrop(void); void show_main_backdrop(void); void show_wps_backdrop(void); -#endif /* HAVE_LCD_COLOR */ +#endif /* LCD_DEPTH > 1 */ #endif /* _BACKDROP_H */ diff --git a/apps/settings.c b/apps/settings.c index ea7e303d1d..fc0e5248a3 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -72,7 +72,7 @@ #include "statusbar.h" #include "splash.h" #include "list.h" -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif @@ -1034,7 +1034,7 @@ int settings_save( void ) i+= MAX_FILENAME; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 strncpy((char *)&config_block[i], (char *)global_settings.backdrop_file, MAX_FILENAME); i+= MAX_FILENAME; @@ -1198,7 +1198,7 @@ void settings_apply(void) global_settings.peak_meter_clip_hold); #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 unload_wps_backdrop(); #endif if ( global_settings.wps_file[0] && @@ -1212,7 +1212,7 @@ void settings_apply(void) wps_data_init(gui_wps[0].data); } -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 if ( global_settings.backdrop_file[0] && global_settings.backdrop_file[0] != 0xff ) { snprintf(buf, sizeof buf, BACKDROP_DIR "/%s.bmp", @@ -1222,7 +1222,9 @@ void settings_apply(void) unload_main_backdrop(); } show_main_backdrop(); +#endif +#ifdef HAVE_LCD_COLOR screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); screens[SCREEN_MAIN].set_background(global_settings.bg_color); #endif @@ -1438,7 +1440,7 @@ void settings_load(int which) i+= MAX_FILENAME; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 strncpy((char *)global_settings.backdrop_file, (char *)&config_block[i], MAX_FILENAME); i+= MAX_FILENAME; @@ -1593,7 +1595,7 @@ bool settings_load_config(const char* file) /* check for the string values */ if (!strcasecmp(name, "wps")) { -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 unload_wps_backdrop(); #endif int fd2; @@ -1629,7 +1631,7 @@ bool settings_load_config(const char* file) set_file(value, (char *)global_settings.font_file, MAX_FILENAME); } #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 else if (!strcasecmp(name, "backdrop")) { if (load_main_backdrop(value)) { set_file(value, (char *)global_settings.backdrop_file, MAX_FILENAME); @@ -1795,7 +1797,7 @@ bool settings_save_config(void) global_settings.font_file); #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 if (global_settings.backdrop_file[0] != 0) fdprintf(fd, "backdrop: %s/%s.bmp\r\n", BACKDROP_DIR, global_settings.backdrop_file); @@ -1898,9 +1900,10 @@ void settings_reset(void) { #endif global_settings.font_file[0] = '\0'; global_settings.lang_file[0] = '\0'; -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 global_settings.backdrop_file[0] = '\0'; - +#endif +#ifdef HAVE_LCD_COLOR global_settings.fg_color = LCD_DEFAULT_FG; global_settings.bg_color = LCD_DEFAULT_BG; #endif diff --git a/apps/settings.h b/apps/settings.h index 7b70ab748c..c0c6a943ce 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -454,7 +454,7 @@ struct user_settings bool dithering_enabled; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 unsigned char backdrop_file[MAX_FILENAME+1]; /* backdrop bitmap file */ #endif diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 0cbe5344fb..83f2452613 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -81,7 +81,7 @@ void dac_line_in(bool enable); #include "dsp.h" #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif @@ -393,7 +393,7 @@ static bool invert_cursor(void) return rc; } -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 /** * Menu to clear the backdrop image */ @@ -404,7 +404,9 @@ static bool clear_main_backdrop(void) show_main_backdrop(); return false; } +#endif +#ifdef HAVE_LCD_COLOR /** * Menu for fore/back colors */ @@ -1969,8 +1971,10 @@ static bool lcd_settings_menu(void) #endif { ID2P(LANG_INVERT_CURSOR), invert_cursor }, #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 { ID2P(LANG_CLEAR_BACKDROP), clear_main_backdrop }, +#endif +#ifdef HAVE_LCD_COLOR { ID2P(LANG_BACKGROUND_COLOR), set_bg_color }, { ID2P(LANG_FOREGROUND_COLOR), set_fg_color }, { ID2P(LANG_RESET_COLORS), reset_color }, diff --git a/apps/tree.c b/apps/tree.c index 623046a4b0..fea7b21529 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -83,7 +83,7 @@ #include "widgets.h" #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 #include "backdrop.h" #endif @@ -118,7 +118,7 @@ const struct filetype filetypes[] = { #ifdef HAVE_REMOTE_LCD { "rwps", TREE_ATTR_RWPS, Icon_Wps, VOICE_EXT_RWPS }, #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 { "bmp", TREE_ATTR_BMP, Icon_Wps, VOICE_EXT_WPS }, #endif #ifdef CONFIG_TUNER @@ -966,7 +966,7 @@ static bool dirbrowse(void) #endif reload_dir = true; #endif -#ifdef HAVE_LCD_COLOR +#if LCD_DEPTH > 1 show_main_backdrop(); #endif #ifdef HAVE_TAGCACHE diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 5ca0426d12..54357433b9 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c @@ -44,6 +44,9 @@ static const unsigned char pixmask[4] ICONST_ATTR = { 0xC0, 0x30, 0x0C, 0x03 }; +static fb_data* lcd_backdrop = NULL; +static long lcd_backdrop_offset IDATA_ATTR = 0; + static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ static int drawmode = DRMODE_SOLID; @@ -164,6 +167,15 @@ static void clearpixel(int x, int y) *address = data ^ ((data ^ bg_pattern) & mask); } +static void clearimgpixel(int x, int y) +{ + unsigned mask = pixmask[x & 3]; + fb_data *address = &lcd_framebuffer[y][x>>2]; + unsigned data = *address; + + *address = data ^ ((data ^ *(address + lcd_backdrop_offset)) & mask); +} + static void flippixel(int x, int y) { unsigned mask = pixmask[x & 3]; @@ -178,11 +190,19 @@ static void nopixel(int x, int y) (void)y; } -lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { +lcd_pixelfunc_type* const lcd_pixelfuncs_bgcolor[8] = { flippixel, nopixel, setpixel, setpixel, nopixel, clearpixel, nopixel, clearpixel }; +lcd_pixelfunc_type* const lcd_pixelfuncs_backdrop[8] = { + flippixel, nopixel, setpixel, setpixel, + nopixel, clearimgpixel, nopixel, clearimgpixel +}; + +lcd_pixelfunc_type* const * lcd_pixelfuncs = lcd_pixelfuncs_bgcolor; + + /* 'mask' and 'bits' contain 2 bits per pixel */ static void flipblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; @@ -200,6 +220,15 @@ static void bgblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bg_pattern) & mask & ~bits); } +static void bgimgblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void bgimgblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + + *address = data ^ ((data ^ *(address + lcd_backdrop_offset)) & mask & ~bits); +} + static void fgblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; static void fgblock(fb_data *address, unsigned mask, unsigned bits) @@ -220,6 +249,17 @@ static void solidblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bits) & mask); } +static void solidimgblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void solidimgblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + unsigned bgp = *(address + lcd_backdrop_offset); + + bits = bgp ^ ((bgp ^ fg_pattern) & bits); + *address = data ^ ((data ^ bits) & mask); +} + static void flipinvblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; static void flipinvblock(fb_data *address, unsigned mask, unsigned bits) @@ -236,6 +276,15 @@ static void bginvblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bg_pattern) & mask & bits); } +static void bgimginvblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void bgimginvblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + + *address = data ^ ((data ^ *(address + lcd_backdrop_offset)) & mask & bits); +} + static void fginvblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; static void fginvblock(fb_data *address, unsigned mask, unsigned bits) @@ -256,11 +305,53 @@ static void solidinvblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bits) & mask); } -lcd_blockfunc_type* const lcd_blockfuncs[8] = { +static void solidimginvblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void solidimginvblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + unsigned fgp = fg_pattern; + + bits = fgp ^ ((fgp ^ *(address + lcd_backdrop_offset)) & bits); + *address = data ^ ((data ^ bits) & mask); +} + +lcd_blockfunc_type* const lcd_blockfuncs_bgcolor[8] = { flipblock, bgblock, fgblock, solidblock, flipinvblock, bginvblock, fginvblock, solidinvblock }; +lcd_blockfunc_type* const lcd_blockfuncs_backdrop[8] = { + flipblock, bgimgblock, fgblock, solidimgblock, + flipinvblock, bgimginvblock, fginvblock, solidimginvblock +}; + +lcd_blockfunc_type* const * lcd_blockfuncs = lcd_blockfuncs_bgcolor; + + +void lcd_set_backdrop(fb_data* backdrop) +{ + lcd_backdrop = backdrop; + if (backdrop) + { + lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; + lcd_pixelfuncs = lcd_pixelfuncs_backdrop; + lcd_blockfuncs = lcd_blockfuncs_backdrop; + } + else + { + lcd_backdrop_offset = 0; + lcd_pixelfuncs = lcd_pixelfuncs_bgcolor; + lcd_blockfuncs = lcd_blockfuncs_bgcolor; + } +} + +fb_data* lcd_get_backdrop(void) +{ + return lcd_backdrop; +} + + static inline void setblock(fb_data *address, unsigned mask, unsigned bits) { unsigned data = *address; @@ -274,9 +365,17 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) /* Clear the whole display */ void lcd_clear_display(void) { - unsigned bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; - - memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); + if (drawmode & DRMODE_INVERSEVID) + { + memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); + } + else + { + if (lcd_backdrop) + memcpy(lcd_framebuffer, lcd_backdrop, sizeof lcd_framebuffer); + else + memset(lcd_framebuffer, bg_pattern, sizeof lcd_framebuffer); + } scrolling_lines = 0; } diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c index 799865c36d..ec20068d95 100644 --- a/firmware/drivers/lcd-2bit-vert.c +++ b/firmware/drivers/lcd-2bit-vert.c @@ -48,6 +48,9 @@ static const unsigned char pixmask[4] ICONST_ATTR = { 0x03, 0x0C, 0x30, 0xC0 }; +static fb_data* lcd_backdrop = NULL; +static long lcd_backdrop_offset IDATA_ATTR = 0; + static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ static int drawmode = DRMODE_SOLID; @@ -167,6 +170,15 @@ static void clearpixel(int x, int y) *address = data ^ ((data ^ bg_pattern) & mask); } +static void clearimgpixel(int x, int y) +{ + unsigned mask = pixmask[y & 3]; + fb_data *address = &lcd_framebuffer[y>>2][x]; + unsigned data = *address; + + *address = data ^ ((data ^ *(address + lcd_backdrop_offset)) & mask); +} + static void flippixel(int x, int y) { unsigned mask = pixmask[y & 3]; @@ -181,11 +193,19 @@ static void nopixel(int x, int y) (void)y; } -lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { +lcd_pixelfunc_type* const lcd_pixelfuncs_bgcolor[8] = { flippixel, nopixel, setpixel, setpixel, nopixel, clearpixel, nopixel, clearpixel }; +lcd_pixelfunc_type* const lcd_pixelfuncs_backdrop[8] = { + flippixel, nopixel, setpixel, setpixel, + nopixel, clearimgpixel, nopixel, clearimgpixel +}; + + +lcd_pixelfunc_type* const * lcd_pixelfuncs = lcd_pixelfuncs_bgcolor; + /* 'mask' and 'bits' contain 2 bits per pixel */ static void flipblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; @@ -203,6 +223,15 @@ static void bgblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bg_pattern) & mask & ~bits); } +static void bgimgblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void bgimgblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + + *address = data ^ ((data ^ *(address + lcd_backdrop_offset)) & mask & ~bits); +} + static void fgblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; static void fgblock(fb_data *address, unsigned mask, unsigned bits) @@ -223,6 +252,17 @@ static void solidblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bits) & mask); } +static void solidimgblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void solidimgblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + unsigned bgp = *(address + lcd_backdrop_offset); + + bits = bgp ^ ((bgp ^ fg_pattern) & bits); + *address = data ^ ((data ^ bits) & mask); +} + static void flipinvblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; static void flipinvblock(fb_data *address, unsigned mask, unsigned bits) @@ -239,6 +279,15 @@ static void bginvblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bg_pattern) & mask & bits); } +static void bgimginvblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void bgimginvblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + + *address = data ^ ((data ^ *(address + lcd_backdrop_offset)) & mask & bits); +} + static void fginvblock(fb_data *address, unsigned mask, unsigned bits) ICODE_ATTR; static void fginvblock(fb_data *address, unsigned mask, unsigned bits) @@ -259,11 +308,53 @@ static void solidinvblock(fb_data *address, unsigned mask, unsigned bits) *address = data ^ ((data ^ bits) & mask); } -lcd_blockfunc_type* const lcd_blockfuncs[8] = { +static void solidimginvblock(fb_data *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void solidimginvblock(fb_data *address, unsigned mask, unsigned bits) +{ + unsigned data = *address; + unsigned fgp = fg_pattern; + + bits = fgp ^ ((fgp ^ *(address + lcd_backdrop_offset)) & bits); + *address = data ^ ((data ^ bits) & mask); +} + +lcd_blockfunc_type* const lcd_blockfuncs_bgcolor[8] = { flipblock, bgblock, fgblock, solidblock, flipinvblock, bginvblock, fginvblock, solidinvblock }; +lcd_blockfunc_type* const lcd_blockfuncs_backdrop[8] = { + flipblock, bgimgblock, fgblock, solidimgblock, + flipinvblock, bgimginvblock, fginvblock, solidimginvblock +}; + +lcd_blockfunc_type* const * lcd_blockfuncs = lcd_blockfuncs_bgcolor; + + +void lcd_set_backdrop(fb_data* backdrop) +{ + lcd_backdrop = backdrop; + if (backdrop) + { + lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; + lcd_pixelfuncs = lcd_pixelfuncs_backdrop; + lcd_blockfuncs = lcd_blockfuncs_backdrop; + } + else + { + lcd_backdrop_offset = 0; + lcd_pixelfuncs = lcd_pixelfuncs_bgcolor; + lcd_blockfuncs = lcd_blockfuncs_bgcolor; + } +} + +fb_data* lcd_get_backdrop(void) +{ + return lcd_backdrop; +} + + static inline void setblock(fb_data *address, unsigned mask, unsigned bits) { unsigned data = *address; @@ -277,9 +368,17 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) /* Clear the whole display */ void lcd_clear_display(void) { - unsigned bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; - - memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); + if (drawmode & DRMODE_INVERSEVID) + { + memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); + } + else + { + if (lcd_backdrop) + memcpy(lcd_framebuffer, lcd_backdrop, sizeof lcd_framebuffer); + else + memset(lcd_framebuffer, bg_pattern, sizeof lcd_framebuffer); + } scrolling_lines = 0; } @@ -487,7 +586,7 @@ void lcd_fillrect(int x, int y, int width, int height) if (drawmode & DRMODE_INVERSEVID) { - if (drawmode & DRMODE_BG) + if ((drawmode & DRMODE_BG) && !lcd_backdrop) { fillopt = true; bits = bg_pattern; @@ -1090,4 +1189,3 @@ static void scroll_thread(void) sleep(scroll_ticks); } } - diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index a39147628d..ceb0f6e3d2 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -310,10 +310,14 @@ extern void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *stri int style, int offset); /* low level drawing function pointer arrays */ +#if LCD_DEPTH >= 8 +extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; +#elif LCD_DEPTH > 1 +extern lcd_pixelfunc_type* const *lcd_pixelfuncs; +extern lcd_blockfunc_type* const *lcd_blockfuncs; +#else extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; extern lcd_blockfunc_type* const lcd_blockfuncs[8]; -#if LCD_DEPTH >= 8 -extern lcd_fastpixelfunc_type* const * lcd_fastpixelfuncs; #endif extern void lcd_drawpixel(int x, int y); @@ -339,10 +343,8 @@ extern void lcd_set_background(unsigned background); extern unsigned lcd_get_background(void); extern void lcd_set_drawinfo(int mode, unsigned foreground, unsigned background); -#ifdef HAVE_LCD_COLOR void lcd_set_backdrop(fb_data* backdrop); fb_data* lcd_get_backdrop(void); -#endif extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height);