summaryrefslogtreecommitdiff
path: root/apps/plugins/lib
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 /apps/plugins/lib
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
Diffstat (limited to 'apps/plugins/lib')
-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
6 files changed, 2092 insertions, 0 deletions
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 */