summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES4
-rw-r--r--apps/bookmark.c4
-rw-r--r--apps/filetree.c4
-rw-r--r--apps/gui/gwps-common.c6
-rw-r--r--apps/gui/gwps.c32
-rw-r--r--apps/onplay.c8
-rw-r--r--apps/plugin.c6
-rw-r--r--apps/recorder/backdrop.c17
-rw-r--r--apps/recorder/backdrop.h9
-rw-r--r--apps/settings.c23
-rw-r--r--apps/settings.h2
-rw-r--r--apps/settings_menu.c10
-rw-r--r--apps/tree.c6
-rw-r--r--firmware/drivers/lcd-2bit-horz.c109
-rw-r--r--firmware/drivers/lcd-2bit-vert.c112
-rw-r--r--firmware/export/lcd.h10
16 files changed, 285 insertions, 77 deletions
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);