9dcde3571c
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30354 a1c6a512-1295-4272-9138-f99709370657
755 lines
23 KiB
C
755 lines
23 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Additional LCD routines not present in the rockbox core
|
|
* Scrolling functions
|
|
*
|
|
* Copyright (C) 2005 Jens Arnold
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
|
|
#include "xlcd.h"
|
|
|
|
#if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
|
|
#endif
|
|
|
|
#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
|
|
void xlcd_scroll_left(int count)
|
|
{
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
|
|
|
|
rb->memmove(rb->lcd_framebuffer, rb->lcd_framebuffer + LCD_HEIGHT*count,
|
|
length * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(LCD_WIDTH-count, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll right */
|
|
void xlcd_scroll_right(int count)
|
|
{
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
|
|
|
|
rb->memmove(rb->lcd_framebuffer + LCD_HEIGHT*count,
|
|
rb->lcd_framebuffer, length * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_up(int count)
|
|
{
|
|
int width, length, oldmode;
|
|
|
|
fb_data *data;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
width = LCD_WIDTH-1;
|
|
data = rb->lcd_framebuffer;
|
|
|
|
do {
|
|
rb->memmove(data,data + count,length * sizeof(fb_data));
|
|
data += LCD_HEIGHT;
|
|
} while(width--);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, length, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll down */
|
|
void xlcd_scroll_down(int count)
|
|
{
|
|
int width, length, oldmode;
|
|
|
|
fb_data *data;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
width = LCD_WIDTH-1;
|
|
data = rb->lcd_framebuffer;
|
|
|
|
do {
|
|
rb->memmove(data + count, data, length * sizeof(fb_data));
|
|
data += LCD_HEIGHT;
|
|
} while(width--);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
#else
|
|
|
|
#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
|
|
|
|
/* Scroll left */
|
|
void xlcd_scroll_left(int count)
|
|
{
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if LCD_DEPTH == 2
|
|
blockcount = count >> 2;
|
|
blocklen = LCD_FBWIDTH - blockcount;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
|
|
if (blockcount)
|
|
{
|
|
unsigned char *data = rb->lcd_framebuffer;
|
|
unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data, data + blockcount, blocklen);
|
|
data += LCD_FBWIDTH;
|
|
}
|
|
while (data < data_end);
|
|
}
|
|
if (bitcount)
|
|
{
|
|
int bx, y;
|
|
unsigned char *addr = rb->lcd_framebuffer + blocklen;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
|
|
#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 << bitcount);
|
|
*row_addr = data;
|
|
}
|
|
addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll right */
|
|
void xlcd_scroll_right(int count)
|
|
{
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if LCD_DEPTH == 2
|
|
blockcount = count >> 2;
|
|
blocklen = LCD_FBWIDTH - blockcount;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
|
|
if (blockcount)
|
|
{
|
|
unsigned char *data = rb->lcd_framebuffer;
|
|
unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data + blockcount, data, blocklen);
|
|
data += LCD_FBWIDTH;
|
|
}
|
|
while (data < data_end);
|
|
}
|
|
if (bitcount)
|
|
{
|
|
int bx, y;
|
|
unsigned char *addr = rb->lcd_framebuffer + blockcount;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = 0x55 * (~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;
|
|
*row_addr = data >> bitcount;
|
|
row_addr++;
|
|
}
|
|
addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
|
|
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)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
data = rb->lcd_framebuffer;
|
|
data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
|
|
length = LCD_WIDTH - count;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data, data + count, length * sizeof(fb_data));
|
|
data += LCD_WIDTH;
|
|
}
|
|
while (data < data_end);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
|
|
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)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
data = rb->lcd_framebuffer;
|
|
data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
|
|
length = LCD_WIDTH - count;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data + count, data, length * sizeof(fb_data));
|
|
data += LCD_WIDTH;
|
|
}
|
|
while (data < data_end);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
|
|
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)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
rb->memmove(rb->lcd_framebuffer,
|
|
rb->lcd_framebuffer + count * LCD_FBWIDTH,
|
|
length * LCD_FBWIDTH * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, length, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll down */
|
|
void xlcd_scroll_down(int count)
|
|
{
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
rb->memmove(rb->lcd_framebuffer + count * LCD_FBWIDTH,
|
|
rb->lcd_framebuffer,
|
|
length * LCD_FBWIDTH * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
#else /* LCD_PIXELFORMAT == VERTICAL_PACKING,
|
|
LCD_PIXELFORMAT == VERTICAL_INTERLEAVED */
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_up(int count)
|
|
{
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if (LCD_DEPTH == 1) \
|
|
|| (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
blockcount = count >> 3;
|
|
bitcount = count & 7;
|
|
#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
|
|
blockcount = count >> 2;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
blocklen = LCD_FBHEIGHT - blockcount;
|
|
|
|
if (blockcount)
|
|
{
|
|
rb->memmove(rb->lcd_framebuffer,
|
|
rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
|
|
blocklen * LCD_FBWIDTH * sizeof(fb_data));
|
|
}
|
|
if (bitcount)
|
|
{
|
|
#if LCD_PIXELFORMAT == VERTICAL_PACKING
|
|
|
|
#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"(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 */
|
|
|
|
"lsl.l #8,%%d1 \n" /* old data to 2nd byte */
|
|
"move.b (%%a1),%%d1 \n" /* combine with new data byte */
|
|
"move.l %%d1,%%d0 \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"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
|
|
[cnt] "d"(bitcount),
|
|
[bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
|
|
: /* clobbers */
|
|
"a1", "d0", "d1", "d2", "d3"
|
|
);
|
|
#else /* C version */
|
|
int x, by;
|
|
unsigned char *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
|
|
#else
|
|
const unsigned fill = 0;
|
|
#endif
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
unsigned char *col_addr = addr++;
|
|
unsigned data = fill;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
col_addr -= LCD_FBWIDTH;
|
|
data = (data << 8) | *col_addr;
|
|
*col_addr = data >> bitcount;
|
|
}
|
|
}
|
|
#endif /* CPU, LCD_DEPTH */
|
|
|
|
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
|
|
|
#if LCD_DEPTH == 2
|
|
int x, by;
|
|
fb_data *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
|
|
unsigned fill, mask;
|
|
|
|
fill = patterns[rb->lcd_get_background() & 3] << 8;
|
|
mask = (0xFFu >> bitcount) << bitcount;
|
|
mask |= mask << 8;
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
fb_data *col_addr = addr++;
|
|
unsigned olddata = fill;
|
|
unsigned data;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
col_addr -= LCD_FBWIDTH;
|
|
data = *col_addr;
|
|
*col_addr = (olddata ^ ((data ^ olddata) & mask)) >> bitcount;
|
|
olddata = data << 8;
|
|
}
|
|
}
|
|
#endif /* LCD_DEPTH == 2 */
|
|
|
|
#endif /* LCD_PIXELFORMAT */
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_down(int count)
|
|
{
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if (LCD_DEPTH == 1) \
|
|
|| (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
blockcount = count >> 3;
|
|
bitcount = count & 7;
|
|
#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
|
|
blockcount = count >> 2;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
blocklen = LCD_FBHEIGHT - blockcount;
|
|
|
|
if (blockcount)
|
|
{
|
|
rb->memmove(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
|
|
rb->lcd_framebuffer,
|
|
blocklen * LCD_FBWIDTH * sizeof(fb_data));
|
|
}
|
|
if (bitcount)
|
|
{
|
|
#if LCD_PIXELFORMAT == VERTICAL_PACKING
|
|
|
|
#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"(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"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
|
|
[cnt] "d"(bitcount),
|
|
[bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
|
|
: /* clobbers */
|
|
"a1", "d0", "d1", "d2", "d3"
|
|
);
|
|
#else /* C version */
|
|
int x, by;
|
|
unsigned char *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
|
|
#else
|
|
const unsigned fill = 0;
|
|
#endif
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
unsigned char *col_addr = addr++;
|
|
unsigned data = fill;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
data = (data >> 8) | (*col_addr << bitcount);
|
|
*col_addr = data;
|
|
col_addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
#endif /* CPU, LCD_DEPTH */
|
|
|
|
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
|
|
|
#if LCD_DEPTH == 2
|
|
int x, by;
|
|
fb_data *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
|
|
unsigned fill, mask;
|
|
|
|
fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount);
|
|
mask = (0xFFu >> bitcount) << bitcount;
|
|
mask |= mask << 8;
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
fb_data *col_addr = addr++;
|
|
unsigned olddata = fill;
|
|
unsigned data;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
data = *col_addr << bitcount;
|
|
*col_addr = olddata ^ ((data ^ olddata) & mask);
|
|
olddata = data >> 8;
|
|
col_addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
#endif /* LCD_DEPTH == 2 */
|
|
|
|
#endif /* LCD_PIXELFORMAT */
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
|
|
#endif /* defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE */
|