summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--apps/plugins/oscilloscope.c69
-rw-r--r--firmware/drivers/lcd-2bit-horz.c18
-rw-r--r--firmware/export/lcd.h8
8 files changed, 1026 insertions, 72 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 */
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index b69d15daae..de85dc3950 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -24,6 +24,7 @@
24 24
25#ifdef HAVE_LCD_BITMAP /* and also not for the Player */ 25#ifdef HAVE_LCD_BITMAP /* and also not for the Player */
26#if CONFIG_CODEC != SWCODEC /* only for MAS-targets */ 26#if CONFIG_CODEC != SWCODEC /* only for MAS-targets */
27#include "xlcd.h"
27 28
28PLUGIN_HEADER 29PLUGIN_HEADER
29 30
@@ -77,88 +78,34 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter);
77 78
78/* implementation */ 79/* implementation */
79 80
80void lcd_scroll_left(int count, bool black_border)
81{
82 int by;
83 unsigned filler;
84 unsigned char *ptr;
85
86 if ((unsigned) count >= LCD_WIDTH)
87 return;
88
89 filler = black_border ? 0xFF : 0;
90
91 for (by = 0; by < (LCD_HEIGHT/8); by++)
92 {
93 ptr = rb->lcd_framebuffer + MULU16(LCD_WIDTH, by);
94 asm volatile (
95 "mov %0,r1 \n" /* check if both source... */
96 "or %2,r1 \n" /* ...and offset are even */
97 "shlr r1 \n" /* -> lsb = 0 */
98 "bf .sl_start2 \n" /* -> copy word-wise */
99
100 "add #-1,%2 \n" /* copy byte-wise */
101 ".sl_loop1: \n"
102 "mov.b @%0+,r1 \n"
103 "mov.b r1,@(%2,%0) \n"
104 "cmp/hi %0,%1 \n"
105 "bt .sl_loop1 \n"
106
107 "bra .sl_end \n"
108 "nop \n"
109
110 ".sl_start2: \n" /* copy word-wise */
111 "add #-2,%2 \n"
112 ".sl_loop2: \n"
113 "mov.w @%0+,r1 \n"
114 "mov.w r1,@(%2,%0) \n"
115 "cmp/hi %0,%1 \n"
116 "bt .sl_loop2 \n"
117
118 ".sl_end: \n"
119 : /* outputs */
120 : /* inputs */
121 /* %0 */ "r"(ptr + count),
122 /* %1 */ "r"(ptr + LCD_WIDTH),
123 /* %2 */ "z"(-count)
124 : /* clobbers */
125 "r1"
126 );
127
128 rb->memset(ptr + LCD_WIDTH - count, filler, count);
129 }
130}
131
132void timer_isr(void) 81void timer_isr(void)
133{ 82{
134 static int last_left, last_right; 83 static int last_left, last_right;
135 bool full_update = false; 84 bool full_update = false;
136 85
137 if (new_val) 86 if (new_val)
138 { 87 {
139 if ((unsigned)x >= LCD_WIDTH) 88 if ((unsigned)x >= LCD_WIDTH)
140 { 89 {
141 if (scroll) 90 if (scroll)
142 { 91 {
143 lcd_scroll_left(1, false); 92 xlcd_scroll_left(1);
144 x = LCD_WIDTH-1; 93 x = LCD_WIDTH-1;
145 full_update = true; 94 full_update = true;
146 } 95 }
147 else 96 else
148 x = 0; 97 x = 0;
149 } 98 }
150 99
151 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 100 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
152 rb->lcd_drawline(x, 0, x, LCD_HEIGHT-1); 101 rb->lcd_vline(x, 0, LCD_HEIGHT-1);
153 rb->lcd_set_drawmode(DRMODE_SOLID); 102 rb->lcd_set_drawmode(DRMODE_SOLID);
154 103
155 switch (draw_mode) 104 switch (draw_mode)
156 { 105 {
157 case DRAW_MODE_FILLED: 106 case DRAW_MODE_FILLED:
158 rb->lcd_drawline(x, LCD_HEIGHT/2+1, 107 rb->lcd_vline(x, LCD_HEIGHT/2+1, LCD_HEIGHT/2+1 + left_val);
159 x, LCD_HEIGHT/2+1 + left_val); 108 rb->lcd_vline(x, LCD_HEIGHT/2-1, LCD_HEIGHT/2-1 - right_val);
160 rb->lcd_drawline(x, LCD_HEIGHT/2-1,
161 x, LCD_HEIGHT/2-1 - right_val);
162 break; 109 break;
163 110
164 case DRAW_MODE_OUTLINE: 111 case DRAW_MODE_OUTLINE:
@@ -205,6 +152,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
205 152
206 (void)parameter; 153 (void)parameter;
207 rb = api; 154 rb = api;
155
156 xlcd_init(rb);
208 157
209 rb->timer_register(1, NULL, FREQ / 67, 1, timer_isr); 158 rb->timer_register(1, NULL, FREQ / 67, 1, timer_isr);
210 159
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c
index 164e94cb73..a76ebe1f0d 100644
--- a/firmware/drivers/lcd-2bit-horz.c
+++ b/firmware/drivers/lcd-2bit-horz.c
@@ -38,7 +38,7 @@
38 38
39/*** globals ***/ 39/*** globals ***/
40 40
41unsigned char lcd_framebuffer[LCD_HEIGHT][FB_WIDTH] IBSS_ATTR; 41unsigned char lcd_framebuffer[LCD_HEIGHT][LCD_FBWIDTH] IBSS_ATTR;
42 42
43static const unsigned char dibits[16] ICONST_ATTR = { 43static const unsigned char dibits[16] ICONST_ATTR = {
44 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, 44 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
@@ -419,11 +419,11 @@ void lcd_vline(int x, int y1, int y2)
419 dst = &lcd_framebuffer[y1][x>>2]; 419 dst = &lcd_framebuffer[y1][x>>2];
420 mask = pixmask[x & 3]; 420 mask = pixmask[x & 3];
421 421
422 dst_end = dst + (y2 - y1) * FB_WIDTH; 422 dst_end = dst + (y2 - y1) * LCD_FBWIDTH;
423 do 423 do
424 { 424 {
425 bfunc(dst, mask, 0xFFu); 425 bfunc(dst, mask, 0xFFu);
426 dst += FB_WIDTH; 426 dst += LCD_FBWIDTH;
427 } 427 }
428 while (dst <= dst_end); 428 while (dst <= dst_end);
429} 429}
@@ -482,11 +482,11 @@ void lcd_fillrect(int x, int y, int width, int height)
482 { 482 {
483 unsigned char *dst_col = dst; 483 unsigned char *dst_col = dst;
484 484
485 dst_end = dst_col + height * FB_WIDTH; 485 dst_end = dst_col + height * LCD_FBWIDTH;
486 do 486 do
487 { 487 {
488 bfunc(dst_col, mask, 0xFFu); 488 bfunc(dst_col, mask, 0xFFu);
489 dst_col += FB_WIDTH; 489 dst_col += LCD_FBWIDTH;
490 } 490 }
491 while (dst_col < dst_end); 491 while (dst_col < dst_end);
492 492
@@ -495,11 +495,11 @@ void lcd_fillrect(int x, int y, int width, int height)
495 } 495 }
496 mask &= mask_right; 496 mask &= mask_right;
497 497
498 dst_end = dst + height * FB_WIDTH; 498 dst_end = dst + height * LCD_FBWIDTH;
499 do 499 do
500 { 500 {
501 bfunc(dst, mask, 0xFFu); 501 bfunc(dst, mask, 0xFFu);
502 dst += FB_WIDTH; 502 dst += LCD_FBWIDTH;
503 } 503 }
504 while (dst < dst_end); 504 while (dst < dst_end);
505} 505}
@@ -651,7 +651,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
651 mask_right = 0xFFu >> (2 * (~nx & 3)); 651 mask_right = 0xFFu >> (2 * (~nx & 3));
652 652
653 shift *= 2; 653 shift *= 2;
654 dst_end = dst + height * FB_WIDTH; 654 dst_end = dst + height * LCD_FBWIDTH;
655 do 655 do
656 { 656 {
657 const unsigned char *src_row = src; 657 const unsigned char *src_row = src;
@@ -678,7 +678,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
678 setblock(dst_row, mask_row & mask_right, data); 678 setblock(dst_row, mask_row & mask_right, data);
679 679
680 src += stride; 680 src += stride;
681 dst += FB_WIDTH; 681 dst += LCD_FBWIDTH;
682 } 682 }
683 while (dst < dst_end); 683 while (dst < dst_end);
684} 684}
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 6f7fef94ee..89bf35300c 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -205,8 +205,8 @@ typedef void lcd_fastpixelfunc_type(fb_data *address);
205extern fb_data lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; 205extern fb_data lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH];
206#elif LCD_DEPTH == 2 206#elif LCD_DEPTH == 2
207#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 207#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
208#define FB_WIDTH ((LCD_WIDTH+3)/4) 208#define LCD_FBWIDTH ((LCD_WIDTH+3)/4)
209extern fb_data lcd_framebuffer[LCD_HEIGHT][FB_WIDTH]; 209extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_FBWIDTH];
210#else 210#else
211extern fb_data lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH]; 211extern fb_data lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH];
212#endif 212#endif
@@ -214,6 +214,10 @@ extern fb_data lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH];
214extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH]; 214extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH];
215#elif LCD_DEPTH == 18 215#elif LCD_DEPTH == 18
216extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH]; 216extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH];
217#endif
218
219#ifndef LCD_FBWIDTH
220#define LCD_FBWIDTH LCD_WIDTH
217#endif 221#endif
218 222
219#if (CONFIG_BACKLIGHT==BL_IRIVER_H300) || (CONFIG_BACKLIGHT==BL_IPOD3G) 223#if (CONFIG_BACKLIGHT==BL_IRIVER_H300) || (CONFIG_BACKLIGHT==BL_IPOD3G)