diff --git a/apps/plugin.c b/apps/plugin.c index 78c3aa9370..6d48329111 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -583,6 +583,10 @@ static const struct plugin_api rockbox_api = { sound_unit, sound_val2phys, #endif /* CONFIG_CODEC == SWCODEC */ + +#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && !defined(SIMULATOR) + lcd_grey_phase_blit, +#endif }; int plugin_load(const char* plugin, void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index 771b5738e8..f782b7a20c 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -119,7 +119,7 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 93 +#define PLUGIN_API_VERSION 94 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -718,6 +718,11 @@ struct plugin_api { const char * (*sound_unit)(int setting); int (*sound_val2phys)(int setting, int value); #endif /* CONFIG_CODEC == SWCODEC */ + +#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && !defined(SIMULATOR) + void (*lcd_grey_phase_blit)(const struct grey_data *data, int bx, int by, + int bwidth, int bheight, int stride); +#endif }; /* plugin header */ diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 57cab53c3d..9a6cc93faa 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -24,7 +24,7 @@ fire,demos fireworks,demos firmware_flash,apps flipit,games -grayscale,demos +greyscale,demos helloworld,demos invadrox,games iriver_flash,apps diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c index 31faf323f9..5eea42f634 100644 --- a/apps/plugins/cube.c +++ b/apps/plugins/cube.c @@ -19,7 +19,7 @@ * ***************************************************************************/ #include "plugin.h" -#include "gray.h" +#include "grey.h" #include "playergfx.h" #include "xlcd.h" #include "fixedpoint.h" @@ -221,16 +221,16 @@ struct my_lcd { void (*putsxy)(int x, int y, const unsigned char *string); }; -static struct my_lcd grayfuncs = { - gray_update, gray_clear_display, gray_drawline, gray_putsxy +static struct my_lcd greyfuncs = { + grey_update, grey_clear_display, grey_drawline, grey_putsxy }; static struct my_lcd lcdfuncs; /* initialised at runtime */ -static struct my_lcd *mylcd = &grayfuncs; +static struct my_lcd *mylcd = &greyfuncs; #define MYLCD(fn) mylcd->fn -#define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) gray_filltriangle(x1, y1, x2, y2, x3, y3) -#define MY_SET_FOREGROUND(fg) gray_set_foreground(fg) -#define MY_GET_FOREGROUND() gray_get_foreground() +#define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) grey_filltriangle(x1, y1, x2, y2, x3, y3) +#define MY_SET_FOREGROUND(fg) grey_set_foreground(fg) +#define MY_GET_FOREGROUND() grey_get_foreground() #else #define MYLCD(fn) rb->lcd_ ## fn @@ -314,8 +314,8 @@ static const unsigned face_colors[6] = LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255) #elif defined(USE_GSLIB) - GRAY_LIGHTGRAY, GRAY_LIGHTGRAY, GRAY_DARKGRAY, - GRAY_DARKGRAY, GRAY_BLACK, GRAY_BLACK + GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY, + GREY_DARKGRAY, GREY_BLACK, GREY_BLACK #else LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY, LCD_DARKGRAY, LCD_BLACK, LCD_BLACK @@ -490,7 +490,7 @@ void cleanup(void *parameter) (void)parameter; #ifdef USE_GSLIB - gray_release(); + grey_release(); #elif defined HAVE_LCD_CHARCELLS pgfx_release(); #endif @@ -527,10 +527,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) xlcd_init(rb); #elif defined(USE_GSLIB) gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size); - if (gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, 3, 0, NULL) - != 3) + if (!grey_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, NULL)) { - rb->splash(HZ, "Couldn't get grayscale buffer"); + rb->splash(HZ, "Couldn't init greyscale display"); return PLUGIN_ERROR; } /* init lcd_ function pointers */ @@ -539,7 +538,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) lcdfuncs.drawline = rb->lcd_drawline; lcdfuncs.putsxy = rb->lcd_putsxy; - gray_setfont(FONT_SYSFIXED); + grey_setfont(FONT_SYSFIXED); #endif rb->lcd_setfont(FONT_SYSFIXED); #else /* LCD_CHARCELLS */ @@ -603,7 +602,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) #ifdef USE_GSLIB if (mode_switch) { - gray_show(mode == SOLID); + grey_show(mode == SOLID); mode_switch = false; } #endif @@ -744,7 +743,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) if (++mode >= NUM_MODES) mode = 0; #ifdef USE_GSLIB - mylcd = (mode == SOLID) ? &grayfuncs : &lcdfuncs; + mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs; mode_switch = true; #endif redraw = true; @@ -785,7 +784,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) } #ifdef USE_GSLIB - gray_release(); + grey_release(); #elif defined(HAVE_LCD_CHARCELLS) pgfx_release(); #endif diff --git a/apps/plugins/doom/i_system.c b/apps/plugins/doom/i_system.c index 40ebe981b4..4a22743405 100644 --- a/apps/plugins/doom/i_system.c +++ b/apps/plugins/doom/i_system.c @@ -72,7 +72,7 @@ /* NOTE: The user timer is used to generate a 70Hz tick for Doom. But it - is unavailable for the grayscale targets (it's used by the grayscale + is unavailable for the greyscale targets (it's used by the greyscale lib) and is not implemented in the simulator - so we have to approximate it using current_tick. */ diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c index 9d9e4bb111..fe2f91b699 100644 --- a/apps/plugins/doom/i_video.c +++ b/apps/plugins/doom/i_video.c @@ -117,13 +117,13 @@ #include "rockmacros.h" #ifndef HAVE_LCD_COLOR -#include "../lib/gray.h" -static unsigned char graybuffer[8*LCD_WIDTH] IBSS_ATTR; /* off screen buffer */ +#include "../lib/grey.h" +static unsigned char greybuffer[LCD_WIDTH] IBSS_ATTR; /* off screen buffer */ static unsigned char *gbuf; #if LCD_PIXELFORMAT == HORIZONTAL_PACKING -#define GRAYBUFSIZE (((LCD_WIDTH+7)/8)*LCD_HEIGHT*32+200) +#define GREYBUFSIZE (((LCD_WIDTH+7)/8)*LCD_HEIGHT*16+200) #else -#define GRAYBUFSIZE (LCD_WIDTH*((LCD_HEIGHT+7)/8)*32+200) +#define GREYBUFSIZE (LCD_WIDTH*((LCD_HEIGHT+7)/8)*16+200) #endif #endif @@ -140,7 +140,7 @@ static fb_data *paldata=NULL; void I_ShutdownGraphics(void) { #ifndef HAVE_LCD_COLOR - gray_release(); + grey_release(); #endif noprintf=0; } @@ -580,23 +580,17 @@ void I_FinishUpdate (void) } rb->lcd_update(); #else /* !HAVE_LCD_COLOR */ - int x, yd = 0; + int x; for (y = 0; y < SCREENHEIGHT; y++) { for (x = 0; x < SCREENWIDTH; x++) { paletteIndex = d_screens[0][y*SCREENWIDTH + x]; - graybuffer[yd * SCREENWIDTH + x]=palette[paletteIndex]; - } - if (++yd == 8) - { - gray_ub_gray_bitmap(graybuffer, 0, y & ~7, SCREENWIDTH, 8); - yd = 0; + greybuffer[x]=palette[paletteIndex]; } + grey_ub_gray_bitmap(greybuffer, 0, y, SCREENWIDTH, 1); } - if (yd > 0) - gray_ub_gray_bitmap(graybuffer, 0, y & ~7, SCREENWIDTH, yd); #endif /* !HAVE_LCD_COLOR */ #endif } @@ -629,11 +623,10 @@ void I_InitGraphics(void) /* Note: The other screens are allocated as needed */ #ifndef HAVE_LCD_COLOR - gbuf=malloc(GRAYBUFSIZE); - gray_init(rb, gbuf, GRAYBUFSIZE, false, LCD_WIDTH, LCD_HEIGHT, 32, - 3<<7 /* 1.5 */, NULL); - /* switch on grayscale overlay */ - gray_show(true); + gbuf=malloc(GREYBUFSIZE); + grey_init(rb, gbuf, GREYBUFSIZE, false, LCD_WIDTH, LCD_HEIGHT, NULL); + /* switch on greyscale overlay */ + grey_show(true); #endif #ifdef CPU_COLDFIRE diff --git a/apps/plugins/grayscale.c b/apps/plugins/greyscale.c similarity index 66% rename from apps/plugins/grayscale.c rename to apps/plugins/greyscale.c index 56e1ce0e31..de90d5737f 100644 --- a/apps/plugins/grayscale.c +++ b/apps/plugins/greyscale.c @@ -7,9 +7,9 @@ * \/ \/ \/ \/ \/ * $Id$ * -* Grayscale demo plugin +* Greyscale demo plugin * -* Copyright (C) 2004 Jens Arnold +* Copyright (C) 2004-2008 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. @@ -23,62 +23,62 @@ #include "helper.h" #if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) -#include "gray.h" +#include "grey.h" PLUGIN_HEADER /* variable button definitions */ #if CONFIG_KEYPAD == RECORDER_PAD -#define GRAYSCALE_SHIFT BUTTON_ON -#define GRAYSCALE_UP BUTTON_UP -#define GRAYSCALE_DOWN BUTTON_DOWN -#define GRAYSCALE_LEFT BUTTON_LEFT -#define GRAYSCALE_RIGHT BUTTON_RIGHT -#define GRAYSCALE_OFF BUTTON_OFF +#define GREYSCALE_SHIFT BUTTON_ON +#define GREYSCALE_UP BUTTON_UP +#define GREYSCALE_DOWN BUTTON_DOWN +#define GREYSCALE_LEFT BUTTON_LEFT +#define GREYSCALE_RIGHT BUTTON_RIGHT +#define GREYSCALE_OFF BUTTON_OFF #elif CONFIG_KEYPAD == ONDIO_PAD -#define GRAYSCALE_SHIFT BUTTON_MENU -#define GRAYSCALE_UP BUTTON_UP -#define GRAYSCALE_DOWN BUTTON_DOWN -#define GRAYSCALE_LEFT BUTTON_LEFT -#define GRAYSCALE_RIGHT BUTTON_RIGHT -#define GRAYSCALE_OFF BUTTON_OFF +#define GREYSCALE_SHIFT BUTTON_MENU +#define GREYSCALE_UP BUTTON_UP +#define GREYSCALE_DOWN BUTTON_DOWN +#define GREYSCALE_LEFT BUTTON_LEFT +#define GREYSCALE_RIGHT BUTTON_RIGHT +#define GREYSCALE_OFF BUTTON_OFF #elif CONFIG_KEYPAD == IRIVER_H100_PAD -#define GRAYSCALE_SHIFT BUTTON_ON -#define GRAYSCALE_UP BUTTON_UP -#define GRAYSCALE_DOWN BUTTON_DOWN -#define GRAYSCALE_LEFT BUTTON_LEFT -#define GRAYSCALE_RIGHT BUTTON_RIGHT -#define GRAYSCALE_OFF BUTTON_OFF +#define GREYSCALE_SHIFT BUTTON_ON +#define GREYSCALE_UP BUTTON_UP +#define GREYSCALE_DOWN BUTTON_DOWN +#define GREYSCALE_LEFT BUTTON_LEFT +#define GREYSCALE_RIGHT BUTTON_RIGHT +#define GREYSCALE_OFF BUTTON_OFF -#define GRAYSCALE_RC_OFF BUTTON_RC_STOP +#define GREYSCALE_RC_OFF BUTTON_RC_STOP #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD) -#define GRAYSCALE_SHIFT BUTTON_SELECT -#define GRAYSCALE_UP BUTTON_SCROLL_BACK -#define GRAYSCALE_DOWN BUTTON_SCROLL_FWD -#define GRAYSCALE_LEFT BUTTON_LEFT -#define GRAYSCALE_RIGHT BUTTON_RIGHT -#define GRAYSCALE_OFF BUTTON_MENU +#define GREYSCALE_SHIFT BUTTON_SELECT +#define GREYSCALE_UP BUTTON_SCROLL_BACK +#define GREYSCALE_DOWN BUTTON_SCROLL_FWD +#define GREYSCALE_LEFT BUTTON_LEFT +#define GREYSCALE_RIGHT BUTTON_RIGHT +#define GREYSCALE_OFF BUTTON_MENU #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD -#define GRAYSCALE_SHIFT BUTTON_PLAY -#define GRAYSCALE_UP BUTTON_UP -#define GRAYSCALE_DOWN BUTTON_DOWN -#define GRAYSCALE_LEFT BUTTON_LEFT -#define GRAYSCALE_RIGHT BUTTON_RIGHT -#define GRAYSCALE_OFF BUTTON_EQ +#define GREYSCALE_SHIFT BUTTON_PLAY +#define GREYSCALE_UP BUTTON_UP +#define GREYSCALE_DOWN BUTTON_DOWN +#define GREYSCALE_LEFT BUTTON_LEFT +#define GREYSCALE_RIGHT BUTTON_RIGHT +#define GREYSCALE_OFF BUTTON_EQ #endif #define GFX_HEIGHT (LCD_HEIGHT-8) #if LCD_WIDTH < 160 -#define GFX_GRAYTONE_WIDTH 86 -#define GFX_GRAYTONE_STEP 3 +#define GFX_GREYTONE_WIDTH 86 +#define GFX_GREYTONE_STEP 3 #else -#define GFX_GRAYTONE_WIDTH 128 -#define GFX_GRAYTONE_STEP 2 +#define GFX_GREYTONE_WIDTH 128 +#define GFX_GREYTONE_STEP 2 #endif /******************************* Globals ***********************************/ @@ -93,7 +93,7 @@ void cleanup(void *parameter) { (void)parameter; - gray_release(); /* switch off overlay and deinitialize */ + grey_release(); /* switch off overlay and deinitialize */ /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(rb); /* backlight control in lib/helper.c */ } @@ -101,7 +101,7 @@ void cleanup(void *parameter) /* this is only a demo of what the framework can do */ int main(void) { - int shades, time; + int time; int x, y, i; int button, scroll_amount; bool black_border = false; @@ -139,7 +139,7 @@ int main(void) 0x10, 0x3E, 0x00, 0x1C, 0x22, 0x22, 0x2A, 0x3A, 0x00 }; - static const unsigned char grayscale_gray[] = { + static const unsigned char grayscale_grey[] = { /* ....................................................... * ..####.####...###..#...#..####..###...###..#.....#####. * .#.....#...#.#...#.#...#.#.....#...#.#...#.#.....#..... @@ -188,82 +188,82 @@ int main(void) gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); /* initialize the greyscale buffer: - Archos: 112 pixels wide, 7 rows (56 pixels) high, (try to) reserve - 32 bitplanes for 33 shades of grey. - H1x0: 160 pixels wide, 30 rows (120 pixels) high, (try to) reserve - 32 bitplanes for 33 shades of grey. */ - shades = gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, GFX_HEIGHT, - 32, 0, NULL) + 1; + Archos: 112 pixels wide, 7 rows (56 pixels) high. + H1x0: 160 pixels wide, 30 rows (120 pixels) high. */ + if (!grey_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, GFX_HEIGHT, NULL)) + { + rb->splash(HZ, "Not enough memory."); + return PLUGIN_ERROR; + } /* place greyscale overlay 1 row down */ - gray_set_position(0, 8); + grey_set_position(0, 8); - rb->snprintf(pbuf, sizeof(pbuf), "Shades: %d", shades); - rb->lcd_puts(0, 0, pbuf); + rb->lcd_puts(0, 0, "Shades: 129"); rb->lcd_update(); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); #endif - gray_show(true); /* switch on greyscale overlay */ + grey_show(true); /* switch on greyscale overlay */ time = *rb->current_tick; /* start time measurement */ - gray_set_background(150); - gray_clear_display(); /* fill everything with grey 150 */ + grey_set_background(150); + grey_clear_display(); /* fill everything with grey 150 */ /* draw a dark grey line star background */ - gray_set_foreground(80); + grey_set_foreground(80); for (y = 0; y < GFX_HEIGHT; y += 8) /* horizontal part */ { - gray_drawline(0, y, (LCD_WIDTH-1), (GFX_HEIGHT-1) - y); /*grey lines */ + grey_drawline(0, y, (LCD_WIDTH-1), (GFX_HEIGHT-1) - y); /*grey lines */ } for (x = 10; x <= LCD_WIDTH; x += 10) /* vertical part */ { - gray_drawline(x, 0, (LCD_WIDTH-1) - x, (GFX_HEIGHT-1)); /*grey lines */ + grey_drawline(x, 0, (LCD_WIDTH-1) - x, (GFX_HEIGHT-1)); /*grey lines */ } - gray_set_foreground(0); - gray_drawrect(0, 0, LCD_WIDTH, GFX_HEIGHT); /* black border */ + grey_set_foreground(0); + grey_drawrect(0, 0, LCD_WIDTH, GFX_HEIGHT); /* black border */ /* draw grey tones */ - for (i = 0; i < GFX_GRAYTONE_WIDTH; i++) + for (i = 0; i < GFX_GREYTONE_WIDTH; i++) { - x = ((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2) + i; - gray_set_foreground(GFX_GRAYTONE_STEP * i); + x = ((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2) + i; + grey_set_foreground(GFX_GREYTONE_STEP * i); /* vertical lines */ - gray_vline(x, (GFX_HEIGHT/8), (GFX_HEIGHT-GFX_HEIGHT/8-1)); + grey_vline(x, (GFX_HEIGHT/8), (GFX_HEIGHT-GFX_HEIGHT/8-1)); } - gray_set_drawmode(DRMODE_COMPLEMENT); + grey_set_drawmode(DRMODE_COMPLEMENT); /* invert rectangle (lower half) */ - gray_fillrect((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2, (GFX_HEIGHT/2+1), - GFX_GRAYTONE_WIDTH, (GFX_HEIGHT/2-GFX_HEIGHT/8-1)); + grey_fillrect((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2, (GFX_HEIGHT/2+1), + GFX_GREYTONE_WIDTH, (GFX_HEIGHT/2-GFX_HEIGHT/8-1)); /* invert a line */ - gray_hline((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2, - (LCD_WIDTH+GFX_GRAYTONE_WIDTH)/2, (GFX_HEIGHT/2-1)); + grey_hline((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2, + (LCD_WIDTH+GFX_GREYTONE_WIDTH)/2, (GFX_HEIGHT/2-1)); /* show bitmaps (1 bit and 8 bit) */ /* opaque */ - gray_set_drawinfo(DRMODE_SOLID, 255, 100); - gray_mono_bitmap(rockbox, - MAX((LCD_WIDTH/2-47), ((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2)), + grey_set_drawinfo(DRMODE_SOLID, 255, 100); + grey_mono_bitmap(rockbox, + MAX((LCD_WIDTH/2-47), ((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2)), (5*GFX_HEIGHT/16-4), 43, 7); /* transparent */ - gray_set_drawinfo(DRMODE_FG, 0, 100); - gray_mono_bitmap(showing, (LCD_WIDTH/2+4) , (5*GFX_HEIGHT/16-4), 39, 7); + grey_set_drawinfo(DRMODE_FG, 0, 100); + grey_mono_bitmap(showing, (LCD_WIDTH/2+4) , (5*GFX_HEIGHT/16-4), 39, 7); /* greyscale */ - gray_gray_bitmap(grayscale_gray, ((LCD_WIDTH-55)/2), (11*GFX_HEIGHT/16-4), + grey_gray_bitmap(grayscale_grey, ((LCD_WIDTH-55)/2), (11*GFX_HEIGHT/16-4), 55, 7); - gray_update(); + grey_update(); time = *rb->current_tick - time; /* end time measurement */ - rb->snprintf(pbuf, sizeof(pbuf), "Shades: %d, %d.%02ds", shades, + rb->snprintf(pbuf, sizeof(pbuf), "Shades: 129, %d.%02ds", time / 100, time % 100); rb->lcd_puts(0, 0, pbuf); - gray_deferred_lcd_update(); /* schedule an lcd_update() */ + grey_deferred_lcd_update(); /* schedule an lcd_update() */ #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(false); #endif @@ -271,7 +271,7 @@ int main(void) /* drawing is now finished, play around with scrolling * until you press OFF or connect USB */ - gray_set_background(255); + grey_set_background(255); while (true) { scroll_amount = 1; @@ -282,11 +282,11 @@ int main(void) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; - if (button & GRAYSCALE_SHIFT) + if (button & GREYSCALE_SHIFT) { if (!black_border) { - gray_set_background(0); + grey_set_background(0); black_border = true; } } @@ -294,7 +294,7 @@ int main(void) { if (black_border) { - gray_set_background(255); + grey_set_background(255); black_border = false; } } @@ -302,35 +302,35 @@ int main(void) if (button & BUTTON_REPEAT) scroll_amount = 4; - switch (button & ~(GRAYSCALE_SHIFT | BUTTON_REPEAT)) + switch (button & ~(GREYSCALE_SHIFT | BUTTON_REPEAT)) { - case GRAYSCALE_LEFT: + case GREYSCALE_LEFT: - gray_scroll_left(scroll_amount); /* scroll left */ - gray_update(); + grey_scroll_left(scroll_amount); /* scroll left */ + grey_update(); break; - case GRAYSCALE_RIGHT: + case GREYSCALE_RIGHT: - gray_scroll_right(scroll_amount); /* scroll right */ - gray_update(); + grey_scroll_right(scroll_amount); /* scroll right */ + grey_update(); break; - case GRAYSCALE_UP: + case GREYSCALE_UP: - gray_scroll_up(scroll_amount); /* scroll up */ - gray_update(); + grey_scroll_up(scroll_amount); /* scroll up */ + grey_update(); break; - case GRAYSCALE_DOWN: + case GREYSCALE_DOWN: - gray_scroll_down(scroll_amount); /* scroll down */ - gray_update(); + grey_scroll_down(scroll_amount); /* scroll down */ + grey_update(); break; -#ifdef GRAYSCALE_RC_OFF - case GRAYSCALE_RC_OFF: +#ifdef GREYSCALE_RC_OFF + case GREYSCALE_RC_OFF: #endif - case GRAYSCALE_OFF: + case GREYSCALE_OFF: cleanup(NULL); return PLUGIN_OK; diff --git a/apps/plugins/jpeg.c b/apps/plugins/jpeg.c index 9e11ca431b..adb76cdd3c 100644 --- a/apps/plugins/jpeg.c +++ b/apps/plugins/jpeg.c @@ -11,8 +11,7 @@ * (This is a real mess if it has to be coded in one single C file) * * File scrolling addition (C) 2005 Alexander Spyridakis -* Copyright (C) 2004 J�g Hohensohn aka [IDC]Dragon -* Grayscale framework (C) 2004 Jens Arnold +* Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon * Heavily borrowed from the IJG implementation (C) Thomas G. Lane * Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org * @@ -30,7 +29,7 @@ #include "helper.h" #ifdef HAVE_LCD_BITMAP -#include "gray.h" +#include "grey.h" #include "xlcd.h" #ifdef HAVE_LCD_COLOR @@ -185,9 +184,9 @@ PLUGIN_HEADER /* different graphics libraries */ #if LCD_DEPTH < 8 #define USEGSLIB -#define MYLCD(fn) gray_ub_ ## fn +#define MYLCD(fn) grey_ub_ ## fn #define MYLCD_UPDATE() -#define MYXLCD(fn) gray_ub_ ## fn +#define MYXLCD(fn) grey_ub_ ## fn #else #define MYLCD(fn) rb->lcd_ ## fn #define MYLCD_UPDATE() rb->lcd_update(); @@ -2409,7 +2408,7 @@ void cleanup(void *parameter) { (void)parameter; #ifdef USEGSLIB - gray_show(false); + grey_show(false); #endif } @@ -2791,13 +2790,13 @@ int scroll_bmp(struct t_disp* pdisp) #endif case JPEG_MENU: #ifdef USEGSLIB - gray_show(false); /* switch off grayscale overlay */ + grey_show(false); /* switch off greyscale overlay */ #endif if (show_menu() == 1) return PLUGIN_OK; #ifdef USEGSLIB - gray_show(true); /* switch on grayscale overlay */ + grey_show(true); /* switch on greyscale overlay */ #else yuv_bitmap_part( pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, @@ -3222,7 +3221,7 @@ int load_and_show(char* filename) MYLCD_UPDATE(); #ifdef USEGSLIB - gray_show(true); /* switch on grayscale overlay */ + grey_show(true); /* switch on greyscale overlay */ #endif /* drawing is now finished, play around with scrolling @@ -3260,7 +3259,7 @@ int load_and_show(char* filename) } #ifdef USEGSLIB - gray_show(false); /* switch off overlay */ + grey_show(false); /* switch off overlay */ #endif rb->lcd_clear_display(); } @@ -3280,8 +3279,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) int condition; #ifdef USEGSLIB - int grayscales; - long graysize; /* helper */ + long greysize; /* helper */ #endif #if LCD_DEPTH > 1 old_backdrop = rb->lcd_get_backdrop(); @@ -3311,16 +3309,13 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) #endif #ifdef USEGSLIB - /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */ - grayscales = gray_init(rb, buf, buf_size, false, LCD_WIDTH, LCD_HEIGHT, - 32, 2<<8, &graysize) + 1; - buf += graysize; - buf_size -= graysize; - if (grayscales < 33 || buf_size <= 0) + if (!grey_init(rb, buf, buf_size, false, LCD_WIDTH, LCD_HEIGHT, &greysize)) { - rb->splash(HZ, "gray buf error"); + rb->splash(HZ, "grey buf error"); return PLUGIN_ERROR; } + buf += greysize; + buf_size -= greysize; #else xlcd_init(rb); #endif @@ -3364,7 +3359,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) backlight_use_settings(rb); /* backlight control in lib/helper.c */ #ifdef USEGSLIB - gray_release(); /* deinitialize */ + grey_release(); /* deinitialize */ #endif return condition; diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index f6711840ee..5433f7e1d7 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -8,6 +8,10 @@ gray_core.c gray_draw.c gray_parm.c gray_scroll.c +grey_core.c +grey_draw.c +grey_parm.c +grey_scroll.c #endif highscore.c #ifndef SIMULATOR diff --git a/apps/plugins/lib/grey.h b/apps/plugins/lib/grey.h new file mode 100644 index 0000000000..136794bd26 --- /dev/null +++ b/apps/plugins/lib/grey.h @@ -0,0 +1,166 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* New greyscale framework +* +* This is a generic framework to display 129 shades of grey on low-depth +* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. +* +* Copyright (C) 2008 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 __GREY_H__ +#define __GREY_H__ + +#include "plugin.h" + +#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) + +#define GREY_BRIGHTNESS(y) (y) + +#define GREY_BLACK GREY_BRIGHTNESS(0) +#define GREY_DARKGRAY GREY_BRIGHTNESS(85) +#define GREY_LIGHTGRAY GREY_BRIGHTNESS(170) +#define GREY_WHITE GREY_BRIGHTNESS(255) + +/* Library initialisation and release */ +bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, + bool buffered, int width, int height, long *buf_taken); +void grey_release(void); + +/* Special functions */ +void grey_show(bool enable); +void grey_deferred_lcd_update(void); + +/* Update functions */ +void grey_update(void); +void grey_update_rect(int x, int y, int width, int height); + +/* Parameter handling */ +void grey_set_position(int x, int y); +void grey_set_drawmode(int mode); +int grey_get_drawmode(void); +void grey_set_foreground(unsigned brightness); +unsigned grey_get_foreground(void); +void grey_set_background(unsigned brightness); +unsigned grey_get_background(void); +void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness); +void grey_setfont(int newfont); +int grey_getstringsize(const unsigned char *str, int *w, int *h); + +/* Whole display */ +void grey_clear_display(void); +void grey_ub_clear_display(void); + +/* Pixel */ +void grey_drawpixel(int x, int y); + +/* Lines */ +void grey_drawline(int x1, int y1, int x2, int y2); +void grey_hline(int x1, int x2, int y); +void grey_vline(int x, int y1, int y2); +void grey_drawrect(int x, int y, int nx, int ny); + +/* Filled primitives */ +void grey_fillrect(int x, int y, int nx, int ny); +void grey_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3); + +/* Bitmaps */ +void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); +void grey_mono_bitmap(const unsigned char *src, int x, int y, int width, + int height); +void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); +void grey_gray_bitmap(const unsigned char *src, int x, int y, int width, + int height); +void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); +void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, + int height); + +/* Text */ +void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str); +void grey_putsxy(int x, int y, const unsigned char *str); + +/* Scrolling */ +void grey_scroll_left(int count); +void grey_scroll_right(int count); +void grey_scroll_up(int count); +void grey_scroll_down(int count); +void grey_ub_scroll_left(int count); +void grey_ub_scroll_right(int count); +void grey_ub_scroll_up(int count); +void grey_ub_scroll_down(int count); + +/*** Internal stuff ***/ + +/* flag definitions */ +#define _GREY_RUNNING 0x0001 /* greyscale overlay is running */ +#define _GREY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */ + +/* fast unsigned multiplication (16x16bit->32bit or 32x32bit->32bit, + * whichever is faster for the architecture) */ +#ifdef CPU_ARM +#define _GREY_MULUQ(a, b) ((uint32_t) (((uint32_t) (a)) * ((uint32_t) (b)))) +#else +#define _GREY_MULUQ(a, b) ((uint32_t) (((uint16_t) (a)) * ((uint16_t) (b)))) +#endif + +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING +#define _GREY_X_ADVANCE sizeof(struct grey_data) +#else +#if LCD_DEPTH == 1 +#define _GREY_X_ADVANCE (8*sizeof(struct grey_data)) +#elif LCD_DEPTH == 2 +#define _GREY_X_ADVANCE (4*sizeof(struct grey_data)) +#endif +#endif /* LCD_PIXELFORMAT */ + +/* The greyscale buffer management structure */ +struct _grey_info +{ + int x; + int y; + int width; + int height; +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + int bx; /* 8-pixel units */ + int bwidth; /* 8-pixel units */ +#else /* vertical packing */ + int by; /* 4-pixel or 8-pixel units */ + int bheight; /* 4-pixel or 8-pixel units */ +#endif + unsigned long flags; /* various flags, see #defines */ +#ifndef SIMULATOR + struct grey_data *data; /* start of greyscale display data */ +#endif + unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */ + unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */ + int fg_val; /* current foreground value */ + int bg_val; /* current background value */ + int fg_brightness; /* current foreground brightness */ + int bg_brightness; /* current background brightness */ + int drawmode; /* current draw mode */ + int curfont; /* current selected font */ +}; + +/* Global variables */ +extern struct plugin_api *_grey_rb; +extern struct _grey_info _grey_info; + +#endif /* HAVE_LCD_BITMAP && (LCD_DEPTH < 4) */ +#endif /* __GREY_H__ */ diff --git a/apps/plugins/lib/grey_core.c b/apps/plugins/lib/grey_core.c new file mode 100644 index 0000000000..b3ab640602 --- /dev/null +++ b/apps/plugins/lib/grey_core.c @@ -0,0 +1,767 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* New greyscale framework +* Core & miscellaneous functions +* +* This is a generic framework to display 129 shades of grey on low-depth +* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. +* +* Copyright (C) 2008 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" +#include "grey.h" + +#if defined(CPU_PP) && defined(HAVE_ADJUSTABLE_CPU_FREQ) +#define NEED_BOOST +#endif + +/* Global variables */ +struct plugin_api *_grey_rb = NULL; /* global api struct pointer */ +struct _grey_info _grey_info; /* global info structure */ + +#ifndef SIMULATOR + +#if CONFIG_LCD == LCD_SSD1815 || CONFIG_LCD == LCD_IFP7XX +/* measured and interpolated curve */ +/* TODO: check for iFP */ +static const unsigned char lcdlinear[256] = { + 0, 3, 5, 8, 11, 13, 16, 18, + 21, 23, 26, 28, 31, 33, 36, 38, + 40, 42, 45, 47, 49, 51, 53, 55, + 57, 59, 60, 62, 64, 66, 67, 69, + 70, 72, 73, 74, 76, 77, 78, 79, + 81, 82, 83, 84, 85, 86, 87, 88, + 88, 89, 90, 91, 92, 92, 93, 94, + 95, 95, 96, 97, 97, 98, 99, 99, + 100, 101, 102, 102, 103, 104, 104, 105, + 106, 106, 107, 107, 108, 109, 109, 110, + 111, 111, 112, 113, 113, 114, 114, 115, + 116, 116, 117, 117, 118, 119, 119, 120, + 120, 121, 121, 122, 122, 123, 123, 124, + 124, 125, 125, 126, 126, 127, 127, 128, + 128, 128, 129, 129, 130, 130, 131, 131, + 132, 132, 133, 133, 133, 134, 134, 135, + 135, 136, 136, 137, 137, 138, 138, 138, + 139, 139, 140, 140, 141, 141, 142, 142, + 143, 143, 144, 144, 145, 145, 146, 146, + 147, 147, 148, 148, 148, 149, 149, 150, + 150, 151, 151, 152, 152, 153, 153, 153, + 154, 154, 155, 155, 156, 156, 157, 157, + 158, 158, 158, 159, 159, 160, 160, 161, + 161, 162, 162, 163, 163, 164, 164, 165, + 165, 166, 167, 167, 168, 168, 169, 169, + 170, 171, 171, 172, 173, 173, 174, 175, + 176, 176, 177, 178, 179, 180, 181, 181, + 182, 183, 184, 185, 186, 188, 189, 190, + 191, 192, 194, 195, 196, 198, 199, 201, + 202, 204, 205, 207, 209, 211, 213, 215, + 217, 219, 222, 224, 226, 229, 231, 234, + 236, 239, 242, 244, 247, 250, 252, 255 +}; +#elif CONFIG_LCD == LCD_S1D15E06 +/* measured and interpolated curve */ +static const unsigned char lcdlinear[256] = { + 0, 5, 11, 16, 21, 27, 32, 37, + 42, 47, 51, 56, 60, 64, 68, 72, + 75, 78, 81, 84, 87, 89, 91, 93, + 95, 96, 98, 99, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 111, + 112, 113, 113, 114, 115, 115, 116, 117, + 117, 118, 118, 119, 119, 120, 120, 121, + 121, 122, 122, 123, 123, 124, 124, 125, + 125, 126, 126, 127, 127, 127, 128, 128, + 129, 129, 130, 130, 131, 131, 132, 132, + 133, 133, 134, 134, 135, 135, 136, 136, + 137, 137, 138, 138, 138, 139, 139, 140, + 140, 141, 141, 141, 142, 142, 143, 143, + 143, 144, 144, 145, 145, 145, 146, 146, + 146, 147, 147, 147, 148, 148, 149, 149, + 149, 150, 150, 150, 151, 151, 151, 152, + 152, 153, 153, 153, 154, 154, 155, 155, + 155, 156, 156, 157, 157, 157, 158, 158, + 159, 159, 159, 160, 160, 161, 161, 162, + 162, 162, 163, 163, 164, 164, 164, 165, + 165, 166, 166, 167, 167, 167, 168, 168, + 169, 169, 170, 170, 170, 171, 171, 172, + 172, 173, 173, 174, 174, 175, 175, 176, + 176, 177, 177, 178, 178, 179, 179, 180, + 180, 181, 182, 182, 183, 184, 184, 185, + 186, 186, 187, 188, 188, 189, 190, 191, + 191, 192, 193, 194, 195, 196, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 213, 214, + 215, 216, 218, 219, 220, 222, 223, 225, + 227, 228, 230, 232, 233, 235, 237, 239, + 241, 243, 245, 247, 249, 251, 253, 255 +}; +#elif (CONFIG_LCD == LCD_IPOD2BPP) || (CONFIG_LCD == LCD_IPODMINI) +/* measured and interpolated curve for mini LCD */ +/* TODO: verify this curve on the fullsize greyscale LCD */ +static const unsigned char lcdlinear[256] = { + 0, 3, 6, 8, 11, 14, 17, 19, + 22, 24, 27, 29, 32, 34, 36, 38, + 40, 42, 44, 45, 47, 48, 50, 51, + 52, 54, 55, 56, 57, 58, 58, 59, + 60, 61, 62, 62, 63, 64, 64, 65, + 66, 66, 67, 67, 68, 68, 69, 69, + 70, 70, 70, 71, 71, 71, 72, 72, + 73, 73, 73, 74, 74, 74, 74, 75, + 75, 75, 76, 76, 76, 77, 77, 77, + 78, 78, 78, 79, 79, 79, 80, 80, + 80, 80, 81, 81, 81, 82, 82, 82, + 83, 83, 83, 84, 84, 84, 85, 85, + 85, 85, 86, 86, 86, 87, 87, 87, + 87, 88, 88, 88, 89, 89, 89, 89, + 90, 90, 90, 91, 91, 91, 92, 92, + 92, 93, 93, 93, 94, 94, 94, 95, + 95, 96, 96, 96, 97, 97, 98, 98, + 99, 99, 99, 100, 100, 101, 101, 102, + 102, 103, 103, 104, 104, 105, 105, 106, + 106, 107, 107, 108, 108, 109, 109, 110, + 110, 111, 111, 112, 113, 113, 114, 114, + 115, 115, 116, 117, 117, 118, 118, 119, + 120, 120, 121, 122, 122, 123, 124, 124, + 125, 126, 126, 127, 128, 128, 129, 130, + 131, 131, 132, 133, 134, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 152, 153, + 154, 156, 157, 159, 160, 162, 163, 165, + 167, 168, 170, 172, 174, 176, 178, 180, + 182, 184, 187, 189, 192, 194, 197, 200, + 203, 206, 209, 212, 215, 219, 222, 226, + 229, 233, 236, 240, 244, 248, 251, 255 +}; +#endif +#else /* SIMULATOR */ +/* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */ +static const unsigned char lcdlinear[256] = { + 0, 16, 23, 28, 32, 36, 39, 42, + 45, 48, 50, 53, 55, 58, 60, 62, + 64, 66, 68, 70, 71, 73, 75, 77, + 78, 80, 81, 83, 84, 86, 87, 89, + 90, 92, 93, 94, 96, 97, 98, 100, + 101, 102, 103, 105, 106, 107, 108, 109, + 111, 112, 113, 114, 115, 116, 117, 118, + 119, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, + 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 145, 146, 147, 148, 149, + 150, 151, 151, 152, 153, 154, 155, 156, + 156, 157, 158, 159, 160, 160, 161, 162, + 163, 164, 164, 165, 166, 167, 167, 168, + 169, 170, 170, 171, 172, 173, 173, 174, + 175, 176, 176, 177, 178, 179, 179, 180, + 181, 181, 182, 183, 183, 184, 185, 186, + 186, 187, 188, 188, 189, 190, 190, 191, + 192, 192, 193, 194, 194, 195, 196, 196, + 197, 198, 198, 199, 199, 200, 201, 201, + 202, 203, 203, 204, 204, 205, 206, 206, + 207, 208, 208, 209, 209, 210, 211, 211, + 212, 212, 213, 214, 214, 215, 215, 216, + 217, 217, 218, 218, 219, 220, 220, 221, + 221, 222, 222, 223, 224, 224, 225, 225, + 226, 226, 227, 228, 228, 229, 229, 230, + 230, 231, 231, 232, 233, 233, 234, 234, + 235, 235, 236, 236, 237, 237, 238, 238, + 239, 240, 240, 241, 241, 242, 242, 243, + 243, 244, 244, 245, 245, 246, 246, 247, + 247, 248, 248, 249, 249, 250, 250, 251, + 251, 252, 252, 253, 253, 254, 254, 255 +}; +#endif /* SIMULATOR */ + +/* Prototypes */ +static inline void _deferred_update(void) __attribute__ ((always_inline)); +static int exp_s16p16(int x); +static int log_s16p16(int x); +static void grey_screendump_hook(int fd); +#ifdef SIMULATOR +static unsigned long _grey_get_pixel(int x, int y); +#else +static void _timer_isr(void); +#endif + +/* Update LCD areas not covered by the greyscale overlay */ +static inline void _deferred_update(void) +{ + int x1 = MAX(_grey_info.x, 0); + int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH); + int y1 = MAX(_grey_info.y, 0); + int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT); + + if (y1 > 0) /* refresh part above overlay, full width */ + _grey_rb->lcd_update_rect(0, 0, LCD_WIDTH, y1); + + if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */ + _grey_rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2); + + if (x1 > 0) /* refresh part to the left of overlay */ + _grey_rb->lcd_update_rect(0, y1, x1, y2 - y1); + + if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */ + _grey_rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1); +} + +#ifndef SIMULATOR +/* Timer interrupt handler: display next frame */ +static void _timer_isr(void) +{ +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.bx, _grey_info.y, + _grey_info.bwidth, _grey_info.height, + _grey_info.width); +#else + _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.x, _grey_info.by, + _grey_info.width, _grey_info.bheight, + _grey_info.width); +#endif + + if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */ + { + _deferred_update(); + _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */ + } +} +#endif /* !SIMULATOR */ + +/* fixed point exp() */ +static int exp_s16p16(int x) +{ + int t; + int y = 0x00010000; + + if (x < 0) x += 0xb1721, y >>= 16; + t = x - 0x58b91; if (t >= 0) x = t, y <<= 8; + t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4; + t = x - 0x162e4; if (t >= 0) x = t, y <<= 2; + t = x - 0x0b172; if (t >= 0) x = t, y <<= 1; + t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1; + t = x - 0x03920; if (t >= 0) x = t, y += y >> 2; + t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3; + t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4; + t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5; + t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6; + t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7; + y += ((y >> 8) * x) >> 8; + + return y; +} + +/* fixed point log() */ +static int log_s16p16(int x) +{ + int t; + int y = 0xa65af; + + if (x < 0x00008000) x <<=16, y -= 0xb1721; + if (x < 0x00800000) x <<= 8, y -= 0x58b91; + if (x < 0x08000000) x <<= 4, y -= 0x2c5c8; + if (x < 0x20000000) x <<= 2, y -= 0x162e4; + if (x < 0x40000000) x <<= 1, y -= 0x0b172; + t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd; + t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920; + t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27; + t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85; + t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1; + t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8; + t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe; + x = 0x80000000 - x; + y -= x >> 15; + + return y; +} + +/* Initialise the framework and prepare the greyscale display buffer + + arguments: + newrb = pointer to plugin api + gbuf = pointer to the memory area to use (e.g. plugin buffer) + gbuf_size = max usable size of the buffer + buffered = use chunky pixel buffering? + This allows to use all drawing functions, but needs more + memory. Unbuffered operation provides only a subset of + drawing functions. (only grey_bitmap drawing and scrolling) + width = width in pixels (1..LCD_WIDTH) + height = height in pixels (1..LCD_HEIGHT) + Note that depending on the target LCD, either height or + width are rounded up to a multiple of 4 or 8. + + result: + true on success, false on failure + + If you need info about the memory taken by the greyscale buffer, supply a + long* as the last parameter. This long will then contain the number of bytes + used. The total memory needed can be calculated as follows: + total_mem = + width * height * 2 [grey display data] + + buffered ? (width * height) : 0 [chunky buffer] + + 0..3 [alignment] + + The function is authentic regarding memory usage on the simulator, even + if it doesn't use all of the allocated memory. */ +bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, + bool buffered, int width, int height, long *buf_taken) +{ + int bdim, i; + long plane_size, buftaken; + unsigned data; +#ifndef SIMULATOR + struct grey_data *grey_data, *grey_end; +#endif + + _grey_rb = newrb; + + if ((unsigned) width > LCD_WIDTH + || (unsigned) height > LCD_HEIGHT) + return false; + +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + bdim = (width + 7) >> 3; + width = bdim << 3; +#else /* vertical packing */ +#if LCD_DEPTH == 1 + bdim = (height + 7) >> 3; + height = bdim << 3; +#elif LCD_DEPTH == 2 + bdim = (height + 3) >> 2; + height = bdim << 2; +#endif +#endif + + /* the buffer has to be long aligned */ + buftaken = (-(long)gbuf) & 3; + gbuf += buftaken; + + plane_size = _GREY_MULUQ(width, height); + + if (buffered) /* chunky buffer */ + { + buftaken += plane_size; + _grey_info.buffer = gbuf; + gbuf += plane_size; + } + buftaken += sizeof(struct grey_data) * plane_size; + if (buftaken > gbuf_size) + return false; + +#ifdef SIMULATOR + _grey_info.buffer = gbuf; +#else + grey_data = (struct grey_data *)gbuf; + grey_end = grey_data + plane_size; + _grey_info.data = grey_data; + + while (grey_data < grey_end) + { + grey_data->phase = _grey_rb->rand() & 0xff; + grey_data->value = 128; /* init to white */ + grey_data++; + } +#endif + + _grey_info.x = 0; + _grey_info.y = 0; + _grey_info.width = width; + _grey_info.height = height; +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + _grey_info.bx = 0; + _grey_info.bwidth = bdim; +#else + _grey_info.by = 0; + _grey_info.bheight = bdim; +#endif + _grey_info.flags = 0; + _grey_info.fg_val = 0; + _grey_info.bg_val = 128; + _grey_info.fg_brightness = 0; + _grey_info.bg_brightness = 255; + _grey_info.drawmode = DRMODE_SOLID; + _grey_info.curfont = FONT_SYSFIXED; + + + /* precalculate the value -> pattern index conversion table, taking + linearisation and gamma correction into account */ + for (i = 0; i < 256; i++) + { + data = exp_s16p16(((2<<8) * log_s16p16(i * 257 + 1)) >> 8) + 128; + data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */ + data = (lcdlinear[data] << 7) + 127; + _grey_info.gvalue[i] = (data + (data >> 8)) >> 8; + /* approx. data / 255 */ + } + + if (buf_taken) /* caller requested info about space taken */ + *buf_taken = buftaken; + + return true; +} + +/* Release the greyscale display buffer and the library + DO CALL either this function or at least grey_show_display(false) + before you exit, otherwise nasty things may happen. */ +void grey_release(void) +{ + grey_show(false); +} + +/* Switch the greyscale overlay on or off + DO NOT call lcd_update() or any other api function that directly accesses + the lcd while the greyscale overlay is running! If you need to do + lcd_update() to update something outside the greyscale overlay area, use + grey_deferred_update() instead. + + Other functions to avoid are: + lcd_blit() (obviously), lcd_update_rect(), lcd_set_contrast(), + lcd_set_invert_display(), lcd_set_flip() */ +void grey_show(bool enable) +{ + if (enable && !(_grey_info.flags & _GREY_RUNNING)) + { + _grey_info.flags |= _GREY_RUNNING; +#ifdef SIMULATOR + _grey_rb->sim_lcd_ex_init(129, _grey_get_pixel); + grey_update(); +#else /* !SIMULATOR */ +#ifdef NEED_BOOST + _grey_rb->cpu_boost(true); +#endif +#if CONFIG_LCD == LCD_SSD1815 + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 67, 1, _timer_isr); +#elif CONFIG_LCD == LCD_S1D15E06 + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 70, 1, _timer_isr); +#elif CONFIG_LCD == LCD_IPOD2BPP +#ifdef IPOD_1G2G + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 95, 1, _timer_isr); /* verified */ +#elif defined IPOD_3G + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 87, 1, _timer_isr); /* verified */ +#else + /* FIXME: verify value */ + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 80, 1, _timer_isr); +#endif +#elif CONFIG_LCD == LCD_IPODMINI + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 88, 1, _timer_isr); +#elif CONFIG_LCD == LCD_IFP7XX + _grey_rb->timer_register(1, NULL, TIMER_FREQ / 83, 1, _timer_isr); +#endif /* CONFIG_LCD */ +#endif /* !SIMULATOR */ + _grey_rb->screen_dump_set_hook(grey_screendump_hook); + } + else if (!enable && (_grey_info.flags & _GREY_RUNNING)) + { +#ifdef SIMULATOR + _grey_rb->sim_lcd_ex_init(0, NULL); +#else + _grey_rb->timer_unregister(); +#ifdef NEED_BOOST + _grey_rb->cpu_boost(false); +#endif +#endif + _grey_info.flags &= ~_GREY_RUNNING; + _grey_rb->screen_dump_set_hook(NULL); + _grey_rb->lcd_update(); /* restore whatever there was before */ + } +} + +#ifdef SIMULATOR +/* Callback function for grey_update_rect() to read a pixel from the greybuffer. + Note that x and y are in LCD coordinates, not greybuffer coordinates! */ +static unsigned long _grey_get_pixel(int x, int y) +{ + return _grey_info.buffer[(y - _grey_info.y) * _grey_info.width + + x - _grey_info.x] + (1 << LCD_DEPTH); +} + +/* Update a rectangular area of the greyscale overlay */ +void grey_update_rect(int x, int y, int width, int height) +{ + if (x + width > _grey_info.width) + width = _grey_info.width - x; + if (y + height > _grey_info.height) + height = _grey_info.height - y; + + x += _grey_info.x; + y += _grey_info.y; + + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; + + _grey_rb->sim_lcd_ex_update_rect(x, y, width, height); +} + +#else /* !SIMULATOR */ + +void grey_update_rect(int x, int y, int width, int height) +{ + unsigned char *src; + + if ((width <= 0) || (height <= 0)) + return; /* nothing to do */ + + if (y + height > _grey_info.height) + height = _grey_info.height - y; + if (x + width > _grey_info.width) + width = _grey_info.width - x; + + src = _grey_info.buffer + _GREY_MULUQ(_grey_info.width, y) + x; + + do + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + int idx = _GREY_MULUQ(_grey_info.width, y) + x; +#else +#if LCD_DEPTH == 1 + int idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (x << 3) + (~y & 7); +#elif LCD_DEPTH == 2 + int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + unsigned char *dst_row = &_grey_info.data[idx].value; + unsigned char *src_row = src; + unsigned char *src_end = src + width; + + do + { + *dst_row = *src_row++; + dst_row += _GREY_X_ADVANCE; + } + while (src_row < src_end); + + y++; + src += _grey_info.width; + } + while (--height > 0); +} + +#endif /* !SIMULATOR */ + +/* Update the whole greyscale overlay */ +void grey_update(void) +{ + grey_update_rect(0, 0, _grey_info.width, _grey_info.height); +} + +/* Do an lcd_update() to show changes done by rb->lcd_xxx() functions + (in areas of the screen not covered by the greyscale overlay). */ +void grey_deferred_lcd_update(void) +{ + if (_grey_info.flags & _GREY_RUNNING) + { +#ifdef SIMULATOR + _deferred_update(); +#else + _grey_info.flags |= _GREY_DEFERRED_UPDATE; +#endif + } + else + _grey_rb->lcd_update(); +} + +/*** Screenshot ***/ + +#define BMP_FIXEDCOLORS (1 << LCD_DEPTH) +#define BMP_VARCOLORS 129 +#define BMP_NUMCOLORS (BMP_FIXEDCOLORS + BMP_VARCOLORS) +#define BMP_BPP 8 +#define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3) +#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS) +#define BMP_DATASIZE (BMP_LINESIZE * LCD_HEIGHT) +#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE) + +#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff +#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff + +static const unsigned char bmpheader[] = +{ + 0x42, 0x4d, /* 'BM' */ + LE32_CONST(BMP_TOTALSIZE), /* Total file size */ + 0x00, 0x00, 0x00, 0x00, /* Reserved */ + LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */ + + 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */ + LE32_CONST(LCD_WIDTH), /* Width in pixels */ + LE32_CONST(LCD_HEIGHT), /* Height in pixels */ + 0x01, 0x00, /* Number of planes (always 1) */ + LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */ + 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */ + LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */ + 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */ + 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */ + LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */ + LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */ + + /* Fixed colours */ +#if LCD_DEPTH == 1 + 0x90, 0xee, 0x90, 0x00, /* Colour #0 */ + 0x00, 0x00, 0x00, 0x00 /* Colour #1 */ +#elif LCD_DEPTH == 2 + 0xe6, 0xd8, 0xad, 0x00, /* Colour #0 */ + 0x99, 0x90, 0x73, 0x00, /* Colour #1 */ + 0x4c, 0x48, 0x39, 0x00, /* Colour #2 */ + 0x00, 0x00, 0x00, 0x00 /* Colour #3 */ +#endif +}; + +#if LCD_DEPTH == 1 +#define BMP_RED 0x90 +#define BMP_GREEN 0xee +#define BMP_BLUE 0x90 +#elif LCD_DEPTH == 2 +#define BMP_RED 0xad +#define BMP_GREEN 0xd8 +#define BMP_BLUE 0xe6 +#endif + +/* Hook function for core screen_dump() to save the current display + content (b&w and greyscale overlay) to an 8-bit BMP file. */ +static void grey_screendump_hook(int fd) +{ + int i; + int x, y, gx, gy; +#if LCD_PIXELFORMAT == VERTICAL_PACKING +#if LCD_DEPTH == 1 + unsigned mask; +#elif LCD_DEPTH == 2 + int shift; +#endif +#endif /* LCD_PIXELFORMAT == VERTICAL_PACKING */ + unsigned char *lcdptr; + unsigned char *clut_entry; + unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)]; + + _grey_rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */ + + /* build clut */ + _grey_rb->memset(linebuf, 0, 4*BMP_VARCOLORS); + clut_entry = linebuf; + + for (i = 0; i <= 128; i++) + { + *clut_entry++ = _GREY_MULUQ(BMP_BLUE, i) >> 7; + *clut_entry++ = _GREY_MULUQ(BMP_GREEN, i) >> 7; + *clut_entry++ = _GREY_MULUQ(BMP_RED, i) >> 7; + clut_entry++; + } + _grey_rb->write(fd, linebuf, 4*BMP_VARCOLORS); + + /* BMP image goes bottom -> top */ + for (y = LCD_HEIGHT - 1; y >= 0; y--) + { + _grey_rb->memset(linebuf, 0, BMP_LINESIZE); + + gy = y - _grey_info.y; +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING +#if LCD_DEPTH == 2 + lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y); + + for (x = 0; x < LCD_WIDTH; x += 4) + { + gx = x - _grey_info.x; + + if (((unsigned)gy < (unsigned)_grey_info.height) + && ((unsigned)gx < (unsigned)_grey_info.width)) + { +#ifdef SIMULATOR + unsigned char *src = _grey_info.buffer + + _GREY_MULUQ(_grey_info.width, gy) + gx; + + for (i = 0; i < 4; i++) + linebuf[x + i] = BMP_FIXEDCOLORS + *src++; +#else + unsigned char *src = &_grey_info.data[_GREY_MULUQ(_grey_info.width, + gy) + gx].value; + for (i = 0; i < 4; i++) + { + linebuf[x + i] = BMP_FIXEDCOLORS + *src; + src += _GREY_X_ADVANCE; + } +#endif + } + else + { + unsigned data = *lcdptr; + linebuf[x] = (data >> 6) & 3; + linebuf[x + 1] = (data >> 4) & 3; + linebuf[x + 2] = (data >> 2) & 3; + linebuf[x + 3] = data & 3; + } + lcdptr++; + } +#endif /* LCD_DEPTH */ +#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ +#if LCD_DEPTH == 1 + mask = 1 << (y & 7); + lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3); + + for (x = 0; x < LCD_WIDTH; x++) + { + gx = x - _grey_info.x; + + if (((unsigned)gy < (unsigned)_grey_info.height) + && ((unsigned)gx < (unsigned)_grey_info.width)) + { +#ifdef SIMULATOR + linebuf[x] = BMP_FIXEDCOLORS + + _grey_info.buffer[_GREY_MULUQ(_grey_info.width, + gy) + gx]; +#else + linebuf[x] = BMP_FIXEDCOLORS + + _grey_info.data[_GREY_MULUQ(_grey_info.width, + gy & ~7) + (gx << 3) + (~gy & 7)].value; +#endif + } + else + { + linebuf[x] = (*lcdptr & mask) ? 1 : 0; + } + lcdptr++; + } +#elif LCD_DEPTH == 2 + shift = 2 * (y & 3); + lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2); + + for (x = 0; x < LCD_WIDTH; x++) + { + gx = x - _grey_info.x; + + if (((unsigned)gy < (unsigned)_grey_info.height) + && ((unsigned)gx < (unsigned)_grey_info.width)) + { +#ifdef SIMULATOR + linebuf[x] = BMP_FIXEDCOLORS + + _grey_info.buffer[_GREY_MULUQ(_grey_info.width, + gy) + gx]; +#else + linebuf[x] = BMP_FIXEDCOLORS + + _grey_info.data[_GREY_MULUQ(_grey_info.width, + gy & ~3) + (gx << 2) + (~gy & 7)].value; +#endif + } + else + { + linebuf[x] = (*lcdptr >> shift) & 3; + } + lcdptr++; + } +#endif /* LCD_DEPTH */ +#endif /* LCD_PIXELFORMAT */ + + _grey_rb->write(fd, linebuf, BMP_LINESIZE); + } +} diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c new file mode 100644 index 0000000000..e243b5fbce --- /dev/null +++ b/apps/plugins/lib/grey_draw.c @@ -0,0 +1,681 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* New greyscale framework +* Drawing functions +* +* This is a generic framework to display 129 shades of grey on low-depth +* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. +* +* Copyright (C) 2008 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" +#include "grey.h" + +/*** low-level drawing functions ***/ + +static void setpixel(unsigned char *address) +{ + *address = _grey_info.fg_val; +} + +static void clearpixel(unsigned char *address) +{ + *address = _grey_info.bg_val; +} + +static void flippixel(unsigned char *address) +{ + *address = 128 - *address; +} + +static void nopixel(unsigned char *address) +{ + (void)address; +} + +void (* const _grey_pixelfuncs[8])(unsigned char *address) = { + flippixel, nopixel, setpixel, setpixel, + nopixel, clearpixel, nopixel, clearpixel +}; + +/*** Drawing functions ***/ + +/* Clear the whole display */ +void grey_clear_display(void) +{ + int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + _grey_rb->memset(_grey_info.buffer, value, + _GREY_MULUQ(_grey_info.width, _grey_info.height)); +} + +/* Set a single pixel */ +void grey_drawpixel(int x, int y) +{ + if (((unsigned)x < (unsigned)_grey_info.width) + && ((unsigned)y < (unsigned)_grey_info.height)) + _grey_pixelfuncs[_grey_info.drawmode](&_grey_info.buffer[_GREY_MULUQ( + _grey_info.width, y) + x]); +} + +/* Draw a line */ +void grey_drawline(int x1, int y1, int x2, int y2) +{ + int numpixels; + int i; + int deltax, deltay; + int d, dinc1, dinc2; + int x, xinc1, xinc2; + int y, yinc1, yinc2; + void (*pfunc)(unsigned char *address) = _grey_pixelfuncs[_grey_info.drawmode]; + + deltax = abs(x2 - x1); + deltay = abs(y2 - y1); + xinc2 = 1; + yinc2 = 1; + + if (deltax >= deltay) + { + numpixels = deltax; + d = 2 * deltay - deltax; + dinc1 = deltay * 2; + dinc2 = (deltay - deltax) * 2; + xinc1 = 1; + yinc1 = 0; + } + else + { + numpixels = deltay; + d = 2 * deltax - deltay; + dinc1 = deltax * 2; + dinc2 = (deltax - deltay) * 2; + xinc1 = 0; + yinc1 = 1; + } + numpixels++; /* include endpoints */ + + if (x1 > x2) + { + xinc1 = -xinc1; + xinc2 = -xinc2; + } + + if (y1 > y2) + { + yinc1 = -yinc1; + yinc2 = -yinc2; + } + + x = x1; + y = y1; + + for (i = 0; i < numpixels; i++) + { + if (((unsigned)x < (unsigned)_grey_info.width) + && ((unsigned)y < (unsigned)_grey_info.height)) + pfunc(&_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]); + + if (d < 0) + { + d += dinc1; + x += xinc1; + y += yinc1; + } + else + { + d += dinc2; + x += xinc2; + y += yinc2; + } + } +} + +/* Draw a horizontal line (optimised) */ +void grey_hline(int x1, int x2, int y) +{ + int x; + int value = 0; + unsigned char *dst; + bool fillopt = false; + void (*pfunc)(unsigned char *address); + + /* direction flip */ + if (x2 < x1) + { + x = x1; + x1 = x2; + x2 = x; + } + + /* nothing to draw? */ + if (((unsigned)y >= (unsigned)_grey_info.height) + || (x1 >= _grey_info.width) || (x2 < 0)) + return; + + /* clipping */ + if (x1 < 0) + x1 = 0; + if (x2 >= _grey_info.width) + x2 = _grey_info.width - 1; + + if (_grey_info.drawmode & DRMODE_INVERSEVID) + { + if (_grey_info.drawmode & DRMODE_BG) + { + fillopt = true; + value = _grey_info.bg_val; + } + } + else + { + if (_grey_info.drawmode & DRMODE_FG) + { + fillopt = true; + value = _grey_info.fg_val; + } + } + pfunc = _grey_pixelfuncs[_grey_info.drawmode]; + dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x1]; + + if (fillopt) + _grey_rb->memset(dst, value, x2 - x1 + 1); + else + { + unsigned char *dst_end = dst + x2 - x1; + do + pfunc(dst++); + while (dst <= dst_end); + } +} + +/* Draw a vertical line (optimised) */ +void grey_vline(int x, int y1, int y2) +{ + int y; + unsigned char *dst, *dst_end; + void (*pfunc)(unsigned char *address); + + /* direction flip */ + if (y2 < y1) + { + y = y1; + y1 = y2; + y2 = y; + } + + /* nothing to draw? */ + if (((unsigned)x >= (unsigned)_grey_info.width) + || (y1 >= _grey_info.height) || (y2 < 0)) + return; + + /* clipping */ + if (y1 < 0) + y1 = 0; + if (y2 >= _grey_info.height) + y2 = _grey_info.height - 1; + + pfunc = _grey_pixelfuncs[_grey_info.drawmode]; + dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y1) + x]; + + dst_end = dst + _GREY_MULUQ(_grey_info.width, y2 - y1); + do + { + pfunc(dst); + dst += _grey_info.width; + } + while (dst <= dst_end); +} + +/* Draw a filled triangle */ +void grey_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++) + { + grey_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++) + { + grey_hline(fp_x1 >> 16, fp_x2 >> 16, y); + fp_x1 += fp_dx1; + fp_x2 += fp_dx2; + } + } + } +} + +/* Draw a rectangular box */ +void grey_drawrect(int x, int y, int width, int height) +{ + if ((width <= 0) || (height <= 0)) + return; + + int x2 = x + width - 1; + int y2 = y + height - 1; + + grey_vline(x, y, y2); + grey_vline(x2, y, y2); + grey_hline(x, x2, y); + grey_hline(x, x2, y2); +} + +/* Fill a rectangular area */ +void grey_fillrect(int x, int y, int width, int height) +{ + int value = 0; + unsigned char *dst, *dst_end; + bool fillopt = false; + void (*pfunc)(unsigned char *address); + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) + || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) + return; + + /* clipping */ + if (x < 0) + { + width += x; + x = 0; + } + if (y < 0) + { + height += y; + y = 0; + } + if (x + width > _grey_info.width) + width = _grey_info.width - x; + if (y + height > _grey_info.height) + height = _grey_info.height - y; + + if (_grey_info.drawmode & DRMODE_INVERSEVID) + { + if (_grey_info.drawmode & DRMODE_BG) + { + fillopt = true; + value = _grey_info.bg_val; + } + } + else + { + if (_grey_info.drawmode & DRMODE_FG) + { + fillopt = true; + value = _grey_info.fg_val; + } + } + pfunc = _grey_pixelfuncs[_grey_info.drawmode]; + dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; + dst_end = dst + _GREY_MULUQ(_grey_info.width, height); + + do + { + if (fillopt) + _grey_rb->memset(dst, value, width); + else + { + unsigned char *dst_row = dst; + unsigned char *row_end = dst_row + width; + + do + pfunc(dst_row++); + while (dst_row < row_end); + } + dst += _grey_info.width; + } + while (dst < dst_end); +} + +/* About Rockbox' internal monochrome bitmap format: + * + * A bitmap contains one bit for every pixel that defines if that pixel is + * foreground (1) or background (0). Bits within a byte are arranged + * vertically, LSB at top. + * The bytes are stored in row-major order, with byte 0 being top left, + * byte 1 2nd from left etc. The first row of bytes defines pixel rows + * 0..7, the second row defines pixel row 8..15 etc. */ + +/* Draw a partial monochrome bitmap */ +void grey_mono_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; + unsigned char *dst, *dst_end; + void (*fgfunc)(unsigned char *address); + void (*bgfunc)(unsigned char *address); + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) + || (y >= _grey_info.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 > _grey_info.width) + width = _grey_info.width - x; + if (y + height > _grey_info.height) + height = _grey_info.height - y; + + src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */ + src_y &= 7; + src_end = src + width; + + fgfunc = _grey_pixelfuncs[_grey_info.drawmode]; + bgfunc = _grey_pixelfuncs[_grey_info.drawmode ^ DRMODE_INVERSEVID]; + dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; + + do + { + const unsigned char *src_col = src++; + unsigned char *dst_col = dst++; + unsigned data = *src_col >> src_y; + int numbits = 8 - src_y; + + dst_end = dst_col + _GREY_MULUQ(_grey_info.width, height); + do + { + if (data & 0x01) + fgfunc(dst_col); + else + bgfunc(dst_col); + + dst_col += _grey_info.width; + + data >>= 1; + if (--numbits == 0) + { + src_col += stride; + data = *src_col; + numbits = 8; + } + } + while (dst_col < dst_end); + } + while (src < src_end); +} + +/* Draw a full monochrome bitmap */ +void grey_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) +{ + grey_mono_bitmap_part(src, 0, 0, width, x, y, width, height); +} + +/* Draw a partial greyscale bitmap, canonical format */ +void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + unsigned char *dst, *dst_end; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) + || (y >= _grey_info.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 > _grey_info.width) + width = _grey_info.width - x; + if (y + height > _grey_info.height) + height = _grey_info.height - y; + + src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ + dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; + dst_end = dst + _GREY_MULUQ(_grey_info.width, height); + + do + { + const unsigned char *src_row = src; + unsigned char *dst_row = dst; + unsigned char *row_end = dst_row + width; + + do + *dst_row++ = _grey_info.gvalue[*src_row++]; + while (dst_row < row_end); + + src += stride; + dst += _grey_info.width; + } + while (dst < dst_end); +} + +/* Draw a full greyscale bitmap, canonical format */ +void grey_gray_bitmap(const unsigned char *src, int x, int y, int width, + int height) +{ + grey_gray_bitmap_part(src, 0, 0, width, x, y, width, height); +} + +/* Put a string at a given pixel position, skipping first ofs pixel columns */ +void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str) +{ + int ch; + struct font* pf = _grey_rb->font_get(_grey_info.curfont); + + while ((ch = *str++) != '\0' && x < _grey_info.width) + { + int width; + const unsigned char *bits; + + /* check input range */ + if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) + ch = pf->defaultchar; + ch -= pf->firstchar; + + /* get proportional width and glyph bits */ + width = pf->width ? pf->width[ch] : pf->maxwidth; + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = pf->bits + (pf->offset ? + pf->offset[ch] : (((pf->height + 7) >> 3) * pf->maxwidth * ch)); + + grey_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); + + x += width - ofs; + ofs = 0; + } +} + +/* Put a string at a given pixel position */ +void grey_putsxy(int x, int y, const unsigned char *str) +{ + grey_putsxyofs(x, y, 0, str); +} + +/*** Unbuffered drawing functions ***/ + +#ifdef SIMULATOR + +/* Clear the whole display */ +void grey_ub_clear_display(void) +{ + grey_clear_display(); + grey_update(); +} + +/* Draw a partial greyscale bitmap, canonical format */ +void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + grey_gray_bitmap_part(src, src_x, src_y, stride, x, y, width, height); + grey_update_rect(x, y, width, height); +} + +#else /* !SIMULATOR */ + +/* Clear the greyscale display (sets all pixels to white) */ +void grey_ub_clear_display(void) +{ + int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + unsigned char *dst = &_grey_info.data[0].value; + unsigned char *dst_end = dst + sizeof(struct grey_data) + * _GREY_MULUQ(_grey_info.width, _grey_info.height); + + do + { + *dst = value; + dst += sizeof(struct grey_data); + } + while (dst < dst_end); +} + +/* Draw a partial greyscale bitmap, canonical format */ +void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) + || (y >= _grey_info.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 > _grey_info.width) + width = _grey_info.width - x; + if (y + height > _grey_info.height) + height = _grey_info.height - y; + + src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ + + do + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + int idx = _GREY_MULUQ(_grey_info.width, y) + x; +#else +#if LCD_DEPTH == 1 + int idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (x << 3) + (~y & 7); +#elif LCD_DEPTH == 2 + int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + unsigned char *dst_row = &_grey_info.data[idx].value; + const unsigned char *src_row = src; + const unsigned char *src_end = src + width; + + do + { + *dst_row = _grey_info.gvalue[*src_row++]; + dst_row += _GREY_X_ADVANCE; + } + while (src_row < src_end); + + y++; + src += stride; + } + while (--height > 0); +} + +#endif /* !SIMULATOR */ + +/* Draw a full greyscale bitmap, canonical format */ +void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width, + int height) +{ + grey_ub_gray_bitmap_part(src, 0, 0, width, x, y, width, height); +} diff --git a/apps/plugins/lib/grey_parm.c b/apps/plugins/lib/grey_parm.c new file mode 100644 index 0000000000..6d605059f8 --- /dev/null +++ b/apps/plugins/lib/grey_parm.c @@ -0,0 +1,116 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* New greyscale framework +* Parameter handling +* +* This is a generic framework to display 129 shades of grey on low-depth +* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. +* +* Copyright (C) 2008 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" +#include "grey.h" + +/* Set position of the top left corner of the greyscale overlay + Note that depending on the target LCD, either x or y gets rounded + to the nearest multiple of 4 or 8 */ +void grey_set_position(int x, int y) +{ +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + _grey_info.bx = (x + 4) >> 3; + x = 8 * _grey_info.bx; +#else +#if LCD_DEPTH == 1 + _grey_info.by = (y + 4) >> 3; + y = 8 * _grey_info.by; +#elif LCD_DEPTH == 2 + _grey_info.by = (y + 2) >> 2; + y = 4 * _grey_info.by; +#endif +#endif /* LCD_PIXELFORMAT */ + _grey_info.x = x; + _grey_info.y = y; + + if (_grey_info.flags & _GREY_RUNNING) + { +#ifdef SIMULATOR + grey_deferred_lcd_update(); + grey_update(); +#else + _grey_info.flags |= _GREY_DEFERRED_UPDATE; +#endif + } +} + +/* Set the draw mode for subsequent drawing operations */ +void grey_set_drawmode(int mode) +{ + _grey_info.drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); +} + +/* Return the current draw mode */ +int grey_get_drawmode(void) +{ + return _grey_info.drawmode; +} + +/* Set the foreground shade for subsequent drawing operations */ +void grey_set_foreground(unsigned brightness) +{ + _grey_info.fg_val = _grey_info.gvalue[brightness]; + _grey_info.fg_brightness = brightness; +} + +/* Return the current foreground shade */ +unsigned grey_get_foreground(void) +{ + return _grey_info.fg_brightness; +} + +/* Set the background shade for subsequent drawing operations */ +void grey_set_background(unsigned brightness) +{ + _grey_info.bg_val = _grey_info.gvalue[brightness]; + _grey_info.bg_brightness = brightness; +} + +/* Return the current background shade */ +unsigned grey_get_background(void) +{ + return _grey_info.bg_brightness; +} + +/* Set draw mode, foreground and background shades at once */ +void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) +{ + grey_set_drawmode(mode); + grey_set_foreground(fg_brightness); + grey_set_background(bg_brightness); +} + +/* Set font for the text output routines */ +void grey_setfont(int newfont) +{ + _grey_info.curfont = newfont; +} + +/* Get width and height of a text when printed with the current font */ +int grey_getstringsize(const unsigned char *str, int *w, int *h) +{ + return _grey_rb->font_getstringsize(str, w, h, _grey_info.curfont); +} diff --git a/apps/plugins/lib/grey_scroll.c b/apps/plugins/lib/grey_scroll.c new file mode 100644 index 0000000000..80496e7706 --- /dev/null +++ b/apps/plugins/lib/grey_scroll.c @@ -0,0 +1,358 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* New greyscale framework +* Scrolling routines +* +* This is a generic framework to display 129 shades of grey on low-depth +* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. +* +* Copyright (C) 2008 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" +#include "grey.h" + +/*** Scrolling ***/ + +/* Scroll left */ +void grey_scroll_left(int count) +{ + unsigned char *data, *data_end; + int length, blank; + + if ((unsigned)count >= (unsigned)_grey_info.width) + return; + + data = _grey_info.buffer; + data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); + length = _grey_info.width - count; + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + do + { + _grey_rb->memmove(data, data + count, length); + _grey_rb->memset(data + length, blank, count); + data += _grey_info.width; + } + while (data < data_end); +} + +/* Scroll right */ +void grey_scroll_right(int count) +{ + unsigned char *data, *data_end; + int length, blank; + + if ((unsigned)count >= (unsigned)_grey_info.width) + return; + + data = _grey_info.buffer; + data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); + length = _grey_info.width - count; + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + do + { + _grey_rb->memmove(data + count, data, length); + _grey_rb->memset(data, blank, count); + data += _grey_info.width; + } + while (data < data_end); +} + +/* Scroll up */ +void grey_scroll_up(int count) +{ + long shift, length; + int blank; + + if ((unsigned)count >= (unsigned)_grey_info.height) + return; + + shift = _GREY_MULUQ(_grey_info.width, count); + length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + _grey_rb->memmove(_grey_info.buffer, _grey_info.buffer + shift, length); + _grey_rb->memset(_grey_info.buffer + length, blank, shift); +} + +/* Scroll down */ +void grey_scroll_down(int count) +{ + long shift, length; + int blank; + + if ((unsigned)count >= (unsigned)_grey_info.height) + return; + + shift = _GREY_MULUQ(_grey_info.width, count); + length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + _grey_rb->memmove(_grey_info.buffer + shift, _grey_info.buffer, length); + _grey_rb->memset(_grey_info.buffer, blank, shift); +} + +/*** Unbuffered scrolling functions ***/ + +#ifdef SIMULATOR + +/* Scroll left */ +void grey_ub_scroll_left(int count) +{ + grey_scroll_left(count); + grey_update(); +} + +/* Scroll right */ +void grey_ub_scroll_right(int count) +{ + grey_scroll_right(count); + grey_update(); +} + +/* Scroll up */ +void grey_ub_scroll_up(int count) +{ + grey_scroll_up(count); + grey_update(); +} + +/* Scroll down */ +void grey_ub_scroll_down(int count) +{ + grey_scroll_down(count); + grey_update(); +} + +#else /* !SIMULATOR */ + +/* Scroll left */ +void grey_ub_scroll_left(int count) +{ + unsigned char *dst, *src, *end; + int blank, y, idx; + + if ((count == 0) || ((unsigned)count >= (unsigned)_grey_info.width)) + return; + + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + for (y = 0; y < _grey_info.height; y++) + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + idx = _GREY_MULUQ(_grey_info.width, y); +#else +#if LCD_DEPTH == 1 + idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (~y & 7); +#elif LCD_DEPTH == 2 + idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + dst = &_grey_info.data[idx].value; + src = dst + count * _GREY_X_ADVANCE; + end = dst + _grey_info.width * _GREY_X_ADVANCE; + + do + { + *dst = *src; + dst += _GREY_X_ADVANCE; + src += _GREY_X_ADVANCE; + } + while (src < end); + + do + { + *dst = blank; + dst += _GREY_X_ADVANCE; + } + while (dst < end); + } +} + +/* Scroll right */ +void grey_ub_scroll_right(int count) +{ + unsigned char *dst, *src, *start; + int blank, y, idx; + + if ((count == 0) || ((unsigned)count >= (unsigned)_grey_info.width)) + return; + + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + for (y = 0; y < _grey_info.height; y++) + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + idx = _GREY_MULUQ(_grey_info.width, y); +#else +#if LCD_DEPTH == 1 + idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (~y & 7); +#elif LCD_DEPTH == 2 + idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + start = &_grey_info.data[idx].value; + dst = start + _grey_info.width * _GREY_X_ADVANCE; + src = dst - count * _GREY_X_ADVANCE; + + do + { + dst -= _GREY_X_ADVANCE; + src -= _GREY_X_ADVANCE; + *dst = *src; + } + while (src > start); + + do + { + dst -= _GREY_X_ADVANCE; + *dst = blank; + } + while (dst > start); + } +} + +void grey_ub_scroll_up(int count) +{ + unsigned char *dst, *dst_end, *src; + int blank, ys, yd, is, id; + + if ((unsigned)count >= (unsigned)_grey_info.height) + return; + + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + for (ys = count, yd = 0; ys < _grey_info.height; ys++, yd++) + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + id = _GREY_MULUQ(_grey_info.width, yd); + is = _GREY_MULUQ(_grey_info.width, ys); +#else +#if LCD_DEPTH == 1 + id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); + is = _GREY_MULUQ(_grey_info.width, ys & ~7) + (~ys & 7); +#elif LCD_DEPTH == 2 + id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); + is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + dst = &_grey_info.data[id].value; + src = &_grey_info.data[is].value; + dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; + + do + { + *dst = *src; + dst += _GREY_X_ADVANCE; + src += _GREY_X_ADVANCE; + } + while (dst < dst_end); + } + for (; yd < _grey_info.height; yd++) + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + id = _GREY_MULUQ(_grey_info.width, yd); +#else +#if LCD_DEPTH == 1 + id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); +#elif LCD_DEPTH == 2 + id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + dst = &_grey_info.data[id].value; + dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; + + do + { + *dst = blank; + dst += _GREY_X_ADVANCE; + } + while (dst < dst_end); + } +} + +void grey_ub_scroll_down(int count) +{ + unsigned char *dst, *dst_end, *src; + int blank, ys, yd, is, id; + + if ((unsigned)count >= (unsigned)_grey_info.height) + return; + + blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? + _grey_info.fg_val : _grey_info.bg_val; + + yd = _grey_info.height - 1; + for (ys = yd - count; ys >= 0; ys--, yd--) + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + id = _GREY_MULUQ(_grey_info.width, yd); + is = _GREY_MULUQ(_grey_info.width, ys); +#else +#if LCD_DEPTH == 1 + id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); + is = _GREY_MULUQ(_grey_info.width, ys & ~7) + (~ys & 7); +#elif LCD_DEPTH == 2 + id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); + is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + dst = &_grey_info.data[id].value; + src = &_grey_info.data[is].value; + dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; + + do + { + *dst = *src; + dst += _GREY_X_ADVANCE; + src += _GREY_X_ADVANCE; + } + while (dst < dst_end); + } + for (; yd >= 0; yd--) + { +#if LCD_PIXELFORMAT == HORIZONTAL_PACKING + id = _GREY_MULUQ(_grey_info.width, yd); +#else +#if LCD_DEPTH == 1 + id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7); +#elif LCD_DEPTH == 2 + id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3); +#endif +#endif /* LCD_PIXELFORMAT */ + dst = &_grey_info.data[id].value; + dst_end = dst + _grey_info.width * _GREY_X_ADVANCE; + + do + { + *dst = blank; + dst += _GREY_X_ADVANCE; + } + while (dst < dst_end); + } +} + +#endif /* !SIMULATOR */ diff --git a/apps/plugins/mandelbrot.c b/apps/plugins/mandelbrot.c index d96f697a19..df1c2030e5 100644 --- a/apps/plugins/mandelbrot.c +++ b/apps/plugins/mandelbrot.c @@ -21,7 +21,7 @@ #include "plugin.h" #ifdef HAVE_LCD_BITMAP -#include "gray.h" +#include "grey.h" #include "xlcd.h" PLUGIN_HEADER @@ -180,9 +180,9 @@ PLUGIN_HEADER #if LCD_DEPTH < 8 #define USEGSLIB -#define MYLCD(fn) gray_ub_ ## fn +#define MYLCD(fn) grey_ub_ ## fn #define MYLCD_UPDATE() -#define MYXLCD(fn) gray_ub_ ## fn +#define MYXLCD(fn) grey_ub_ ## fn #else #define UPDATE_FREQ (HZ/50) #define MYLCD(fn) rb->lcd_ ## fn @@ -486,7 +486,7 @@ void calc_mandelbrot_low_prec(void) } } #ifdef USEGSLIB - gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, + grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, p_x, py_min, 1, py_max - py_min); #else rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1, @@ -549,7 +549,7 @@ void calc_mandelbrot_high_prec(void) } } #ifdef USEGSLIB - gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, + grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, p_x, py_min, 1, py_max - py_min); #else rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1, @@ -569,7 +569,7 @@ void cleanup(void *parameter) { (void)parameter; #ifdef USEGSLIB - gray_release(); + grey_release(); #endif } @@ -582,10 +582,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) int button; int lastbutton = BUTTON_NONE; int redraw = REDRAW_FULL; -#ifdef USEGSLIB - int grayscales; - char buff[32]; -#endif rb = api; (void)parameter; @@ -594,19 +590,13 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) /* get the remainder of the plugin buffer */ gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); - /* initialize the grayscale buffer: - * 8 bitplanes for 9 shades of gray.*/ - grayscales = gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, - 8, 0, NULL) + 1; - if (grayscales != 9) { - rb->snprintf(buff, sizeof(buff), "%d", grayscales); - rb->lcd_puts(0, 1, buff); - rb->lcd_update(); - rb->sleep(HZ*2); - return(0); + /* initialize the greyscale buffer.*/ + if (!grey_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, NULL)) + { + rb->splash(HZ, "Couldn't init greyscale display"); + return 0; } - - gray_show(true); /* switch on grayscale overlay */ + grey_show(true); /* switch on greyscale overlay */ #else xlcd_init(rb); #endif @@ -650,7 +640,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) #endif case MANDELBROT_QUIT: #ifdef USEGSLIB - gray_release(); + grey_release(); #endif return PLUGIN_OK; @@ -755,7 +745,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) lastbutton = button; } #ifdef USEGSLIB - gray_release(); + grey_release(); #endif return PLUGIN_OK; } diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 8ea4ee3abd..48bb73065c 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -868,7 +868,7 @@ static void wvs_refresh(int hint) vo_unlock(); #else - gray_deferred_lcd_update(); + grey_deferred_lcd_update(); #endif } diff --git a/apps/plugins/mpegplayer/mpegplayer.h b/apps/plugins/mpegplayer/mpegplayer.h index ae1234d39d..4ebf321fce 100644 --- a/apps/plugins/mpegplayer/mpegplayer.h +++ b/apps/plugins/mpegplayer/mpegplayer.h @@ -85,12 +85,12 @@ enum mpeg_malloc_reason_t #define GRAY_VIDEO_FLUSH_ICACHE() #define GRAY_VIDEO_INVALIDATE_ICACHE() #else -#include "gray.h" -#define DRAW_BLACK GRAY_BLACK -#define DRAW_DARKGRAY GRAY_DARKGRAY -#define DRAW_LIGHTGRAY GRAY_LIGHTGRAY -#define DRAW_WHITE GRAY_WHITE -#define lcd_(fn) gray_##fn +#include "grey.h" +#define DRAW_BLACK GREY_BLACK +#define DRAW_DARKGRAY GREY_DARKGRAY +#define DRAW_LIGHTGRAY GREY_LIGHTGRAY +#define DRAW_WHITE GREY_WHITE +#define lcd_(fn) grey_##fn #define GRAY_FLUSH_ICACHE() \ IF_COP(flush_icache()) diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c index 8d2e42f62b..c473db3ce3 100644 --- a/apps/plugins/mpegplayer/stream_mgr.c +++ b/apps/plugins/mpegplayer/stream_mgr.c @@ -20,7 +20,7 @@ ****************************************************************************/ #include "plugin.h" #include "mpegplayer.h" -#include "gray.h" +#include "grey.h" #include "mpeg_settings.h" static struct event_queue stream_mgr_queue NOCACHEBSS_ATTR; @@ -712,7 +712,7 @@ bool stream_show_vo(bool show) GRAY_VIDEO_INVALIDATE_ICACHE(); GRAY_INVALIDATE_ICACHE(); - gray_show(show); + grey_show(show); GRAY_FLUSH_ICACHE(); #endif @@ -801,11 +801,10 @@ bool stream_set_gray_rect(const struct vo_rect *rc) vo_lock(); - gray_init(rb, stream_mgr.graymem, stream_mgr.graysize, - false, rc_gray.r - rc_gray.l, rc_gray.b - rc_gray.t, - 32, 2<<8, NULL); + grey_init(rb, stream_mgr.graymem, stream_mgr.graysize, false, + rc_gray.r - rc_gray.l, rc_gray.b - rc_gray.t, NULL); - gray_set_position(rc_gray.l, rc_gray.t); + grey_set_position(rc_gray.l, rc_gray.t); vo_unlock(); @@ -818,7 +817,7 @@ bool stream_set_gray_rect(const struct vo_rect *rc) if (vis) { - gray_show(true); + grey_show(true); parser_send_video_msg(VIDEO_DISPLAY_SHOW, true); } } @@ -836,7 +835,7 @@ void stream_gray_show(bool show) GRAY_VIDEO_INVALIDATE_ICACHE(); GRAY_INVALIDATE_ICACHE(); - gray_show(show); + grey_show(show); GRAY_FLUSH_ICACHE(); @@ -1095,16 +1094,14 @@ int stream_init(void) /* Initialize non-allocator blocks first */ #ifndef HAVE_LCD_COLOR - int grayscales; + bool success; /* This can run on another processor - align data */ memsize = CACHEALIGN_BUFFER(&mem, memsize); stream_mgr.graymem = mem; - /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */ - grayscales = gray_init(rb, mem, memsize, false, - LCD_WIDTH, LCD_HEIGHT, - 32, 2<<8, &stream_mgr.graysize) + 1; + success = grey_init(rb, mem, memsize, false, LCD_WIDTH, + LCD_HEIGHT, &stream_mgr.graysize); /* This can run on another processor - align size */ stream_mgr.graysize = CACHEALIGN_UP(stream_mgr.graysize); @@ -1112,9 +1109,9 @@ int stream_init(void) mem += stream_mgr.graysize; memsize -= stream_mgr.graysize; - if (grayscales < 33 || (ssize_t)memsize <= 0) + if (!success || (ssize_t)memsize <= 0) { - rb->splash(HZ, "graylib init failed!"); + rb->splash(HZ, "greylib init failed!"); stream_mgr.graymem = NULL; return STREAM_ERROR; } @@ -1188,6 +1185,6 @@ void stream_exit(void) #ifndef HAVE_LCD_COLOR if (stream_mgr.graymem != NULL) - gray_release(); + grey_release(); #endif } diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index 39d0e82c3b..12431bef4a 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c @@ -107,7 +107,7 @@ static inline void yuv_blit(uint8_t * const * buf, int src_x, int src_y, #ifdef HAVE_LCD_COLOR rb->lcd_yuv_blit(buf, src_x, src_y, stride, x, y , width, height); #else - gray_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); + grey_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); #endif video_unlock(); diff --git a/apps/plugins/plasma.c b/apps/plugins/plasma.c index 76c54122e0..4f5fc39eb2 100644 --- a/apps/plugins/plasma.c +++ b/apps/plugins/plasma.c @@ -28,7 +28,7 @@ #ifdef HAVE_LCD_BITMAP #ifndef HAVE_LCD_COLOR -#include "gray.h" +#include "grey.h" #endif #include "fixedpoint.h" @@ -45,7 +45,7 @@ static int redphase = 0, greenphase = 50, bluephase = 100; /* lower chance of gray at regular intervals */ #else static unsigned char colours[256]; /* Smooth transition of shades */ -static unsigned char graybuffer[LCD_HEIGHT*LCD_WIDTH]; /* off screen buffer */ +static unsigned char greybuffer[LCD_HEIGHT*LCD_WIDTH]; /* off screen buffer */ static unsigned char *gbuf; static size_t gbuf_size = 0; #endif @@ -171,7 +171,7 @@ void cleanup(void *parameter) (void)parameter; #ifndef HAVE_LCD_COLOR - gray_release(); + grey_release(); #endif /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(rb); /* backlight control in lib/helper.c */ @@ -203,9 +203,9 @@ int main(void) /* get the remainder of the plugin buffer */ gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); - gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, 32, 2<<8, NULL); - /* switch on grayscale overlay */ - gray_show(true); + grey_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, NULL); + /* switch on greyscale overlay */ + grey_show(true); #endif sp1 = 4; sp2 = 2; @@ -218,7 +218,7 @@ int main(void) shades_generate(time++); /* dynamically */ ptr = rb->lcd_framebuffer; #else - ptr = graybuffer; + ptr = greybuffer; #endif t1=p1; t2=p2; @@ -245,7 +245,7 @@ int main(void) #ifdef HAVE_LCD_COLOR rb->lcd_update(); #else - gray_ub_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); + grey_ub_gray_bitmap(greybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); #endif button = rb->button_get(false); diff --git a/apps/plugins/zxbox/interf.c b/apps/plugins/zxbox/interf.c index 7f37262140..10c3dfa363 100644 --- a/apps/plugins/zxbox/interf.c +++ b/apps/plugins/zxbox/interf.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 1996-1998 Szeredi Miklos * Email: mszeredi@inf.bme.hu * @@ -94,7 +94,7 @@ char *spif_get_tape_fileinfo(int *startp, int *nump) void put_msg(const char *msg) { -#ifndef USE_GRAY +#ifndef USE_GREY rb->splash (HZ/2, msg ); #else LOGF(msg); @@ -105,7 +105,7 @@ void put_msg(const char *msg) void put_tmp_msg(const char *msg) { -#ifndef USE_GRAY +#ifndef USE_GREY rb->splash (HZ/10, msg ); #else LOGF(msg); diff --git a/apps/plugins/zxbox/spmain.c b/apps/plugins/zxbox/spmain.c index ca0fa9bc71..51344763f9 100644 --- a/apps/plugins/zxbox/spmain.c +++ b/apps/plugins/zxbox/spmain.c @@ -42,8 +42,8 @@ #include #include #include -#ifdef USE_GRAY -#include "../lib/gray.h" +#ifdef USE_GREY +#include "../lib/grey.h" #endif #include "zxbox_keyb.h" @@ -426,8 +426,8 @@ static bool zxbox_menu(void) else intkeys[i] = (unsigned) settings.keymap[i]; } -#ifdef USE_GRAY - gray_show(true); +#ifdef USE_GREY + grey_show(true); #endif return (exit); } @@ -465,8 +465,8 @@ static void run_singlemode(void) if (zxbox_menu()){ /* Save the user settings if they have changed */ if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) { -#ifdef USE_GRAY - gray_show(false); +#ifdef USE_GREY + grey_show(false); #endif rb->splash(0, "Saving settings..."); configfile_save(GLOBALCFG, config,sizeof(config)/sizeof(*config),SETTINGS_VERSION); @@ -531,7 +531,7 @@ static void init_load(void *parameter) check_params (parameter); if(spcf_init_snapshot != NULL) { -#ifndef USE_GRAY +#ifndef USE_GREY rb->splash(HZ, "Loading snapshot '%s'", spcf_init_snapshot); #endif diff --git a/apps/plugins/zxbox/zxbox.c b/apps/plugins/zxbox/zxbox.c index c7e3d0a5db..ebb689ce9c 100644 --- a/apps/plugins/zxbox/zxbox.c +++ b/apps/plugins/zxbox/zxbox.c @@ -50,7 +50,7 @@ unsigned char image_array [ HEIGHT * WIDTH ]; static int previous_state; -#ifdef USE_GRAY +#ifdef USE_GREY static unsigned char *gbuf; static size_t gbuf_size = 0; #endif @@ -69,17 +69,17 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) sp_init(); -#ifdef USE_GRAY +#ifdef USE_GREY /* get the remainder of the plugin buffer */ gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); -#ifdef USE_BUFFERED_GRAY - gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, 15, 0, NULL); +#ifdef USE_BUFFERED_GREY + grey_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, NULL); #else - gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, 15, 0, NULL); -#endif /* USE_BUFFERED_GRAY */ - /* switch on grayscale overlay */ - gray_show(true); -#endif /* USE_GRAY */ + grey_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, NULL); +#endif /* USE_BUFFERED_GREY */ + /* switch on greyscale overlay */ + grey_show(true); +#endif /* USE_GREY */ #if defined(HAVE_ADJUSTABLE_CPU_FREQ) @@ -102,9 +102,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) rb->cpu_boost(false); #endif -#ifdef USE_GRAY -gray_show(false); -gray_release(); +#ifdef USE_GREY +grey_show(false); +grey_release(); #endif #if CONFIG_CODEC == SWCODEC && !defined SIMULATOR @@ -133,8 +133,8 @@ void spkb_process_events( int evenframe ) rb->cpu_boost(false); #endif exit_requested=1; -#ifdef USE_GRAY - gray_show(false); +#ifdef USE_GREY + grey_show(false); #endif return; } @@ -151,8 +151,8 @@ void spkb_process_events( int evenframe ) rb->cpu_boost(false); #endif exit_requested=1; -#ifdef USE_GRAY - gray_show(false); +#ifdef USE_GREY + grey_show(false); #endif return; } diff --git a/apps/plugins/zxbox/zxconfig.h b/apps/plugins/zxbox/zxconfig.h index ddd91d0020..f83c091ab9 100644 --- a/apps/plugins/zxbox/zxconfig.h +++ b/apps/plugins/zxbox/zxconfig.h @@ -17,11 +17,10 @@ extern int intkeys[5]; #define SETTINGS_MIN_VERSION 2 #define SETTINGS_VERSION 2 -/* undef not to use grayscale lib */ -#if !defined HAVE_LCD_COLOR && LCD_PIXELFORMAT != HORIZONTAL_PACKING -/* grayscale is far slower for now at least on ipods :( */ -#define USE_GRAY -#define USE_BUFFERED_GRAY +/* undef not to use greyscale lib */ +#if !defined HAVE_LCD_COLOR +#define USE_GREY +#define USE_BUFFERED_GREY #endif diff --git a/apps/plugins/zxbox/zxvid_4bpp.c b/apps/plugins/zxbox/zxvid_4bpp.c index 4846340c4d..c05e48b8e6 100644 --- a/apps/plugins/zxbox/zxvid_4bpp.c +++ b/apps/plugins/zxbox/zxvid_4bpp.c @@ -1,6 +1,6 @@ #include "zxvid_com.h" -#if !defined USE_GRAY && LCD_DEPTH < 4 +#if !defined USE_GREY && LCD_DEPTH < 4 /* screen routines for greyscale targets not using greyscale lib */ #if LCD_PIXELFORMAT == HORIZONTAL_PACKING diff --git a/apps/plugins/zxbox/zxvid_com.h b/apps/plugins/zxbox/zxvid_com.h index 730971d6a5..2ef67c6385 100644 --- a/apps/plugins/zxbox/zxvid_com.h +++ b/apps/plugins/zxbox/zxvid_com.h @@ -2,8 +2,8 @@ #define ZXVIDCOMMON_H #include "zxconfig.h" -#ifdef USE_GRAY -#include "../lib/gray.h" +#ifdef USE_GREY +#include "../lib/grey.h" #endif #include "spscr_p.h" diff --git a/apps/plugins/zxbox/zxvid_grey.c b/apps/plugins/zxbox/zxvid_grey.c index 8491e6bf18..de9cd97874 100644 --- a/apps/plugins/zxbox/zxvid_grey.c +++ b/apps/plugins/zxbox/zxvid_grey.c @@ -1,5 +1,5 @@ #include "zxvid_com.h" -#if !defined HAVE_LCD_COLOR && defined USE_GRAY +#if !defined HAVE_LCD_COLOR && defined USE_GREY /* use for slightly different colors #define N0 0x04 @@ -67,8 +67,8 @@ void update_screen(void) srcy &= 0xffff; /* set up the y-coordinate between 0 and 1 */ } -#ifdef USE_BUFFERED_GRAY - gray_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); +#ifdef USE_BUFFERED_GREY + grey_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); #endif if ( settings.showfps ) { @@ -77,8 +77,8 @@ void update_screen(void) if ((*rb->current_tick-start_time) > TPF ) percent = 100*video_frames/((*rb->current_tick-start_time)/TPF); rb->snprintf(str,sizeof(str),"%d %%",percent); -#if defined USE_BUFFERED_GRAY - gray_putsxy(0,0,str); +#if defined USE_BUFFERED_GREY + grey_putsxy(0,0,str); #else LOGF(str); #endif @@ -86,10 +86,10 @@ void update_screen(void) } -#if defined USE_BUFFERED_GRAY - gray_update(); +#if defined USE_BUFFERED_GREY + grey_update(); #else - gray_ub_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); + grey_ub_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); #endif } diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index de03222441..60d9efaf92 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -95,15 +95,24 @@ extern void lcd_puts_scroll(int x, int y, const unsigned char* string); extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, int style); +#ifdef HAVE_LCD_BITMAP + #if defined(HAVE_LCD_COLOR) #define LCD_YUV_DITHER 0x1 extern void lcd_yuv_set_options(unsigned options); extern void lcd_yuv_blit(unsigned char * const src[3], int src_x, int src_y, int stride, int x, int y, int width, int height); +#else +struct grey_data { + unsigned char phase; /* SH1 uses it signed (doesn't matter for high level) */ + unsigned char value; /* 0..128 are allowed */ +} __attribute__((packed)); +extern void lcd_grey_data(const struct grey_data *data, int count); /* private */ +extern void lcd_grey_phase_blit(const struct grey_data *data, int bx, int by, + int bwidth, int bheight, int stride); #endif -#ifdef HAVE_LCD_BITMAP /* performance function */ extern void lcd_blit(const fb_data* data, int x, int by, int width, int bheight, int stride); diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c index 65fa2a779e..c7f4074c0b 100644 --- a/firmware/target/arm/ipod/lcd-gray.c +++ b/firmware/target/arm/ipod/lcd-gray.c @@ -299,6 +299,123 @@ void lcd_blit(const unsigned char* data, int bx, int y, int bwidth, } } +/* Performance function that works with an external buffer + note that bx and bwidth are in 8-pixel units! */ +void lcd_grey_phase_blit(const struct grey_data *data, int bx, int y, + int bwidth, int height, int stride) +{ + const struct grey_data *addr; + int width; + + while (height--) { + lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx); + lcd_prepare_cmd(R_RAM_DATA); + + addr = data; + width = bwidth; + asm volatile ( + "10: \n" + "ldmia %[addr]!, {r0-r3} \n" /* r0 = v1p1v0p0 ... */ +#ifdef IPOD_MINI2G + "mov r5, #0x7600 \n" +#else + "mov r5, #0 \n" +#endif + + "and r4, r0, %[mask] \n" /* r4 = --p1--p0 */ + "and r0, %[mask], r0, lsr #8 \n" /* r0 = --v1--v0 */ + + "tst r4, #0x80 \n" + "orreq r5, r5, #0xc0 \n" + "tst r4, #0x800000 \n" + "orreq r5, r5, #0x30 \n" + "bic r4, r4, %[clbt] \n" + + "add r4, r0, r4 \n" /* p0 += v0; p1 += v1; */ + "strb r4, [%[addr], #-16] \n" + "mov r4, r4, lsr #16 \n" + "strb r4, [%[addr], #-14] \n" + + "and r4, r1, %[mask] \n" + "and r1, %[mask], r1, lsr #8 \n" + + "tst r4, #0x80 \n" + "orreq r5, r5, #0x0c \n" + "tst r4, #0x800000 \n" + "orreq r5, r5, #0x03 \n" + "bic r4, r4, %[clbt] \n" + + "add r4, r1, r4 \n" + "strb r4, [%[addr], #-12] \n" + "mov r4, r4, lsr #16 \n" + "strb r4, [%[addr], #-10] \n" + +#ifdef IPOD_MINI2G + "mov r5, r5, lsl #8 \n" +#else + "1: \n" + "ldr r4, [%[lcdb]] \n" + "tst r4, #0x8000 \n" + "bne 1b \n" + + "str r5, [%[lcdb], #0x10] \n" + "mov r5, #0 \n" +#endif + + "and r4, r2, %[mask] \n" + "and r2, %[mask], r2, lsr #8 \n" + + "tst r4, #0x80 \n" + "orreq r5, r5, #0xc0 \n" + "tst r4, #0x800000 \n" + "orreq r5, r5, #0x30 \n" + "bic r4, r4, %[clbt] \n" + + "add r4, r2, r4 \n" + "strb r4, [%[addr], #-8] \n" + "mov r4, r4, lsr #16 \n" + "strb r4, [%[addr], #-6] \n" + + "and r4, r3, %[mask] \n" + "and r3, %[mask], r3, lsr #8 \n" + + "tst r4, #0x80 \n" + "orreq r5, r5, #0x0c \n" + "tst r4, #0x800000 \n" + "orreq r5, r5, #0x03 \n" + "bic r4, r4, %[clbt] \n" + + "add r4, r3, r4 \n" + "strb r4, [%[addr], #-4] \n" + "mov r4, r4, lsr #16 \n" + "strb r4, [%[addr], #-2] \n" + + "1: \n" + "ldr r4, [%[lcdb]] \n" + "tst r4, #0x8000 \n" + "bne 1b \n" +#ifdef IPOD_MINI2G + "str r5, [%[lcdb], #0x08] \n" +#else + "str r5, [%[lcdb], #0x10] \n" +#endif + + "subs %[wdth], %[wdth], #1 \n" + "bne 10b \n" + : /* outputs */ + [addr]"+r"(addr), + [wdth]"+r"(width) + : /* inputs */ + [mask]"r"(0x00ff00ff), + [clbt]"r"(0x00800080), + [lcdb]"r"(LCD1_BASE) + : /* clobbers */ + "r0", "r1", "r2", "r3", "r4", "r5" + ); + data += stride; + } +} + void lcd_update_rect(int x, int y, int width, int height) { int xmax, ymax; diff --git a/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S b/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S index 4a88dc92b0..7e89815ec8 100644 --- a/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S +++ b/firmware/target/coldfire/iaudio/m5/lcd-as-m5.S @@ -41,18 +41,18 @@ lcd_write_command: lcd_write_command_ex: lea.l 0xf0008000, %a0 - move.l (4, %sp), %d0 /* Command */ - move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */ + move.l (4, %sp), %d0 /* Command */ + move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */ - move.l (8, %sp), %d0 /* Data */ - cmp.l #-1, %d0 /* -1? */ + move.l (8, %sp), %d0 /* Data */ + cmp.l #-1, %d0 /* -1? */ beq.b .last - move.w %d0, (%a0) /* Write to LCD */ + move.w %d0, (%a0) /* Write to LCD */ - move.l (12, %sp), %d0 /* Data */ - cmp.l #-1, %d0 /* -1? */ + move.l (12, %sp), %d0 /* Data */ + cmp.l #-1, %d0 /* -1? */ beq.b .last - move.w %d0, (%a0) /* Write to LCD */ + move.w %d0, (%a0) /* Write to LCD */ .last: rts @@ -65,19 +65,80 @@ lcd_write_command_ex: .type lcd_write_data,@function lcd_write_data: - move.l (4,%sp), %a0 /* Data pointer */ - move.l (8,%sp), %d0 /* Length */ - + movem.l (4, %sp), %a0-%a1 /* Data pointer */ + move.l %a1, %d0 /* Length */ lea 0xf0008002, %a1 + .loop: /* When running in IRAM, this loop takes 10 cycles plus the LCD write. The 10 cycles are necessary to follow the LCD timing specs at 140MHz */ - nop /* 3(0/0) */ - move.b (%a0)+, %d1 /* 3(1/0) */ - move.w %d1, (%a1) /* 1(0/1) */ - subq.l #1, %d0 /* 1(0/0) */ - bne .loop /* 2(0/0) */ + nop /* 3(0/0) */ + move.b (%a0)+, %d1 /* 3(1/0) */ + move.w %d1, (%a1) /* 1(0/1) */ + subq.l #1, %d0 /* 1(0/0) */ + bne .loop /* 2(0/0) */ rts .wd_end: .size lcd_write_data,.wd_end-lcd_write_data + + + .align 2 + .global lcd_grey_data + .type lcd_grey_data,@function + +lcd_grey_data: + lea.l (-4*4, %sp), %sp + movem.l %d2-%d5, (%sp) + movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */ + move.l %a1, %d0 /* Length */ + lea 0xf0008002, %a1 /* LCD data port */ + move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */ + +.greyloop: + movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */ + /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */ + move.l %d2, %d3 /* copy mask */ + and.l %d4, %d3 /* %d3 = p0--p1-- */ + eor.l %d3, %d4 /* %d4 = --v0--v1 */ + lsr.l #8, %d3 /* %d3 = --p0--p1 */ + + bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */ + seq.b %d1 /* %d1 = ........................00000000 */ + lsl.l #2, %d1 /* %d1 = ......................00000000.. */ + bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */ + seq.b %d1 /* %d1 = ......................0011111111 */ + lsl.l #2, %d1 /* %d1 = ....................0011111111.. */ + + add.l %d4, %d3 /* p0 += v0; p1 += v1; */ + move.b %d3, (2, %a0) /* store p1 */ + swap %d3 + move.b %d3, (%a0) /* store p0 */ + + move.l %d2, %d3 /* copy mask */ + and.l %d5, %d3 /* %d3 = p2--p3-- */ + eor.l %d3, %d5 /* %d5 = --v2--v3 */ + lsr.l #8, %d3 /* %d3 = --p2--p3 */ + + bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */ + seq.b %d1 /* %d1 = ....................001122222222 */ + lsl.l #2, %d1 /* %d1 = ..................001122222222.. */ + bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */ + seq.b %d1 /* %d1 = ..................00112233333333 */ + lsr.l #6, %d1 /* %d1 = ........................00112233 */ + + add.l %d5, %d3 /* p2 += v2; p3 += v3; */ + move.b %d3, (6, %a0) /* store p3 */ + swap %d3 + move.b %d3, (4, %a0) /* store p2 */ + + move.w %d1, (%a1) /* write pixel block */ + addq.l #8, %a0 /* advance address pointer */ + subq.l #1, %d0 /* any blocks left? */ + bne.b .greyloop + + movem.l (%sp), %d2-%d5 + lea.l (4*4, %sp), %sp + rts +.gd_end: + .size lcd_grey_data,.gd_end-lcd_grey_data diff --git a/firmware/target/coldfire/iaudio/m5/lcd-m5.c b/firmware/target/coldfire/iaudio/m5/lcd-m5.c index 2af46b3145..4f963795c7 100644 --- a/firmware/target/coldfire/iaudio/m5/lcd-m5.c +++ b/firmware/target/coldfire/iaudio/m5/lcd-m5.c @@ -171,6 +171,21 @@ void lcd_blit(const unsigned char* data, int x, int by, int width, } } +/* Performance function that works with an external buffer + note that by and bheight are in 4-pixel units! */ +void lcd_grey_phase_blit(const struct grey_data *data, int x, int by, + int width, int bheight, int stride) +{ + stride <<= 2; /* 4 pixels per block */ + while (bheight--) + { + lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); + lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); + lcd_write_command(LCD_CNTL_DATA_WRITE); + lcd_grey_data(data, width); + data += stride; + } +} /* Update the display. This must be called after all other LCD functions that change the display. */ diff --git a/firmware/target/coldfire/iriver/h100/lcd-as-h100.S b/firmware/target/coldfire/iriver/h100/lcd-as-h100.S index c7509871fc..df410fa379 100644 --- a/firmware/target/coldfire/iriver/h100/lcd-as-h100.S +++ b/firmware/target/coldfire/iriver/h100/lcd-as-h100.S @@ -28,11 +28,10 @@ .type lcd_write_command,@function lcd_write_command: - move.l (4,%sp),%d0 - lea MBAR2,%a1 - move.l #~8,%d1 - and.l %d1,(0xb4,%a1) - move.w %d0,0xf0000000 + move.l #~8, %d1 + and.l %d1, (MBAR2+0xb4) + move.l (4, %sp), %d0 + move.w %d0, 0xf0000000 rts .wc_end: .size lcd_write_command,.wc_end-lcd_write_command @@ -43,26 +42,27 @@ lcd_write_command: .type lcd_write_command_ex,@function lcd_write_command_ex: - lea MBAR2,%a1 + lea.l 0xf0000000, %a0 + lea.l MBAR2+0xb4, %a1 - move.l (4,%sp),%d0 /* Command */ + move.l #~8, %d1 /* Set A0 = 0 */ + and.l %d1, (%a1) - move.l #~8,%d1 /* Set A0 = 0 */ - and.l %d1,(0xb4,%a1) - move.w %d0,0xf0000000 /* Write to LCD */ + move.l (4, %sp), %d0 /* Command */ + move.w %d0, (%a0) /* Write to LCD */ - not.l %d1 /* Set A0 = 1 */ - or.l %d1,(0xb4,%a1) + not.l %d1 /* Set A0 = 1 */ + or.l %d1, (%a1) - move.l (8,%sp),%d0 /* Data */ - cmp.l #0xffffffff,%d0 /* -1? */ + move.l (8, %sp), %d0 /* Data */ + cmp.l #-1, %d0 /* -1? */ beq.b .last - move.w %d0,0xf0000000 /* Write to LCD */ + move.w %d0, (%a0) /* Write to LCD */ - move.l (12,%sp),%d0 /* Data */ - cmp.l #0xffffffff,%d0 /* -1? */ + move.l (12, %sp), %d0 /* Data */ + cmp.l #-1, %d0 /* -1? */ beq.b .last - move.w %d0,0xf0000000 /* Write to LCD */ + move.w %d0, (%a0) /* Write to LCD */ .last: rts @@ -75,22 +75,84 @@ lcd_write_command_ex: .type lcd_write_data,@function lcd_write_data: - move.l (4,%sp),%a0 /* Data pointer */ - move.l (8,%sp),%d0 /* Length */ - lea MBAR2,%a1 - moveq #8,%d1 - or.l %d1,(0xb4,%a1) + movem.l (4, %sp), %a0-%a1 /* Data pointer */ + move.l %a1, %d0 /* Length */ + moveq #8, %d1 + or.l %d1, (MBAR2+0xb4) + lea.l 0xf0000000, %a1 - lea 0xf0000000,%a1 .loop: /* When running in IRAM, this loop takes 10 cycles plus the LCD write. The 10 cycles are necessary to follow the LCD timing specs at 140MHz */ - nop /* 3(0/0) */ - move.b (%a0)+,%d1 /* 3(1/0) */ - move.w %d1,(%a1) /* 1(0/1) */ - subq.l #1,%d0 /* 1(0/0) */ - bne .loop /* 2(0/0) */ + nop /* 3(0/0) */ + move.b (%a0)+, %d1 /* 3(1/0) */ + move.w %d1, (%a1) /* 1(0/1) */ + subq.l #1, %d0 /* 1(0/0) */ + bne .loop /* 2(0/0) */ rts .wd_end: .size lcd_write_data,.wd_end-lcd_write_data + + + .align 2 + .global lcd_grey_data + .type lcd_grey_data,@function + +lcd_grey_data: + lea.l (-4*4, %sp), %sp + movem.l %d2-%d5, (%sp) + movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */ + move.l %a1, %d0 /* Length */ + moveq #8, %d1 + or.l %d1, (MBAR2+0xb4) /* A0 = 1 (data) */ + lea 0xf0000000, %a1 /* LCD data port */ + move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */ + +.greyloop: + movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */ + /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */ + move.l %d2, %d3 /* copy mask */ + and.l %d4, %d3 /* %d3 = p0--p1-- */ + eor.l %d3, %d4 /* %d4 = --v0--v1 */ + lsr.l #8, %d3 /* %d3 = --p0--p1 */ + + bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */ + seq.b %d1 /* %d1 = ........................00000000 */ + lsl.l #2, %d1 /* %d1 = ......................00000000.. */ + bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */ + seq.b %d1 /* %d1 = ......................0011111111 */ + lsl.l #2, %d1 /* %d1 = ....................0011111111.. */ + + add.l %d4, %d3 /* p0 += v0; p1 += v1; */ + move.b %d3, (2, %a0) /* store p1 */ + swap %d3 + move.b %d3, (%a0) /* store p0 */ + + move.l %d2, %d3 /* copy mask */ + and.l %d5, %d3 /* %d3 = p2--p3-- */ + eor.l %d3, %d5 /* %d5 = --v2--v3 */ + lsr.l #8, %d3 /* %d3 = --p2--p3 */ + + bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */ + seq.b %d1 /* %d1 = ....................001122222222 */ + lsl.l #2, %d1 /* %d1 = ..................001122222222.. */ + bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */ + seq.b %d1 /* %d1 = ..................00112233333333 */ + lsr.l #6, %d1 /* %d1 = ........................00112233 */ + + add.l %d5, %d3 /* p2 += v2; p3 += v3; */ + move.b %d3, (6, %a0) /* store p3 */ + swap %d3 + move.b %d3, (4, %a0) /* store p2 */ + + move.w %d1, (%a1) /* write pixel block */ + addq.l #8, %a0 /* advance address pointer */ + subq.l #1, %d0 /* any blocks left? */ + bne.b .greyloop + + movem.l (%sp), %d2-%d5 + lea.l (4*4, %sp), %sp + rts +.gd_end: + .size lcd_grey_data,.gd_end-lcd_grey_data diff --git a/firmware/target/coldfire/iriver/h100/lcd-h100.c b/firmware/target/coldfire/iriver/h100/lcd-h100.c index a721273384..c17de952c3 100644 --- a/firmware/target/coldfire/iriver/h100/lcd-h100.c +++ b/firmware/target/coldfire/iriver/h100/lcd-h100.c @@ -180,6 +180,21 @@ void lcd_blit(const unsigned char* data, int x, int by, int width, } } +/* Performance function that works with an external buffer + note that by and bheight are in 4-pixel units! */ +void lcd_grey_phase_blit(const struct grey_data *data, int x, int by, + int width, int bheight, int stride) +{ + stride <<= 2; /* 4 pixels per block */ + while (bheight--) + { + lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1); + lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); + lcd_write_command(LCD_CNTL_DATA_WRITE); + lcd_grey_data(data, width); + data += stride; + } +} /* Update the display. This must be called after all other LCD functions that change the display. */ diff --git a/firmware/target/sh/archos/lcd-archos-bitmap.c b/firmware/target/sh/archos/lcd-archos-bitmap.c index 28600a9769..17c4d76092 100644 --- a/firmware/target/sh/archos/lcd-archos-bitmap.c +++ b/firmware/target/sh/archos/lcd-archos-bitmap.c @@ -155,10 +155,26 @@ void lcd_blit(const unsigned char* data, int x, int by, int width, } } +/* Performance function that works with an external buffer + note that by and bheight are in 8-pixel units! */ +void lcd_grey_phase_blit(const struct grey_data *data, int x, int by, + int width, int bheight, int stride) +{ + stride <<= 3; /* 8 pixels per block */ + while (bheight--) + { + lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); + lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf)); + lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf)); + + lcd_grey_data(data, width); + data += stride; + } +} + /* Update the display. This must be called after all other LCD functions that change the display. */ -void lcd_update(void) ICODE_ATTR; void lcd_update(void) { int y; @@ -175,7 +191,6 @@ void lcd_update(void) } /* Update a fraction of the display. */ -void lcd_update_rect(int, int, int, int) ICODE_ATTR; void lcd_update_rect(int x, int y, int width, int height) { int ymax; diff --git a/firmware/target/sh/archos/lcd-as-archos-bitmap.S b/firmware/target/sh/archos/lcd-as-archos-bitmap.S index bef231c3c7..a84ce50686 100644 --- a/firmware/target/sh/archos/lcd-as-archos-bitmap.S +++ b/firmware/target/sh/archos/lcd-as-archos-bitmap.S @@ -81,26 +81,25 @@ */ _lcd_write_command: - mov.l .lcdr,r3 /* put lcd data port address in r3 */ - mov r4,r1 /* copy data byte to r1 */ - mov #1,r5 /* set byte count to 1 (!) */ + mov.l .lcdr, r3 /* put lcd data port address in r3 */ + mov r4, r1 /* copy data byte to r1 */ /* This code will fail if an interrupt changes the contents of PBDRL. * If so, we must disable the interrupt here. */ - mov.b @r3,r0 /* r0 = PBDRL */ - or #(LCD_SD),r0 /* r0 |= LCD_SD */ - and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */ + mov.b @r3, r0 /* r0 = PBDRL */ + mov r4, r5 /* (fake) end address = current address */ + or #(LCD_SD), r0 /* r0 |= LCD_SD */ + and #(~(LCD_CS|LCD_DS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */ bra .single_transfer /* jump into the transfer loop */ - neg r0,r2 /* r2 = 0 - r0 */ + neg r0, r2 /* r2 = 0 - r0 */ .align 2 .global _lcd_write_data .type _lcd_write_data,@function - /* A high performance function to write data to the display, * one or multiple bytes. * @@ -117,8 +116,8 @@ _lcd_write_command: */ _lcd_write_data: - mov.l .lcdr,r3 /* put lcd data port address in r3 */ - nop /* align here */ + mov.l .lcdr, r3 /* put lcd data port address in r3 */ + add r4, r5 /* end address */ /* This code will fail if an interrupt changes the contents of PBDRL. * If so, we must disable the interrupt here. If disabling interrupts @@ -127,85 +126,233 @@ _lcd_write_data: * disable/precalculate/transfer/enable for each iteration. However, * this would significantly decrease performance. */ - mov.b @r3,r0 /* r0 = PBDRL */ - or #(LCD_DS|LCD_SD),r0 /* r0 |= LCD_DS|LCD_SD */ - and #(~(LCD_CS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_SC) */ - neg r0,r2 /* r2 = 0 - r0 */ + mov.b @r3, r0 /* r0 = PBDRL */ + or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */ + and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */ + neg r0, r2 /* r2 = 0 - r0 */ /* loop exploits that SD is on bit 0 for recorders and Ondios */ .align 2 .multi_transfer: - mov.b @r4+,r1 /* load data byte from memory */ + mov.b @r4+, r1 /* load data byte from memory */ nop .single_transfer: shll16 r1 /* shift data to most significant byte */ shll8 r1 - not r1,r1 /* and invert for use with negc */ + not r1, r1 /* and invert for use with negc */ shll r1 /* shift the MSB into carry */ - negc r2,r0 /* carry to SD, SC low */ + negc r2, r0 /* carry to SD, SC low */ shll r1 /* next shift here for alignment */ - mov.b r0,@r3 /* set data to port */ - or #(LCD_SC),r0 /* rise SC (independent of SD level) */ - mov.b r0,@r3 /* set to port */ + mov.b r0, @r3 /* set data to port */ + or #(LCD_SC), r0 /* rise SC (independent of SD level) */ + mov.b r0, @r3 /* set to port */ - negc r2,r0 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + negc r2, r0 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 shll r1 - negc r2,r0 + negc r2, r0 shll r1 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 - negc r2,r0 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + negc r2, r0 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 shll r1 - negc r2,r0 + negc r2, r0 shll r1 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 - negc r2,r0 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + negc r2, r0 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 shll r1 - negc r2,r0 + negc r2, r0 shll r1 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 - negc r2,r0 - mov.b r0,@r3 - or #(LCD_SC),r0 - mov.b r0,@r3 + negc r2, r0 + mov.b r0, @r3 + or #(LCD_SC), r0 + mov.b r0, @r3 - add #-1,r5 /* decrease byte count */ - tst r5,r5 /* r5 == 0 ? */ - bf .multi_transfer /* no: next iteration */ + cmp/hi r4, r5 /* some blocks left? */ + bt .multi_transfer - or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC),r0 /* restore port */ + or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0 /* restore port */ rts - mov.b r0,@r3 + mov.b r0, @r3 /* This is the place to reenable the interrupts, if we have disabled * them. See above. */ + + .align 2 + .global _lcd_grey_data + .type _lcd_grey_data,@function + +/* A high performance function to write grey phase data to the display, + * one or multiple pixels. + * + * Arguments: + * r4 - data address, (phase,value)-pairs + * r5 - pixel block count + * + * Register usage: + * r0 - current pixel value + * r1 - scratch + * r2 - precalculated port value (CS and SC low, DS and SD high), + * negated (neg)! + * r3 - lcd port address + * r5 - end address + * r6/r7 - current/next pixel phase + * r8 - current block address (for writing back phase) + * r9 - 0x80 (for phase modification) + */ + +_lcd_grey_data: + mov.l r8, @-r15 /* save r8 */ + shll2 r5 /* v */ + mov.l r9, @-r15 /* save r9 */ + shll2 r5 /* r5 *= 16; (8 pixel per block * 2 bytes/pixel) */ + mov.l .lcdr, r3 /* put lcd data port address in r3 */ + add r4, r5 /* end address */ + + /* This code will fail if an interrupt changes the contents of PBDRL. + * If so, we must disable the interrupt here. If disabling interrupts + * for a long time is undesirable, the loop has to be rewritten to + * disable/precalculate/transfer/enable for each iteration. However, + * this would significantly decrease performance. */ + + mov.b @r3, r0 /* r0 = PBDRL */ + mov r4, r8 /* copy start address */ + mov.b @r4+, r6 /* fetch first pixel phase */ + or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */ + and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */ + neg r0, r2 /* r2 = 0 - r0 */ + mov #0x80, r9 /* for phase modification - "or #imm,xx" only allows r0 */ + + /* loop exploits that SD is on bit 0 for recorders and Ondios */ + +.greyloop: + cmp/pz r6 /* phase non-negative? */ + mov.b @r4+, r0 /* fetch pixel value */ + negc r2, r1 /* T -> SD, SC low */ + mov.b r1, @r3 /* set port */ + or r9, r6 /* r6 -= (r6 >= 0) ? 128 : 0; */ + mov.b @r4+, r7 /* fetch next pixel phase */ + add #(LCD_SC), r1 /* rise SC */ + mov.b r1, @r3 /* set port */ + add r6, r0 /* calculate new phase */ + mov.b r0, @r8 /* store phase */ + + cmp/pz r7 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r7 + mov.b @r4+, r6 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r7, r0 + mov.b r0, @(2,r8) + + cmp/pz r6 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r6 + mov.b @r4+, r7 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r6, r0 + mov.b r0, @(4,r8) + + cmp/pz r7 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r7 + mov.b @r4+, r6 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r7, r0 + mov.b r0, @(6,r8) + + cmp/pz r6 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r6 + mov.b @r4+, r7 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r6, r0 + mov.b r0, @(8,r8) + + cmp/pz r7 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r7 + mov.b @r4+, r6 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r7, r0 + mov.b r0, @(10,r8) + + cmp/pz r6 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r6 + mov.b @r4+, r7 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r6, r0 + mov.b r0, @(12,r8) + + cmp/pz r7 + mov.b @r4+, r0 + negc r2, r1 + mov.b r1, @r3 + or r9, r7 + mov.b @r4+, r6 + add #(LCD_SC), r1 + mov.b r1, @r3 + add r7, r0 + mov.b r0, @(14,r8) + + add #16, r8 /* advance current block address */ + cmp/hi r4, r5 /* some blocks left? */ + bt .greyloop + + mov.l @r15+, r9 /* restore r9 */ + mov #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0 + mov.l @r15+, r8 /* restore r8 */ + or r0, r1 /* restore port */ + rts + mov.b r1, @r3 + + /* This is the place to reenable the interrupts, if we have disabled + * them. See above. */ + + .align 2 .lcdr: .long LCDR - -.end: - .size _lcd_write_command,.end-_lcd_write_command