summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/xlcd_scroll.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lib/xlcd_scroll.c')
-rwxr-xr-xapps/plugins/lib/xlcd_scroll.c576
1 files changed, 576 insertions, 0 deletions
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 */