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
This commit is contained in:
Jens Arnold 2006-03-08 01:14:46 +00:00
parent 761652abf7
commit 19b45a4374
8 changed files with 1026 additions and 72 deletions

View file

@ -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

View file

@ -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__ */

View file

@ -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 */

379
apps/plugins/lib/xlcd_draw.c Executable file
View file

@ -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 */

576
apps/plugins/lib/xlcd_scroll.c Executable file
View file

@ -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 */

View file

@ -24,6 +24,7 @@
#ifdef HAVE_LCD_BITMAP /* and also not for the Player */
#if CONFIG_CODEC != SWCODEC /* only for MAS-targets */
#include "xlcd.h"
PLUGIN_HEADER
@ -77,58 +78,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter);
/* implementation */
void lcd_scroll_left(int count, bool black_border)
{
int by;
unsigned filler;
unsigned char *ptr;
if ((unsigned) count >= LCD_WIDTH)
return;
filler = black_border ? 0xFF : 0;
for (by = 0; by < (LCD_HEIGHT/8); by++)
{
ptr = rb->lcd_framebuffer + MULU16(LCD_WIDTH, by);
asm volatile (
"mov %0,r1 \n" /* check if both source... */
"or %2,r1 \n" /* ...and offset are even */
"shlr r1 \n" /* -> lsb = 0 */
"bf .sl_start2 \n" /* -> copy word-wise */
"add #-1,%2 \n" /* copy byte-wise */
".sl_loop1: \n"
"mov.b @%0+,r1 \n"
"mov.b r1,@(%2,%0) \n"
"cmp/hi %0,%1 \n"
"bt .sl_loop1 \n"
"bra .sl_end \n"
"nop \n"
".sl_start2: \n" /* copy word-wise */
"add #-2,%2 \n"
".sl_loop2: \n"
"mov.w @%0+,r1 \n"
"mov.w r1,@(%2,%0) \n"
"cmp/hi %0,%1 \n"
"bt .sl_loop2 \n"
".sl_end: \n"
: /* outputs */
: /* inputs */
/* %0 */ "r"(ptr + count),
/* %1 */ "r"(ptr + LCD_WIDTH),
/* %2 */ "z"(-count)
: /* clobbers */
"r1"
);
rb->memset(ptr + LCD_WIDTH - count, filler, count);
}
}
void timer_isr(void)
{
static int last_left, last_right;
@ -140,7 +89,7 @@ void timer_isr(void)
{
if (scroll)
{
lcd_scroll_left(1, false);
xlcd_scroll_left(1);
x = LCD_WIDTH-1;
full_update = true;
}
@ -149,16 +98,14 @@ void timer_isr(void)
}
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
rb->lcd_drawline(x, 0, x, LCD_HEIGHT-1);
rb->lcd_vline(x, 0, LCD_HEIGHT-1);
rb->lcd_set_drawmode(DRMODE_SOLID);
switch (draw_mode)
{
case DRAW_MODE_FILLED:
rb->lcd_drawline(x, LCD_HEIGHT/2+1,
x, LCD_HEIGHT/2+1 + left_val);
rb->lcd_drawline(x, LCD_HEIGHT/2-1,
x, LCD_HEIGHT/2-1 - right_val);
rb->lcd_vline(x, LCD_HEIGHT/2+1, LCD_HEIGHT/2+1 + left_val);
rb->lcd_vline(x, LCD_HEIGHT/2-1, LCD_HEIGHT/2-1 - right_val);
break;
case DRAW_MODE_OUTLINE:
@ -206,6 +153,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
(void)parameter;
rb = api;
xlcd_init(rb);
rb->timer_register(1, NULL, FREQ / 67, 1, timer_isr);
while (!exit)

View file

@ -38,7 +38,7 @@
/*** globals ***/
unsigned char lcd_framebuffer[LCD_HEIGHT][FB_WIDTH] IBSS_ATTR;
unsigned char lcd_framebuffer[LCD_HEIGHT][LCD_FBWIDTH] IBSS_ATTR;
static const unsigned char dibits[16] ICONST_ATTR = {
0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
@ -419,11 +419,11 @@ void lcd_vline(int x, int y1, int y2)
dst = &lcd_framebuffer[y1][x>>2];
mask = pixmask[x & 3];
dst_end = dst + (y2 - y1) * FB_WIDTH;
dst_end = dst + (y2 - y1) * LCD_FBWIDTH;
do
{
bfunc(dst, mask, 0xFFu);
dst += FB_WIDTH;
dst += LCD_FBWIDTH;
}
while (dst <= dst_end);
}
@ -482,11 +482,11 @@ void lcd_fillrect(int x, int y, int width, int height)
{
unsigned char *dst_col = dst;
dst_end = dst_col + height * FB_WIDTH;
dst_end = dst_col + height * LCD_FBWIDTH;
do
{
bfunc(dst_col, mask, 0xFFu);
dst_col += FB_WIDTH;
dst_col += LCD_FBWIDTH;
}
while (dst_col < dst_end);
@ -495,11 +495,11 @@ void lcd_fillrect(int x, int y, int width, int height)
}
mask &= mask_right;
dst_end = dst + height * FB_WIDTH;
dst_end = dst + height * LCD_FBWIDTH;
do
{
bfunc(dst, mask, 0xFFu);
dst += FB_WIDTH;
dst += LCD_FBWIDTH;
}
while (dst < dst_end);
}
@ -651,7 +651,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
mask_right = 0xFFu >> (2 * (~nx & 3));
shift *= 2;
dst_end = dst + height * FB_WIDTH;
dst_end = dst + height * LCD_FBWIDTH;
do
{
const unsigned char *src_row = src;
@ -678,7 +678,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
setblock(dst_row, mask_row & mask_right, data);
src += stride;
dst += FB_WIDTH;
dst += LCD_FBWIDTH;
}
while (dst < dst_end);
}

View file

@ -205,8 +205,8 @@ typedef void lcd_fastpixelfunc_type(fb_data *address);
extern fb_data lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH];
#elif LCD_DEPTH == 2
#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
#define FB_WIDTH ((LCD_WIDTH+3)/4)
extern fb_data lcd_framebuffer[LCD_HEIGHT][FB_WIDTH];
#define LCD_FBWIDTH ((LCD_WIDTH+3)/4)
extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_FBWIDTH];
#else
extern fb_data lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH];
#endif
@ -216,6 +216,10 @@ extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH];
extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH];
#endif
#ifndef LCD_FBWIDTH
#define LCD_FBWIDTH LCD_WIDTH
#endif
#if (CONFIG_BACKLIGHT==BL_IRIVER_H300) || (CONFIG_BACKLIGHT==BL_IPOD3G)
extern void lcd_enable(bool on);
#endif