From 19b45a4374bb3efda4f554d3d806835368d1536a Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Wed, 8 Mar 2006 01:14:46 +0000 Subject: LCD extension library: Implemented scrolling for LCD depths below 8 bit. * Oscilloscope: Use new scrolling function, some minor optimisations. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8951 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/lib/SOURCES | 4 +- apps/plugins/lib/xlcd.h | 3 + apps/plugins/lib/xlcd_core.c | 41 +++ apps/plugins/lib/xlcd_draw.c | 379 +++++++++++++++++++++++++++ apps/plugins/lib/xlcd_scroll.c | 576 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 apps/plugins/lib/xlcd_core.c create mode 100755 apps/plugins/lib/xlcd_draw.c create mode 100755 apps/plugins/lib/xlcd_scroll.c (limited to 'apps/plugins/lib') diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index 6bcddbab96..f0930269f7 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -16,5 +16,7 @@ playergfx.c profile_plugin.c #endif #ifdef HAVE_LCD_BITMAP -xlcd.c +xlcd_core.c +xlcd_draw.c +xlcd_scroll.c #endif diff --git a/apps/plugins/lib/xlcd.h b/apps/plugins/lib/xlcd.h index 8f3071443e..473c51c732 100644 --- a/apps/plugins/lib/xlcd.h +++ b/apps/plugins/lib/xlcd.h @@ -47,6 +47,9 @@ void xlcd_scroll_right(int count); void xlcd_scroll_up(int count); void xlcd_scroll_down(int count); +/* internal stuff */ +extern struct plugin_api *_xlcd_rb; /* global api struct pointer */ + #endif /* HAVE_LCD_BITMAP */ #endif /* __XLCD_H__ */ diff --git a/apps/plugins/lib/xlcd_core.c b/apps/plugins/lib/xlcd_core.c new file mode 100644 index 0000000000..e8cc688591 --- /dev/null +++ b/apps/plugins/lib/xlcd_core.c @@ -0,0 +1,41 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Additional LCD routines not present in the rockbox core +* Core functions +* +* Copyright (C) 2005 Jens Arnold +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "plugin.h" + +#ifdef HAVE_LCD_BITMAP +#include "xlcd.h" + +/*** globals ***/ + +struct plugin_api *_xlcd_rb = NULL; /* global api struct pointer */ + +/*** functions ***/ + +/* library init */ +void xlcd_init(struct plugin_api* newrb) +{ + _xlcd_rb = newrb; +} + +#endif /* HAVE_LCD_BITMAP */ + diff --git a/apps/plugins/lib/xlcd_draw.c b/apps/plugins/lib/xlcd_draw.c new file mode 100755 index 0000000000..3ccdea9139 --- /dev/null +++ b/apps/plugins/lib/xlcd_draw.c @@ -0,0 +1,379 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Additional LCD routines not present in the rockbox core +* Drawing functions +* +* Copyright (C) 2005 Jens Arnold +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "plugin.h" + +#ifdef HAVE_LCD_BITMAP +#include "xlcd.h" + +#if (LCD_DEPTH >= 8) || (LCD_PIXELFORMAT == HORIZONTAL_PACKING) +/* draw a filled triangle, using horizontal lines for speed */ +void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) +{ + int x, y; + long fp_x1, fp_x2, fp_dx1, fp_dx2; + + /* sort vertices by increasing y value */ + if (y1 > y3) + { + if (y2 < y3) /* y2 < y3 < y1 */ + { + x = x1; x1 = x2; x2 = x3; x3 = x; + y = y1; y1 = y2; y2 = y3; y3 = y; + } + else if (y2 > y1) /* y3 < y1 < y2 */ + { + x = x1; x1 = x3; x3 = x2; x2 = x; + y = y1; y1 = y3; y3 = y2; y2 = y; + } + else /* y3 <= y2 <= y1 */ + { + x = x1; x1 = x3; x3 = x; + y = y1; y1 = y3; y3 = y; + } + } + else + { + if (y2 < y1) /* y2 < y1 <= y3 */ + { + x = x1; x1 = x2; x2 = x; + y = y1; y1 = y2; y2 = y; + } + else if (y2 > y3) /* y1 <= y3 < y2 */ + { + x = x2; x2 = x3; x3 = x; + y = y2; y2 = y3; y3 = y; + } + /* else already sorted */ + } + + if (y1 < y3) /* draw */ + { + fp_dx1 = ((x3 - x1) << 16) / (y3 - y1); + fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1); + + if (y1 < y2) /* first part */ + { + fp_dx2 = ((x2 - x1) << 16) / (y2 - y1); + fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1); + for (y = y1; y < y2; y++) + { + _xlcd_rb->lcd_hline(fp_x1 >> 16, fp_x2 >> 16, y); + fp_x1 += fp_dx1; + fp_x2 += fp_dx2; + } + } + if (y2 < y3) /* second part */ + { + fp_dx2 = ((x3 - x2) << 16) / (y3 - y2); + fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1); + for (y = y2; y < y3; y++) + { + _xlcd_rb->lcd_hline(fp_x1 >> 16, fp_x2 >> 16, y); + fp_x1 += fp_dx1; + fp_x2 += fp_dx2; + } + } + } +} +#else /* (LCD_DEPTH < 8) && (LCD_PIXELFORMAT == VERTICAL_PACKING) */ +/* draw a filled triangle, using vertical lines for speed */ +void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) +{ + int x, y; + long fp_y1, fp_y2, fp_dy1, fp_dy2; + + /* sort vertices by increasing x value */ + if (x1 > x3) + { + if (x2 < x3) /* x2 < x3 < x1 */ + { + x = x1; x1 = x2; x2 = x3; x3 = x; + y = y1; y1 = y2; y2 = y3; y3 = y; + } + else if (x2 > x1) /* x3 < x1 < x2 */ + { + x = x1; x1 = x3; x3 = x2; x2 = x; + y = y1; y1 = y3; y3 = y2; y2 = y; + } + else /* x3 <= x2 <= x1 */ + { + x = x1; x1 = x3; x3 = x; + y = y1; y1 = y3; y3 = y; + } + } + else + { + if (x2 < x1) /* x2 < x1 <= x3 */ + { + x = x1; x1 = x2; x2 = x; + y = y1; y1 = y2; y2 = y; + } + else if (x2 > x3) /* x1 <= x3 < x2 */ + { + x = x2; x2 = x3; x3 = x; + y = y2; y2 = y3; y3 = y; + } + /* else already sorted */ + } + + if (x1 < x3) /* draw */ + { + fp_dy1 = ((y3 - y1) << 16) / (x3 - x1); + fp_y1 = (y1 << 16) + (1<<15) + (fp_dy1 >> 1); + + if (x1 < x2) /* first part */ + { + fp_dy2 = ((y2 - y1) << 16) / (x2 - x1); + fp_y2 = (y1 << 16) + (1<<15) + (fp_dy2 >> 1); + for (x = x1; x < x2; x++) + { + _xlcd_rb->lcd_vline(x, fp_y1 >> 16, fp_y2 >> 16); + fp_y1 += fp_dy1; + fp_y2 += fp_dy2; + } + } + if (x2 < x3) /* second part */ + { + fp_dy2 = ((y3 - y2) << 16) / (x3 - x2); + fp_y2 = (y2 << 16) + (1<<15) + (fp_dy2 >> 1); + for (x = x2; x < x3; x++) + { + _xlcd_rb->lcd_vline(x, fp_y1 >> 16, fp_y2 >> 16); + fp_y1 += fp_dy1; + fp_y2 += fp_dy2; + } + } + } +} +#endif /* LCD_DEPTH, LCD_PIXELFORMAT */ + +#if LCD_DEPTH >= 8 + +#ifdef HAVE_LCD_COLOR +static const fb_data graylut[256] = { +#if LCD_PIXELFORMAT == RGB565 + 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841, + 0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082, + 0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3, + 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104, + 0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945, + 0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186, + 0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7, + 0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208, + 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49, + 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a, + 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab, + 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec, + 0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d, + 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d, + 0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae, + 0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71, + 0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2, + 0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3, + 0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534, + 0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75, + 0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6, + 0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7, + 0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638, + 0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79, + 0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba, + 0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb, + 0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c, + 0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d, + 0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be, + 0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff +#elif LCD_PIXELFORMAT == RGB565SWAPPED + 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108, + 0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210, + 0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318, + 0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421, + 0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529, + 0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631, + 0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739, + 0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842, + 0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a, + 0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52, + 0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a, + 0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62, + 0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b, + 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b, + 0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73, + 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b, + 0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084, + 0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c, + 0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294, + 0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c, + 0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5, + 0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad, + 0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5, + 0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd, + 0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6, + 0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce, + 0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6, + 0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde, + 0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7, + 0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def, + 0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7, + 0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff +#endif /* LCD_PIXELFORMAT */ +}; +#endif /* HAVE_LCD_COLOR */ + +/* Draw a partial greyscale bitmap, canonical 8 bit format */ +void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + const unsigned char *src_end; + fb_data *dst; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) + || (x + width <= 0) || (y + height <= 0)) + return; + + /* clipping */ + if (x < 0) + { + width += x; + src_x -= x; + x = 0; + } + if (y < 0) + { + height += y; + src_y -= y; + y = 0; + } + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; + + src += stride * src_y + src_x; /* move starting point */ + src_end = src + stride * height; + dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x; + + do + { + const unsigned char *src_row = src; + const unsigned char *row_end = src_row + width; + fb_data *dst_row = dst; + +#ifdef HAVE_LCD_COLOR + do + *dst_row++ = graylut[*src_row++]; + while (src_row < row_end); +#endif + + src += stride; + dst += LCD_WIDTH; + } + while (src < src_end); +} + +/* Draw a full greyscale bitmap, canonical 8 bit format */ +void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width, + int height) +{ + xlcd_gray_bitmap_part(src, 0, 0, width, x, y, width, height); +} + +#ifdef HAVE_LCD_COLOR +/* Draw a partial colour bitmap, canonical 24 bit RGB format */ +void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + const unsigned char *src_end; + fb_data *dst; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) + || (x + width <= 0) || (y + height <= 0)) + return; + + /* clipping */ + if (x < 0) + { + width += x; + src_x -= x; + x = 0; + } + if (y < 0) + { + height += y; + src_y -= y; + y = 0; + } + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; + + src += 3 * (stride * src_y + src_x); /* move starting point */ + src_end = src + 3 * stride * height; + dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x; + + do + { + const unsigned char *src_row = src; + const unsigned char *row_end = src_row + 3 * width; + fb_data *dst_row = dst; + + do + { /* only RGB565 and RGB565SWAPPED so far */ + unsigned red = 31 * (*src_row++) + 127; + unsigned green = 63 * (*src_row++) + 127; + unsigned blue = 31 * (*src_row++) + 127; + + red = (red + (red >> 8)) >> 8; /* approx red /= 255: */ + green = (green + (green >> 8)) >> 8; /* approx green /= 255: */ + blue = (blue + (blue >> 8)) >> 8; /* approx blue /= 255: */ + +#if LCD_PIXELFORMAT == RGB565 + *dst_row++ = (red << 11) | (green << 5) | blue; +#elif LCD_PIXELFORMAT == RGB565SWAPPED + *dst_row++ = swap16((red << 11) | (green << 5) | blue); +#endif + } + while (src_row < row_end); + + src += 3 * stride; + dst += LCD_WIDTH; + } + while (src < src_end); +} + +/* Draw a full colour bitmap, canonical 24 bit RGB format */ +void xlcd_color_bitmap(const unsigned char *src, int x, int y, int width, + int height) +{ + xlcd_color_bitmap_part(src, 0, 0, width, x, y, width, height); +} +#endif /* HAVE_LCD_COLOR */ + +#endif /* LCD_DEPTH >= 8 */ + +#endif /* HAVE_LCD_BITMAP */ + diff --git a/apps/plugins/lib/xlcd_scroll.c b/apps/plugins/lib/xlcd_scroll.c new file mode 100755 index 0000000000..44117b452c --- /dev/null +++ b/apps/plugins/lib/xlcd_scroll.c @@ -0,0 +1,576 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Additional LCD routines not present in the rockbox core +* Scrolling functions +* +* Copyright (C) 2005 Jens Arnold +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "plugin.h" + +#ifdef HAVE_LCD_BITMAP +#include "xlcd.h" + +#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8) + +/* Scroll left */ +void xlcd_scroll_left(int count) +{ + int bitcount, oldmode; + int blockcount, blocklen; + + if ((unsigned) count >= LCD_WIDTH) + return; + +#if LCD_DEPTH == 2 + blockcount = count >> 2; + blocklen = LCD_FBWIDTH - blockcount; + bitcount = 2 * (count & 3); +#endif + + if (blockcount) + { + unsigned char *data = _xlcd_rb->lcd_framebuffer; + unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT; + + do + { + _xlcd_rb->memmove(data, data + blockcount, blocklen); + data += LCD_FBWIDTH; + } + while (data < data_end); + } + if (bitcount) + { + int bx, y; + unsigned char *addr = _xlcd_rb->lcd_framebuffer + blocklen; +#if LCD_DEPTH == 2 + unsigned fill = 0x55 * (~_xlcd_rb->lcd_get_background() & 3); +#endif + + for (y = 0; y < LCD_HEIGHT; y++) + { + unsigned char *row_addr = addr; + unsigned data = fill; + + for (bx = 0; bx < blocklen; bx++) + { + --row_addr; + data = (data << 8) | *row_addr; + *row_addr = data >> bitcount; + } + addr += LCD_FBWIDTH; + } + } + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +/* Scroll right */ +void xlcd_scroll_right(int count) +{ + int bitcount, oldmode; + int blockcount, blocklen; + + if ((unsigned) count >= LCD_WIDTH) + return; + +#if LCD_DEPTH == 2 + blockcount = count >> 2; + blocklen = LCD_FBWIDTH - blockcount; + bitcount = 2 * (count & 3); +#endif + + if (blockcount) + { + unsigned char *data = _xlcd_rb->lcd_framebuffer; + unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT; + + do + { + _xlcd_rb->memmove(data + blockcount, data, blocklen); + data += LCD_FBWIDTH; + } + while (data < data_end); + } + if (bitcount) + { + int bx, y; + unsigned char *addr = _xlcd_rb->lcd_framebuffer + blockcount; +#if LCD_DEPTH == 2 + unsigned fill = 0x55 * (~_xlcd_rb->lcd_get_background() & 3); +#endif + + for (y = 0; y < LCD_HEIGHT; y++) + { + unsigned char *row_addr = addr; + unsigned data = fill; + + for (bx = 0; bx < blocklen; bx++) + { + data = (data >> 8) | (*row_addr << bitcount); + *row_addr = data; + row_addr++; + } + addr += LCD_FBWIDTH; + } + } + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(0, 0, count, LCD_HEIGHT); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +#else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */ + +/* Scroll left */ +void xlcd_scroll_left(int count) +{ + fb_data *data, *data_end; + int length, oldmode; + + if ((unsigned)count >= LCD_WIDTH) + return; + + data = _xlcd_rb->lcd_framebuffer; +#if LCD_DEPTH >= 8 + data_end = data + LCD_WIDTH*LCD_HEIGHT; +#else + data_end = data + LCD_WIDTH*((LCD_HEIGHT*LCD_DEPTH+7)/8); +#endif + length = LCD_WIDTH - count; + + do + { + _xlcd_rb->memmove(data, data + count, length * sizeof(fb_data)); + data += LCD_WIDTH; + } + while (data < data_end); + + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(length, 0, count, LCD_HEIGHT); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +/* Scroll right */ +void xlcd_scroll_right(int count) +{ + fb_data *data, *data_end; + int length, oldmode; + + if ((unsigned)count >= LCD_WIDTH) + return; + + data = _xlcd_rb->lcd_framebuffer; +#if LCD_DEPTH >= 8 + data_end = data + LCD_WIDTH*LCD_HEIGHT; +#else + data_end = data + LCD_WIDTH*((LCD_HEIGHT*LCD_DEPTH+7)/8); +#endif + length = LCD_WIDTH - count; + + do + { + _xlcd_rb->memmove(data + count, data, length * sizeof(fb_data)); + data += LCD_WIDTH; + } + while (data < data_end); + + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(0, 0, count, LCD_HEIGHT); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +#endif /* LCD_PIXELFORMAT, LCD_DEPTH */ + +#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8) + +/* Scroll up */ +void xlcd_scroll_up(int count) +{ + int length, oldmode; + + if ((unsigned)count >= LCD_HEIGHT) + return; + + length = LCD_HEIGHT - count; + + _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer, + _xlcd_rb->lcd_framebuffer + count * LCD_FBWIDTH, + length * LCD_FBWIDTH * sizeof(fb_data)); + + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(0, length, LCD_WIDTH, count); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +/* Scroll down */ +void xlcd_scroll_down(int count) +{ + int length, oldmode; + + if ((unsigned)count >= LCD_HEIGHT) + return; + + length = LCD_HEIGHT - count; + + _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer + count * LCD_FBWIDTH, + _xlcd_rb->lcd_framebuffer, + length * LCD_FBWIDTH * sizeof(fb_data)); + + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(0, 0, LCD_WIDTH, count); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +#else /* LCD_PIXELFORMAT vertical packed */ + +/* Scroll up */ +void xlcd_scroll_up(int count) +{ + int bitcount, oldmode; + int blockcount, blocklen; + + if ((unsigned) count >= LCD_HEIGHT) + return; + +#if LCD_DEPTH == 1 + blockcount = count >> 3; + blocklen = ((LCD_HEIGHT+7)/8) - blockcount; + bitcount = count & 7; +#elif LCD_DEPTH == 2 + blockcount = count >> 2; + blocklen = ((LCD_HEIGHT+3)/4) - blockcount; + bitcount = 2 * (count & 3); +#endif + + if (blockcount) + { + _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer, + _xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH, + blocklen * LCD_FBWIDTH); + } + if (bitcount) + { +#if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1) + asm ( + "mov #0,r4 \n" /* x = 0 */ + "mova .su_shifttbl,r0 \n" /* calculate jump destination for */ + "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */ + "bra .su_cloop \n" /* skip table */ + "add r0,%[cnt] \n" + + ".align 2 \n" + ".su_shifttbl: \n" /* shift jump offset table */ + ".byte .su_shift0 - .su_shifttbl \n" + ".byte .su_shift1 - .su_shifttbl \n" + ".byte .su_shift2 - .su_shifttbl \n" + ".byte .su_shift3 - .su_shifttbl \n" + ".byte .su_shift4 - .su_shifttbl \n" + ".byte .su_shift5 - .su_shifttbl \n" + ".byte .su_shift6 - .su_shifttbl \n" + ".byte .su_shift7 - .su_shifttbl \n" + + ".su_cloop: \n" /* repeat for every column */ + "mov %[addr],r2 \n" /* get start address */ + "mov #0,r3 \n" /* current_row = 0 */ + "mov #0,r1 \n" /* fill with zero */ + + ".su_iloop: \n" /* repeat for all rows */ + "sub %[wide],r2 \n" /* address -= width */ + "mov.b @r2,r0 \n" /* get data byte */ + "shll8 r1 \n" /* old data to 2nd byte */ + "extu.b r0,r0 \n" /* extend unsigned */ + "or r1,r0 \n" /* combine old data */ + "jmp @%[cnt] \n" /* jump into shift "path" */ + "extu.b r0,r1 \n" /* store data for next round */ + + ".su_shift6: \n" /* shift right by 0..7 bits */ + "shll2 r0 \n" + "bra .su_shift0 \n" + "shlr8 r0 \n" + ".su_shift4: \n" + "shlr2 r0 \n" + ".su_shift2: \n" + "bra .su_shift0 \n" + "shlr2 r0 \n" + ".su_shift7: \n" + "shlr2 r0 \n" + ".su_shift5: \n" + "shlr2 r0 \n" + ".su_shift3: \n" + "shlr2 r0 \n" + ".su_shift1: \n" + "shlr r0 \n" + ".su_shift0: \n" + + "mov.b r0,@r2 \n" /* store data */ + "add #1,r3 \n" /* current_row++ */ + "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */ + "bt .su_iloop \n" + + "add #1,%[addr] \n" /* start_address++ */ + "add #1,r4 \n" /* x++ */ + "cmp/hi r4,%[wide] \n" /* x < width ? */ + "bt .su_cloop \n" + : /* outputs */ + : /* inputs */ + [addr]"r"(_xlcd_rb->lcd_framebuffer + blocklen * LCD_FBWIDTH), + [wide]"r"(LCD_FBWIDTH), + [rows]"r"(blocklen), + [cnt] "r"(bitcount) + : /* clobbers */ + "r0", "r1", "r2", "r3", "r4" + ); +#elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2) + asm ( + "move.l %[wide],%%d3\n" /* columns = width */ + + ".su_cloop: \n" /* repeat for every column */ + "move.l %[addr],%%a1\n" /* get start address */ + "move.l %[rows],%%d2\n" /* rows = row_count */ + "move.l %[bkg],%%d1 \n" /* fill with background */ + + ".su_iloop: \n" /* repeat for all rows */ + "sub.l %[wide],%%a1\n" /* address -= width */ + + "clr.l %%d0 \n" + "move.b (%%a1),%%d0 \n" /* get data byte */ + "lsl.l #8,%%d1 \n" /* old data to 2nd byte */ + "or.l %%d1,%%d0 \n" /* combine old data */ + "clr.l %%d1 \n" + "move.b %%d0,%%d1 \n" /* keep data for next round */ + "lsr.l %[cnt],%%d0 \n" /* shift right */ + "move.b %%d0,(%%a1) \n" /* store data */ + + "subq.l #1,%%d2 \n" /* rows-- */ + "bne.b .su_iloop \n" + + "addq.l #1,%[addr] \n" /* start_address++ */ + "subq.l #1,%%d3 \n" /* columns-- */ + "bne.b .su_cloop \n" + : /* outputs */ + : /* inputs */ + [wide]"r"(LCD_FBWIDTH), + [rows]"r"(blocklen), + [addr]"a"(_xlcd_rb->lcd_framebuffer + blocklen * LCD_FBWIDTH), + [cnt] "d"(bitcount), + [bkg] "d"(0x55 * (~_xlcd_rb->lcd_get_background() & 3)) + : /* clobbers */ + "a1", "d0", "d1", "d2", "d3" + ); +#else /* C version */ + int x, by; + unsigned char *addr = _xlcd_rb->lcd_framebuffer + blocklen * LCD_FBWIDTH; +#if LCD_DEPTH == 2 + unsigned fill = 0x55 * (~_xlcd_rb->lcd_get_background() & 3); +#endif + + for (x = 0; x < LCD_WIDTH; x++) + { + unsigned char *col_addr = addr++; +#if LCD_DEPTH == 1 + unsigned data = 0; +#else + unsigned data = fill; +#endif + + for (by = 0; by < blocklen; by++) + { + col_addr -= LCD_FBWIDTH; + data = (data << 8) | *col_addr; + *col_addr = data >> bitcount; + } + } +#endif /* CPU, LCD_DEPTH */ + } + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +/* Scroll up */ +void xlcd_scroll_down(int count) +{ + int bitcount, oldmode; + int blockcount, blocklen; + + if ((unsigned) count >= LCD_HEIGHT) + return; + +#if LCD_DEPTH == 1 + blockcount = count >> 3; + blocklen = ((LCD_HEIGHT+7)/8) - blockcount; + bitcount = count & 7; +#elif LCD_DEPTH == 2 + blockcount = count >> 2; + blocklen = ((LCD_HEIGHT+3)/4) - blockcount; + bitcount = 2 * (count & 3); +#endif + + if (blockcount) + { + _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH, + _xlcd_rb->lcd_framebuffer, + blocklen * LCD_FBWIDTH); + } + if (bitcount) + { +#if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1) + asm ( + "mov #0,r4 \n" /* x = 0 */ + "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */ + "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */ + "bra .sd_cloop \n" /* skip table */ + "add r0,%[cnt] \n" + + ".align 2 \n" + ".sd_shifttbl: \n" /* shift jump offset table */ + ".byte .sd_shift0 - .sd_shifttbl \n" + ".byte .sd_shift1 - .sd_shifttbl \n" + ".byte .sd_shift2 - .sd_shifttbl \n" + ".byte .sd_shift3 - .sd_shifttbl \n" + ".byte .sd_shift4 - .sd_shifttbl \n" + ".byte .sd_shift5 - .sd_shifttbl \n" + ".byte .sd_shift6 - .sd_shifttbl \n" + ".byte .sd_shift7 - .sd_shifttbl \n" + + ".sd_cloop: \n" /* repeat for every column */ + "mov %[addr],r2 \n" /* get start address */ + "mov #0,r3 \n" /* current_row = 0 */ + "mov #0,r1 \n" /* fill with zero */ + + ".sd_iloop: \n" /* repeat for all rows */ + "shlr8 r1 \n" /* shift right to get residue */ + "mov.b @r2,r0 \n" /* get data byte */ + "jmp @%[cnt] \n" /* jump into shift "path" */ + "extu.b r0,r0 \n" /* extend unsigned */ + + ".sd_shift6: \n" /* shift left by 0..7 bits */ + "shll8 r0 \n" + "bra .sd_shift0 \n" + "shlr2 r0 \n" + ".sd_shift4: \n" + "shll2 r0 \n" + ".sd_shift2: \n" + "bra .sd_shift0 \n" + "shll2 r0 \n" + ".sd_shift7: \n" + "shll2 r0 \n" + ".sd_shift5: \n" + "shll2 r0 \n" + ".sd_shift3: \n" + "shll2 r0 \n" + ".sd_shift1: \n" + "shll r0 \n" + ".sd_shift0: \n" + + "or r0,r1 \n" /* combine with last residue */ + "mov.b r1,@r2 \n" /* store data */ + "add %[wide],r2 \n" /* address += width */ + "add #1,r3 \n" /* current_row++ */ + "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */ + "bt .sd_iloop \n" + + "add #1,%[addr] \n" /* start_address++ */ + "add #1,r4 \n" /* x++ */ + "cmp/hi r4,%[wide] \n" /* x < width ? */ + "bt .sd_cloop \n" + : /* outputs */ + : /* inputs */ + [addr]"r"(_xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH), + [wide]"r"(LCD_WIDTH), + [rows]"r"(blocklen), + [cnt] "r"(bitcount) + : /* clobbers */ + "r0", "r1", "r2", "r3", "r4" + ); +#elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2) + asm ( + "move.l %[wide],%%d3\n" /* columns = width */ + + ".sd_cloop: \n" /* repeat for every column */ + "move.l %[addr],%%a1\n" /* get start address */ + "move.l %[rows],%%d2\n" /* rows = row_count */ + "move.l %[bkg],%%d1 \n" /* fill with background */ + + ".sd_iloop: \n" /* repeat for all rows */ + "lsr.l #8,%%d1 \n" /* shift right to get residue */ + "clr.l %%d0 \n" + "move.b (%%a1),%%d0 \n" /* get data byte */ + "lsl.l %[cnt],%%d0 \n" + "or.l %%d0,%%d1 \n" /* combine with last residue */ + "move.b %%d1,(%%a1) \n" /* store data */ + + "add.l %[wide],%%a1\n" /* address += width */ + "subq.l #1,%%d2 \n" /* rows-- */ + "bne.b .sd_iloop \n" + + "lea.l (1,%[addr]),%[addr] \n" /* start_address++ */ + "subq.l #1,%%d3 \n" /* columns-- */ + "bne.b .sd_cloop \n" + : /* outputs */ + : /* inputs */ + [wide]"r"(LCD_WIDTH), + [rows]"r"(blocklen), + [addr]"a"(_xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH), + [cnt] "d"(bitcount), + [bkg] "d"((0x55 * (~_xlcd_rb->lcd_get_background() & 3)) << bitcount) + : /* clobbers */ + "a1", "d0", "d1", "d2", "d3" + ); +#else /* C version */ + int x, by; + unsigned char *addr = _xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH; +#if LCD_DEPTH == 2 + unsigned fill = (0x55 * (~_xlcd_rb->lcd_get_background() & 3)) << bitcount; +#endif + + for (x = 0; x < LCD_WIDTH; x++) + { + unsigned char *col_addr = addr++; +#if LCD_DEPTH == 1 + unsigned data = 0; +#else + unsigned data = fill; +#endif + + for (by = 0; by < blocklen; by++) + { + data = (data >> 8) | (*col_addr << bitcount); + *col_addr = data; + col_addr += LCD_FBWIDTH; + } + } +#endif /* CPU, LCD_DEPTH */ + } + oldmode = _xlcd_rb->lcd_get_drawmode(); + _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + _xlcd_rb->lcd_fillrect(0, 0, LCD_WIDTH, count); + _xlcd_rb->lcd_set_drawmode(oldmode); +} + +#endif /* LCD_PIXELFORMAT, LCD_DEPTH */ + +#endif /* HAVE_LCD_BITMAP */ -- cgit v1.2.3