rockbox/apps/plugins/lib/gray_scroll_up.c

136 lines
5.3 KiB
C
Raw Normal View History

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Grayscale framework
* gray_scroll_up() function
*
* This is a generic framework to use grayscale display within Rockbox
* plugins. It obviously does not work for the player.
*
* Copyright (C) 2004 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.
*
****************************************************************************/
#ifndef SIMULATOR /* not for simulator by now */
#include "plugin.h"
#if CONFIG_LCD == LCD_SSD1815 /* only for Recorder/Ondio */
#include "gray.h"
/*---------------------------------------------------------------------------
Scroll the whole grayscale buffer up by <count> pixels (<= 7)
----------------------------------------------------------------------------
black_border determines if the pixels scrolled in at the bottom are black
or white
Scrolling up/down pixel-wise is significantly slower than scrolling
left/right or scrolling up/down byte-wise because it involves bit
shifting. That's why it is asm optimized.
*/
void gray_scroll_up(int count, bool black_border)
{
unsigned filler;
if ((unsigned) count > 7)
return;
filler = black_border ? 0xFFu : 0;
/* scroll column by column to minimize flicker */
asm volatile (
"mov #0,r6 \n" /* x = 0 */
"mova .su_shifttbl,r0 \n" /* calculate jump destination for */
"mov.b @(r0,%6),%6 \n" /* shift amount from table */
"bra .su_cloop \n" /* skip table */
"add r0,%6 \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 %1,r2 \n" /* get start address */
"mov #0,r3 \n" /* current_plane = 0 */
".su_oloop: \n" /* repeat for every bitplane */
"mov r2,r4 \n" /* get start address */
"mov #0,r5 \n" /* current_row = 0 */
"mov %5,r1 \n" /* get filler bits */
".su_iloop: \n" /* repeat for all rows */
"sub %2,r4 \n" /* address -= width */
"mov.b @r4,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 @%6 \n" /* jump into shift "path" */
"extu.b r0,r1 \n" /* store data for next round */
".su_shift6: \n" /* shift right by 0..7 bits */
"shlr2 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,@r4 \n" /* store data */
"add #1,r5 \n" /* current_row++ */
"cmp/hi r5,%3 \n" /* current_row < bheight ? */
"bt .su_iloop \n"
"add %4,r2 \n" /* start_address += plane_size */
"add #1,r3 \n" /* current_plane++ */
"cmp/hi r3,%0 \n" /* current_plane < depth ? */
"bt .su_oloop \n"
"add #1,%1 \n" /* start_address++ */
"add #1,r6 \n" /* x++ */
"cmp/hi r6,%2 \n" /* x < width ? */
"bt .su_cloop \n"
: /* outputs */
: /* inputs */
/* %0 */ "r"(_graybuf->depth),
/* %1 */ "r"(_graybuf->data + _graybuf->plane_size),
/* %2 */ "r"(_graybuf->width),
/* %3 */ "r"(_graybuf->bheight),
/* %4 */ "r"(_graybuf->plane_size),
/* %5 */ "r"(filler),
/* %6 */ "r"(count)
: /* clobbers */
"r0", "r1", "r2", "r3", "r4", "r5", "r6"
);
}
#endif // #ifdef HAVE_LCD_BITMAP
#endif // #ifndef SIMULATOR