summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-01-04 23:42:38 +0000
committerJens Arnold <amiconn@rockbox.org>2008-01-04 23:42:38 +0000
commitfeb5b15e9bf9292e3d4d82ea1e01ab3557fb1240 (patch)
treed854c9a6fbbb3263537071fb02df349fdfa62361
parentd3586837fa9221a7ef104550b4c0aadc1a6ea77c (diff)
downloadrockbox-feb5b15e9bf9292e3d4d82ea1e01ab3557fb1240.tar.gz
rockbox-feb5b15e9bf9292e3d4d82ea1e01ab3557fb1240.zip
All-new greyscale library, replacing the old one. Features: (1) Drawing/updating is faster than the old grayscale lib at full depth. (2) Always 129 shades instead of 2..33 shades. (3) No graininess caused by frequent updates (mpegplayer, doom, ...). (4) Needs less memory than the old grayscale lib at full depth. * The tradeoff is slightly higher CPU load in the ISR (frames are calculated 'live') and an extra function in the core. * Ported all plugins which used the graylib to use the new one. * Some slight optimisations for archos and H1x0 LCD update.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15998 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c4
-rw-r--r--apps/plugin.h7
-rw-r--r--apps/plugins/CATEGORIES2
-rw-r--r--apps/plugins/cube.c33
-rw-r--r--apps/plugins/doom/i_system.c2
-rw-r--r--apps/plugins/doom/i_video.c31
-rw-r--r--apps/plugins/greyscale.c (renamed from apps/plugins/grayscale.c)192
-rw-r--r--apps/plugins/jpeg.c35
-rw-r--r--apps/plugins/lib/SOURCES4
-rw-r--r--apps/plugins/lib/grey.h166
-rw-r--r--apps/plugins/lib/grey_core.c767
-rw-r--r--apps/plugins/lib/grey_draw.c681
-rw-r--r--apps/plugins/lib/grey_parm.c116
-rw-r--r--apps/plugins/lib/grey_scroll.c358
-rw-r--r--apps/plugins/mandelbrot.c38
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c2
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.h12
-rw-r--r--apps/plugins/mpegplayer/stream_mgr.c29
-rw-r--r--apps/plugins/mpegplayer/video_out_rockbox.c2
-rw-r--r--apps/plugins/plasma.c16
-rw-r--r--apps/plugins/zxbox/interf.c6
-rw-r--r--apps/plugins/zxbox/spmain.c14
-rw-r--r--apps/plugins/zxbox/zxbox.c32
-rw-r--r--apps/plugins/zxbox/zxconfig.h9
-rw-r--r--apps/plugins/zxbox/zxvid_4bpp.c2
-rw-r--r--apps/plugins/zxbox/zxvid_com.h4
-rw-r--r--apps/plugins/zxbox/zxvid_grey.c16
-rw-r--r--firmware/export/lcd.h11
-rw-r--r--firmware/target/arm/ipod/lcd-gray.c117
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-as-m5.S93
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-m5.c15
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-as-h100.S120
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-h100.c15
-rw-r--r--firmware/target/sh/archos/lcd-archos-bitmap.c19
-rw-r--r--firmware/target/sh/archos/lcd-as-archos-bitmap.S259
35 files changed, 2872 insertions, 357 deletions
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 = {
583 sound_unit, 583 sound_unit,
584 sound_val2phys, 584 sound_val2phys,
585#endif /* CONFIG_CODEC == SWCODEC */ 585#endif /* CONFIG_CODEC == SWCODEC */
586
587#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && !defined(SIMULATOR)
588 lcd_grey_phase_blit,
589#endif
586}; 590};
587 591
588int plugin_load(const char* plugin, void* parameter) 592int 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 @@
119#define PLUGIN_MAGIC 0x526F634B /* RocK */ 119#define PLUGIN_MAGIC 0x526F634B /* RocK */
120 120
121/* increase this every time the api struct changes */ 121/* increase this every time the api struct changes */
122#define PLUGIN_API_VERSION 93 122#define PLUGIN_API_VERSION 94
123 123
124/* update this to latest version if a change to the api struct breaks 124/* update this to latest version if a change to the api struct breaks
125 backwards compatibility (and please take the opportunity to sort in any 125 backwards compatibility (and please take the opportunity to sort in any
@@ -718,6 +718,11 @@ struct plugin_api {
718 const char * (*sound_unit)(int setting); 718 const char * (*sound_unit)(int setting);
719 int (*sound_val2phys)(int setting, int value); 719 int (*sound_val2phys)(int setting, int value);
720#endif /* CONFIG_CODEC == SWCODEC */ 720#endif /* CONFIG_CODEC == SWCODEC */
721
722#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && !defined(SIMULATOR)
723 void (*lcd_grey_phase_blit)(const struct grey_data *data, int bx, int by,
724 int bwidth, int bheight, int stride);
725#endif
721}; 726};
722 727
723/* plugin header */ 728/* 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
24fireworks,demos 24fireworks,demos
25firmware_flash,apps 25firmware_flash,apps
26flipit,games 26flipit,games
27grayscale,demos 27greyscale,demos
28helloworld,demos 28helloworld,demos
29invadrox,games 29invadrox,games
30iriver_flash,apps 30iriver_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 @@
19* 19*
20***************************************************************************/ 20***************************************************************************/
21#include "plugin.h" 21#include "plugin.h"
22#include "gray.h" 22#include "grey.h"
23#include "playergfx.h" 23#include "playergfx.h"
24#include "xlcd.h" 24#include "xlcd.h"
25#include "fixedpoint.h" 25#include "fixedpoint.h"
@@ -221,16 +221,16 @@ struct my_lcd {
221 void (*putsxy)(int x, int y, const unsigned char *string); 221 void (*putsxy)(int x, int y, const unsigned char *string);
222}; 222};
223 223
224static struct my_lcd grayfuncs = { 224static struct my_lcd greyfuncs = {
225 gray_update, gray_clear_display, gray_drawline, gray_putsxy 225 grey_update, grey_clear_display, grey_drawline, grey_putsxy
226}; 226};
227static struct my_lcd lcdfuncs; /* initialised at runtime */ 227static struct my_lcd lcdfuncs; /* initialised at runtime */
228static struct my_lcd *mylcd = &grayfuncs; 228static struct my_lcd *mylcd = &greyfuncs;
229 229
230#define MYLCD(fn) mylcd->fn 230#define MYLCD(fn) mylcd->fn
231#define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) gray_filltriangle(x1, y1, x2, y2, x3, y3) 231#define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) grey_filltriangle(x1, y1, x2, y2, x3, y3)
232#define MY_SET_FOREGROUND(fg) gray_set_foreground(fg) 232#define MY_SET_FOREGROUND(fg) grey_set_foreground(fg)
233#define MY_GET_FOREGROUND() gray_get_foreground() 233#define MY_GET_FOREGROUND() grey_get_foreground()
234 234
235#else 235#else
236#define MYLCD(fn) rb->lcd_ ## fn 236#define MYLCD(fn) rb->lcd_ ## fn
@@ -314,8 +314,8 @@ static const unsigned face_colors[6] =
314 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0), 314 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
315 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255) 315 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
316#elif defined(USE_GSLIB) 316#elif defined(USE_GSLIB)
317 GRAY_LIGHTGRAY, GRAY_LIGHTGRAY, GRAY_DARKGRAY, 317 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
318 GRAY_DARKGRAY, GRAY_BLACK, GRAY_BLACK 318 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
319#else 319#else
320 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY, 320 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
321 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK 321 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
@@ -490,7 +490,7 @@ void cleanup(void *parameter)
490 (void)parameter; 490 (void)parameter;
491 491
492#ifdef USE_GSLIB 492#ifdef USE_GSLIB
493 gray_release(); 493 grey_release();
494#elif defined HAVE_LCD_CHARCELLS 494#elif defined HAVE_LCD_CHARCELLS
495 pgfx_release(); 495 pgfx_release();
496#endif 496#endif
@@ -527,10 +527,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
527 xlcd_init(rb); 527 xlcd_init(rb);
528#elif defined(USE_GSLIB) 528#elif defined(USE_GSLIB)
529 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size); 529 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
530 if (gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, 3, 0, NULL) 530 if (!grey_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, NULL))
531 != 3)
532 { 531 {
533 rb->splash(HZ, "Couldn't get grayscale buffer"); 532 rb->splash(HZ, "Couldn't init greyscale display");
534 return PLUGIN_ERROR; 533 return PLUGIN_ERROR;
535 } 534 }
536 /* init lcd_ function pointers */ 535 /* init lcd_ function pointers */
@@ -539,7 +538,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
539 lcdfuncs.drawline = rb->lcd_drawline; 538 lcdfuncs.drawline = rb->lcd_drawline;
540 lcdfuncs.putsxy = rb->lcd_putsxy; 539 lcdfuncs.putsxy = rb->lcd_putsxy;
541 540
542 gray_setfont(FONT_SYSFIXED); 541 grey_setfont(FONT_SYSFIXED);
543#endif 542#endif
544 rb->lcd_setfont(FONT_SYSFIXED); 543 rb->lcd_setfont(FONT_SYSFIXED);
545#else /* LCD_CHARCELLS */ 544#else /* LCD_CHARCELLS */
@@ -603,7 +602,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
603#ifdef USE_GSLIB 602#ifdef USE_GSLIB
604 if (mode_switch) 603 if (mode_switch)
605 { 604 {
606 gray_show(mode == SOLID); 605 grey_show(mode == SOLID);
607 mode_switch = false; 606 mode_switch = false;
608 } 607 }
609#endif 608#endif
@@ -744,7 +743,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
744 if (++mode >= NUM_MODES) 743 if (++mode >= NUM_MODES)
745 mode = 0; 744 mode = 0;
746#ifdef USE_GSLIB 745#ifdef USE_GSLIB
747 mylcd = (mode == SOLID) ? &grayfuncs : &lcdfuncs; 746 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
748 mode_switch = true; 747 mode_switch = true;
749#endif 748#endif
750 redraw = true; 749 redraw = true;
@@ -785,7 +784,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
785 } 784 }
786 785
787#ifdef USE_GSLIB 786#ifdef USE_GSLIB
788 gray_release(); 787 grey_release();
789#elif defined(HAVE_LCD_CHARCELLS) 788#elif defined(HAVE_LCD_CHARCELLS)
790 pgfx_release(); 789 pgfx_release();
791#endif 790#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 @@
72/* NOTE: 72/* NOTE:
73 73
74 The user timer is used to generate a 70Hz tick for Doom. But it 74 The user timer is used to generate a 70Hz tick for Doom. But it
75 is unavailable for the grayscale targets (it's used by the grayscale 75 is unavailable for the greyscale targets (it's used by the greyscale
76 lib) and is not implemented in the simulator - so we have to 76 lib) and is not implemented in the simulator - so we have to
77 approximate it using current_tick. 77 approximate it using current_tick.
78*/ 78*/
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 @@
117#include "rockmacros.h" 117#include "rockmacros.h"
118 118
119#ifndef HAVE_LCD_COLOR 119#ifndef HAVE_LCD_COLOR
120#include "../lib/gray.h" 120#include "../lib/grey.h"
121static unsigned char graybuffer[8*LCD_WIDTH] IBSS_ATTR; /* off screen buffer */ 121static unsigned char greybuffer[LCD_WIDTH] IBSS_ATTR; /* off screen buffer */
122static unsigned char *gbuf; 122static unsigned char *gbuf;
123#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 123#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
124#define GRAYBUFSIZE (((LCD_WIDTH+7)/8)*LCD_HEIGHT*32+200) 124#define GREYBUFSIZE (((LCD_WIDTH+7)/8)*LCD_HEIGHT*16+200)
125#else 125#else
126#define GRAYBUFSIZE (LCD_WIDTH*((LCD_HEIGHT+7)/8)*32+200) 126#define GREYBUFSIZE (LCD_WIDTH*((LCD_HEIGHT+7)/8)*16+200)
127#endif 127#endif
128#endif 128#endif
129 129
@@ -140,7 +140,7 @@ static fb_data *paldata=NULL;
140void I_ShutdownGraphics(void) 140void I_ShutdownGraphics(void)
141{ 141{
142#ifndef HAVE_LCD_COLOR 142#ifndef HAVE_LCD_COLOR
143 gray_release(); 143 grey_release();
144#endif 144#endif
145 noprintf=0; 145 noprintf=0;
146} 146}
@@ -580,23 +580,17 @@ void I_FinishUpdate (void)
580 } 580 }
581 rb->lcd_update(); 581 rb->lcd_update();
582#else /* !HAVE_LCD_COLOR */ 582#else /* !HAVE_LCD_COLOR */
583 int x, yd = 0; 583 int x;
584 584
585 for (y = 0; y < SCREENHEIGHT; y++) 585 for (y = 0; y < SCREENHEIGHT; y++)
586 { 586 {
587 for (x = 0; x < SCREENWIDTH; x++) 587 for (x = 0; x < SCREENWIDTH; x++)
588 { 588 {
589 paletteIndex = d_screens[0][y*SCREENWIDTH + x]; 589 paletteIndex = d_screens[0][y*SCREENWIDTH + x];
590 graybuffer[yd * SCREENWIDTH + x]=palette[paletteIndex]; 590 greybuffer[x]=palette[paletteIndex];
591 }
592 if (++yd == 8)
593 {
594 gray_ub_gray_bitmap(graybuffer, 0, y & ~7, SCREENWIDTH, 8);
595 yd = 0;
596 } 591 }
592 grey_ub_gray_bitmap(greybuffer, 0, y, SCREENWIDTH, 1);
597 } 593 }
598 if (yd > 0)
599 gray_ub_gray_bitmap(graybuffer, 0, y & ~7, SCREENWIDTH, yd);
600#endif /* !HAVE_LCD_COLOR */ 594#endif /* !HAVE_LCD_COLOR */
601#endif 595#endif
602} 596}
@@ -629,11 +623,10 @@ void I_InitGraphics(void)
629 /* Note: The other screens are allocated as needed */ 623 /* Note: The other screens are allocated as needed */
630 624
631#ifndef HAVE_LCD_COLOR 625#ifndef HAVE_LCD_COLOR
632 gbuf=malloc(GRAYBUFSIZE); 626 gbuf=malloc(GREYBUFSIZE);
633 gray_init(rb, gbuf, GRAYBUFSIZE, false, LCD_WIDTH, LCD_HEIGHT, 32, 627 grey_init(rb, gbuf, GREYBUFSIZE, false, LCD_WIDTH, LCD_HEIGHT, NULL);
634 3<<7 /* 1.5 */, NULL); 628 /* switch on greyscale overlay */
635 /* switch on grayscale overlay */ 629 grey_show(true);
636 gray_show(true);
637#endif 630#endif
638 631
639#ifdef CPU_COLDFIRE 632#ifdef CPU_COLDFIRE
diff --git a/apps/plugins/grayscale.c b/apps/plugins/greyscale.c
index 56e1ce0e31..de90d5737f 100644
--- a/apps/plugins/grayscale.c
+++ b/apps/plugins/greyscale.c
@@ -7,9 +7,9 @@
7* \/ \/ \/ \/ \/ 7* \/ \/ \/ \/ \/
8* $Id$ 8* $Id$
9* 9*
10* Grayscale demo plugin 10* Greyscale demo plugin
11* 11*
12* Copyright (C) 2004 Jens Arnold 12* Copyright (C) 2004-2008 Jens Arnold
13* 13*
14* All files in this archive are subject to the GNU General Public License. 14* All files in this archive are subject to the GNU General Public License.
15* See the file COPYING in the source tree root for full license agreement. 15* See the file COPYING in the source tree root for full license agreement.
@@ -23,62 +23,62 @@
23#include "helper.h" 23#include "helper.h"
24 24
25#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) 25#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4)
26#include "gray.h" 26#include "grey.h"
27 27
28PLUGIN_HEADER 28PLUGIN_HEADER
29 29
30/* variable button definitions */ 30/* variable button definitions */
31#if CONFIG_KEYPAD == RECORDER_PAD 31#if CONFIG_KEYPAD == RECORDER_PAD
32#define GRAYSCALE_SHIFT BUTTON_ON 32#define GREYSCALE_SHIFT BUTTON_ON
33#define GRAYSCALE_UP BUTTON_UP 33#define GREYSCALE_UP BUTTON_UP
34#define GRAYSCALE_DOWN BUTTON_DOWN 34#define GREYSCALE_DOWN BUTTON_DOWN
35#define GRAYSCALE_LEFT BUTTON_LEFT 35#define GREYSCALE_LEFT BUTTON_LEFT
36#define GRAYSCALE_RIGHT BUTTON_RIGHT 36#define GREYSCALE_RIGHT BUTTON_RIGHT
37#define GRAYSCALE_OFF BUTTON_OFF 37#define GREYSCALE_OFF BUTTON_OFF
38 38
39#elif CONFIG_KEYPAD == ONDIO_PAD 39#elif CONFIG_KEYPAD == ONDIO_PAD
40#define GRAYSCALE_SHIFT BUTTON_MENU 40#define GREYSCALE_SHIFT BUTTON_MENU
41#define GRAYSCALE_UP BUTTON_UP 41#define GREYSCALE_UP BUTTON_UP
42#define GRAYSCALE_DOWN BUTTON_DOWN 42#define GREYSCALE_DOWN BUTTON_DOWN
43#define GRAYSCALE_LEFT BUTTON_LEFT 43#define GREYSCALE_LEFT BUTTON_LEFT
44#define GRAYSCALE_RIGHT BUTTON_RIGHT 44#define GREYSCALE_RIGHT BUTTON_RIGHT
45#define GRAYSCALE_OFF BUTTON_OFF 45#define GREYSCALE_OFF BUTTON_OFF
46 46
47#elif CONFIG_KEYPAD == IRIVER_H100_PAD 47#elif CONFIG_KEYPAD == IRIVER_H100_PAD
48#define GRAYSCALE_SHIFT BUTTON_ON 48#define GREYSCALE_SHIFT BUTTON_ON
49#define GRAYSCALE_UP BUTTON_UP 49#define GREYSCALE_UP BUTTON_UP
50#define GRAYSCALE_DOWN BUTTON_DOWN 50#define GREYSCALE_DOWN BUTTON_DOWN
51#define GRAYSCALE_LEFT BUTTON_LEFT 51#define GREYSCALE_LEFT BUTTON_LEFT
52#define GRAYSCALE_RIGHT BUTTON_RIGHT 52#define GREYSCALE_RIGHT BUTTON_RIGHT
53#define GRAYSCALE_OFF BUTTON_OFF 53#define GREYSCALE_OFF BUTTON_OFF
54 54
55#define GRAYSCALE_RC_OFF BUTTON_RC_STOP 55#define GREYSCALE_RC_OFF BUTTON_RC_STOP
56 56
57#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 57#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
58 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 58 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
59#define GRAYSCALE_SHIFT BUTTON_SELECT 59#define GREYSCALE_SHIFT BUTTON_SELECT
60#define GRAYSCALE_UP BUTTON_SCROLL_BACK 60#define GREYSCALE_UP BUTTON_SCROLL_BACK
61#define GRAYSCALE_DOWN BUTTON_SCROLL_FWD 61#define GREYSCALE_DOWN BUTTON_SCROLL_FWD
62#define GRAYSCALE_LEFT BUTTON_LEFT 62#define GREYSCALE_LEFT BUTTON_LEFT
63#define GRAYSCALE_RIGHT BUTTON_RIGHT 63#define GREYSCALE_RIGHT BUTTON_RIGHT
64#define GRAYSCALE_OFF BUTTON_MENU 64#define GREYSCALE_OFF BUTTON_MENU
65 65
66#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD 66#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
67#define GRAYSCALE_SHIFT BUTTON_PLAY 67#define GREYSCALE_SHIFT BUTTON_PLAY
68#define GRAYSCALE_UP BUTTON_UP 68#define GREYSCALE_UP BUTTON_UP
69#define GRAYSCALE_DOWN BUTTON_DOWN 69#define GREYSCALE_DOWN BUTTON_DOWN
70#define GRAYSCALE_LEFT BUTTON_LEFT 70#define GREYSCALE_LEFT BUTTON_LEFT
71#define GRAYSCALE_RIGHT BUTTON_RIGHT 71#define GREYSCALE_RIGHT BUTTON_RIGHT
72#define GRAYSCALE_OFF BUTTON_EQ 72#define GREYSCALE_OFF BUTTON_EQ
73#endif 73#endif
74 74
75#define GFX_HEIGHT (LCD_HEIGHT-8) 75#define GFX_HEIGHT (LCD_HEIGHT-8)
76#if LCD_WIDTH < 160 76#if LCD_WIDTH < 160
77#define GFX_GRAYTONE_WIDTH 86 77#define GFX_GREYTONE_WIDTH 86
78#define GFX_GRAYTONE_STEP 3 78#define GFX_GREYTONE_STEP 3
79#else 79#else
80#define GFX_GRAYTONE_WIDTH 128 80#define GFX_GREYTONE_WIDTH 128
81#define GFX_GRAYTONE_STEP 2 81#define GFX_GREYTONE_STEP 2
82#endif 82#endif
83/******************************* Globals ***********************************/ 83/******************************* Globals ***********************************/
84 84
@@ -93,7 +93,7 @@ void cleanup(void *parameter)
93{ 93{
94 (void)parameter; 94 (void)parameter;
95 95
96 gray_release(); /* switch off overlay and deinitialize */ 96 grey_release(); /* switch off overlay and deinitialize */
97 /* Turn on backlight timeout (revert to settings) */ 97 /* Turn on backlight timeout (revert to settings) */
98 backlight_use_settings(rb); /* backlight control in lib/helper.c */ 98 backlight_use_settings(rb); /* backlight control in lib/helper.c */
99} 99}
@@ -101,7 +101,7 @@ void cleanup(void *parameter)
101/* this is only a demo of what the framework can do */ 101/* this is only a demo of what the framework can do */
102int main(void) 102int main(void)
103{ 103{
104 int shades, time; 104 int time;
105 int x, y, i; 105 int x, y, i;
106 int button, scroll_amount; 106 int button, scroll_amount;
107 bool black_border = false; 107 bool black_border = false;
@@ -139,7 +139,7 @@ int main(void)
139 0x10, 0x3E, 0x00, 0x1C, 0x22, 0x22, 0x2A, 0x3A, 0x00 139 0x10, 0x3E, 0x00, 0x1C, 0x22, 0x22, 0x2A, 0x3A, 0x00
140 }; 140 };
141 141
142 static const unsigned char grayscale_gray[] = { 142 static const unsigned char grayscale_grey[] = {
143 /* ....................................................... 143 /* .......................................................
144 * ..####.####...###..#...#..####..###...###..#.....#####. 144 * ..####.####...###..#...#..####..###...###..#.....#####.
145 * .#.....#...#.#...#.#...#.#.....#...#.#...#.#.....#..... 145 * .#.....#...#.#...#.#...#.#.....#...#.#...#.#.....#.....
@@ -188,82 +188,82 @@ int main(void)
188 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); 188 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
189 189
190 /* initialize the greyscale buffer: 190 /* initialize the greyscale buffer:
191 Archos: 112 pixels wide, 7 rows (56 pixels) high, (try to) reserve 191 Archos: 112 pixels wide, 7 rows (56 pixels) high.
192 32 bitplanes for 33 shades of grey. 192 H1x0: 160 pixels wide, 30 rows (120 pixels) high. */
193 H1x0: 160 pixels wide, 30 rows (120 pixels) high, (try to) reserve 193 if (!grey_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, GFX_HEIGHT, NULL))
194 32 bitplanes for 33 shades of grey. */ 194 {
195 shades = gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, GFX_HEIGHT, 195 rb->splash(HZ, "Not enough memory.");
196 32, 0, NULL) + 1; 196 return PLUGIN_ERROR;
197 }
197 198
198 /* place greyscale overlay 1 row down */ 199 /* place greyscale overlay 1 row down */
199 gray_set_position(0, 8); 200 grey_set_position(0, 8);
200 201
201 rb->snprintf(pbuf, sizeof(pbuf), "Shades: %d", shades); 202 rb->lcd_puts(0, 0, "Shades: 129");
202 rb->lcd_puts(0, 0, pbuf);
203 rb->lcd_update(); 203 rb->lcd_update();
204 204
205#ifdef HAVE_ADJUSTABLE_CPU_FREQ 205#ifdef HAVE_ADJUSTABLE_CPU_FREQ
206 rb->cpu_boost(true); 206 rb->cpu_boost(true);
207#endif 207#endif
208 gray_show(true); /* switch on greyscale overlay */ 208 grey_show(true); /* switch on greyscale overlay */
209 209
210 time = *rb->current_tick; /* start time measurement */ 210 time = *rb->current_tick; /* start time measurement */
211 211
212 gray_set_background(150); 212 grey_set_background(150);
213 gray_clear_display(); /* fill everything with grey 150 */ 213 grey_clear_display(); /* fill everything with grey 150 */
214 214
215 /* draw a dark grey line star background */ 215 /* draw a dark grey line star background */
216 gray_set_foreground(80); 216 grey_set_foreground(80);
217 for (y = 0; y < GFX_HEIGHT; y += 8) /* horizontal part */ 217 for (y = 0; y < GFX_HEIGHT; y += 8) /* horizontal part */
218 { 218 {
219 gray_drawline(0, y, (LCD_WIDTH-1), (GFX_HEIGHT-1) - y); /*grey lines */ 219 grey_drawline(0, y, (LCD_WIDTH-1), (GFX_HEIGHT-1) - y); /*grey lines */
220 } 220 }
221 for (x = 10; x <= LCD_WIDTH; x += 10) /* vertical part */ 221 for (x = 10; x <= LCD_WIDTH; x += 10) /* vertical part */
222 { 222 {
223 gray_drawline(x, 0, (LCD_WIDTH-1) - x, (GFX_HEIGHT-1)); /*grey lines */ 223 grey_drawline(x, 0, (LCD_WIDTH-1) - x, (GFX_HEIGHT-1)); /*grey lines */
224 } 224 }
225 225
226 gray_set_foreground(0); 226 grey_set_foreground(0);
227 gray_drawrect(0, 0, LCD_WIDTH, GFX_HEIGHT); /* black border */ 227 grey_drawrect(0, 0, LCD_WIDTH, GFX_HEIGHT); /* black border */
228 228
229 /* draw grey tones */ 229 /* draw grey tones */
230 for (i = 0; i < GFX_GRAYTONE_WIDTH; i++) 230 for (i = 0; i < GFX_GREYTONE_WIDTH; i++)
231 { 231 {
232 x = ((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2) + i; 232 x = ((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2) + i;
233 gray_set_foreground(GFX_GRAYTONE_STEP * i); 233 grey_set_foreground(GFX_GREYTONE_STEP * i);
234 /* vertical lines */ 234 /* vertical lines */
235 gray_vline(x, (GFX_HEIGHT/8), (GFX_HEIGHT-GFX_HEIGHT/8-1)); 235 grey_vline(x, (GFX_HEIGHT/8), (GFX_HEIGHT-GFX_HEIGHT/8-1));
236 } 236 }
237 237
238 gray_set_drawmode(DRMODE_COMPLEMENT); 238 grey_set_drawmode(DRMODE_COMPLEMENT);
239 /* invert rectangle (lower half) */ 239 /* invert rectangle (lower half) */
240 gray_fillrect((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2, (GFX_HEIGHT/2+1), 240 grey_fillrect((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2, (GFX_HEIGHT/2+1),
241 GFX_GRAYTONE_WIDTH, (GFX_HEIGHT/2-GFX_HEIGHT/8-1)); 241 GFX_GREYTONE_WIDTH, (GFX_HEIGHT/2-GFX_HEIGHT/8-1));
242 /* invert a line */ 242 /* invert a line */
243 gray_hline((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2, 243 grey_hline((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2,
244 (LCD_WIDTH+GFX_GRAYTONE_WIDTH)/2, (GFX_HEIGHT/2-1)); 244 (LCD_WIDTH+GFX_GREYTONE_WIDTH)/2, (GFX_HEIGHT/2-1));
245 245
246 /* show bitmaps (1 bit and 8 bit) */ 246 /* show bitmaps (1 bit and 8 bit) */
247 /* opaque */ 247 /* opaque */
248 gray_set_drawinfo(DRMODE_SOLID, 255, 100); 248 grey_set_drawinfo(DRMODE_SOLID, 255, 100);
249 gray_mono_bitmap(rockbox, 249 grey_mono_bitmap(rockbox,
250 MAX((LCD_WIDTH/2-47), ((LCD_WIDTH-GFX_GRAYTONE_WIDTH)/2)), 250 MAX((LCD_WIDTH/2-47), ((LCD_WIDTH-GFX_GREYTONE_WIDTH)/2)),
251 (5*GFX_HEIGHT/16-4), 43, 7); 251 (5*GFX_HEIGHT/16-4), 43, 7);
252 /* transparent */ 252 /* transparent */
253 gray_set_drawinfo(DRMODE_FG, 0, 100); 253 grey_set_drawinfo(DRMODE_FG, 0, 100);
254 gray_mono_bitmap(showing, (LCD_WIDTH/2+4) , (5*GFX_HEIGHT/16-4), 39, 7); 254 grey_mono_bitmap(showing, (LCD_WIDTH/2+4) , (5*GFX_HEIGHT/16-4), 39, 7);
255 /* greyscale */ 255 /* greyscale */
256 gray_gray_bitmap(grayscale_gray, ((LCD_WIDTH-55)/2), (11*GFX_HEIGHT/16-4), 256 grey_gray_bitmap(grayscale_grey, ((LCD_WIDTH-55)/2), (11*GFX_HEIGHT/16-4),
257 55, 7); 257 55, 7);
258 258
259 gray_update(); 259 grey_update();
260 260
261 time = *rb->current_tick - time; /* end time measurement */ 261 time = *rb->current_tick - time; /* end time measurement */
262 262
263 rb->snprintf(pbuf, sizeof(pbuf), "Shades: %d, %d.%02ds", shades, 263 rb->snprintf(pbuf, sizeof(pbuf), "Shades: 129, %d.%02ds",
264 time / 100, time % 100); 264 time / 100, time % 100);
265 rb->lcd_puts(0, 0, pbuf); 265 rb->lcd_puts(0, 0, pbuf);
266 gray_deferred_lcd_update(); /* schedule an lcd_update() */ 266 grey_deferred_lcd_update(); /* schedule an lcd_update() */
267#ifdef HAVE_ADJUSTABLE_CPU_FREQ 267#ifdef HAVE_ADJUSTABLE_CPU_FREQ
268 rb->cpu_boost(false); 268 rb->cpu_boost(false);
269#endif 269#endif
@@ -271,7 +271,7 @@ int main(void)
271 /* drawing is now finished, play around with scrolling 271 /* drawing is now finished, play around with scrolling
272 * until you press OFF or connect USB 272 * until you press OFF or connect USB
273 */ 273 */
274 gray_set_background(255); 274 grey_set_background(255);
275 while (true) 275 while (true)
276 { 276 {
277 scroll_amount = 1; 277 scroll_amount = 1;
@@ -282,11 +282,11 @@ int main(void)
282 == SYS_USB_CONNECTED) 282 == SYS_USB_CONNECTED)
283 return PLUGIN_USB_CONNECTED; 283 return PLUGIN_USB_CONNECTED;
284 284
285 if (button & GRAYSCALE_SHIFT) 285 if (button & GREYSCALE_SHIFT)
286 { 286 {
287 if (!black_border) 287 if (!black_border)
288 { 288 {
289 gray_set_background(0); 289 grey_set_background(0);
290 black_border = true; 290 black_border = true;
291 } 291 }
292 } 292 }
@@ -294,7 +294,7 @@ int main(void)
294 { 294 {
295 if (black_border) 295 if (black_border)
296 { 296 {
297 gray_set_background(255); 297 grey_set_background(255);
298 black_border = false; 298 black_border = false;
299 } 299 }
300 } 300 }
@@ -302,35 +302,35 @@ int main(void)
302 if (button & BUTTON_REPEAT) 302 if (button & BUTTON_REPEAT)
303 scroll_amount = 4; 303 scroll_amount = 4;
304 304
305 switch (button & ~(GRAYSCALE_SHIFT | BUTTON_REPEAT)) 305 switch (button & ~(GREYSCALE_SHIFT | BUTTON_REPEAT))
306 { 306 {
307 case GRAYSCALE_LEFT: 307 case GREYSCALE_LEFT:
308 308
309 gray_scroll_left(scroll_amount); /* scroll left */ 309 grey_scroll_left(scroll_amount); /* scroll left */
310 gray_update(); 310 grey_update();
311 break; 311 break;
312 312
313 case GRAYSCALE_RIGHT: 313 case GREYSCALE_RIGHT:
314 314
315 gray_scroll_right(scroll_amount); /* scroll right */ 315 grey_scroll_right(scroll_amount); /* scroll right */
316 gray_update(); 316 grey_update();
317 break; 317 break;
318 318
319 case GRAYSCALE_UP: 319 case GREYSCALE_UP:
320 320
321 gray_scroll_up(scroll_amount); /* scroll up */ 321 grey_scroll_up(scroll_amount); /* scroll up */
322 gray_update(); 322 grey_update();
323 break; 323 break;
324 324
325 case GRAYSCALE_DOWN: 325 case GREYSCALE_DOWN:
326 326
327 gray_scroll_down(scroll_amount); /* scroll down */ 327 grey_scroll_down(scroll_amount); /* scroll down */
328 gray_update(); 328 grey_update();
329 break; 329 break;
330#ifdef GRAYSCALE_RC_OFF 330#ifdef GREYSCALE_RC_OFF
331 case GRAYSCALE_RC_OFF: 331 case GREYSCALE_RC_OFF:
332#endif 332#endif
333 case GRAYSCALE_OFF: 333 case GREYSCALE_OFF:
334 334
335 cleanup(NULL); 335 cleanup(NULL);
336 return PLUGIN_OK; 336 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 @@
11* (This is a real mess if it has to be coded in one single C file) 11* (This is a real mess if it has to be coded in one single C file)
12* 12*
13* File scrolling addition (C) 2005 Alexander Spyridakis 13* File scrolling addition (C) 2005 Alexander Spyridakis
14* Copyright (C) 2004 J�g Hohensohn aka [IDC]Dragon 14* Copyright (C) 2004 Jörg Hohensohn aka [IDC]Dragon
15* Grayscale framework (C) 2004 Jens Arnold
16* Heavily borrowed from the IJG implementation (C) Thomas G. Lane 15* Heavily borrowed from the IJG implementation (C) Thomas G. Lane
17* Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org 16* Small & fast downscaling IDCT (C) 2002 by Guido Vollbeding JPEGclub.org
18* 17*
@@ -30,7 +29,7 @@
30#include "helper.h" 29#include "helper.h"
31 30
32#ifdef HAVE_LCD_BITMAP 31#ifdef HAVE_LCD_BITMAP
33#include "gray.h" 32#include "grey.h"
34#include "xlcd.h" 33#include "xlcd.h"
35 34
36#ifdef HAVE_LCD_COLOR 35#ifdef HAVE_LCD_COLOR
@@ -185,9 +184,9 @@ PLUGIN_HEADER
185/* different graphics libraries */ 184/* different graphics libraries */
186#if LCD_DEPTH < 8 185#if LCD_DEPTH < 8
187#define USEGSLIB 186#define USEGSLIB
188#define MYLCD(fn) gray_ub_ ## fn 187#define MYLCD(fn) grey_ub_ ## fn
189#define MYLCD_UPDATE() 188#define MYLCD_UPDATE()
190#define MYXLCD(fn) gray_ub_ ## fn 189#define MYXLCD(fn) grey_ub_ ## fn
191#else 190#else
192#define MYLCD(fn) rb->lcd_ ## fn 191#define MYLCD(fn) rb->lcd_ ## fn
193#define MYLCD_UPDATE() rb->lcd_update(); 192#define MYLCD_UPDATE() rb->lcd_update();
@@ -2409,7 +2408,7 @@ void cleanup(void *parameter)
2409{ 2408{
2410 (void)parameter; 2409 (void)parameter;
2411#ifdef USEGSLIB 2410#ifdef USEGSLIB
2412 gray_show(false); 2411 grey_show(false);
2413#endif 2412#endif
2414} 2413}
2415 2414
@@ -2791,13 +2790,13 @@ int scroll_bmp(struct t_disp* pdisp)
2791#endif 2790#endif
2792 case JPEG_MENU: 2791 case JPEG_MENU:
2793#ifdef USEGSLIB 2792#ifdef USEGSLIB
2794 gray_show(false); /* switch off grayscale overlay */ 2793 grey_show(false); /* switch off greyscale overlay */
2795#endif 2794#endif
2796 if (show_menu() == 1) 2795 if (show_menu() == 1)
2797 return PLUGIN_OK; 2796 return PLUGIN_OK;
2798 2797
2799#ifdef USEGSLIB 2798#ifdef USEGSLIB
2800 gray_show(true); /* switch on grayscale overlay */ 2799 grey_show(true); /* switch on greyscale overlay */
2801#else 2800#else
2802 yuv_bitmap_part( 2801 yuv_bitmap_part(
2803 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, 2802 pdisp->bitmap, pdisp->csub_x, pdisp->csub_y,
@@ -3222,7 +3221,7 @@ int load_and_show(char* filename)
3222 MYLCD_UPDATE(); 3221 MYLCD_UPDATE();
3223 3222
3224#ifdef USEGSLIB 3223#ifdef USEGSLIB
3225 gray_show(true); /* switch on grayscale overlay */ 3224 grey_show(true); /* switch on greyscale overlay */
3226#endif 3225#endif
3227 3226
3228 /* drawing is now finished, play around with scrolling 3227 /* drawing is now finished, play around with scrolling
@@ -3260,7 +3259,7 @@ int load_and_show(char* filename)
3260 } 3259 }
3261 3260
3262#ifdef USEGSLIB 3261#ifdef USEGSLIB
3263 gray_show(false); /* switch off overlay */ 3262 grey_show(false); /* switch off overlay */
3264#endif 3263#endif
3265 rb->lcd_clear_display(); 3264 rb->lcd_clear_display();
3266 } 3265 }
@@ -3280,8 +3279,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
3280 3279
3281 int condition; 3280 int condition;
3282#ifdef USEGSLIB 3281#ifdef USEGSLIB
3283 int grayscales; 3282 long greysize; /* helper */
3284 long graysize; /* helper */
3285#endif 3283#endif
3286#if LCD_DEPTH > 1 3284#if LCD_DEPTH > 1
3287 old_backdrop = rb->lcd_get_backdrop(); 3285 old_backdrop = rb->lcd_get_backdrop();
@@ -3311,16 +3309,13 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
3311#endif 3309#endif
3312 3310
3313#ifdef USEGSLIB 3311#ifdef USEGSLIB
3314 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */ 3312 if (!grey_init(rb, buf, buf_size, false, LCD_WIDTH, LCD_HEIGHT, &greysize))
3315 grayscales = gray_init(rb, buf, buf_size, false, LCD_WIDTH, LCD_HEIGHT,
3316 32, 2<<8, &graysize) + 1;
3317 buf += graysize;
3318 buf_size -= graysize;
3319 if (grayscales < 33 || buf_size <= 0)
3320 { 3313 {
3321 rb->splash(HZ, "gray buf error"); 3314 rb->splash(HZ, "grey buf error");
3322 return PLUGIN_ERROR; 3315 return PLUGIN_ERROR;
3323 } 3316 }
3317 buf += greysize;
3318 buf_size -= greysize;
3324#else 3319#else
3325 xlcd_init(rb); 3320 xlcd_init(rb);
3326#endif 3321#endif
@@ -3364,7 +3359,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
3364 backlight_use_settings(rb); /* backlight control in lib/helper.c */ 3359 backlight_use_settings(rb); /* backlight control in lib/helper.c */
3365 3360
3366#ifdef USEGSLIB 3361#ifdef USEGSLIB
3367 gray_release(); /* deinitialize */ 3362 grey_release(); /* deinitialize */
3368#endif 3363#endif
3369 3364
3370 return condition; 3365 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
8gray_draw.c 8gray_draw.c
9gray_parm.c 9gray_parm.c
10gray_scroll.c 10gray_scroll.c
11grey_core.c
12grey_draw.c
13grey_parm.c
14grey_scroll.c
11#endif 15#endif
12highscore.c 16highscore.c
13#ifndef SIMULATOR 17#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 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* New greyscale framework
11*
12* This is a generic framework to display 129 shades of grey on low-depth
13* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
14*
15* Copyright (C) 2008 Jens Arnold
16*
17* All files in this archive are subject to the GNU General Public License.
18* See the file COPYING in the source tree root for full license agreement.
19*
20* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21* KIND, either express or implied.
22*
23****************************************************************************/
24
25#ifndef __GREY_H__
26#define __GREY_H__
27
28#include "plugin.h"
29
30#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4)
31
32#define GREY_BRIGHTNESS(y) (y)
33
34#define GREY_BLACK GREY_BRIGHTNESS(0)
35#define GREY_DARKGRAY GREY_BRIGHTNESS(85)
36#define GREY_LIGHTGRAY GREY_BRIGHTNESS(170)
37#define GREY_WHITE GREY_BRIGHTNESS(255)
38
39/* Library initialisation and release */
40bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
41 bool buffered, int width, int height, long *buf_taken);
42void grey_release(void);
43
44/* Special functions */
45void grey_show(bool enable);
46void grey_deferred_lcd_update(void);
47
48/* Update functions */
49void grey_update(void);
50void grey_update_rect(int x, int y, int width, int height);
51
52/* Parameter handling */
53void grey_set_position(int x, int y);
54void grey_set_drawmode(int mode);
55int grey_get_drawmode(void);
56void grey_set_foreground(unsigned brightness);
57unsigned grey_get_foreground(void);
58void grey_set_background(unsigned brightness);
59unsigned grey_get_background(void);
60void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness);
61void grey_setfont(int newfont);
62int grey_getstringsize(const unsigned char *str, int *w, int *h);
63
64/* Whole display */
65void grey_clear_display(void);
66void grey_ub_clear_display(void);
67
68/* Pixel */
69void grey_drawpixel(int x, int y);
70
71/* Lines */
72void grey_drawline(int x1, int y1, int x2, int y2);
73void grey_hline(int x1, int x2, int y);
74void grey_vline(int x, int y1, int y2);
75void grey_drawrect(int x, int y, int nx, int ny);
76
77/* Filled primitives */
78void grey_fillrect(int x, int y, int nx, int ny);
79void grey_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3);
80
81/* Bitmaps */
82void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
83 int stride, int x, int y, int width, int height);
84void grey_mono_bitmap(const unsigned char *src, int x, int y, int width,
85 int height);
86void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
87 int stride, int x, int y, int width, int height);
88void grey_gray_bitmap(const unsigned char *src, int x, int y, int width,
89 int height);
90void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
91 int stride, int x, int y, int width, int height);
92void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width,
93 int height);
94
95/* Text */
96void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str);
97void grey_putsxy(int x, int y, const unsigned char *str);
98
99/* Scrolling */
100void grey_scroll_left(int count);
101void grey_scroll_right(int count);
102void grey_scroll_up(int count);
103void grey_scroll_down(int count);
104void grey_ub_scroll_left(int count);
105void grey_ub_scroll_right(int count);
106void grey_ub_scroll_up(int count);
107void grey_ub_scroll_down(int count);
108
109/*** Internal stuff ***/
110
111/* flag definitions */
112#define _GREY_RUNNING 0x0001 /* greyscale overlay is running */
113#define _GREY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */
114
115/* fast unsigned multiplication (16x16bit->32bit or 32x32bit->32bit,
116 * whichever is faster for the architecture) */
117#ifdef CPU_ARM
118#define _GREY_MULUQ(a, b) ((uint32_t) (((uint32_t) (a)) * ((uint32_t) (b))))
119#else
120#define _GREY_MULUQ(a, b) ((uint32_t) (((uint16_t) (a)) * ((uint16_t) (b))))
121#endif
122
123#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
124#define _GREY_X_ADVANCE sizeof(struct grey_data)
125#else
126#if LCD_DEPTH == 1
127#define _GREY_X_ADVANCE (8*sizeof(struct grey_data))
128#elif LCD_DEPTH == 2
129#define _GREY_X_ADVANCE (4*sizeof(struct grey_data))
130#endif
131#endif /* LCD_PIXELFORMAT */
132
133/* The greyscale buffer management structure */
134struct _grey_info
135{
136 int x;
137 int y;
138 int width;
139 int height;
140#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
141 int bx; /* 8-pixel units */
142 int bwidth; /* 8-pixel units */
143#else /* vertical packing */
144 int by; /* 4-pixel or 8-pixel units */
145 int bheight; /* 4-pixel or 8-pixel units */
146#endif
147 unsigned long flags; /* various flags, see #defines */
148#ifndef SIMULATOR
149 struct grey_data *data; /* start of greyscale display data */
150#endif
151 unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */
152 unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */
153 int fg_val; /* current foreground value */
154 int bg_val; /* current background value */
155 int fg_brightness; /* current foreground brightness */
156 int bg_brightness; /* current background brightness */
157 int drawmode; /* current draw mode */
158 int curfont; /* current selected font */
159};
160
161/* Global variables */
162extern struct plugin_api *_grey_rb;
163extern struct _grey_info _grey_info;
164
165#endif /* HAVE_LCD_BITMAP && (LCD_DEPTH < 4) */
166#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 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* New greyscale framework
11* Core & miscellaneous functions
12*
13* This is a generic framework to display 129 shades of grey on low-depth
14* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
15*
16* Copyright (C) 2008 Jens Arnold
17*
18* All files in this archive are subject to the GNU General Public License.
19* See the file COPYING in the source tree root for full license agreement.
20*
21* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22* KIND, either express or implied.
23*
24****************************************************************************/
25
26#include "plugin.h"
27#include "grey.h"
28
29#if defined(CPU_PP) && defined(HAVE_ADJUSTABLE_CPU_FREQ)
30#define NEED_BOOST
31#endif
32
33/* Global variables */
34struct plugin_api *_grey_rb = NULL; /* global api struct pointer */
35struct _grey_info _grey_info; /* global info structure */
36
37#ifndef SIMULATOR
38
39#if CONFIG_LCD == LCD_SSD1815 || CONFIG_LCD == LCD_IFP7XX
40/* measured and interpolated curve */
41/* TODO: check for iFP */
42static const unsigned char lcdlinear[256] = {
43 0, 3, 5, 8, 11, 13, 16, 18,
44 21, 23, 26, 28, 31, 33, 36, 38,
45 40, 42, 45, 47, 49, 51, 53, 55,
46 57, 59, 60, 62, 64, 66, 67, 69,
47 70, 72, 73, 74, 76, 77, 78, 79,
48 81, 82, 83, 84, 85, 86, 87, 88,
49 88, 89, 90, 91, 92, 92, 93, 94,
50 95, 95, 96, 97, 97, 98, 99, 99,
51 100, 101, 102, 102, 103, 104, 104, 105,
52 106, 106, 107, 107, 108, 109, 109, 110,
53 111, 111, 112, 113, 113, 114, 114, 115,
54 116, 116, 117, 117, 118, 119, 119, 120,
55 120, 121, 121, 122, 122, 123, 123, 124,
56 124, 125, 125, 126, 126, 127, 127, 128,
57 128, 128, 129, 129, 130, 130, 131, 131,
58 132, 132, 133, 133, 133, 134, 134, 135,
59 135, 136, 136, 137, 137, 138, 138, 138,
60 139, 139, 140, 140, 141, 141, 142, 142,
61 143, 143, 144, 144, 145, 145, 146, 146,
62 147, 147, 148, 148, 148, 149, 149, 150,
63 150, 151, 151, 152, 152, 153, 153, 153,
64 154, 154, 155, 155, 156, 156, 157, 157,
65 158, 158, 158, 159, 159, 160, 160, 161,
66 161, 162, 162, 163, 163, 164, 164, 165,
67 165, 166, 167, 167, 168, 168, 169, 169,
68 170, 171, 171, 172, 173, 173, 174, 175,
69 176, 176, 177, 178, 179, 180, 181, 181,
70 182, 183, 184, 185, 186, 188, 189, 190,
71 191, 192, 194, 195, 196, 198, 199, 201,
72 202, 204, 205, 207, 209, 211, 213, 215,
73 217, 219, 222, 224, 226, 229, 231, 234,
74 236, 239, 242, 244, 247, 250, 252, 255
75};
76#elif CONFIG_LCD == LCD_S1D15E06
77/* measured and interpolated curve */
78static const unsigned char lcdlinear[256] = {
79 0, 5, 11, 16, 21, 27, 32, 37,
80 42, 47, 51, 56, 60, 64, 68, 72,
81 75, 78, 81, 84, 87, 89, 91, 93,
82 95, 96, 98, 99, 101, 102, 103, 104,
83 105, 106, 107, 108, 109, 110, 111, 111,
84 112, 113, 113, 114, 115, 115, 116, 117,
85 117, 118, 118, 119, 119, 120, 120, 121,
86 121, 122, 122, 123, 123, 124, 124, 125,
87 125, 126, 126, 127, 127, 127, 128, 128,
88 129, 129, 130, 130, 131, 131, 132, 132,
89 133, 133, 134, 134, 135, 135, 136, 136,
90 137, 137, 138, 138, 138, 139, 139, 140,
91 140, 141, 141, 141, 142, 142, 143, 143,
92 143, 144, 144, 145, 145, 145, 146, 146,
93 146, 147, 147, 147, 148, 148, 149, 149,
94 149, 150, 150, 150, 151, 151, 151, 152,
95 152, 153, 153, 153, 154, 154, 155, 155,
96 155, 156, 156, 157, 157, 157, 158, 158,
97 159, 159, 159, 160, 160, 161, 161, 162,
98 162, 162, 163, 163, 164, 164, 164, 165,
99 165, 166, 166, 167, 167, 167, 168, 168,
100 169, 169, 170, 170, 170, 171, 171, 172,
101 172, 173, 173, 174, 174, 175, 175, 176,
102 176, 177, 177, 178, 178, 179, 179, 180,
103 180, 181, 182, 182, 183, 184, 184, 185,
104 186, 186, 187, 188, 188, 189, 190, 191,
105 191, 192, 193, 194, 195, 196, 196, 197,
106 198, 199, 200, 201, 202, 203, 204, 205,
107 206, 207, 208, 209, 210, 211, 213, 214,
108 215, 216, 218, 219, 220, 222, 223, 225,
109 227, 228, 230, 232, 233, 235, 237, 239,
110 241, 243, 245, 247, 249, 251, 253, 255
111};
112#elif (CONFIG_LCD == LCD_IPOD2BPP) || (CONFIG_LCD == LCD_IPODMINI)
113/* measured and interpolated curve for mini LCD */
114/* TODO: verify this curve on the fullsize greyscale LCD */
115static const unsigned char lcdlinear[256] = {
116 0, 3, 6, 8, 11, 14, 17, 19,
117 22, 24, 27, 29, 32, 34, 36, 38,
118 40, 42, 44, 45, 47, 48, 50, 51,
119 52, 54, 55, 56, 57, 58, 58, 59,
120 60, 61, 62, 62, 63, 64, 64, 65,
121 66, 66, 67, 67, 68, 68, 69, 69,
122 70, 70, 70, 71, 71, 71, 72, 72,
123 73, 73, 73, 74, 74, 74, 74, 75,
124 75, 75, 76, 76, 76, 77, 77, 77,
125 78, 78, 78, 79, 79, 79, 80, 80,
126 80, 80, 81, 81, 81, 82, 82, 82,
127 83, 83, 83, 84, 84, 84, 85, 85,
128 85, 85, 86, 86, 86, 87, 87, 87,
129 87, 88, 88, 88, 89, 89, 89, 89,
130 90, 90, 90, 91, 91, 91, 92, 92,
131 92, 93, 93, 93, 94, 94, 94, 95,
132 95, 96, 96, 96, 97, 97, 98, 98,
133 99, 99, 99, 100, 100, 101, 101, 102,
134 102, 103, 103, 104, 104, 105, 105, 106,
135 106, 107, 107, 108, 108, 109, 109, 110,
136 110, 111, 111, 112, 113, 113, 114, 114,
137 115, 115, 116, 117, 117, 118, 118, 119,
138 120, 120, 121, 122, 122, 123, 124, 124,
139 125, 126, 126, 127, 128, 128, 129, 130,
140 131, 131, 132, 133, 134, 134, 135, 136,
141 137, 138, 139, 140, 141, 142, 143, 144,
142 145, 146, 147, 148, 149, 150, 152, 153,
143 154, 156, 157, 159, 160, 162, 163, 165,
144 167, 168, 170, 172, 174, 176, 178, 180,
145 182, 184, 187, 189, 192, 194, 197, 200,
146 203, 206, 209, 212, 215, 219, 222, 226,
147 229, 233, 236, 240, 244, 248, 251, 255
148};
149#endif
150#else /* SIMULATOR */
151/* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */
152static const unsigned char lcdlinear[256] = {
153 0, 16, 23, 28, 32, 36, 39, 42,
154 45, 48, 50, 53, 55, 58, 60, 62,
155 64, 66, 68, 70, 71, 73, 75, 77,
156 78, 80, 81, 83, 84, 86, 87, 89,
157 90, 92, 93, 94, 96, 97, 98, 100,
158 101, 102, 103, 105, 106, 107, 108, 109,
159 111, 112, 113, 114, 115, 116, 117, 118,
160 119, 121, 122, 123, 124, 125, 126, 127,
161 128, 129, 130, 131, 132, 133, 134, 135,
162 135, 136, 137, 138, 139, 140, 141, 142,
163 143, 144, 145, 145, 146, 147, 148, 149,
164 150, 151, 151, 152, 153, 154, 155, 156,
165 156, 157, 158, 159, 160, 160, 161, 162,
166 163, 164, 164, 165, 166, 167, 167, 168,
167 169, 170, 170, 171, 172, 173, 173, 174,
168 175, 176, 176, 177, 178, 179, 179, 180,
169 181, 181, 182, 183, 183, 184, 185, 186,
170 186, 187, 188, 188, 189, 190, 190, 191,
171 192, 192, 193, 194, 194, 195, 196, 196,
172 197, 198, 198, 199, 199, 200, 201, 201,
173 202, 203, 203, 204, 204, 205, 206, 206,
174 207, 208, 208, 209, 209, 210, 211, 211,
175 212, 212, 213, 214, 214, 215, 215, 216,
176 217, 217, 218, 218, 219, 220, 220, 221,
177 221, 222, 222, 223, 224, 224, 225, 225,
178 226, 226, 227, 228, 228, 229, 229, 230,
179 230, 231, 231, 232, 233, 233, 234, 234,
180 235, 235, 236, 236, 237, 237, 238, 238,
181 239, 240, 240, 241, 241, 242, 242, 243,
182 243, 244, 244, 245, 245, 246, 246, 247,
183 247, 248, 248, 249, 249, 250, 250, 251,
184 251, 252, 252, 253, 253, 254, 254, 255
185};
186#endif /* SIMULATOR */
187
188/* Prototypes */
189static inline void _deferred_update(void) __attribute__ ((always_inline));
190static int exp_s16p16(int x);
191static int log_s16p16(int x);
192static void grey_screendump_hook(int fd);
193#ifdef SIMULATOR
194static unsigned long _grey_get_pixel(int x, int y);
195#else
196static void _timer_isr(void);
197#endif
198
199/* Update LCD areas not covered by the greyscale overlay */
200static inline void _deferred_update(void)
201{
202 int x1 = MAX(_grey_info.x, 0);
203 int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH);
204 int y1 = MAX(_grey_info.y, 0);
205 int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT);
206
207 if (y1 > 0) /* refresh part above overlay, full width */
208 _grey_rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
209
210 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
211 _grey_rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
212
213 if (x1 > 0) /* refresh part to the left of overlay */
214 _grey_rb->lcd_update_rect(0, y1, x1, y2 - y1);
215
216 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
217 _grey_rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
218}
219
220#ifndef SIMULATOR
221/* Timer interrupt handler: display next frame */
222static void _timer_isr(void)
223{
224#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
225 _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.bx, _grey_info.y,
226 _grey_info.bwidth, _grey_info.height,
227 _grey_info.width);
228#else
229 _grey_rb->lcd_grey_phase_blit(_grey_info.data, _grey_info.x, _grey_info.by,
230 _grey_info.width, _grey_info.bheight,
231 _grey_info.width);
232#endif
233
234 if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */
235 {
236 _deferred_update();
237 _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */
238 }
239}
240#endif /* !SIMULATOR */
241
242/* fixed point exp() */
243static int exp_s16p16(int x)
244{
245 int t;
246 int y = 0x00010000;
247
248 if (x < 0) x += 0xb1721, y >>= 16;
249 t = x - 0x58b91; if (t >= 0) x = t, y <<= 8;
250 t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4;
251 t = x - 0x162e4; if (t >= 0) x = t, y <<= 2;
252 t = x - 0x0b172; if (t >= 0) x = t, y <<= 1;
253 t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1;
254 t = x - 0x03920; if (t >= 0) x = t, y += y >> 2;
255 t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3;
256 t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4;
257 t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5;
258 t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6;
259 t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7;
260 y += ((y >> 8) * x) >> 8;
261
262 return y;
263}
264
265/* fixed point log() */
266static int log_s16p16(int x)
267{
268 int t;
269 int y = 0xa65af;
270
271 if (x < 0x00008000) x <<=16, y -= 0xb1721;
272 if (x < 0x00800000) x <<= 8, y -= 0x58b91;
273 if (x < 0x08000000) x <<= 4, y -= 0x2c5c8;
274 if (x < 0x20000000) x <<= 2, y -= 0x162e4;
275 if (x < 0x40000000) x <<= 1, y -= 0x0b172;
276 t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd;
277 t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920;
278 t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27;
279 t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85;
280 t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1;
281 t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8;
282 t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe;
283 x = 0x80000000 - x;
284 y -= x >> 15;
285
286 return y;
287}
288
289/* Initialise the framework and prepare the greyscale display buffer
290
291 arguments:
292 newrb = pointer to plugin api
293 gbuf = pointer to the memory area to use (e.g. plugin buffer)
294 gbuf_size = max usable size of the buffer
295 buffered = use chunky pixel buffering?
296 This allows to use all drawing functions, but needs more
297 memory. Unbuffered operation provides only a subset of
298 drawing functions. (only grey_bitmap drawing and scrolling)
299 width = width in pixels (1..LCD_WIDTH)
300 height = height in pixels (1..LCD_HEIGHT)
301 Note that depending on the target LCD, either height or
302 width are rounded up to a multiple of 4 or 8.
303
304 result:
305 true on success, false on failure
306
307 If you need info about the memory taken by the greyscale buffer, supply a
308 long* as the last parameter. This long will then contain the number of bytes
309 used. The total memory needed can be calculated as follows:
310 total_mem =
311 width * height * 2 [grey display data]
312 + buffered ? (width * height) : 0 [chunky buffer]
313 + 0..3 [alignment]
314
315 The function is authentic regarding memory usage on the simulator, even
316 if it doesn't use all of the allocated memory. */
317bool grey_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
318 bool buffered, int width, int height, long *buf_taken)
319{
320 int bdim, i;
321 long plane_size, buftaken;
322 unsigned data;
323#ifndef SIMULATOR
324 struct grey_data *grey_data, *grey_end;
325#endif
326
327 _grey_rb = newrb;
328
329 if ((unsigned) width > LCD_WIDTH
330 || (unsigned) height > LCD_HEIGHT)
331 return false;
332
333#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
334 bdim = (width + 7) >> 3;
335 width = bdim << 3;
336#else /* vertical packing */
337#if LCD_DEPTH == 1
338 bdim = (height + 7) >> 3;
339 height = bdim << 3;
340#elif LCD_DEPTH == 2
341 bdim = (height + 3) >> 2;
342 height = bdim << 2;
343#endif
344#endif
345
346 /* the buffer has to be long aligned */
347 buftaken = (-(long)gbuf) & 3;
348 gbuf += buftaken;
349
350 plane_size = _GREY_MULUQ(width, height);
351
352 if (buffered) /* chunky buffer */
353 {
354 buftaken += plane_size;
355 _grey_info.buffer = gbuf;
356 gbuf += plane_size;
357 }
358 buftaken += sizeof(struct grey_data) * plane_size;
359 if (buftaken > gbuf_size)
360 return false;
361
362#ifdef SIMULATOR
363 _grey_info.buffer = gbuf;
364#else
365 grey_data = (struct grey_data *)gbuf;
366 grey_end = grey_data + plane_size;
367 _grey_info.data = grey_data;
368
369 while (grey_data < grey_end)
370 {
371 grey_data->phase = _grey_rb->rand() & 0xff;
372 grey_data->value = 128; /* init to white */
373 grey_data++;
374 }
375#endif
376
377 _grey_info.x = 0;
378 _grey_info.y = 0;
379 _grey_info.width = width;
380 _grey_info.height = height;
381#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
382 _grey_info.bx = 0;
383 _grey_info.bwidth = bdim;
384#else
385 _grey_info.by = 0;
386 _grey_info.bheight = bdim;
387#endif
388 _grey_info.flags = 0;
389 _grey_info.fg_val = 0;
390 _grey_info.bg_val = 128;
391 _grey_info.fg_brightness = 0;
392 _grey_info.bg_brightness = 255;
393 _grey_info.drawmode = DRMODE_SOLID;
394 _grey_info.curfont = FONT_SYSFIXED;
395
396
397 /* precalculate the value -> pattern index conversion table, taking
398 linearisation and gamma correction into account */
399 for (i = 0; i < 256; i++)
400 {
401 data = exp_s16p16(((2<<8) * log_s16p16(i * 257 + 1)) >> 8) + 128;
402 data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */
403 data = (lcdlinear[data] << 7) + 127;
404 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
405 /* approx. data / 255 */
406 }
407
408 if (buf_taken) /* caller requested info about space taken */
409 *buf_taken = buftaken;
410
411 return true;
412}
413
414/* Release the greyscale display buffer and the library
415 DO CALL either this function or at least grey_show_display(false)
416 before you exit, otherwise nasty things may happen. */
417void grey_release(void)
418{
419 grey_show(false);
420}
421
422/* Switch the greyscale overlay on or off
423 DO NOT call lcd_update() or any other api function that directly accesses
424 the lcd while the greyscale overlay is running! If you need to do
425 lcd_update() to update something outside the greyscale overlay area, use
426 grey_deferred_update() instead.
427
428 Other functions to avoid are:
429 lcd_blit() (obviously), lcd_update_rect(), lcd_set_contrast(),
430 lcd_set_invert_display(), lcd_set_flip() */
431void grey_show(bool enable)
432{
433 if (enable && !(_grey_info.flags & _GREY_RUNNING))
434 {
435 _grey_info.flags |= _GREY_RUNNING;
436#ifdef SIMULATOR
437 _grey_rb->sim_lcd_ex_init(129, _grey_get_pixel);
438 grey_update();
439#else /* !SIMULATOR */
440#ifdef NEED_BOOST
441 _grey_rb->cpu_boost(true);
442#endif
443#if CONFIG_LCD == LCD_SSD1815
444 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 67, 1, _timer_isr);
445#elif CONFIG_LCD == LCD_S1D15E06
446 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 70, 1, _timer_isr);
447#elif CONFIG_LCD == LCD_IPOD2BPP
448#ifdef IPOD_1G2G
449 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 95, 1, _timer_isr); /* verified */
450#elif defined IPOD_3G
451 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 87, 1, _timer_isr); /* verified */
452#else
453 /* FIXME: verify value */
454 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 80, 1, _timer_isr);
455#endif
456#elif CONFIG_LCD == LCD_IPODMINI
457 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 88, 1, _timer_isr);
458#elif CONFIG_LCD == LCD_IFP7XX
459 _grey_rb->timer_register(1, NULL, TIMER_FREQ / 83, 1, _timer_isr);
460#endif /* CONFIG_LCD */
461#endif /* !SIMULATOR */
462 _grey_rb->screen_dump_set_hook(grey_screendump_hook);
463 }
464 else if (!enable && (_grey_info.flags & _GREY_RUNNING))
465 {
466#ifdef SIMULATOR
467 _grey_rb->sim_lcd_ex_init(0, NULL);
468#else
469 _grey_rb->timer_unregister();
470#ifdef NEED_BOOST
471 _grey_rb->cpu_boost(false);
472#endif
473#endif
474 _grey_info.flags &= ~_GREY_RUNNING;
475 _grey_rb->screen_dump_set_hook(NULL);
476 _grey_rb->lcd_update(); /* restore whatever there was before */
477 }
478}
479
480#ifdef SIMULATOR
481/* Callback function for grey_update_rect() to read a pixel from the greybuffer.
482 Note that x and y are in LCD coordinates, not greybuffer coordinates! */
483static unsigned long _grey_get_pixel(int x, int y)
484{
485 return _grey_info.buffer[(y - _grey_info.y) * _grey_info.width
486 + x - _grey_info.x] + (1 << LCD_DEPTH);
487}
488
489/* Update a rectangular area of the greyscale overlay */
490void grey_update_rect(int x, int y, int width, int height)
491{
492 if (x + width > _grey_info.width)
493 width = _grey_info.width - x;
494 if (y + height > _grey_info.height)
495 height = _grey_info.height - y;
496
497 x += _grey_info.x;
498 y += _grey_info.y;
499
500 if (x + width > LCD_WIDTH)
501 width = LCD_WIDTH - x;
502 if (y + height > LCD_HEIGHT)
503 height = LCD_HEIGHT - y;
504
505 _grey_rb->sim_lcd_ex_update_rect(x, y, width, height);
506}
507
508#else /* !SIMULATOR */
509
510void grey_update_rect(int x, int y, int width, int height)
511{
512 unsigned char *src;
513
514 if ((width <= 0) || (height <= 0))
515 return; /* nothing to do */
516
517 if (y + height > _grey_info.height)
518 height = _grey_info.height - y;
519 if (x + width > _grey_info.width)
520 width = _grey_info.width - x;
521
522 src = _grey_info.buffer + _GREY_MULUQ(_grey_info.width, y) + x;
523
524 do
525 {
526#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
527 int idx = _GREY_MULUQ(_grey_info.width, y) + x;
528#else
529#if LCD_DEPTH == 1
530 int idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (x << 3) + (~y & 7);
531#elif LCD_DEPTH == 2
532 int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3);
533#endif
534#endif /* LCD_PIXELFORMAT */
535 unsigned char *dst_row = &_grey_info.data[idx].value;
536 unsigned char *src_row = src;
537 unsigned char *src_end = src + width;
538
539 do
540 {
541 *dst_row = *src_row++;
542 dst_row += _GREY_X_ADVANCE;
543 }
544 while (src_row < src_end);
545
546 y++;
547 src += _grey_info.width;
548 }
549 while (--height > 0);
550}
551
552#endif /* !SIMULATOR */
553
554/* Update the whole greyscale overlay */
555void grey_update(void)
556{
557 grey_update_rect(0, 0, _grey_info.width, _grey_info.height);
558}
559
560/* Do an lcd_update() to show changes done by rb->lcd_xxx() functions
561 (in areas of the screen not covered by the greyscale overlay). */
562void grey_deferred_lcd_update(void)
563{
564 if (_grey_info.flags & _GREY_RUNNING)
565 {
566#ifdef SIMULATOR
567 _deferred_update();
568#else
569 _grey_info.flags |= _GREY_DEFERRED_UPDATE;
570#endif
571 }
572 else
573 _grey_rb->lcd_update();
574}
575
576/*** Screenshot ***/
577
578#define BMP_FIXEDCOLORS (1 << LCD_DEPTH)
579#define BMP_VARCOLORS 129
580#define BMP_NUMCOLORS (BMP_FIXEDCOLORS + BMP_VARCOLORS)
581#define BMP_BPP 8
582#define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3)
583#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
584#define BMP_DATASIZE (BMP_LINESIZE * LCD_HEIGHT)
585#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
586
587#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff
588#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff
589
590static const unsigned char bmpheader[] =
591{
592 0x42, 0x4d, /* 'BM' */
593 LE32_CONST(BMP_TOTALSIZE), /* Total file size */
594 0x00, 0x00, 0x00, 0x00, /* Reserved */
595 LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
596
597 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
598 LE32_CONST(LCD_WIDTH), /* Width in pixels */
599 LE32_CONST(LCD_HEIGHT), /* Height in pixels */
600 0x01, 0x00, /* Number of planes (always 1) */
601 LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
602 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */
603 LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
604 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
605 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
606 LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
607 LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
608
609 /* Fixed colours */
610#if LCD_DEPTH == 1
611 0x90, 0xee, 0x90, 0x00, /* Colour #0 */
612 0x00, 0x00, 0x00, 0x00 /* Colour #1 */
613#elif LCD_DEPTH == 2
614 0xe6, 0xd8, 0xad, 0x00, /* Colour #0 */
615 0x99, 0x90, 0x73, 0x00, /* Colour #1 */
616 0x4c, 0x48, 0x39, 0x00, /* Colour #2 */
617 0x00, 0x00, 0x00, 0x00 /* Colour #3 */
618#endif
619};
620
621#if LCD_DEPTH == 1
622#define BMP_RED 0x90
623#define BMP_GREEN 0xee
624#define BMP_BLUE 0x90
625#elif LCD_DEPTH == 2
626#define BMP_RED 0xad
627#define BMP_GREEN 0xd8
628#define BMP_BLUE 0xe6
629#endif
630
631/* Hook function for core screen_dump() to save the current display
632 content (b&w and greyscale overlay) to an 8-bit BMP file. */
633static void grey_screendump_hook(int fd)
634{
635 int i;
636 int x, y, gx, gy;
637#if LCD_PIXELFORMAT == VERTICAL_PACKING
638#if LCD_DEPTH == 1
639 unsigned mask;
640#elif LCD_DEPTH == 2
641 int shift;
642#endif
643#endif /* LCD_PIXELFORMAT == VERTICAL_PACKING */
644 unsigned char *lcdptr;
645 unsigned char *clut_entry;
646 unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)];
647
648 _grey_rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */
649
650 /* build clut */
651 _grey_rb->memset(linebuf, 0, 4*BMP_VARCOLORS);
652 clut_entry = linebuf;
653
654 for (i = 0; i <= 128; i++)
655 {
656 *clut_entry++ = _GREY_MULUQ(BMP_BLUE, i) >> 7;
657 *clut_entry++ = _GREY_MULUQ(BMP_GREEN, i) >> 7;
658 *clut_entry++ = _GREY_MULUQ(BMP_RED, i) >> 7;
659 clut_entry++;
660 }
661 _grey_rb->write(fd, linebuf, 4*BMP_VARCOLORS);
662
663 /* BMP image goes bottom -> top */
664 for (y = LCD_HEIGHT - 1; y >= 0; y--)
665 {
666 _grey_rb->memset(linebuf, 0, BMP_LINESIZE);
667
668 gy = y - _grey_info.y;
669#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
670#if LCD_DEPTH == 2
671 lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y);
672
673 for (x = 0; x < LCD_WIDTH; x += 4)
674 {
675 gx = x - _grey_info.x;
676
677 if (((unsigned)gy < (unsigned)_grey_info.height)
678 && ((unsigned)gx < (unsigned)_grey_info.width))
679 {
680#ifdef SIMULATOR
681 unsigned char *src = _grey_info.buffer
682 + _GREY_MULUQ(_grey_info.width, gy) + gx;
683
684 for (i = 0; i < 4; i++)
685 linebuf[x + i] = BMP_FIXEDCOLORS + *src++;
686#else
687 unsigned char *src = &_grey_info.data[_GREY_MULUQ(_grey_info.width,
688 gy) + gx].value;
689 for (i = 0; i < 4; i++)
690 {
691 linebuf[x + i] = BMP_FIXEDCOLORS + *src;
692 src += _GREY_X_ADVANCE;
693 }
694#endif
695 }
696 else
697 {
698 unsigned data = *lcdptr;
699 linebuf[x] = (data >> 6) & 3;
700 linebuf[x + 1] = (data >> 4) & 3;
701 linebuf[x + 2] = (data >> 2) & 3;
702 linebuf[x + 3] = data & 3;
703 }
704 lcdptr++;
705 }
706#endif /* LCD_DEPTH */
707#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */
708#if LCD_DEPTH == 1
709 mask = 1 << (y & 7);
710 lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
711
712 for (x = 0; x < LCD_WIDTH; x++)
713 {
714 gx = x - _grey_info.x;
715
716 if (((unsigned)gy < (unsigned)_grey_info.height)
717 && ((unsigned)gx < (unsigned)_grey_info.width))
718 {
719#ifdef SIMULATOR
720 linebuf[x] = BMP_FIXEDCOLORS
721 + _grey_info.buffer[_GREY_MULUQ(_grey_info.width,
722 gy) + gx];
723#else
724 linebuf[x] = BMP_FIXEDCOLORS
725 + _grey_info.data[_GREY_MULUQ(_grey_info.width,
726 gy & ~7) + (gx << 3) + (~gy & 7)].value;
727#endif
728 }
729 else
730 {
731 linebuf[x] = (*lcdptr & mask) ? 1 : 0;
732 }
733 lcdptr++;
734 }
735#elif LCD_DEPTH == 2
736 shift = 2 * (y & 3);
737 lcdptr = _grey_rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2);
738
739 for (x = 0; x < LCD_WIDTH; x++)
740 {
741 gx = x - _grey_info.x;
742
743 if (((unsigned)gy < (unsigned)_grey_info.height)
744 && ((unsigned)gx < (unsigned)_grey_info.width))
745 {
746#ifdef SIMULATOR
747 linebuf[x] = BMP_FIXEDCOLORS
748 + _grey_info.buffer[_GREY_MULUQ(_grey_info.width,
749 gy) + gx];
750#else
751 linebuf[x] = BMP_FIXEDCOLORS
752 + _grey_info.data[_GREY_MULUQ(_grey_info.width,
753 gy & ~3) + (gx << 2) + (~gy & 7)].value;
754#endif
755 }
756 else
757 {
758 linebuf[x] = (*lcdptr >> shift) & 3;
759 }
760 lcdptr++;
761 }
762#endif /* LCD_DEPTH */
763#endif /* LCD_PIXELFORMAT */
764
765 _grey_rb->write(fd, linebuf, BMP_LINESIZE);
766 }
767}
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 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* New greyscale framework
11* Drawing functions
12*
13* This is a generic framework to display 129 shades of grey on low-depth
14* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
15*
16* Copyright (C) 2008 Jens Arnold
17*
18* All files in this archive are subject to the GNU General Public License.
19* See the file COPYING in the source tree root for full license agreement.
20*
21* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22* KIND, either express or implied.
23*
24****************************************************************************/
25
26#include "plugin.h"
27#include "grey.h"
28
29/*** low-level drawing functions ***/
30
31static void setpixel(unsigned char *address)
32{
33 *address = _grey_info.fg_val;
34}
35
36static void clearpixel(unsigned char *address)
37{
38 *address = _grey_info.bg_val;
39}
40
41static void flippixel(unsigned char *address)
42{
43 *address = 128 - *address;
44}
45
46static void nopixel(unsigned char *address)
47{
48 (void)address;
49}
50
51void (* const _grey_pixelfuncs[8])(unsigned char *address) = {
52 flippixel, nopixel, setpixel, setpixel,
53 nopixel, clearpixel, nopixel, clearpixel
54};
55
56/*** Drawing functions ***/
57
58/* Clear the whole display */
59void grey_clear_display(void)
60{
61 int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
62 _grey_info.fg_val : _grey_info.bg_val;
63
64 _grey_rb->memset(_grey_info.buffer, value,
65 _GREY_MULUQ(_grey_info.width, _grey_info.height));
66}
67
68/* Set a single pixel */
69void grey_drawpixel(int x, int y)
70{
71 if (((unsigned)x < (unsigned)_grey_info.width)
72 && ((unsigned)y < (unsigned)_grey_info.height))
73 _grey_pixelfuncs[_grey_info.drawmode](&_grey_info.buffer[_GREY_MULUQ(
74 _grey_info.width, y) + x]);
75}
76
77/* Draw a line */
78void grey_drawline(int x1, int y1, int x2, int y2)
79{
80 int numpixels;
81 int i;
82 int deltax, deltay;
83 int d, dinc1, dinc2;
84 int x, xinc1, xinc2;
85 int y, yinc1, yinc2;
86 void (*pfunc)(unsigned char *address) = _grey_pixelfuncs[_grey_info.drawmode];
87
88 deltax = abs(x2 - x1);
89 deltay = abs(y2 - y1);
90 xinc2 = 1;
91 yinc2 = 1;
92
93 if (deltax >= deltay)
94 {
95 numpixels = deltax;
96 d = 2 * deltay - deltax;
97 dinc1 = deltay * 2;
98 dinc2 = (deltay - deltax) * 2;
99 xinc1 = 1;
100 yinc1 = 0;
101 }
102 else
103 {
104 numpixels = deltay;
105 d = 2 * deltax - deltay;
106 dinc1 = deltax * 2;
107 dinc2 = (deltax - deltay) * 2;
108 xinc1 = 0;
109 yinc1 = 1;
110 }
111 numpixels++; /* include endpoints */
112
113 if (x1 > x2)
114 {
115 xinc1 = -xinc1;
116 xinc2 = -xinc2;
117 }
118
119 if (y1 > y2)
120 {
121 yinc1 = -yinc1;
122 yinc2 = -yinc2;
123 }
124
125 x = x1;
126 y = y1;
127
128 for (i = 0; i < numpixels; i++)
129 {
130 if (((unsigned)x < (unsigned)_grey_info.width)
131 && ((unsigned)y < (unsigned)_grey_info.height))
132 pfunc(&_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]);
133
134 if (d < 0)
135 {
136 d += dinc1;
137 x += xinc1;
138 y += yinc1;
139 }
140 else
141 {
142 d += dinc2;
143 x += xinc2;
144 y += yinc2;
145 }
146 }
147}
148
149/* Draw a horizontal line (optimised) */
150void grey_hline(int x1, int x2, int y)
151{
152 int x;
153 int value = 0;
154 unsigned char *dst;
155 bool fillopt = false;
156 void (*pfunc)(unsigned char *address);
157
158 /* direction flip */
159 if (x2 < x1)
160 {
161 x = x1;
162 x1 = x2;
163 x2 = x;
164 }
165
166 /* nothing to draw? */
167 if (((unsigned)y >= (unsigned)_grey_info.height)
168 || (x1 >= _grey_info.width) || (x2 < 0))
169 return;
170
171 /* clipping */
172 if (x1 < 0)
173 x1 = 0;
174 if (x2 >= _grey_info.width)
175 x2 = _grey_info.width - 1;
176
177 if (_grey_info.drawmode & DRMODE_INVERSEVID)
178 {
179 if (_grey_info.drawmode & DRMODE_BG)
180 {
181 fillopt = true;
182 value = _grey_info.bg_val;
183 }
184 }
185 else
186 {
187 if (_grey_info.drawmode & DRMODE_FG)
188 {
189 fillopt = true;
190 value = _grey_info.fg_val;
191 }
192 }
193 pfunc = _grey_pixelfuncs[_grey_info.drawmode];
194 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x1];
195
196 if (fillopt)
197 _grey_rb->memset(dst, value, x2 - x1 + 1);
198 else
199 {
200 unsigned char *dst_end = dst + x2 - x1;
201 do
202 pfunc(dst++);
203 while (dst <= dst_end);
204 }
205}
206
207/* Draw a vertical line (optimised) */
208void grey_vline(int x, int y1, int y2)
209{
210 int y;
211 unsigned char *dst, *dst_end;
212 void (*pfunc)(unsigned char *address);
213
214 /* direction flip */
215 if (y2 < y1)
216 {
217 y = y1;
218 y1 = y2;
219 y2 = y;
220 }
221
222 /* nothing to draw? */
223 if (((unsigned)x >= (unsigned)_grey_info.width)
224 || (y1 >= _grey_info.height) || (y2 < 0))
225 return;
226
227 /* clipping */
228 if (y1 < 0)
229 y1 = 0;
230 if (y2 >= _grey_info.height)
231 y2 = _grey_info.height - 1;
232
233 pfunc = _grey_pixelfuncs[_grey_info.drawmode];
234 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y1) + x];
235
236 dst_end = dst + _GREY_MULUQ(_grey_info.width, y2 - y1);
237 do
238 {
239 pfunc(dst);
240 dst += _grey_info.width;
241 }
242 while (dst <= dst_end);
243}
244
245/* Draw a filled triangle */
246void grey_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3)
247{
248 int x, y;
249 long fp_x1, fp_x2, fp_dx1, fp_dx2;
250
251 /* sort vertices by increasing y value */
252 if (y1 > y3)
253 {
254 if (y2 < y3) /* y2 < y3 < y1 */
255 {
256 x = x1; x1 = x2; x2 = x3; x3 = x;
257 y = y1; y1 = y2; y2 = y3; y3 = y;
258 }
259 else if (y2 > y1) /* y3 < y1 < y2 */
260 {
261 x = x1; x1 = x3; x3 = x2; x2 = x;
262 y = y1; y1 = y3; y3 = y2; y2 = y;
263 }
264 else /* y3 <= y2 <= y1 */
265 {
266 x = x1; x1 = x3; x3 = x;
267 y = y1; y1 = y3; y3 = y;
268 }
269 }
270 else
271 {
272 if (y2 < y1) /* y2 < y1 <= y3 */
273 {
274 x = x1; x1 = x2; x2 = x;
275 y = y1; y1 = y2; y2 = y;
276 }
277 else if (y2 > y3) /* y1 <= y3 < y2 */
278 {
279 x = x2; x2 = x3; x3 = x;
280 y = y2; y2 = y3; y3 = y;
281 }
282 /* else already sorted */
283 }
284
285 if (y1 < y3) /* draw */
286 {
287 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
288 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
289
290 if (y1 < y2) /* first part */
291 {
292 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
293 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
294 for (y = y1; y < y2; y++)
295 {
296 grey_hline(fp_x1 >> 16, fp_x2 >> 16, y);
297 fp_x1 += fp_dx1;
298 fp_x2 += fp_dx2;
299 }
300 }
301 if (y2 < y3) /* second part */
302 {
303 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
304 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
305 for (y = y2; y < y3; y++)
306 {
307 grey_hline(fp_x1 >> 16, fp_x2 >> 16, y);
308 fp_x1 += fp_dx1;
309 fp_x2 += fp_dx2;
310 }
311 }
312 }
313}
314
315/* Draw a rectangular box */
316void grey_drawrect(int x, int y, int width, int height)
317{
318 if ((width <= 0) || (height <= 0))
319 return;
320
321 int x2 = x + width - 1;
322 int y2 = y + height - 1;
323
324 grey_vline(x, y, y2);
325 grey_vline(x2, y, y2);
326 grey_hline(x, x2, y);
327 grey_hline(x, x2, y2);
328}
329
330/* Fill a rectangular area */
331void grey_fillrect(int x, int y, int width, int height)
332{
333 int value = 0;
334 unsigned char *dst, *dst_end;
335 bool fillopt = false;
336 void (*pfunc)(unsigned char *address);
337
338 /* nothing to draw? */
339 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
340 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
341 return;
342
343 /* clipping */
344 if (x < 0)
345 {
346 width += x;
347 x = 0;
348 }
349 if (y < 0)
350 {
351 height += y;
352 y = 0;
353 }
354 if (x + width > _grey_info.width)
355 width = _grey_info.width - x;
356 if (y + height > _grey_info.height)
357 height = _grey_info.height - y;
358
359 if (_grey_info.drawmode & DRMODE_INVERSEVID)
360 {
361 if (_grey_info.drawmode & DRMODE_BG)
362 {
363 fillopt = true;
364 value = _grey_info.bg_val;
365 }
366 }
367 else
368 {
369 if (_grey_info.drawmode & DRMODE_FG)
370 {
371 fillopt = true;
372 value = _grey_info.fg_val;
373 }
374 }
375 pfunc = _grey_pixelfuncs[_grey_info.drawmode];
376 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x];
377 dst_end = dst + _GREY_MULUQ(_grey_info.width, height);
378
379 do
380 {
381 if (fillopt)
382 _grey_rb->memset(dst, value, width);
383 else
384 {
385 unsigned char *dst_row = dst;
386 unsigned char *row_end = dst_row + width;
387
388 do
389 pfunc(dst_row++);
390 while (dst_row < row_end);
391 }
392 dst += _grey_info.width;
393 }
394 while (dst < dst_end);
395}
396
397/* About Rockbox' internal monochrome bitmap format:
398 *
399 * A bitmap contains one bit for every pixel that defines if that pixel is
400 * foreground (1) or background (0). Bits within a byte are arranged
401 * vertically, LSB at top.
402 * The bytes are stored in row-major order, with byte 0 being top left,
403 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
404 * 0..7, the second row defines pixel row 8..15 etc. */
405
406/* Draw a partial monochrome bitmap */
407void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
408 int stride, int x, int y, int width, int height)
409{
410 const unsigned char *src_end;
411 unsigned char *dst, *dst_end;
412 void (*fgfunc)(unsigned char *address);
413 void (*bgfunc)(unsigned char *address);
414
415 /* nothing to draw? */
416 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
417 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
418 return;
419
420 /* clipping */
421 if (x < 0)
422 {
423 width += x;
424 src_x -= x;
425 x = 0;
426 }
427 if (y < 0)
428 {
429 height += y;
430 src_y -= y;
431 y = 0;
432 }
433 if (x + width > _grey_info.width)
434 width = _grey_info.width - x;
435 if (y + height > _grey_info.height)
436 height = _grey_info.height - y;
437
438 src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */
439 src_y &= 7;
440 src_end = src + width;
441
442 fgfunc = _grey_pixelfuncs[_grey_info.drawmode];
443 bgfunc = _grey_pixelfuncs[_grey_info.drawmode ^ DRMODE_INVERSEVID];
444 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x];
445
446 do
447 {
448 const unsigned char *src_col = src++;
449 unsigned char *dst_col = dst++;
450 unsigned data = *src_col >> src_y;
451 int numbits = 8 - src_y;
452
453 dst_end = dst_col + _GREY_MULUQ(_grey_info.width, height);
454 do
455 {
456 if (data & 0x01)
457 fgfunc(dst_col);
458 else
459 bgfunc(dst_col);
460
461 dst_col += _grey_info.width;
462
463 data >>= 1;
464 if (--numbits == 0)
465 {
466 src_col += stride;
467 data = *src_col;
468 numbits = 8;
469 }
470 }
471 while (dst_col < dst_end);
472 }
473 while (src < src_end);
474}
475
476/* Draw a full monochrome bitmap */
477void grey_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
478{
479 grey_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
480}
481
482/* Draw a partial greyscale bitmap, canonical format */
483void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
484 int stride, int x, int y, int width, int height)
485{
486 unsigned char *dst, *dst_end;
487
488 /* nothing to draw? */
489 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
490 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
491 return;
492
493 /* clipping */
494 if (x < 0)
495 {
496 width += x;
497 src_x -= x;
498 x = 0;
499 }
500 if (y < 0)
501 {
502 height += y;
503 src_y -= y;
504 y = 0;
505 }
506 if (x + width > _grey_info.width)
507 width = _grey_info.width - x;
508 if (y + height > _grey_info.height)
509 height = _grey_info.height - y;
510
511 src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */
512 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x];
513 dst_end = dst + _GREY_MULUQ(_grey_info.width, height);
514
515 do
516 {
517 const unsigned char *src_row = src;
518 unsigned char *dst_row = dst;
519 unsigned char *row_end = dst_row + width;
520
521 do
522 *dst_row++ = _grey_info.gvalue[*src_row++];
523 while (dst_row < row_end);
524
525 src += stride;
526 dst += _grey_info.width;
527 }
528 while (dst < dst_end);
529}
530
531/* Draw a full greyscale bitmap, canonical format */
532void grey_gray_bitmap(const unsigned char *src, int x, int y, int width,
533 int height)
534{
535 grey_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
536}
537
538/* Put a string at a given pixel position, skipping first ofs pixel columns */
539void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str)
540{
541 int ch;
542 struct font* pf = _grey_rb->font_get(_grey_info.curfont);
543
544 while ((ch = *str++) != '\0' && x < _grey_info.width)
545 {
546 int width;
547 const unsigned char *bits;
548
549 /* check input range */
550 if (ch < pf->firstchar || ch >= pf->firstchar+pf->size)
551 ch = pf->defaultchar;
552 ch -= pf->firstchar;
553
554 /* get proportional width and glyph bits */
555 width = pf->width ? pf->width[ch] : pf->maxwidth;
556
557 if (ofs > width)
558 {
559 ofs -= width;
560 continue;
561 }
562
563 bits = pf->bits + (pf->offset ?
564 pf->offset[ch] : (((pf->height + 7) >> 3) * pf->maxwidth * ch));
565
566 grey_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height);
567
568 x += width - ofs;
569 ofs = 0;
570 }
571}
572
573/* Put a string at a given pixel position */
574void grey_putsxy(int x, int y, const unsigned char *str)
575{
576 grey_putsxyofs(x, y, 0, str);
577}
578
579/*** Unbuffered drawing functions ***/
580
581#ifdef SIMULATOR
582
583/* Clear the whole display */
584void grey_ub_clear_display(void)
585{
586 grey_clear_display();
587 grey_update();
588}
589
590/* Draw a partial greyscale bitmap, canonical format */
591void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
592 int stride, int x, int y, int width, int height)
593{
594 grey_gray_bitmap_part(src, src_x, src_y, stride, x, y, width, height);
595 grey_update_rect(x, y, width, height);
596}
597
598#else /* !SIMULATOR */
599
600/* Clear the greyscale display (sets all pixels to white) */
601void grey_ub_clear_display(void)
602{
603 int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
604 _grey_info.fg_val : _grey_info.bg_val;
605 unsigned char *dst = &_grey_info.data[0].value;
606 unsigned char *dst_end = dst + sizeof(struct grey_data)
607 * _GREY_MULUQ(_grey_info.width, _grey_info.height);
608
609 do
610 {
611 *dst = value;
612 dst += sizeof(struct grey_data);
613 }
614 while (dst < dst_end);
615}
616
617/* Draw a partial greyscale bitmap, canonical format */
618void grey_ub_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
619 int stride, int x, int y, int width, int height)
620{
621 /* nothing to draw? */
622 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
623 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
624 return;
625
626 /* clipping */
627 if (x < 0)
628 {
629 width += x;
630 src_x -= x;
631 x = 0;
632 }
633 if (y < 0)
634 {
635 height += y;
636 src_y -= y;
637 y = 0;
638 }
639 if (x + width > _grey_info.width)
640 width = _grey_info.width - x;
641 if (y + height > _grey_info.height)
642 height = _grey_info.height - y;
643
644 src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */
645
646 do
647 {
648#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
649 int idx = _GREY_MULUQ(_grey_info.width, y) + x;
650#else
651#if LCD_DEPTH == 1
652 int idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (x << 3) + (~y & 7);
653#elif LCD_DEPTH == 2
654 int idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (x << 2) + (~y & 3);
655#endif
656#endif /* LCD_PIXELFORMAT */
657 unsigned char *dst_row = &_grey_info.data[idx].value;
658 const unsigned char *src_row = src;
659 const unsigned char *src_end = src + width;
660
661 do
662 {
663 *dst_row = _grey_info.gvalue[*src_row++];
664 dst_row += _GREY_X_ADVANCE;
665 }
666 while (src_row < src_end);
667
668 y++;
669 src += stride;
670 }
671 while (--height > 0);
672}
673
674#endif /* !SIMULATOR */
675
676/* Draw a full greyscale bitmap, canonical format */
677void grey_ub_gray_bitmap(const unsigned char *src, int x, int y, int width,
678 int height)
679{
680 grey_ub_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
681}
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 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* New greyscale framework
11* Parameter handling
12*
13* This is a generic framework to display 129 shades of grey on low-depth
14* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
15*
16* Copyright (C) 2008 Jens Arnold
17*
18* All files in this archive are subject to the GNU General Public License.
19* See the file COPYING in the source tree root for full license agreement.
20*
21* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22* KIND, either express or implied.
23*
24****************************************************************************/
25
26#include "plugin.h"
27#include "grey.h"
28
29/* Set position of the top left corner of the greyscale overlay
30 Note that depending on the target LCD, either x or y gets rounded
31 to the nearest multiple of 4 or 8 */
32void grey_set_position(int x, int y)
33{
34#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
35 _grey_info.bx = (x + 4) >> 3;
36 x = 8 * _grey_info.bx;
37#else
38#if LCD_DEPTH == 1
39 _grey_info.by = (y + 4) >> 3;
40 y = 8 * _grey_info.by;
41#elif LCD_DEPTH == 2
42 _grey_info.by = (y + 2) >> 2;
43 y = 4 * _grey_info.by;
44#endif
45#endif /* LCD_PIXELFORMAT */
46 _grey_info.x = x;
47 _grey_info.y = y;
48
49 if (_grey_info.flags & _GREY_RUNNING)
50 {
51#ifdef SIMULATOR
52 grey_deferred_lcd_update();
53 grey_update();
54#else
55 _grey_info.flags |= _GREY_DEFERRED_UPDATE;
56#endif
57 }
58}
59
60/* Set the draw mode for subsequent drawing operations */
61void grey_set_drawmode(int mode)
62{
63 _grey_info.drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
64}
65
66/* Return the current draw mode */
67int grey_get_drawmode(void)
68{
69 return _grey_info.drawmode;
70}
71
72/* Set the foreground shade for subsequent drawing operations */
73void grey_set_foreground(unsigned brightness)
74{
75 _grey_info.fg_val = _grey_info.gvalue[brightness];
76 _grey_info.fg_brightness = brightness;
77}
78
79/* Return the current foreground shade */
80unsigned grey_get_foreground(void)
81{
82 return _grey_info.fg_brightness;
83}
84
85/* Set the background shade for subsequent drawing operations */
86void grey_set_background(unsigned brightness)
87{
88 _grey_info.bg_val = _grey_info.gvalue[brightness];
89 _grey_info.bg_brightness = brightness;
90}
91
92/* Return the current background shade */
93unsigned grey_get_background(void)
94{
95 return _grey_info.bg_brightness;
96}
97
98/* Set draw mode, foreground and background shades at once */
99void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness)
100{
101 grey_set_drawmode(mode);
102 grey_set_foreground(fg_brightness);
103 grey_set_background(bg_brightness);
104}
105
106/* Set font for the text output routines */
107void grey_setfont(int newfont)
108{
109 _grey_info.curfont = newfont;
110}
111
112/* Get width and height of a text when printed with the current font */
113int grey_getstringsize(const unsigned char *str, int *w, int *h)
114{
115 return _grey_rb->font_getstringsize(str, w, h, _grey_info.curfont);
116}
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 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* New greyscale framework
11* Scrolling routines
12*
13* This is a generic framework to display 129 shades of grey on low-depth
14* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
15*
16* Copyright (C) 2008 Jens Arnold
17*
18* All files in this archive are subject to the GNU General Public License.
19* See the file COPYING in the source tree root for full license agreement.
20*
21* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22* KIND, either express or implied.
23*
24****************************************************************************/
25
26#include "plugin.h"
27#include "grey.h"
28
29/*** Scrolling ***/
30
31/* Scroll left */
32void grey_scroll_left(int count)
33{
34 unsigned char *data, *data_end;
35 int length, blank;
36
37 if ((unsigned)count >= (unsigned)_grey_info.width)
38 return;
39
40 data = _grey_info.buffer;
41 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
42 length = _grey_info.width - count;
43 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
44 _grey_info.fg_val : _grey_info.bg_val;
45
46 do
47 {
48 _grey_rb->memmove(data, data + count, length);
49 _grey_rb->memset(data + length, blank, count);
50 data += _grey_info.width;
51 }
52 while (data < data_end);
53}
54
55/* Scroll right */
56void grey_scroll_right(int count)
57{
58 unsigned char *data, *data_end;
59 int length, blank;
60
61 if ((unsigned)count >= (unsigned)_grey_info.width)
62 return;
63
64 data = _grey_info.buffer;
65 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
66 length = _grey_info.width - count;
67 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
68 _grey_info.fg_val : _grey_info.bg_val;
69
70 do
71 {
72 _grey_rb->memmove(data + count, data, length);
73 _grey_rb->memset(data, blank, count);
74 data += _grey_info.width;
75 }
76 while (data < data_end);
77}
78
79/* Scroll up */
80void grey_scroll_up(int count)
81{
82 long shift, length;
83 int blank;
84
85 if ((unsigned)count >= (unsigned)_grey_info.height)
86 return;
87
88 shift = _GREY_MULUQ(_grey_info.width, count);
89 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count);
90 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
91 _grey_info.fg_val : _grey_info.bg_val;
92
93 _grey_rb->memmove(_grey_info.buffer, _grey_info.buffer + shift, length);
94 _grey_rb->memset(_grey_info.buffer + length, blank, shift);
95}
96
97/* Scroll down */
98void grey_scroll_down(int count)
99{
100 long shift, length;
101 int blank;
102
103 if ((unsigned)count >= (unsigned)_grey_info.height)
104 return;
105
106 shift = _GREY_MULUQ(_grey_info.width, count);
107 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count);
108 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
109 _grey_info.fg_val : _grey_info.bg_val;
110
111 _grey_rb->memmove(_grey_info.buffer + shift, _grey_info.buffer, length);
112 _grey_rb->memset(_grey_info.buffer, blank, shift);
113}
114
115/*** Unbuffered scrolling functions ***/
116
117#ifdef SIMULATOR
118
119/* Scroll left */
120void grey_ub_scroll_left(int count)
121{
122 grey_scroll_left(count);
123 grey_update();
124}
125
126/* Scroll right */
127void grey_ub_scroll_right(int count)
128{
129 grey_scroll_right(count);
130 grey_update();
131}
132
133/* Scroll up */
134void grey_ub_scroll_up(int count)
135{
136 grey_scroll_up(count);
137 grey_update();
138}
139
140/* Scroll down */
141void grey_ub_scroll_down(int count)
142{
143 grey_scroll_down(count);
144 grey_update();
145}
146
147#else /* !SIMULATOR */
148
149/* Scroll left */
150void grey_ub_scroll_left(int count)
151{
152 unsigned char *dst, *src, *end;
153 int blank, y, idx;
154
155 if ((count == 0) || ((unsigned)count >= (unsigned)_grey_info.width))
156 return;
157
158 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
159 _grey_info.fg_val : _grey_info.bg_val;
160
161 for (y = 0; y < _grey_info.height; y++)
162 {
163#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
164 idx = _GREY_MULUQ(_grey_info.width, y);
165#else
166#if LCD_DEPTH == 1
167 idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (~y & 7);
168#elif LCD_DEPTH == 2
169 idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3);
170#endif
171#endif /* LCD_PIXELFORMAT */
172 dst = &_grey_info.data[idx].value;
173 src = dst + count * _GREY_X_ADVANCE;
174 end = dst + _grey_info.width * _GREY_X_ADVANCE;
175
176 do
177 {
178 *dst = *src;
179 dst += _GREY_X_ADVANCE;
180 src += _GREY_X_ADVANCE;
181 }
182 while (src < end);
183
184 do
185 {
186 *dst = blank;
187 dst += _GREY_X_ADVANCE;
188 }
189 while (dst < end);
190 }
191}
192
193/* Scroll right */
194void grey_ub_scroll_right(int count)
195{
196 unsigned char *dst, *src, *start;
197 int blank, y, idx;
198
199 if ((count == 0) || ((unsigned)count >= (unsigned)_grey_info.width))
200 return;
201
202 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
203 _grey_info.fg_val : _grey_info.bg_val;
204
205 for (y = 0; y < _grey_info.height; y++)
206 {
207#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
208 idx = _GREY_MULUQ(_grey_info.width, y);
209#else
210#if LCD_DEPTH == 1
211 idx = _GREY_MULUQ(_grey_info.width, y & ~7) + (~y & 7);
212#elif LCD_DEPTH == 2
213 idx = _GREY_MULUQ(_grey_info.width, y & ~3) + (~y & 3);
214#endif
215#endif /* LCD_PIXELFORMAT */
216 start = &_grey_info.data[idx].value;
217 dst = start + _grey_info.width * _GREY_X_ADVANCE;
218 src = dst - count * _GREY_X_ADVANCE;
219
220 do
221 {
222 dst -= _GREY_X_ADVANCE;
223 src -= _GREY_X_ADVANCE;
224 *dst = *src;
225 }
226 while (src > start);
227
228 do
229 {
230 dst -= _GREY_X_ADVANCE;
231 *dst = blank;
232 }
233 while (dst > start);
234 }
235}
236
237void grey_ub_scroll_up(int count)
238{
239 unsigned char *dst, *dst_end, *src;
240 int blank, ys, yd, is, id;
241
242 if ((unsigned)count >= (unsigned)_grey_info.height)
243 return;
244
245 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
246 _grey_info.fg_val : _grey_info.bg_val;
247
248 for (ys = count, yd = 0; ys < _grey_info.height; ys++, yd++)
249 {
250#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
251 id = _GREY_MULUQ(_grey_info.width, yd);
252 is = _GREY_MULUQ(_grey_info.width, ys);
253#else
254#if LCD_DEPTH == 1
255 id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7);
256 is = _GREY_MULUQ(_grey_info.width, ys & ~7) + (~ys & 7);
257#elif LCD_DEPTH == 2
258 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3);
259 is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3);
260#endif
261#endif /* LCD_PIXELFORMAT */
262 dst = &_grey_info.data[id].value;
263 src = &_grey_info.data[is].value;
264 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
265
266 do
267 {
268 *dst = *src;
269 dst += _GREY_X_ADVANCE;
270 src += _GREY_X_ADVANCE;
271 }
272 while (dst < dst_end);
273 }
274 for (; yd < _grey_info.height; yd++)
275 {
276#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
277 id = _GREY_MULUQ(_grey_info.width, yd);
278#else
279#if LCD_DEPTH == 1
280 id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7);
281#elif LCD_DEPTH == 2
282 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3);
283#endif
284#endif /* LCD_PIXELFORMAT */
285 dst = &_grey_info.data[id].value;
286 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
287
288 do
289 {
290 *dst = blank;
291 dst += _GREY_X_ADVANCE;
292 }
293 while (dst < dst_end);
294 }
295}
296
297void grey_ub_scroll_down(int count)
298{
299 unsigned char *dst, *dst_end, *src;
300 int blank, ys, yd, is, id;
301
302 if ((unsigned)count >= (unsigned)_grey_info.height)
303 return;
304
305 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
306 _grey_info.fg_val : _grey_info.bg_val;
307
308 yd = _grey_info.height - 1;
309 for (ys = yd - count; ys >= 0; ys--, yd--)
310 {
311#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
312 id = _GREY_MULUQ(_grey_info.width, yd);
313 is = _GREY_MULUQ(_grey_info.width, ys);
314#else
315#if LCD_DEPTH == 1
316 id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7);
317 is = _GREY_MULUQ(_grey_info.width, ys & ~7) + (~ys & 7);
318#elif LCD_DEPTH == 2
319 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3);
320 is = _GREY_MULUQ(_grey_info.width, ys & ~3) + (~ys & 3);
321#endif
322#endif /* LCD_PIXELFORMAT */
323 dst = &_grey_info.data[id].value;
324 src = &_grey_info.data[is].value;
325 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
326
327 do
328 {
329 *dst = *src;
330 dst += _GREY_X_ADVANCE;
331 src += _GREY_X_ADVANCE;
332 }
333 while (dst < dst_end);
334 }
335 for (; yd >= 0; yd--)
336 {
337#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
338 id = _GREY_MULUQ(_grey_info.width, yd);
339#else
340#if LCD_DEPTH == 1
341 id = _GREY_MULUQ(_grey_info.width, yd & ~7) + (~yd & 7);
342#elif LCD_DEPTH == 2
343 id = _GREY_MULUQ(_grey_info.width, yd & ~3) + (~yd & 3);
344#endif
345#endif /* LCD_PIXELFORMAT */
346 dst = &_grey_info.data[id].value;
347 dst_end = dst + _grey_info.width * _GREY_X_ADVANCE;
348
349 do
350 {
351 *dst = blank;
352 dst += _GREY_X_ADVANCE;
353 }
354 while (dst < dst_end);
355 }
356}
357
358#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 @@
21#include "plugin.h" 21#include "plugin.h"
22 22
23#ifdef HAVE_LCD_BITMAP 23#ifdef HAVE_LCD_BITMAP
24#include "gray.h" 24#include "grey.h"
25#include "xlcd.h" 25#include "xlcd.h"
26 26
27PLUGIN_HEADER 27PLUGIN_HEADER
@@ -180,9 +180,9 @@ PLUGIN_HEADER
180 180
181#if LCD_DEPTH < 8 181#if LCD_DEPTH < 8
182#define USEGSLIB 182#define USEGSLIB
183#define MYLCD(fn) gray_ub_ ## fn 183#define MYLCD(fn) grey_ub_ ## fn
184#define MYLCD_UPDATE() 184#define MYLCD_UPDATE()
185#define MYXLCD(fn) gray_ub_ ## fn 185#define MYXLCD(fn) grey_ub_ ## fn
186#else 186#else
187#define UPDATE_FREQ (HZ/50) 187#define UPDATE_FREQ (HZ/50)
188#define MYLCD(fn) rb->lcd_ ## fn 188#define MYLCD(fn) rb->lcd_ ## fn
@@ -486,7 +486,7 @@ void calc_mandelbrot_low_prec(void)
486 } 486 }
487 } 487 }
488#ifdef USEGSLIB 488#ifdef USEGSLIB
489 gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, 489 grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
490 p_x, py_min, 1, py_max - py_min); 490 p_x, py_min, 1, py_max - py_min);
491#else 491#else
492 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1, 492 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
@@ -549,7 +549,7 @@ void calc_mandelbrot_high_prec(void)
549 } 549 }
550 } 550 }
551#ifdef USEGSLIB 551#ifdef USEGSLIB
552 gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, 552 grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
553 p_x, py_min, 1, py_max - py_min); 553 p_x, py_min, 1, py_max - py_min);
554#else 554#else
555 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1, 555 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
@@ -569,7 +569,7 @@ void cleanup(void *parameter)
569{ 569{
570 (void)parameter; 570 (void)parameter;
571#ifdef USEGSLIB 571#ifdef USEGSLIB
572 gray_release(); 572 grey_release();
573#endif 573#endif
574} 574}
575 575
@@ -582,10 +582,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
582 int button; 582 int button;
583 int lastbutton = BUTTON_NONE; 583 int lastbutton = BUTTON_NONE;
584 int redraw = REDRAW_FULL; 584 int redraw = REDRAW_FULL;
585#ifdef USEGSLIB
586 int grayscales;
587 char buff[32];
588#endif
589 585
590 rb = api; 586 rb = api;
591 (void)parameter; 587 (void)parameter;
@@ -594,19 +590,13 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
594 /* get the remainder of the plugin buffer */ 590 /* get the remainder of the plugin buffer */
595 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); 591 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
596 592
597 /* initialize the grayscale buffer: 593 /* initialize the greyscale buffer.*/
598 * 8 bitplanes for 9 shades of gray.*/ 594 if (!grey_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, NULL))
599 grayscales = gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, 595 {
600 8, 0, NULL) + 1; 596 rb->splash(HZ, "Couldn't init greyscale display");
601 if (grayscales != 9) { 597 return 0;
602 rb->snprintf(buff, sizeof(buff), "%d", grayscales);
603 rb->lcd_puts(0, 1, buff);
604 rb->lcd_update();
605 rb->sleep(HZ*2);
606 return(0);
607 } 598 }
608 599 grey_show(true); /* switch on greyscale overlay */
609 gray_show(true); /* switch on grayscale overlay */
610#else 600#else
611 xlcd_init(rb); 601 xlcd_init(rb);
612#endif 602#endif
@@ -650,7 +640,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
650#endif 640#endif
651 case MANDELBROT_QUIT: 641 case MANDELBROT_QUIT:
652#ifdef USEGSLIB 642#ifdef USEGSLIB
653 gray_release(); 643 grey_release();
654#endif 644#endif
655 return PLUGIN_OK; 645 return PLUGIN_OK;
656 646
@@ -755,7 +745,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
755 lastbutton = button; 745 lastbutton = button;
756 } 746 }
757#ifdef USEGSLIB 747#ifdef USEGSLIB
758 gray_release(); 748 grey_release();
759#endif 749#endif
760 return PLUGIN_OK; 750 return PLUGIN_OK;
761} 751}
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)
868 868
869 vo_unlock(); 869 vo_unlock();
870#else 870#else
871 gray_deferred_lcd_update(); 871 grey_deferred_lcd_update();
872#endif 872#endif
873} 873}
874 874
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
85#define GRAY_VIDEO_FLUSH_ICACHE() 85#define GRAY_VIDEO_FLUSH_ICACHE()
86#define GRAY_VIDEO_INVALIDATE_ICACHE() 86#define GRAY_VIDEO_INVALIDATE_ICACHE()
87#else 87#else
88#include "gray.h" 88#include "grey.h"
89#define DRAW_BLACK GRAY_BLACK 89#define DRAW_BLACK GREY_BLACK
90#define DRAW_DARKGRAY GRAY_DARKGRAY 90#define DRAW_DARKGRAY GREY_DARKGRAY
91#define DRAW_LIGHTGRAY GRAY_LIGHTGRAY 91#define DRAW_LIGHTGRAY GREY_LIGHTGRAY
92#define DRAW_WHITE GRAY_WHITE 92#define DRAW_WHITE GREY_WHITE
93#define lcd_(fn) gray_##fn 93#define lcd_(fn) grey_##fn
94 94
95#define GRAY_FLUSH_ICACHE() \ 95#define GRAY_FLUSH_ICACHE() \
96 IF_COP(flush_icache()) 96 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 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "plugin.h" 21#include "plugin.h"
22#include "mpegplayer.h" 22#include "mpegplayer.h"
23#include "gray.h" 23#include "grey.h"
24#include "mpeg_settings.h" 24#include "mpeg_settings.h"
25 25
26static struct event_queue stream_mgr_queue NOCACHEBSS_ATTR; 26static struct event_queue stream_mgr_queue NOCACHEBSS_ATTR;
@@ -712,7 +712,7 @@ bool stream_show_vo(bool show)
712 GRAY_VIDEO_INVALIDATE_ICACHE(); 712 GRAY_VIDEO_INVALIDATE_ICACHE();
713 GRAY_INVALIDATE_ICACHE(); 713 GRAY_INVALIDATE_ICACHE();
714 714
715 gray_show(show); 715 grey_show(show);
716 716
717 GRAY_FLUSH_ICACHE(); 717 GRAY_FLUSH_ICACHE();
718#endif 718#endif
@@ -801,11 +801,10 @@ bool stream_set_gray_rect(const struct vo_rect *rc)
801 801
802 vo_lock(); 802 vo_lock();
803 803
804 gray_init(rb, stream_mgr.graymem, stream_mgr.graysize, 804 grey_init(rb, stream_mgr.graymem, stream_mgr.graysize, false,
805 false, rc_gray.r - rc_gray.l, rc_gray.b - rc_gray.t, 805 rc_gray.r - rc_gray.l, rc_gray.b - rc_gray.t, NULL);
806 32, 2<<8, NULL);
807 806
808 gray_set_position(rc_gray.l, rc_gray.t); 807 grey_set_position(rc_gray.l, rc_gray.t);
809 808
810 vo_unlock(); 809 vo_unlock();
811 810
@@ -818,7 +817,7 @@ bool stream_set_gray_rect(const struct vo_rect *rc)
818 817
819 if (vis) 818 if (vis)
820 { 819 {
821 gray_show(true); 820 grey_show(true);
822 parser_send_video_msg(VIDEO_DISPLAY_SHOW, true); 821 parser_send_video_msg(VIDEO_DISPLAY_SHOW, true);
823 } 822 }
824 } 823 }
@@ -836,7 +835,7 @@ void stream_gray_show(bool show)
836 GRAY_VIDEO_INVALIDATE_ICACHE(); 835 GRAY_VIDEO_INVALIDATE_ICACHE();
837 GRAY_INVALIDATE_ICACHE(); 836 GRAY_INVALIDATE_ICACHE();
838 837
839 gray_show(show); 838 grey_show(show);
840 839
841 GRAY_FLUSH_ICACHE(); 840 GRAY_FLUSH_ICACHE();
842 841
@@ -1095,16 +1094,14 @@ int stream_init(void)
1095 1094
1096 /* Initialize non-allocator blocks first */ 1095 /* Initialize non-allocator blocks first */
1097#ifndef HAVE_LCD_COLOR 1096#ifndef HAVE_LCD_COLOR
1098 int grayscales; 1097 bool success;
1099 1098
1100 /* This can run on another processor - align data */ 1099 /* This can run on another processor - align data */
1101 memsize = CACHEALIGN_BUFFER(&mem, memsize); 1100 memsize = CACHEALIGN_BUFFER(&mem, memsize);
1102 stream_mgr.graymem = mem; 1101 stream_mgr.graymem = mem;
1103 1102
1104 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */ 1103 success = grey_init(rb, mem, memsize, false, LCD_WIDTH,
1105 grayscales = gray_init(rb, mem, memsize, false, 1104 LCD_HEIGHT, &stream_mgr.graysize);
1106 LCD_WIDTH, LCD_HEIGHT,
1107 32, 2<<8, &stream_mgr.graysize) + 1;
1108 1105
1109 /* This can run on another processor - align size */ 1106 /* This can run on another processor - align size */
1110 stream_mgr.graysize = CACHEALIGN_UP(stream_mgr.graysize); 1107 stream_mgr.graysize = CACHEALIGN_UP(stream_mgr.graysize);
@@ -1112,9 +1109,9 @@ int stream_init(void)
1112 mem += stream_mgr.graysize; 1109 mem += stream_mgr.graysize;
1113 memsize -= stream_mgr.graysize; 1110 memsize -= stream_mgr.graysize;
1114 1111
1115 if (grayscales < 33 || (ssize_t)memsize <= 0) 1112 if (!success || (ssize_t)memsize <= 0)
1116 { 1113 {
1117 rb->splash(HZ, "graylib init failed!"); 1114 rb->splash(HZ, "greylib init failed!");
1118 stream_mgr.graymem = NULL; 1115 stream_mgr.graymem = NULL;
1119 return STREAM_ERROR; 1116 return STREAM_ERROR;
1120 } 1117 }
@@ -1188,6 +1185,6 @@ void stream_exit(void)
1188 1185
1189#ifndef HAVE_LCD_COLOR 1186#ifndef HAVE_LCD_COLOR
1190 if (stream_mgr.graymem != NULL) 1187 if (stream_mgr.graymem != NULL)
1191 gray_release(); 1188 grey_release();
1192#endif 1189#endif
1193} 1190}
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,
107#ifdef HAVE_LCD_COLOR 107#ifdef HAVE_LCD_COLOR
108 rb->lcd_yuv_blit(buf, src_x, src_y, stride, x, y , width, height); 108 rb->lcd_yuv_blit(buf, src_x, src_y, stride, x, y , width, height);
109#else 109#else
110 gray_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); 110 grey_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height);
111#endif 111#endif
112 112
113 video_unlock(); 113 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 @@
28#ifdef HAVE_LCD_BITMAP 28#ifdef HAVE_LCD_BITMAP
29 29
30#ifndef HAVE_LCD_COLOR 30#ifndef HAVE_LCD_COLOR
31#include "gray.h" 31#include "grey.h"
32#endif 32#endif
33#include "fixedpoint.h" 33#include "fixedpoint.h"
34 34
@@ -45,7 +45,7 @@ static int redphase = 0, greenphase = 50, bluephase = 100;
45 /* lower chance of gray at regular intervals */ 45 /* lower chance of gray at regular intervals */
46#else 46#else
47static unsigned char colours[256]; /* Smooth transition of shades */ 47static unsigned char colours[256]; /* Smooth transition of shades */
48static unsigned char graybuffer[LCD_HEIGHT*LCD_WIDTH]; /* off screen buffer */ 48static unsigned char greybuffer[LCD_HEIGHT*LCD_WIDTH]; /* off screen buffer */
49static unsigned char *gbuf; 49static unsigned char *gbuf;
50static size_t gbuf_size = 0; 50static size_t gbuf_size = 0;
51#endif 51#endif
@@ -171,7 +171,7 @@ void cleanup(void *parameter)
171 (void)parameter; 171 (void)parameter;
172 172
173#ifndef HAVE_LCD_COLOR 173#ifndef HAVE_LCD_COLOR
174 gray_release(); 174 grey_release();
175#endif 175#endif
176 /* Turn on backlight timeout (revert to settings) */ 176 /* Turn on backlight timeout (revert to settings) */
177 backlight_use_settings(rb); /* backlight control in lib/helper.c */ 177 backlight_use_settings(rb); /* backlight control in lib/helper.c */
@@ -203,9 +203,9 @@ int main(void)
203 /* get the remainder of the plugin buffer */ 203 /* get the remainder of the plugin buffer */
204 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); 204 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
205 205
206 gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, 32, 2<<8, NULL); 206 grey_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, NULL);
207 /* switch on grayscale overlay */ 207 /* switch on greyscale overlay */
208 gray_show(true); 208 grey_show(true);
209#endif 209#endif
210 sp1 = 4; 210 sp1 = 4;
211 sp2 = 2; 211 sp2 = 2;
@@ -218,7 +218,7 @@ int main(void)
218 shades_generate(time++); /* dynamically */ 218 shades_generate(time++); /* dynamically */
219 ptr = rb->lcd_framebuffer; 219 ptr = rb->lcd_framebuffer;
220#else 220#else
221 ptr = graybuffer; 221 ptr = greybuffer;
222#endif 222#endif
223 t1=p1; 223 t1=p1;
224 t2=p2; 224 t2=p2;
@@ -245,7 +245,7 @@ int main(void)
245#ifdef HAVE_LCD_COLOR 245#ifdef HAVE_LCD_COLOR
246 rb->lcd_update(); 246 rb->lcd_update();
247#else 247#else
248 gray_ub_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); 248 grey_ub_gray_bitmap(greybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT);
249#endif 249#endif
250 250
251 button = rb->button_get(false); 251 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 @@
1/* 1/*
2 * Copyright (C) 1996-1998 Szeredi Miklos 2 * Copyright (C) 1996-1998 Szeredi Miklos
3 * Email: mszeredi@inf.bme.hu 3 * Email: mszeredi@inf.bme.hu
4 * 4 *
@@ -94,7 +94,7 @@ char *spif_get_tape_fileinfo(int *startp, int *nump)
94 94
95void put_msg(const char *msg) 95void put_msg(const char *msg)
96{ 96{
97#ifndef USE_GRAY 97#ifndef USE_GREY
98 rb->splash (HZ/2, msg ); 98 rb->splash (HZ/2, msg );
99#else 99#else
100 LOGF(msg); 100 LOGF(msg);
@@ -105,7 +105,7 @@ void put_msg(const char *msg)
105 105
106void put_tmp_msg(const char *msg) 106void put_tmp_msg(const char *msg)
107{ 107{
108#ifndef USE_GRAY 108#ifndef USE_GREY
109 rb->splash (HZ/10, msg ); 109 rb->splash (HZ/10, msg );
110#else 110#else
111 LOGF(msg); 111 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 @@
42#include <string.h> 42#include <string.h>
43#include <stdlib.h> 43#include <stdlib.h>
44#include <errno.h> 44#include <errno.h>
45#ifdef USE_GRAY 45#ifdef USE_GREY
46#include "../lib/gray.h" 46#include "../lib/grey.h"
47#endif 47#endif
48 48
49#include "zxbox_keyb.h" 49#include "zxbox_keyb.h"
@@ -426,8 +426,8 @@ static bool zxbox_menu(void)
426 else 426 else
427 intkeys[i] = (unsigned) settings.keymap[i]; 427 intkeys[i] = (unsigned) settings.keymap[i];
428 } 428 }
429#ifdef USE_GRAY 429#ifdef USE_GREY
430 gray_show(true); 430 grey_show(true);
431#endif 431#endif
432 return (exit); 432 return (exit);
433} 433}
@@ -465,8 +465,8 @@ static void run_singlemode(void)
465 if (zxbox_menu()){ 465 if (zxbox_menu()){
466 /* Save the user settings if they have changed */ 466 /* Save the user settings if they have changed */
467 if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) { 467 if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) {
468#ifdef USE_GRAY 468#ifdef USE_GREY
469 gray_show(false); 469 grey_show(false);
470#endif 470#endif
471 rb->splash(0, "Saving settings..."); 471 rb->splash(0, "Saving settings...");
472 configfile_save(GLOBALCFG, config,sizeof(config)/sizeof(*config),SETTINGS_VERSION); 472 configfile_save(GLOBALCFG, config,sizeof(config)/sizeof(*config),SETTINGS_VERSION);
@@ -531,7 +531,7 @@ static void init_load(void *parameter)
531 531
532 check_params (parameter); 532 check_params (parameter);
533 if(spcf_init_snapshot != NULL) { 533 if(spcf_init_snapshot != NULL) {
534#ifndef USE_GRAY 534#ifndef USE_GREY
535 rb->splash(HZ, "Loading snapshot '%s'", spcf_init_snapshot); 535 rb->splash(HZ, "Loading snapshot '%s'", spcf_init_snapshot);
536#endif 536#endif
537 537
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 ];
50 50
51static int previous_state; 51static int previous_state;
52 52
53#ifdef USE_GRAY 53#ifdef USE_GREY
54static unsigned char *gbuf; 54static unsigned char *gbuf;
55static size_t gbuf_size = 0; 55static size_t gbuf_size = 0;
56#endif 56#endif
@@ -69,17 +69,17 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
69 69
70 sp_init(); 70 sp_init();
71 71
72#ifdef USE_GRAY 72#ifdef USE_GREY
73 /* get the remainder of the plugin buffer */ 73 /* get the remainder of the plugin buffer */
74 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); 74 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
75#ifdef USE_BUFFERED_GRAY 75#ifdef USE_BUFFERED_GREY
76 gray_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, 15, 0, NULL); 76 grey_init(rb, gbuf, gbuf_size, true, LCD_WIDTH, LCD_HEIGHT, NULL);
77#else 77#else
78 gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, 15, 0, NULL); 78 grey_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT, NULL);
79#endif /* USE_BUFFERED_GRAY */ 79#endif /* USE_BUFFERED_GREY */
80 /* switch on grayscale overlay */ 80 /* switch on greyscale overlay */
81 gray_show(true); 81 grey_show(true);
82#endif /* USE_GRAY */ 82#endif /* USE_GREY */
83 83
84 84
85#if defined(HAVE_ADJUSTABLE_CPU_FREQ) 85#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
@@ -102,9 +102,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
102 rb->cpu_boost(false); 102 rb->cpu_boost(false);
103#endif 103#endif
104 104
105#ifdef USE_GRAY 105#ifdef USE_GREY
106gray_show(false); 106grey_show(false);
107gray_release(); 107grey_release();
108#endif 108#endif
109 109
110#if CONFIG_CODEC == SWCODEC && !defined SIMULATOR 110#if CONFIG_CODEC == SWCODEC && !defined SIMULATOR
@@ -133,8 +133,8 @@ void spkb_process_events( int evenframe )
133 rb->cpu_boost(false); 133 rb->cpu_boost(false);
134#endif 134#endif
135 exit_requested=1; 135 exit_requested=1;
136#ifdef USE_GRAY 136#ifdef USE_GREY
137 gray_show(false); 137 grey_show(false);
138#endif 138#endif
139 return; 139 return;
140 } 140 }
@@ -151,8 +151,8 @@ void spkb_process_events( int evenframe )
151 rb->cpu_boost(false); 151 rb->cpu_boost(false);
152#endif 152#endif
153 exit_requested=1; 153 exit_requested=1;
154#ifdef USE_GRAY 154#ifdef USE_GREY
155 gray_show(false); 155 grey_show(false);
156#endif 156#endif
157 return; 157 return;
158 } 158 }
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];
17#define SETTINGS_MIN_VERSION 2 17#define SETTINGS_MIN_VERSION 2
18#define SETTINGS_VERSION 2 18#define SETTINGS_VERSION 2
19 19
20/* undef not to use grayscale lib */ 20/* undef not to use greyscale lib */
21#if !defined HAVE_LCD_COLOR && LCD_PIXELFORMAT != HORIZONTAL_PACKING 21#if !defined HAVE_LCD_COLOR
22/* grayscale is far slower for now at least on ipods :( */ 22#define USE_GREY
23#define USE_GRAY 23#define USE_BUFFERED_GREY
24#define USE_BUFFERED_GRAY
25#endif 24#endif
26 25
27 26
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 @@
1#include "zxvid_com.h" 1#include "zxvid_com.h"
2 2
3#if !defined USE_GRAY && LCD_DEPTH < 4 3#if !defined USE_GREY && LCD_DEPTH < 4
4/* screen routines for greyscale targets not using greyscale lib */ 4/* screen routines for greyscale targets not using greyscale lib */
5 5
6#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 6#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 @@
2#define ZXVIDCOMMON_H 2#define ZXVIDCOMMON_H
3#include "zxconfig.h" 3#include "zxconfig.h"
4 4
5#ifdef USE_GRAY 5#ifdef USE_GREY
6#include "../lib/gray.h" 6#include "../lib/grey.h"
7#endif 7#endif
8 8
9#include "spscr_p.h" 9#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 @@
1#include "zxvid_com.h" 1#include "zxvid_com.h"
2#if !defined HAVE_LCD_COLOR && defined USE_GRAY 2#if !defined HAVE_LCD_COLOR && defined USE_GREY
3/* 3/*
4use for slightly different colors 4use for slightly different colors
5#define N0 0x04 5#define N0 0x04
@@ -67,8 +67,8 @@ void update_screen(void)
67 srcy &= 0xffff; /* set up the y-coordinate between 0 and 1 */ 67 srcy &= 0xffff; /* set up the y-coordinate between 0 and 1 */
68 } 68 }
69 69
70#ifdef USE_BUFFERED_GRAY 70#ifdef USE_BUFFERED_GREY
71 gray_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); 71 grey_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT);
72#endif 72#endif
73 73
74 if ( settings.showfps ) { 74 if ( settings.showfps ) {
@@ -77,8 +77,8 @@ void update_screen(void)
77 if ((*rb->current_tick-start_time) > TPF ) 77 if ((*rb->current_tick-start_time) > TPF )
78 percent = 100*video_frames/((*rb->current_tick-start_time)/TPF); 78 percent = 100*video_frames/((*rb->current_tick-start_time)/TPF);
79 rb->snprintf(str,sizeof(str),"%d %%",percent); 79 rb->snprintf(str,sizeof(str),"%d %%",percent);
80#if defined USE_BUFFERED_GRAY 80#if defined USE_BUFFERED_GREY
81 gray_putsxy(0,0,str); 81 grey_putsxy(0,0,str);
82#else 82#else
83 LOGF(str); 83 LOGF(str);
84#endif 84#endif
@@ -86,10 +86,10 @@ void update_screen(void)
86 } 86 }
87 87
88 88
89#if defined USE_BUFFERED_GRAY 89#if defined USE_BUFFERED_GREY
90 gray_update(); 90 grey_update();
91#else 91#else
92 gray_ub_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT); 92 grey_ub_gray_bitmap(graybuffer, 0, 0, LCD_WIDTH, LCD_HEIGHT);
93#endif 93#endif
94 94
95} 95}
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);
95extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string, 95extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
96 int style); 96 int style);
97 97
98#ifdef HAVE_LCD_BITMAP
99
98#if defined(HAVE_LCD_COLOR) 100#if defined(HAVE_LCD_COLOR)
99#define LCD_YUV_DITHER 0x1 101#define LCD_YUV_DITHER 0x1
100extern void lcd_yuv_set_options(unsigned options); 102extern void lcd_yuv_set_options(unsigned options);
101extern void lcd_yuv_blit(unsigned char * const src[3], 103extern void lcd_yuv_blit(unsigned char * const src[3],
102 int src_x, int src_y, int stride, 104 int src_x, int src_y, int stride,
103 int x, int y, int width, int height); 105 int x, int y, int width, int height);
106#else
107struct grey_data {
108 unsigned char phase; /* SH1 uses it signed (doesn't matter for high level) */
109 unsigned char value; /* 0..128 are allowed */
110} __attribute__((packed));
111extern void lcd_grey_data(const struct grey_data *data, int count); /* private */
112extern void lcd_grey_phase_blit(const struct grey_data *data, int bx, int by,
113 int bwidth, int bheight, int stride);
104#endif 114#endif
105 115
106#ifdef HAVE_LCD_BITMAP
107/* performance function */ 116/* performance function */
108extern void lcd_blit(const fb_data* data, int x, int by, int width, 117extern void lcd_blit(const fb_data* data, int x, int by, int width,
109 int bheight, int stride); 118 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,
299 } 299 }
300} 300}
301 301
302/* Performance function that works with an external buffer
303 note that bx and bwidth are in 8-pixel units! */
304void lcd_grey_phase_blit(const struct grey_data *data, int bx, int y,
305 int bwidth, int height, int stride)
306{
307 const struct grey_data *addr;
308 int width;
309
310 while (height--) {
311 lcd_cmd_and_data(R_RAM_ADDR_SET, (y++ << 5) + addr_offset - bx);
312 lcd_prepare_cmd(R_RAM_DATA);
313
314 addr = data;
315 width = bwidth;
316 asm volatile (
317 "10: \n"
318 "ldmia %[addr]!, {r0-r3} \n" /* r0 = v1p1v0p0 ... */
319#ifdef IPOD_MINI2G
320 "mov r5, #0x7600 \n"
321#else
322 "mov r5, #0 \n"
323#endif
324
325 "and r4, r0, %[mask] \n" /* r4 = --p1--p0 */
326 "and r0, %[mask], r0, lsr #8 \n" /* r0 = --v1--v0 */
327
328 "tst r4, #0x80 \n"
329 "orreq r5, r5, #0xc0 \n"
330 "tst r4, #0x800000 \n"
331 "orreq r5, r5, #0x30 \n"
332 "bic r4, r4, %[clbt] \n"
333
334 "add r4, r0, r4 \n" /* p0 += v0; p1 += v1; */
335 "strb r4, [%[addr], #-16] \n"
336 "mov r4, r4, lsr #16 \n"
337 "strb r4, [%[addr], #-14] \n"
338
339 "and r4, r1, %[mask] \n"
340 "and r1, %[mask], r1, lsr #8 \n"
341
342 "tst r4, #0x80 \n"
343 "orreq r5, r5, #0x0c \n"
344 "tst r4, #0x800000 \n"
345 "orreq r5, r5, #0x03 \n"
346 "bic r4, r4, %[clbt] \n"
347
348 "add r4, r1, r4 \n"
349 "strb r4, [%[addr], #-12] \n"
350 "mov r4, r4, lsr #16 \n"
351 "strb r4, [%[addr], #-10] \n"
352
353#ifdef IPOD_MINI2G
354 "mov r5, r5, lsl #8 \n"
355#else
356 "1: \n"
357 "ldr r4, [%[lcdb]] \n"
358 "tst r4, #0x8000 \n"
359 "bne 1b \n"
360
361 "str r5, [%[lcdb], #0x10] \n"
362 "mov r5, #0 \n"
363#endif
364
365 "and r4, r2, %[mask] \n"
366 "and r2, %[mask], r2, lsr #8 \n"
367
368 "tst r4, #0x80 \n"
369 "orreq r5, r5, #0xc0 \n"
370 "tst r4, #0x800000 \n"
371 "orreq r5, r5, #0x30 \n"
372 "bic r4, r4, %[clbt] \n"
373
374 "add r4, r2, r4 \n"
375 "strb r4, [%[addr], #-8] \n"
376 "mov r4, r4, lsr #16 \n"
377 "strb r4, [%[addr], #-6] \n"
378
379 "and r4, r3, %[mask] \n"
380 "and r3, %[mask], r3, lsr #8 \n"
381
382 "tst r4, #0x80 \n"
383 "orreq r5, r5, #0x0c \n"
384 "tst r4, #0x800000 \n"
385 "orreq r5, r5, #0x03 \n"
386 "bic r4, r4, %[clbt] \n"
387
388 "add r4, r3, r4 \n"
389 "strb r4, [%[addr], #-4] \n"
390 "mov r4, r4, lsr #16 \n"
391 "strb r4, [%[addr], #-2] \n"
392
393 "1: \n"
394 "ldr r4, [%[lcdb]] \n"
395 "tst r4, #0x8000 \n"
396 "bne 1b \n"
397#ifdef IPOD_MINI2G
398 "str r5, [%[lcdb], #0x08] \n"
399#else
400 "str r5, [%[lcdb], #0x10] \n"
401#endif
402
403 "subs %[wdth], %[wdth], #1 \n"
404 "bne 10b \n"
405 : /* outputs */
406 [addr]"+r"(addr),
407 [wdth]"+r"(width)
408 : /* inputs */
409 [mask]"r"(0x00ff00ff),
410 [clbt]"r"(0x00800080),
411 [lcdb]"r"(LCD1_BASE)
412 : /* clobbers */
413 "r0", "r1", "r2", "r3", "r4", "r5"
414 );
415 data += stride;
416 }
417}
418
302void lcd_update_rect(int x, int y, int width, int height) 419void lcd_update_rect(int x, int y, int width, int height)
303{ 420{
304 int xmax, ymax; 421 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:
41lcd_write_command_ex: 41lcd_write_command_ex:
42 lea.l 0xf0008000, %a0 42 lea.l 0xf0008000, %a0
43 43
44 move.l (4, %sp), %d0 /* Command */ 44 move.l (4, %sp), %d0 /* Command */
45 move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */ 45 move.w %d0, (%a0)+ /* Write to LCD, set A0 = 1 */
46 46
47 move.l (8, %sp), %d0 /* Data */ 47 move.l (8, %sp), %d0 /* Data */
48 cmp.l #-1, %d0 /* -1? */ 48 cmp.l #-1, %d0 /* -1? */
49 beq.b .last 49 beq.b .last
50 move.w %d0, (%a0) /* Write to LCD */ 50 move.w %d0, (%a0) /* Write to LCD */
51 51
52 move.l (12, %sp), %d0 /* Data */ 52 move.l (12, %sp), %d0 /* Data */
53 cmp.l #-1, %d0 /* -1? */ 53 cmp.l #-1, %d0 /* -1? */
54 beq.b .last 54 beq.b .last
55 move.w %d0, (%a0) /* Write to LCD */ 55 move.w %d0, (%a0) /* Write to LCD */
56 56
57.last: 57.last:
58 rts 58 rts
@@ -65,19 +65,80 @@ lcd_write_command_ex:
65 .type lcd_write_data,@function 65 .type lcd_write_data,@function
66 66
67lcd_write_data: 67lcd_write_data:
68 move.l (4,%sp), %a0 /* Data pointer */ 68 movem.l (4, %sp), %a0-%a1 /* Data pointer */
69 move.l (8,%sp), %d0 /* Length */ 69 move.l %a1, %d0 /* Length */
70
71 lea 0xf0008002, %a1 70 lea 0xf0008002, %a1
71
72.loop: 72.loop:
73 /* When running in IRAM, this loop takes 10 cycles plus the LCD write. 73 /* When running in IRAM, this loop takes 10 cycles plus the LCD write.
74 The 10 cycles are necessary to follow the LCD timing specs 74 The 10 cycles are necessary to follow the LCD timing specs
75 at 140MHz */ 75 at 140MHz */
76 nop /* 3(0/0) */ 76 nop /* 3(0/0) */
77 move.b (%a0)+, %d1 /* 3(1/0) */ 77 move.b (%a0)+, %d1 /* 3(1/0) */
78 move.w %d1, (%a1) /* 1(0/1) */ 78 move.w %d1, (%a1) /* 1(0/1) */
79 subq.l #1, %d0 /* 1(0/0) */ 79 subq.l #1, %d0 /* 1(0/0) */
80 bne .loop /* 2(0/0) */ 80 bne .loop /* 2(0/0) */
81 rts 81 rts
82.wd_end: 82.wd_end:
83 .size lcd_write_data,.wd_end-lcd_write_data 83 .size lcd_write_data,.wd_end-lcd_write_data
84
85
86 .align 2
87 .global lcd_grey_data
88 .type lcd_grey_data,@function
89
90lcd_grey_data:
91 lea.l (-4*4, %sp), %sp
92 movem.l %d2-%d5, (%sp)
93 movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */
94 move.l %a1, %d0 /* Length */
95 lea 0xf0008002, %a1 /* LCD data port */
96 move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */
97
98.greyloop:
99 movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */
100 /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */
101 move.l %d2, %d3 /* copy mask */
102 and.l %d4, %d3 /* %d3 = p0--p1-- */
103 eor.l %d3, %d4 /* %d4 = --v0--v1 */
104 lsr.l #8, %d3 /* %d3 = --p0--p1 */
105
106 bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
107 seq.b %d1 /* %d1 = ........................00000000 */
108 lsl.l #2, %d1 /* %d1 = ......................00000000.. */
109 bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
110 seq.b %d1 /* %d1 = ......................0011111111 */
111 lsl.l #2, %d1 /* %d1 = ....................0011111111.. */
112
113 add.l %d4, %d3 /* p0 += v0; p1 += v1; */
114 move.b %d3, (2, %a0) /* store p1 */
115 swap %d3
116 move.b %d3, (%a0) /* store p0 */
117
118 move.l %d2, %d3 /* copy mask */
119 and.l %d5, %d3 /* %d3 = p2--p3-- */
120 eor.l %d3, %d5 /* %d5 = --v2--v3 */
121 lsr.l #8, %d3 /* %d3 = --p2--p3 */
122
123 bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
124 seq.b %d1 /* %d1 = ....................001122222222 */
125 lsl.l #2, %d1 /* %d1 = ..................001122222222.. */
126 bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
127 seq.b %d1 /* %d1 = ..................00112233333333 */
128 lsr.l #6, %d1 /* %d1 = ........................00112233 */
129
130 add.l %d5, %d3 /* p2 += v2; p3 += v3; */
131 move.b %d3, (6, %a0) /* store p3 */
132 swap %d3
133 move.b %d3, (4, %a0) /* store p2 */
134
135 move.w %d1, (%a1) /* write pixel block */
136 addq.l #8, %a0 /* advance address pointer */
137 subq.l #1, %d0 /* any blocks left? */
138 bne.b .greyloop
139
140 movem.l (%sp), %d2-%d5
141 lea.l (4*4, %sp), %sp
142 rts
143.gd_end:
144 .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,
171 } 171 }
172} 172}
173 173
174/* Performance function that works with an external buffer
175 note that by and bheight are in 4-pixel units! */
176void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
177 int width, int bheight, int stride)
178{
179 stride <<= 2; /* 4 pixels per block */
180 while (bheight--)
181 {
182 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1);
183 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
184 lcd_write_command(LCD_CNTL_DATA_WRITE);
185 lcd_grey_data(data, width);
186 data += stride;
187 }
188}
174 189
175/* Update the display. 190/* Update the display.
176 This must be called after all other LCD functions that change the display. */ 191 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 @@
28 .type lcd_write_command,@function 28 .type lcd_write_command,@function
29 29
30lcd_write_command: 30lcd_write_command:
31 move.l (4,%sp),%d0 31 move.l #~8, %d1
32 lea MBAR2,%a1 32 and.l %d1, (MBAR2+0xb4)
33 move.l #~8,%d1 33 move.l (4, %sp), %d0
34 and.l %d1,(0xb4,%a1) 34 move.w %d0, 0xf0000000
35 move.w %d0,0xf0000000
36 rts 35 rts
37.wc_end: 36.wc_end:
38 .size lcd_write_command,.wc_end-lcd_write_command 37 .size lcd_write_command,.wc_end-lcd_write_command
@@ -43,26 +42,27 @@ lcd_write_command:
43 .type lcd_write_command_ex,@function 42 .type lcd_write_command_ex,@function
44 43
45lcd_write_command_ex: 44lcd_write_command_ex:
46 lea MBAR2,%a1 45 lea.l 0xf0000000, %a0
46 lea.l MBAR2+0xb4, %a1
47 47
48 move.l (4,%sp),%d0 /* Command */ 48 move.l #~8, %d1 /* Set A0 = 0 */
49 and.l %d1, (%a1)
49 50
50 move.l #~8,%d1 /* Set A0 = 0 */ 51 move.l (4, %sp), %d0 /* Command */
51 and.l %d1,(0xb4,%a1) 52 move.w %d0, (%a0) /* Write to LCD */
52 move.w %d0,0xf0000000 /* Write to LCD */
53 53
54 not.l %d1 /* Set A0 = 1 */ 54 not.l %d1 /* Set A0 = 1 */
55 or.l %d1,(0xb4,%a1) 55 or.l %d1, (%a1)
56 56
57 move.l (8,%sp),%d0 /* Data */ 57 move.l (8, %sp), %d0 /* Data */
58 cmp.l #0xffffffff,%d0 /* -1? */ 58 cmp.l #-1, %d0 /* -1? */
59 beq.b .last 59 beq.b .last
60 move.w %d0,0xf0000000 /* Write to LCD */ 60 move.w %d0, (%a0) /* Write to LCD */
61 61
62 move.l (12,%sp),%d0 /* Data */ 62 move.l (12, %sp), %d0 /* Data */
63 cmp.l #0xffffffff,%d0 /* -1? */ 63 cmp.l #-1, %d0 /* -1? */
64 beq.b .last 64 beq.b .last
65 move.w %d0,0xf0000000 /* Write to LCD */ 65 move.w %d0, (%a0) /* Write to LCD */
66 66
67.last: 67.last:
68 rts 68 rts
@@ -75,22 +75,84 @@ lcd_write_command_ex:
75 .type lcd_write_data,@function 75 .type lcd_write_data,@function
76 76
77lcd_write_data: 77lcd_write_data:
78 move.l (4,%sp),%a0 /* Data pointer */ 78 movem.l (4, %sp), %a0-%a1 /* Data pointer */
79 move.l (8,%sp),%d0 /* Length */ 79 move.l %a1, %d0 /* Length */
80 lea MBAR2,%a1 80 moveq #8, %d1
81 moveq #8,%d1 81 or.l %d1, (MBAR2+0xb4)
82 or.l %d1,(0xb4,%a1) 82 lea.l 0xf0000000, %a1
83 83
84 lea 0xf0000000,%a1
85.loop: 84.loop:
86 /* When running in IRAM, this loop takes 10 cycles plus the LCD write. 85 /* When running in IRAM, this loop takes 10 cycles plus the LCD write.
87 The 10 cycles are necessary to follow the LCD timing specs 86 The 10 cycles are necessary to follow the LCD timing specs
88 at 140MHz */ 87 at 140MHz */
89 nop /* 3(0/0) */ 88 nop /* 3(0/0) */
90 move.b (%a0)+,%d1 /* 3(1/0) */ 89 move.b (%a0)+, %d1 /* 3(1/0) */
91 move.w %d1,(%a1) /* 1(0/1) */ 90 move.w %d1, (%a1) /* 1(0/1) */
92 subq.l #1,%d0 /* 1(0/0) */ 91 subq.l #1, %d0 /* 1(0/0) */
93 bne .loop /* 2(0/0) */ 92 bne .loop /* 2(0/0) */
94 rts 93 rts
95.wd_end: 94.wd_end:
96 .size lcd_write_data,.wd_end-lcd_write_data 95 .size lcd_write_data,.wd_end-lcd_write_data
96
97
98 .align 2
99 .global lcd_grey_data
100 .type lcd_grey_data,@function
101
102lcd_grey_data:
103 lea.l (-4*4, %sp), %sp
104 movem.l %d2-%d5, (%sp)
105 movem.l (4*4+4, %sp), %a0-%a1 /* Data pointer */
106 move.l %a1, %d0 /* Length */
107 moveq #8, %d1
108 or.l %d1, (MBAR2+0xb4) /* A0 = 1 (data) */
109 lea 0xf0000000, %a1 /* LCD data port */
110 move.l #0xff00ff00, %d2 /* mask for splitting value/phase pairs */
111
112.greyloop:
113 movem.l (%a0), %d4-%d5 /* fetch 4 pixel phase/value pairs at once */
114 /* %d4 = p0v0p1v1, %d5 = p2v2p3v3 */
115 move.l %d2, %d3 /* copy mask */
116 and.l %d4, %d3 /* %d3 = p0--p1-- */
117 eor.l %d3, %d4 /* %d4 = --v0--v1 */
118 lsr.l #8, %d3 /* %d3 = --p0--p1 */
119
120 bclr.l #23, %d3 /* Z = !(p0 & 0x80); p0 &= ~0x80; */
121 seq.b %d1 /* %d1 = ........................00000000 */
122 lsl.l #2, %d1 /* %d1 = ......................00000000.. */
123 bclr.l #7, %d3 /* Z = !(p1 & 0x80); p1 &= ~0x80; */
124 seq.b %d1 /* %d1 = ......................0011111111 */
125 lsl.l #2, %d1 /* %d1 = ....................0011111111.. */
126
127 add.l %d4, %d3 /* p0 += v0; p1 += v1; */
128 move.b %d3, (2, %a0) /* store p1 */
129 swap %d3
130 move.b %d3, (%a0) /* store p0 */
131
132 move.l %d2, %d3 /* copy mask */
133 and.l %d5, %d3 /* %d3 = p2--p3-- */
134 eor.l %d3, %d5 /* %d5 = --v2--v3 */
135 lsr.l #8, %d3 /* %d3 = --p2--p3 */
136
137 bclr.l #23, %d3 /* Z = !(p2 & 0x80); p2 &= ~0x80; */
138 seq.b %d1 /* %d1 = ....................001122222222 */
139 lsl.l #2, %d1 /* %d1 = ..................001122222222.. */
140 bclr.l #7, %d3 /* Z = !(p3 & 0x80); p3 &= ~0x80; */
141 seq.b %d1 /* %d1 = ..................00112233333333 */
142 lsr.l #6, %d1 /* %d1 = ........................00112233 */
143
144 add.l %d5, %d3 /* p2 += v2; p3 += v3; */
145 move.b %d3, (6, %a0) /* store p3 */
146 swap %d3
147 move.b %d3, (4, %a0) /* store p2 */
148
149 move.w %d1, (%a1) /* write pixel block */
150 addq.l #8, %a0 /* advance address pointer */
151 subq.l #1, %d0 /* any blocks left? */
152 bne.b .greyloop
153
154 movem.l (%sp), %d2-%d5
155 lea.l (4*4, %sp), %sp
156 rts
157.gd_end:
158 .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,
180 } 180 }
181} 181}
182 182
183/* Performance function that works with an external buffer
184 note that by and bheight are in 4-pixel units! */
185void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
186 int width, int bheight, int stride)
187{
188 stride <<= 2; /* 4 pixels per block */
189 while (bheight--)
190 {
191 lcd_write_command_ex(LCD_CNTL_PAGE, by++, -1);
192 lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
193 lcd_write_command(LCD_CNTL_DATA_WRITE);
194 lcd_grey_data(data, width);
195 data += stride;
196 }
197}
183 198
184/* Update the display. 199/* Update the display.
185 This must be called after all other LCD functions that change the display. */ 200 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,
155 } 155 }
156} 156}
157 157
158/* Performance function that works with an external buffer
159 note that by and bheight are in 8-pixel units! */
160void lcd_grey_phase_blit(const struct grey_data *data, int x, int by,
161 int width, int bheight, int stride)
162{
163 stride <<= 3; /* 8 pixels per block */
164 while (bheight--)
165 {
166 lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf));
167 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
168 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
169
170 lcd_grey_data(data, width);
171 data += stride;
172 }
173}
174
158 175
159/* Update the display. 176/* Update the display.
160 This must be called after all other LCD functions that change the display. */ 177 This must be called after all other LCD functions that change the display. */
161void lcd_update(void) ICODE_ATTR;
162void lcd_update(void) 178void lcd_update(void)
163{ 179{
164 int y; 180 int y;
@@ -175,7 +191,6 @@ void lcd_update(void)
175} 191}
176 192
177/* Update a fraction of the display. */ 193/* Update a fraction of the display. */
178void lcd_update_rect(int, int, int, int) ICODE_ATTR;
179void lcd_update_rect(int x, int y, int width, int height) 194void lcd_update_rect(int x, int y, int width, int height)
180{ 195{
181 int ymax; 196 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 @@
81 */ 81 */
82 82
83_lcd_write_command: 83_lcd_write_command:
84 mov.l .lcdr,r3 /* put lcd data port address in r3 */ 84 mov.l .lcdr, r3 /* put lcd data port address in r3 */
85 mov r4,r1 /* copy data byte to r1 */ 85 mov r4, r1 /* copy data byte to r1 */
86 mov #1,r5 /* set byte count to 1 (!) */
87 86
88 /* This code will fail if an interrupt changes the contents of PBDRL. 87 /* This code will fail if an interrupt changes the contents of PBDRL.
89 * If so, we must disable the interrupt here. */ 88 * If so, we must disable the interrupt here. */
90 89
91 mov.b @r3,r0 /* r0 = PBDRL */ 90 mov.b @r3, r0 /* r0 = PBDRL */
92 or #(LCD_SD),r0 /* r0 |= LCD_SD */ 91 mov r4, r5 /* (fake) end address = current address */
93 and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */ 92 or #(LCD_SD), r0 /* r0 |= LCD_SD */
93 and #(~(LCD_CS|LCD_DS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */
94 94
95 bra .single_transfer /* jump into the transfer loop */ 95 bra .single_transfer /* jump into the transfer loop */
96 neg r0,r2 /* r2 = 0 - r0 */ 96 neg r0, r2 /* r2 = 0 - r0 */
97 97
98 98
99 .align 2 99 .align 2
100 .global _lcd_write_data 100 .global _lcd_write_data
101 .type _lcd_write_data,@function 101 .type _lcd_write_data,@function
102 102
103
104/* A high performance function to write data to the display, 103/* A high performance function to write data to the display,
105 * one or multiple bytes. 104 * one or multiple bytes.
106 * 105 *
@@ -117,8 +116,8 @@ _lcd_write_command:
117 */ 116 */
118 117
119_lcd_write_data: 118_lcd_write_data:
120 mov.l .lcdr,r3 /* put lcd data port address in r3 */ 119 mov.l .lcdr, r3 /* put lcd data port address in r3 */
121 nop /* align here */ 120 add r4, r5 /* end address */
122 121
123 /* This code will fail if an interrupt changes the contents of PBDRL. 122 /* This code will fail if an interrupt changes the contents of PBDRL.
124 * If so, we must disable the interrupt here. If disabling interrupts 123 * If so, we must disable the interrupt here. If disabling interrupts
@@ -127,85 +126,233 @@ _lcd_write_data:
127 * disable/precalculate/transfer/enable for each iteration. However, 126 * disable/precalculate/transfer/enable for each iteration. However,
128 * this would significantly decrease performance. */ 127 * this would significantly decrease performance. */
129 128
130 mov.b @r3,r0 /* r0 = PBDRL */ 129 mov.b @r3, r0 /* r0 = PBDRL */
131 or #(LCD_DS|LCD_SD),r0 /* r0 |= LCD_DS|LCD_SD */ 130 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
132 and #(~(LCD_CS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_SC) */ 131 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
133 neg r0,r2 /* r2 = 0 - r0 */ 132 neg r0, r2 /* r2 = 0 - r0 */
134 133
135 /* loop exploits that SD is on bit 0 for recorders and Ondios */ 134 /* loop exploits that SD is on bit 0 for recorders and Ondios */
136 135
137 .align 2 136 .align 2
138.multi_transfer: 137.multi_transfer:
139 mov.b @r4+,r1 /* load data byte from memory */ 138 mov.b @r4+, r1 /* load data byte from memory */
140 nop 139 nop
141 140
142.single_transfer: 141.single_transfer:
143 shll16 r1 /* shift data to most significant byte */ 142 shll16 r1 /* shift data to most significant byte */
144 shll8 r1 143 shll8 r1
145 not r1,r1 /* and invert for use with negc */ 144 not r1, r1 /* and invert for use with negc */
146 145
147 shll r1 /* shift the MSB into carry */ 146 shll r1 /* shift the MSB into carry */
148 negc r2,r0 /* carry to SD, SC low */ 147 negc r2, r0 /* carry to SD, SC low */
149 shll r1 /* next shift here for alignment */ 148 shll r1 /* next shift here for alignment */
150 mov.b r0,@r3 /* set data to port */ 149 mov.b r0, @r3 /* set data to port */
151 or #(LCD_SC),r0 /* rise SC (independent of SD level) */ 150 or #(LCD_SC), r0 /* rise SC (independent of SD level) */
152 mov.b r0,@r3 /* set to port */ 151 mov.b r0, @r3 /* set to port */
153 152
154 negc r2,r0 153 negc r2, r0
155 mov.b r0,@r3 154 mov.b r0, @r3
156 or #(LCD_SC),r0 155 or #(LCD_SC), r0
157 mov.b r0,@r3 156 mov.b r0, @r3
158 157
159 shll r1 158 shll r1
160 negc r2,r0 159 negc r2, r0
161 shll r1 160 shll r1
162 mov.b r0,@r3 161 mov.b r0, @r3
163 or #(LCD_SC),r0 162 or #(LCD_SC), r0
164 mov.b r0,@r3 163 mov.b r0, @r3
165 164
166 negc r2,r0 165 negc r2, r0
167 mov.b r0,@r3 166 mov.b r0, @r3
168 or #(LCD_SC),r0 167 or #(LCD_SC), r0
169 mov.b r0,@r3 168 mov.b r0, @r3
170 169
171 shll r1 170 shll r1
172 negc r2,r0 171 negc r2, r0
173 shll r1 172 shll r1
174 mov.b r0,@r3 173 mov.b r0, @r3
175 or #(LCD_SC),r0 174 or #(LCD_SC), r0
176 mov.b r0,@r3 175 mov.b r0, @r3
177 176
178 negc r2,r0 177 negc r2, r0
179 mov.b r0,@r3 178 mov.b r0, @r3
180 or #(LCD_SC),r0 179 or #(LCD_SC), r0
181 mov.b r0,@r3 180 mov.b r0, @r3
182 181
183 shll r1 182 shll r1
184 negc r2,r0 183 negc r2, r0
185 shll r1 184 shll r1
186 mov.b r0,@r3 185 mov.b r0, @r3
187 or #(LCD_SC),r0 186 or #(LCD_SC), r0
188 mov.b r0,@r3 187 mov.b r0, @r3
188
189 negc r2, r0
190 mov.b r0, @r3
191 or #(LCD_SC), r0
192 mov.b r0, @r3
193
194 cmp/hi r4, r5 /* some blocks left? */
195 bt .multi_transfer
196
197 or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0 /* restore port */
198 rts
199 mov.b r0, @r3
200
201 /* This is the place to reenable the interrupts, if we have disabled
202 * them. See above. */
203
204
205 .align 2
206 .global _lcd_grey_data
207 .type _lcd_grey_data,@function
208
209/* A high performance function to write grey phase data to the display,
210 * one or multiple pixels.
211 *
212 * Arguments:
213 * r4 - data address, (phase,value)-pairs
214 * r5 - pixel block count
215 *
216 * Register usage:
217 * r0 - current pixel value
218 * r1 - scratch
219 * r2 - precalculated port value (CS and SC low, DS and SD high),
220 * negated (neg)!
221 * r3 - lcd port address
222 * r5 - end address
223 * r6/r7 - current/next pixel phase
224 * r8 - current block address (for writing back phase)
225 * r9 - 0x80 (for phase modification)
226 */
227
228_lcd_grey_data:
229 mov.l r8, @-r15 /* save r8 */
230 shll2 r5 /* v */
231 mov.l r9, @-r15 /* save r9 */
232 shll2 r5 /* r5 *= 16; (8 pixel per block * 2 bytes/pixel) */
233 mov.l .lcdr, r3 /* put lcd data port address in r3 */
234 add r4, r5 /* end address */
189 235
190 negc r2,r0 236 /* This code will fail if an interrupt changes the contents of PBDRL.
191 mov.b r0,@r3 237 * If so, we must disable the interrupt here. If disabling interrupts
192 or #(LCD_SC),r0 238 * for a long time is undesirable, the loop has to be rewritten to
193 mov.b r0,@r3 239 * disable/precalculate/transfer/enable for each iteration. However,
240 * this would significantly decrease performance. */
194 241
195 add #-1,r5 /* decrease byte count */ 242 mov.b @r3, r0 /* r0 = PBDRL */
196 tst r5,r5 /* r5 == 0 ? */ 243 mov r4, r8 /* copy start address */
197 bf .multi_transfer /* no: next iteration */ 244 mov.b @r4+, r6 /* fetch first pixel phase */
245 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
246 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
247 neg r0, r2 /* r2 = 0 - r0 */
248 mov #0x80, r9 /* for phase modification - "or #imm,xx" only allows r0 */
249
250 /* loop exploits that SD is on bit 0 for recorders and Ondios */
198 251
199 or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC),r0 /* restore port */ 252.greyloop:
253 cmp/pz r6 /* phase non-negative? */
254 mov.b @r4+, r0 /* fetch pixel value */
255 negc r2, r1 /* T -> SD, SC low */
256 mov.b r1, @r3 /* set port */
257 or r9, r6 /* r6 -= (r6 >= 0) ? 128 : 0; */
258 mov.b @r4+, r7 /* fetch next pixel phase */
259 add #(LCD_SC), r1 /* rise SC */
260 mov.b r1, @r3 /* set port */
261 add r6, r0 /* calculate new phase */
262 mov.b r0, @r8 /* store phase */
263
264 cmp/pz r7
265 mov.b @r4+, r0
266 negc r2, r1
267 mov.b r1, @r3
268 or r9, r7
269 mov.b @r4+, r6
270 add #(LCD_SC), r1
271 mov.b r1, @r3
272 add r7, r0
273 mov.b r0, @(2,r8)
274
275 cmp/pz r6
276 mov.b @r4+, r0
277 negc r2, r1
278 mov.b r1, @r3
279 or r9, r6
280 mov.b @r4+, r7
281 add #(LCD_SC), r1
282 mov.b r1, @r3
283 add r6, r0
284 mov.b r0, @(4,r8)
285
286 cmp/pz r7
287 mov.b @r4+, r0
288 negc r2, r1
289 mov.b r1, @r3
290 or r9, r7
291 mov.b @r4+, r6
292 add #(LCD_SC), r1
293 mov.b r1, @r3
294 add r7, r0
295 mov.b r0, @(6,r8)
296
297 cmp/pz r6
298 mov.b @r4+, r0
299 negc r2, r1
300 mov.b r1, @r3
301 or r9, r6
302 mov.b @r4+, r7
303 add #(LCD_SC), r1
304 mov.b r1, @r3
305 add r6, r0
306 mov.b r0, @(8,r8)
307
308 cmp/pz r7
309 mov.b @r4+, r0
310 negc r2, r1
311 mov.b r1, @r3
312 or r9, r7
313 mov.b @r4+, r6
314 add #(LCD_SC), r1
315 mov.b r1, @r3
316 add r7, r0
317 mov.b r0, @(10,r8)
318
319 cmp/pz r6
320 mov.b @r4+, r0
321 negc r2, r1
322 mov.b r1, @r3
323 or r9, r6
324 mov.b @r4+, r7
325 add #(LCD_SC), r1
326 mov.b r1, @r3
327 add r6, r0
328 mov.b r0, @(12,r8)
329
330 cmp/pz r7
331 mov.b @r4+, r0
332 negc r2, r1
333 mov.b r1, @r3
334 or r9, r7
335 mov.b @r4+, r6
336 add #(LCD_SC), r1
337 mov.b r1, @r3
338 add r7, r0
339 mov.b r0, @(14,r8)
340
341 add #16, r8 /* advance current block address */
342 cmp/hi r4, r5 /* some blocks left? */
343 bt .greyloop
344
345 mov.l @r15+, r9 /* restore r9 */
346 mov #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0
347 mov.l @r15+, r8 /* restore r8 */
348 or r0, r1 /* restore port */
200 rts 349 rts
201 mov.b r0,@r3 350 mov.b r1, @r3
202 351
203 /* This is the place to reenable the interrupts, if we have disabled 352 /* This is the place to reenable the interrupts, if we have disabled
204 * them. See above. */ 353 * them. See above. */
205 354
355
206 .align 2 356 .align 2
207.lcdr: 357.lcdr:
208 .long LCDR 358 .long LCDR
209
210.end:
211 .size _lcd_write_command,.end-_lcd_write_command