summaryrefslogtreecommitdiff
path: root/apps/plugins/lib
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-03-08 01:14:46 +0000
committerJens Arnold <amiconn@rockbox.org>2006-03-08 01:14:46 +0000
commit19b45a4374bb3efda4f554d3d806835368d1536a (patch)
tree1fac6f5b900e7e40d9f770d14c5701db6231ec0f /apps/plugins/lib
parent761652abf71dcae63769a67388575fa47b6e8567 (diff)
downloadrockbox-19b45a4374bb3efda4f554d3d806835368d1536a.tar.gz
rockbox-19b45a4374bb3efda4f554d3d806835368d1536a.zip
LCD extension library: Implemented scrolling for LCD depths below 8 bit. * Oscilloscope: Use new scrolling function, some minor optimisations.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8951 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/lib')
-rw-r--r--apps/plugins/lib/SOURCES4
-rw-r--r--apps/plugins/lib/xlcd.h3
-rw-r--r--apps/plugins/lib/xlcd_core.c41
-rwxr-xr-xapps/plugins/lib/xlcd_draw.c379
-rwxr-xr-xapps/plugins/lib/xlcd_scroll.c576
5 files changed, 1002 insertions, 1 deletions
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES
index 6bcddbab96..f0930269f7 100644
--- a/apps/plugins/lib/SOURCES
+++ b/apps/plugins/lib/SOURCES
@@ -16,5 +16,7 @@ playergfx.c
16profile_plugin.c 16profile_plugin.c
17#endif 17#endif
18#ifdef HAVE_LCD_BITMAP 18#ifdef HAVE_LCD_BITMAP
19xlcd.c 19xlcd_core.c
20xlcd_draw.c
21xlcd_scroll.c
20#endif 22#endif
diff --git a/apps/plugins/lib/xlcd.h b/apps/plugins/lib/xlcd.h
index 8f3071443e..473c51c732 100644
--- a/apps/plugins/lib/xlcd.h
+++ b/apps/plugins/lib/xlcd.h
@@ -47,6 +47,9 @@ void xlcd_scroll_right(int count);
47void xlcd_scroll_up(int count); 47void xlcd_scroll_up(int count);
48void xlcd_scroll_down(int count); 48void xlcd_scroll_down(int count);
49 49
50/* internal stuff */
51extern struct plugin_api *_xlcd_rb; /* global api struct pointer */
52
50#endif /* HAVE_LCD_BITMAP */ 53#endif /* HAVE_LCD_BITMAP */
51#endif /* __XLCD_H__ */ 54#endif /* __XLCD_H__ */
52 55
diff --git a/apps/plugins/lib/xlcd_core.c b/apps/plugins/lib/xlcd_core.c
new file mode 100644
index 0000000000..e8cc688591
--- /dev/null
+++ b/apps/plugins/lib/xlcd_core.c
@@ -0,0 +1,41 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Additional LCD routines not present in the rockbox core
11* Core functions
12*
13* Copyright (C) 2005 Jens Arnold
14*
15* All files in this archive are subject to the GNU General Public License.
16* See the file COPYING in the source tree root for full license agreement.
17*
18* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19* KIND, either express or implied.
20*
21****************************************************************************/
22
23#include "plugin.h"
24
25#ifdef HAVE_LCD_BITMAP
26#include "xlcd.h"
27
28/*** globals ***/
29
30struct plugin_api *_xlcd_rb = NULL; /* global api struct pointer */
31
32/*** functions ***/
33
34/* library init */
35void xlcd_init(struct plugin_api* newrb)
36{
37 _xlcd_rb = newrb;
38}
39
40#endif /* HAVE_LCD_BITMAP */
41
diff --git a/apps/plugins/lib/xlcd_draw.c b/apps/plugins/lib/xlcd_draw.c
new file mode 100755
index 0000000000..3ccdea9139
--- /dev/null
+++ b/apps/plugins/lib/xlcd_draw.c
@@ -0,0 +1,379 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Additional LCD routines not present in the rockbox core
11* Drawing functions
12*
13* Copyright (C) 2005 Jens Arnold
14*
15* All files in this archive are subject to the GNU General Public License.
16* See the file COPYING in the source tree root for full license agreement.
17*
18* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19* KIND, either express or implied.
20*
21****************************************************************************/
22
23#include "plugin.h"
24
25#ifdef HAVE_LCD_BITMAP
26#include "xlcd.h"
27
28#if (LCD_DEPTH >= 8) || (LCD_PIXELFORMAT == HORIZONTAL_PACKING)
29/* draw a filled triangle, using horizontal lines for speed */
30void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3)
31{
32 int x, y;
33 long fp_x1, fp_x2, fp_dx1, fp_dx2;
34
35 /* sort vertices by increasing y value */
36 if (y1 > y3)
37 {
38 if (y2 < y3) /* y2 < y3 < y1 */
39 {
40 x = x1; x1 = x2; x2 = x3; x3 = x;
41 y = y1; y1 = y2; y2 = y3; y3 = y;
42 }
43 else if (y2 > y1) /* y3 < y1 < y2 */
44 {
45 x = x1; x1 = x3; x3 = x2; x2 = x;
46 y = y1; y1 = y3; y3 = y2; y2 = y;
47 }
48 else /* y3 <= y2 <= y1 */
49 {
50 x = x1; x1 = x3; x3 = x;
51 y = y1; y1 = y3; y3 = y;
52 }
53 }
54 else
55 {
56 if (y2 < y1) /* y2 < y1 <= y3 */
57 {
58 x = x1; x1 = x2; x2 = x;
59 y = y1; y1 = y2; y2 = y;
60 }
61 else if (y2 > y3) /* y1 <= y3 < y2 */
62 {
63 x = x2; x2 = x3; x3 = x;
64 y = y2; y2 = y3; y3 = y;
65 }
66 /* else already sorted */
67 }
68
69 if (y1 < y3) /* draw */
70 {
71 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
72 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
73
74 if (y1 < y2) /* first part */
75 {
76 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
77 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
78 for (y = y1; y < y2; y++)
79 {
80 _xlcd_rb->lcd_hline(fp_x1 >> 16, fp_x2 >> 16, y);
81 fp_x1 += fp_dx1;
82 fp_x2 += fp_dx2;
83 }
84 }
85 if (y2 < y3) /* second part */
86 {
87 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
88 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
89 for (y = y2; y < y3; y++)
90 {
91 _xlcd_rb->lcd_hline(fp_x1 >> 16, fp_x2 >> 16, y);
92 fp_x1 += fp_dx1;
93 fp_x2 += fp_dx2;
94 }
95 }
96 }
97}
98#else /* (LCD_DEPTH < 8) && (LCD_PIXELFORMAT == VERTICAL_PACKING) */
99/* draw a filled triangle, using vertical lines for speed */
100void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3)
101{
102 int x, y;
103 long fp_y1, fp_y2, fp_dy1, fp_dy2;
104
105 /* sort vertices by increasing x value */
106 if (x1 > x3)
107 {
108 if (x2 < x3) /* x2 < x3 < x1 */
109 {
110 x = x1; x1 = x2; x2 = x3; x3 = x;
111 y = y1; y1 = y2; y2 = y3; y3 = y;
112 }
113 else if (x2 > x1) /* x3 < x1 < x2 */
114 {
115 x = x1; x1 = x3; x3 = x2; x2 = x;
116 y = y1; y1 = y3; y3 = y2; y2 = y;
117 }
118 else /* x3 <= x2 <= x1 */
119 {
120 x = x1; x1 = x3; x3 = x;
121 y = y1; y1 = y3; y3 = y;
122 }
123 }
124 else
125 {
126 if (x2 < x1) /* x2 < x1 <= x3 */
127 {
128 x = x1; x1 = x2; x2 = x;
129 y = y1; y1 = y2; y2 = y;
130 }
131 else if (x2 > x3) /* x1 <= x3 < x2 */
132 {
133 x = x2; x2 = x3; x3 = x;
134 y = y2; y2 = y3; y3 = y;
135 }
136 /* else already sorted */
137 }
138
139 if (x1 < x3) /* draw */
140 {
141 fp_dy1 = ((y3 - y1) << 16) / (x3 - x1);
142 fp_y1 = (y1 << 16) + (1<<15) + (fp_dy1 >> 1);
143
144 if (x1 < x2) /* first part */
145 {
146 fp_dy2 = ((y2 - y1) << 16) / (x2 - x1);
147 fp_y2 = (y1 << 16) + (1<<15) + (fp_dy2 >> 1);
148 for (x = x1; x < x2; x++)
149 {
150 _xlcd_rb->lcd_vline(x, fp_y1 >> 16, fp_y2 >> 16);
151 fp_y1 += fp_dy1;
152 fp_y2 += fp_dy2;
153 }
154 }
155 if (x2 < x3) /* second part */
156 {
157 fp_dy2 = ((y3 - y2) << 16) / (x3 - x2);
158 fp_y2 = (y2 << 16) + (1<<15) + (fp_dy2 >> 1);
159 for (x = x2; x < x3; x++)
160 {
161 _xlcd_rb->lcd_vline(x, fp_y1 >> 16, fp_y2 >> 16);
162 fp_y1 += fp_dy1;
163 fp_y2 += fp_dy2;
164 }
165 }
166 }
167}
168#endif /* LCD_DEPTH, LCD_PIXELFORMAT */
169
170#if LCD_DEPTH >= 8
171
172#ifdef HAVE_LCD_COLOR
173static const fb_data graylut[256] = {
174#if LCD_PIXELFORMAT == RGB565
175 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841,
176 0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082,
177 0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3,
178 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104,
179 0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945,
180 0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186,
181 0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7,
182 0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208,
183 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49,
184 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a,
185 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab,
186 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec,
187 0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d,
188 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d,
189 0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae,
190 0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef,
191 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430,
192 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71,
193 0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2,
194 0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3,
195 0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534,
196 0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75,
197 0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6,
198 0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7,
199 0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638,
200 0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79,
201 0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba,
202 0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb,
203 0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c,
204 0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d,
205 0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be,
206 0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff
207#elif LCD_PIXELFORMAT == RGB565SWAPPED
208 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108,
209 0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210,
210 0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318,
211 0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421,
212 0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529,
213 0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631,
214 0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739,
215 0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842,
216 0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a,
217 0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52,
218 0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a,
219 0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62,
220 0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b,
221 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b,
222 0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73,
223 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b,
224 0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084,
225 0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c,
226 0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294,
227 0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c,
228 0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5,
229 0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad,
230 0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5,
231 0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd,
232 0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6,
233 0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce,
234 0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6,
235 0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde,
236 0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7,
237 0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def,
238 0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7,
239 0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff
240#endif /* LCD_PIXELFORMAT */
241};
242#endif /* HAVE_LCD_COLOR */
243
244/* Draw a partial greyscale bitmap, canonical 8 bit format */
245void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
246 int stride, int x, int y, int width, int height)
247{
248 const unsigned char *src_end;
249 fb_data *dst;
250
251 /* nothing to draw? */
252 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
253 || (x + width <= 0) || (y + height <= 0))
254 return;
255
256 /* clipping */
257 if (x < 0)
258 {
259 width += x;
260 src_x -= x;
261 x = 0;
262 }
263 if (y < 0)
264 {
265 height += y;
266 src_y -= y;
267 y = 0;
268 }
269 if (x + width > LCD_WIDTH)
270 width = LCD_WIDTH - x;
271 if (y + height > LCD_HEIGHT)
272 height = LCD_HEIGHT - y;
273
274 src += stride * src_y + src_x; /* move starting point */
275 src_end = src + stride * height;
276 dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x;
277
278 do
279 {
280 const unsigned char *src_row = src;
281 const unsigned char *row_end = src_row + width;
282 fb_data *dst_row = dst;
283
284#ifdef HAVE_LCD_COLOR
285 do
286 *dst_row++ = graylut[*src_row++];
287 while (src_row < row_end);
288#endif
289
290 src += stride;
291 dst += LCD_WIDTH;
292 }
293 while (src < src_end);
294}
295
296/* Draw a full greyscale bitmap, canonical 8 bit format */
297void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width,
298 int height)
299{
300 xlcd_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
301}
302
303#ifdef HAVE_LCD_COLOR
304/* Draw a partial colour bitmap, canonical 24 bit RGB format */
305void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
306 int stride, int x, int y, int width, int height)
307{
308 const unsigned char *src_end;
309 fb_data *dst;
310
311 /* nothing to draw? */
312 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
313 || (x + width <= 0) || (y + height <= 0))
314 return;
315
316 /* clipping */
317 if (x < 0)
318 {
319 width += x;
320 src_x -= x;
321 x = 0;
322 }
323 if (y < 0)
324 {
325 height += y;
326 src_y -= y;
327 y = 0;
328 }
329 if (x + width > LCD_WIDTH)
330 width = LCD_WIDTH - x;
331 if (y + height > LCD_HEIGHT)
332 height = LCD_HEIGHT - y;
333
334 src += 3 * (stride * src_y + src_x); /* move starting point */
335 src_end = src + 3 * stride * height;
336 dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x;
337
338 do
339 {
340 const unsigned char *src_row = src;
341 const unsigned char *row_end = src_row + 3 * width;
342 fb_data *dst_row = dst;
343
344 do
345 { /* only RGB565 and RGB565SWAPPED so far */
346 unsigned red = 31 * (*src_row++) + 127;
347 unsigned green = 63 * (*src_row++) + 127;
348 unsigned blue = 31 * (*src_row++) + 127;
349
350 red = (red + (red >> 8)) >> 8; /* approx red /= 255: */
351 green = (green + (green >> 8)) >> 8; /* approx green /= 255: */
352 blue = (blue + (blue >> 8)) >> 8; /* approx blue /= 255: */
353
354#if LCD_PIXELFORMAT == RGB565
355 *dst_row++ = (red << 11) | (green << 5) | blue;
356#elif LCD_PIXELFORMAT == RGB565SWAPPED
357 *dst_row++ = swap16((red << 11) | (green << 5) | blue);
358#endif
359 }
360 while (src_row < row_end);
361
362 src += 3 * stride;
363 dst += LCD_WIDTH;
364 }
365 while (src < src_end);
366}
367
368/* Draw a full colour bitmap, canonical 24 bit RGB format */
369void xlcd_color_bitmap(const unsigned char *src, int x, int y, int width,
370 int height)
371{
372 xlcd_color_bitmap_part(src, 0, 0, width, x, y, width, height);
373}
374#endif /* HAVE_LCD_COLOR */
375
376#endif /* LCD_DEPTH >= 8 */
377
378#endif /* HAVE_LCD_BITMAP */
379
diff --git a/apps/plugins/lib/xlcd_scroll.c b/apps/plugins/lib/xlcd_scroll.c
new file mode 100755
index 0000000000..44117b452c
--- /dev/null
+++ b/apps/plugins/lib/xlcd_scroll.c
@@ -0,0 +1,576 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Additional LCD routines not present in the rockbox core
11* Scrolling functions
12*
13* Copyright (C) 2005 Jens Arnold
14*
15* All files in this archive are subject to the GNU General Public License.
16* See the file COPYING in the source tree root for full license agreement.
17*
18* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19* KIND, either express or implied.
20*
21****************************************************************************/
22
23#include "plugin.h"
24
25#ifdef HAVE_LCD_BITMAP
26#include "xlcd.h"
27
28#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
29
30/* Scroll left */
31void xlcd_scroll_left(int count)
32{
33 int bitcount, oldmode;
34 int blockcount, blocklen;
35
36 if ((unsigned) count >= LCD_WIDTH)
37 return;
38
39#if LCD_DEPTH == 2
40 blockcount = count >> 2;
41 blocklen = LCD_FBWIDTH - blockcount;
42 bitcount = 2 * (count & 3);
43#endif
44
45 if (blockcount)
46 {
47 unsigned char *data = _xlcd_rb->lcd_framebuffer;
48 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
49
50 do
51 {
52 _xlcd_rb->memmove(data, data + blockcount, blocklen);
53 data += LCD_FBWIDTH;
54 }
55 while (data < data_end);
56 }
57 if (bitcount)
58 {
59 int bx, y;
60 unsigned char *addr = _xlcd_rb->lcd_framebuffer + blocklen;
61#if LCD_DEPTH == 2
62 unsigned fill = 0x55 * (~_xlcd_rb->lcd_get_background() & 3);
63#endif
64
65 for (y = 0; y < LCD_HEIGHT; y++)
66 {
67 unsigned char *row_addr = addr;
68 unsigned data = fill;
69
70 for (bx = 0; bx < blocklen; bx++)
71 {
72 --row_addr;
73 data = (data << 8) | *row_addr;
74 *row_addr = data >> bitcount;
75 }
76 addr += LCD_FBWIDTH;
77 }
78 }
79 oldmode = _xlcd_rb->lcd_get_drawmode();
80 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
81 _xlcd_rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
82 _xlcd_rb->lcd_set_drawmode(oldmode);
83}
84
85/* Scroll right */
86void xlcd_scroll_right(int count)
87{
88 int bitcount, oldmode;
89 int blockcount, blocklen;
90
91 if ((unsigned) count >= LCD_WIDTH)
92 return;
93
94#if LCD_DEPTH == 2
95 blockcount = count >> 2;
96 blocklen = LCD_FBWIDTH - blockcount;
97 bitcount = 2 * (count & 3);
98#endif
99
100 if (blockcount)
101 {
102 unsigned char *data = _xlcd_rb->lcd_framebuffer;
103 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
104
105 do
106 {
107 _xlcd_rb->memmove(data + blockcount, data, blocklen);
108 data += LCD_FBWIDTH;
109 }
110 while (data < data_end);
111 }
112 if (bitcount)
113 {
114 int bx, y;
115 unsigned char *addr = _xlcd_rb->lcd_framebuffer + blockcount;
116#if LCD_DEPTH == 2
117 unsigned fill = 0x55 * (~_xlcd_rb->lcd_get_background() & 3);
118#endif
119
120 for (y = 0; y < LCD_HEIGHT; y++)
121 {
122 unsigned char *row_addr = addr;
123 unsigned data = fill;
124
125 for (bx = 0; bx < blocklen; bx++)
126 {
127 data = (data >> 8) | (*row_addr << bitcount);
128 *row_addr = data;
129 row_addr++;
130 }
131 addr += LCD_FBWIDTH;
132 }
133 }
134 oldmode = _xlcd_rb->lcd_get_drawmode();
135 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
136 _xlcd_rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
137 _xlcd_rb->lcd_set_drawmode(oldmode);
138}
139
140#else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */
141
142/* Scroll left */
143void xlcd_scroll_left(int count)
144{
145 fb_data *data, *data_end;
146 int length, oldmode;
147
148 if ((unsigned)count >= LCD_WIDTH)
149 return;
150
151 data = _xlcd_rb->lcd_framebuffer;
152#if LCD_DEPTH >= 8
153 data_end = data + LCD_WIDTH*LCD_HEIGHT;
154#else
155 data_end = data + LCD_WIDTH*((LCD_HEIGHT*LCD_DEPTH+7)/8);
156#endif
157 length = LCD_WIDTH - count;
158
159 do
160 {
161 _xlcd_rb->memmove(data, data + count, length * sizeof(fb_data));
162 data += LCD_WIDTH;
163 }
164 while (data < data_end);
165
166 oldmode = _xlcd_rb->lcd_get_drawmode();
167 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
168 _xlcd_rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
169 _xlcd_rb->lcd_set_drawmode(oldmode);
170}
171
172/* Scroll right */
173void xlcd_scroll_right(int count)
174{
175 fb_data *data, *data_end;
176 int length, oldmode;
177
178 if ((unsigned)count >= LCD_WIDTH)
179 return;
180
181 data = _xlcd_rb->lcd_framebuffer;
182#if LCD_DEPTH >= 8
183 data_end = data + LCD_WIDTH*LCD_HEIGHT;
184#else
185 data_end = data + LCD_WIDTH*((LCD_HEIGHT*LCD_DEPTH+7)/8);
186#endif
187 length = LCD_WIDTH - count;
188
189 do
190 {
191 _xlcd_rb->memmove(data + count, data, length * sizeof(fb_data));
192 data += LCD_WIDTH;
193 }
194 while (data < data_end);
195
196 oldmode = _xlcd_rb->lcd_get_drawmode();
197 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
198 _xlcd_rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
199 _xlcd_rb->lcd_set_drawmode(oldmode);
200}
201
202#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
203
204#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8)
205
206/* Scroll up */
207void xlcd_scroll_up(int count)
208{
209 int length, oldmode;
210
211 if ((unsigned)count >= LCD_HEIGHT)
212 return;
213
214 length = LCD_HEIGHT - count;
215
216 _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer,
217 _xlcd_rb->lcd_framebuffer + count * LCD_FBWIDTH,
218 length * LCD_FBWIDTH * sizeof(fb_data));
219
220 oldmode = _xlcd_rb->lcd_get_drawmode();
221 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
222 _xlcd_rb->lcd_fillrect(0, length, LCD_WIDTH, count);
223 _xlcd_rb->lcd_set_drawmode(oldmode);
224}
225
226/* Scroll down */
227void xlcd_scroll_down(int count)
228{
229 int length, oldmode;
230
231 if ((unsigned)count >= LCD_HEIGHT)
232 return;
233
234 length = LCD_HEIGHT - count;
235
236 _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer + count * LCD_FBWIDTH,
237 _xlcd_rb->lcd_framebuffer,
238 length * LCD_FBWIDTH * sizeof(fb_data));
239
240 oldmode = _xlcd_rb->lcd_get_drawmode();
241 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
242 _xlcd_rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
243 _xlcd_rb->lcd_set_drawmode(oldmode);
244}
245
246#else /* LCD_PIXELFORMAT vertical packed */
247
248/* Scroll up */
249void xlcd_scroll_up(int count)
250{
251 int bitcount, oldmode;
252 int blockcount, blocklen;
253
254 if ((unsigned) count >= LCD_HEIGHT)
255 return;
256
257#if LCD_DEPTH == 1
258 blockcount = count >> 3;
259 blocklen = ((LCD_HEIGHT+7)/8) - blockcount;
260 bitcount = count & 7;
261#elif LCD_DEPTH == 2
262 blockcount = count >> 2;
263 blocklen = ((LCD_HEIGHT+3)/4) - blockcount;
264 bitcount = 2 * (count & 3);
265#endif
266
267 if (blockcount)
268 {
269 _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer,
270 _xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
271 blocklen * LCD_FBWIDTH);
272 }
273 if (bitcount)
274 {
275#if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
276 asm (
277 "mov #0,r4 \n" /* x = 0 */
278 "mova .su_shifttbl,r0 \n" /* calculate jump destination for */
279 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
280 "bra .su_cloop \n" /* skip table */
281 "add r0,%[cnt] \n"
282
283 ".align 2 \n"
284 ".su_shifttbl: \n" /* shift jump offset table */
285 ".byte .su_shift0 - .su_shifttbl \n"
286 ".byte .su_shift1 - .su_shifttbl \n"
287 ".byte .su_shift2 - .su_shifttbl \n"
288 ".byte .su_shift3 - .su_shifttbl \n"
289 ".byte .su_shift4 - .su_shifttbl \n"
290 ".byte .su_shift5 - .su_shifttbl \n"
291 ".byte .su_shift6 - .su_shifttbl \n"
292 ".byte .su_shift7 - .su_shifttbl \n"
293
294 ".su_cloop: \n" /* repeat for every column */
295 "mov %[addr],r2 \n" /* get start address */
296 "mov #0,r3 \n" /* current_row = 0 */
297 "mov #0,r1 \n" /* fill with zero */
298
299 ".su_iloop: \n" /* repeat for all rows */
300 "sub %[wide],r2 \n" /* address -= width */
301 "mov.b @r2,r0 \n" /* get data byte */
302 "shll8 r1 \n" /* old data to 2nd byte */
303 "extu.b r0,r0 \n" /* extend unsigned */
304 "or r1,r0 \n" /* combine old data */
305 "jmp @%[cnt] \n" /* jump into shift "path" */
306 "extu.b r0,r1 \n" /* store data for next round */
307
308 ".su_shift6: \n" /* shift right by 0..7 bits */
309 "shll2 r0 \n"
310 "bra .su_shift0 \n"
311 "shlr8 r0 \n"
312 ".su_shift4: \n"
313 "shlr2 r0 \n"
314 ".su_shift2: \n"
315 "bra .su_shift0 \n"
316 "shlr2 r0 \n"
317 ".su_shift7: \n"
318 "shlr2 r0 \n"
319 ".su_shift5: \n"
320 "shlr2 r0 \n"
321 ".su_shift3: \n"
322 "shlr2 r0 \n"
323 ".su_shift1: \n"
324 "shlr r0 \n"
325 ".su_shift0: \n"
326
327 "mov.b r0,@r2 \n" /* store data */
328 "add #1,r3 \n" /* current_row++ */
329 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
330 "bt .su_iloop \n"
331
332 "add #1,%[addr] \n" /* start_address++ */
333 "add #1,r4 \n" /* x++ */
334 "cmp/hi r4,%[wide] \n" /* x < width ? */
335 "bt .su_cloop \n"
336 : /* outputs */
337 : /* inputs */
338 [addr]"r"(_xlcd_rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
339 [wide]"r"(LCD_FBWIDTH),
340 [rows]"r"(blocklen),
341 [cnt] "r"(bitcount)
342 : /* clobbers */
343 "r0", "r1", "r2", "r3", "r4"
344 );
345#elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
346 asm (
347 "move.l %[wide],%%d3\n" /* columns = width */
348
349 ".su_cloop: \n" /* repeat for every column */
350 "move.l %[addr],%%a1\n" /* get start address */
351 "move.l %[rows],%%d2\n" /* rows = row_count */
352 "move.l %[bkg],%%d1 \n" /* fill with background */
353
354 ".su_iloop: \n" /* repeat for all rows */
355 "sub.l %[wide],%%a1\n" /* address -= width */
356
357 "clr.l %%d0 \n"
358 "move.b (%%a1),%%d0 \n" /* get data byte */
359 "lsl.l #8,%%d1 \n" /* old data to 2nd byte */
360 "or.l %%d1,%%d0 \n" /* combine old data */
361 "clr.l %%d1 \n"
362 "move.b %%d0,%%d1 \n" /* keep data for next round */
363 "lsr.l %[cnt],%%d0 \n" /* shift right */
364 "move.b %%d0,(%%a1) \n" /* store data */
365
366 "subq.l #1,%%d2 \n" /* rows-- */
367 "bne.b .su_iloop \n"
368
369 "addq.l #1,%[addr] \n" /* start_address++ */
370 "subq.l #1,%%d3 \n" /* columns-- */
371 "bne.b .su_cloop \n"
372 : /* outputs */
373 : /* inputs */
374 [wide]"r"(LCD_FBWIDTH),
375 [rows]"r"(blocklen),
376 [addr]"a"(_xlcd_rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
377 [cnt] "d"(bitcount),
378 [bkg] "d"(0x55 * (~_xlcd_rb->lcd_get_background() & 3))
379 : /* clobbers */
380 "a1", "d0", "d1", "d2", "d3"
381 );
382#else /* C version */
383 int x, by;
384 unsigned char *addr = _xlcd_rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
385#if LCD_DEPTH == 2
386 unsigned fill = 0x55 * (~_xlcd_rb->lcd_get_background() & 3);
387#endif
388
389 for (x = 0; x < LCD_WIDTH; x++)
390 {
391 unsigned char *col_addr = addr++;
392#if LCD_DEPTH == 1
393 unsigned data = 0;
394#else
395 unsigned data = fill;
396#endif
397
398 for (by = 0; by < blocklen; by++)
399 {
400 col_addr -= LCD_FBWIDTH;
401 data = (data << 8) | *col_addr;
402 *col_addr = data >> bitcount;
403 }
404 }
405#endif /* CPU, LCD_DEPTH */
406 }
407 oldmode = _xlcd_rb->lcd_get_drawmode();
408 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
409 _xlcd_rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
410 _xlcd_rb->lcd_set_drawmode(oldmode);
411}
412
413/* Scroll up */
414void xlcd_scroll_down(int count)
415{
416 int bitcount, oldmode;
417 int blockcount, blocklen;
418
419 if ((unsigned) count >= LCD_HEIGHT)
420 return;
421
422#if LCD_DEPTH == 1
423 blockcount = count >> 3;
424 blocklen = ((LCD_HEIGHT+7)/8) - blockcount;
425 bitcount = count & 7;
426#elif LCD_DEPTH == 2
427 blockcount = count >> 2;
428 blocklen = ((LCD_HEIGHT+3)/4) - blockcount;
429 bitcount = 2 * (count & 3);
430#endif
431
432 if (blockcount)
433 {
434 _xlcd_rb->memmove(_xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
435 _xlcd_rb->lcd_framebuffer,
436 blocklen * LCD_FBWIDTH);
437 }
438 if (bitcount)
439 {
440#if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
441 asm (
442 "mov #0,r4 \n" /* x = 0 */
443 "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */
444 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
445 "bra .sd_cloop \n" /* skip table */
446 "add r0,%[cnt] \n"
447
448 ".align 2 \n"
449 ".sd_shifttbl: \n" /* shift jump offset table */
450 ".byte .sd_shift0 - .sd_shifttbl \n"
451 ".byte .sd_shift1 - .sd_shifttbl \n"
452 ".byte .sd_shift2 - .sd_shifttbl \n"
453 ".byte .sd_shift3 - .sd_shifttbl \n"
454 ".byte .sd_shift4 - .sd_shifttbl \n"
455 ".byte .sd_shift5 - .sd_shifttbl \n"
456 ".byte .sd_shift6 - .sd_shifttbl \n"
457 ".byte .sd_shift7 - .sd_shifttbl \n"
458
459 ".sd_cloop: \n" /* repeat for every column */
460 "mov %[addr],r2 \n" /* get start address */
461 "mov #0,r3 \n" /* current_row = 0 */
462 "mov #0,r1 \n" /* fill with zero */
463
464 ".sd_iloop: \n" /* repeat for all rows */
465 "shlr8 r1 \n" /* shift right to get residue */
466 "mov.b @r2,r0 \n" /* get data byte */
467 "jmp @%[cnt] \n" /* jump into shift "path" */
468 "extu.b r0,r0 \n" /* extend unsigned */
469
470 ".sd_shift6: \n" /* shift left by 0..7 bits */
471 "shll8 r0 \n"
472 "bra .sd_shift0 \n"
473 "shlr2 r0 \n"
474 ".sd_shift4: \n"
475 "shll2 r0 \n"
476 ".sd_shift2: \n"
477 "bra .sd_shift0 \n"
478 "shll2 r0 \n"
479 ".sd_shift7: \n"
480 "shll2 r0 \n"
481 ".sd_shift5: \n"
482 "shll2 r0 \n"
483 ".sd_shift3: \n"
484 "shll2 r0 \n"
485 ".sd_shift1: \n"
486 "shll r0 \n"
487 ".sd_shift0: \n"
488
489 "or r0,r1 \n" /* combine with last residue */
490 "mov.b r1,@r2 \n" /* store data */
491 "add %[wide],r2 \n" /* address += width */
492 "add #1,r3 \n" /* current_row++ */
493 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
494 "bt .sd_iloop \n"
495
496 "add #1,%[addr] \n" /* start_address++ */
497 "add #1,r4 \n" /* x++ */
498 "cmp/hi r4,%[wide] \n" /* x < width ? */
499 "bt .sd_cloop \n"
500 : /* outputs */
501 : /* inputs */
502 [addr]"r"(_xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
503 [wide]"r"(LCD_WIDTH),
504 [rows]"r"(blocklen),
505 [cnt] "r"(bitcount)
506 : /* clobbers */
507 "r0", "r1", "r2", "r3", "r4"
508 );
509#elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
510 asm (
511 "move.l %[wide],%%d3\n" /* columns = width */
512
513 ".sd_cloop: \n" /* repeat for every column */
514 "move.l %[addr],%%a1\n" /* get start address */
515 "move.l %[rows],%%d2\n" /* rows = row_count */
516 "move.l %[bkg],%%d1 \n" /* fill with background */
517
518 ".sd_iloop: \n" /* repeat for all rows */
519 "lsr.l #8,%%d1 \n" /* shift right to get residue */
520 "clr.l %%d0 \n"
521 "move.b (%%a1),%%d0 \n" /* get data byte */
522 "lsl.l %[cnt],%%d0 \n"
523 "or.l %%d0,%%d1 \n" /* combine with last residue */
524 "move.b %%d1,(%%a1) \n" /* store data */
525
526 "add.l %[wide],%%a1\n" /* address += width */
527 "subq.l #1,%%d2 \n" /* rows-- */
528 "bne.b .sd_iloop \n"
529
530 "lea.l (1,%[addr]),%[addr] \n" /* start_address++ */
531 "subq.l #1,%%d3 \n" /* columns-- */
532 "bne.b .sd_cloop \n"
533 : /* outputs */
534 : /* inputs */
535 [wide]"r"(LCD_WIDTH),
536 [rows]"r"(blocklen),
537 [addr]"a"(_xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
538 [cnt] "d"(bitcount),
539 [bkg] "d"((0x55 * (~_xlcd_rb->lcd_get_background() & 3)) << bitcount)
540 : /* clobbers */
541 "a1", "d0", "d1", "d2", "d3"
542 );
543#else /* C version */
544 int x, by;
545 unsigned char *addr = _xlcd_rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
546#if LCD_DEPTH == 2
547 unsigned fill = (0x55 * (~_xlcd_rb->lcd_get_background() & 3)) << bitcount;
548#endif
549
550 for (x = 0; x < LCD_WIDTH; x++)
551 {
552 unsigned char *col_addr = addr++;
553#if LCD_DEPTH == 1
554 unsigned data = 0;
555#else
556 unsigned data = fill;
557#endif
558
559 for (by = 0; by < blocklen; by++)
560 {
561 data = (data >> 8) | (*col_addr << bitcount);
562 *col_addr = data;
563 col_addr += LCD_FBWIDTH;
564 }
565 }
566#endif /* CPU, LCD_DEPTH */
567 }
568 oldmode = _xlcd_rb->lcd_get_drawmode();
569 _xlcd_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
570 _xlcd_rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
571 _xlcd_rb->lcd_set_drawmode(oldmode);
572}
573
574#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
575
576#endif /* HAVE_LCD_BITMAP */