Rearange menu of mpegplayer. Add new menu with "settings" and "quit", and remove...
[kugel-rb.git] / apps / plugins / lib / xlcd_scroll.c
blob6b70e2cfd2a6049a4503e061ba93945e7f3a516f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Additional LCD routines not present in the rockbox core
11 * Scrolling functions
13 * Copyright (C) 2005 Jens Arnold
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include "plugin.h"
27 #ifdef HAVE_LCD_BITMAP
28 #include "xlcd.h"
30 #if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
31 static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
32 #endif
34 #if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
36 /* Scroll left */
37 void xlcd_scroll_left(int count)
39 int bitcount, oldmode;
40 int blockcount, blocklen;
42 if ((unsigned) count >= LCD_WIDTH)
43 return;
45 #if LCD_DEPTH == 2
46 blockcount = count >> 2;
47 blocklen = LCD_FBWIDTH - blockcount;
48 bitcount = 2 * (count & 3);
49 #endif
51 if (blockcount)
53 unsigned char *data = rb->lcd_framebuffer;
54 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
58 rb->memmove(data, data + blockcount, blocklen);
59 data += LCD_FBWIDTH;
61 while (data < data_end);
63 if (bitcount)
65 int bx, y;
66 unsigned char *addr = rb->lcd_framebuffer + blocklen;
67 #if LCD_DEPTH == 2
68 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
69 #endif
71 for (y = 0; y < LCD_HEIGHT; y++)
73 unsigned char *row_addr = addr;
74 unsigned data = fill;
76 for (bx = 0; bx < blocklen; bx++)
78 --row_addr;
79 data = (data >> 8) | (*row_addr << bitcount);
80 *row_addr = data;
82 addr += LCD_FBWIDTH;
85 oldmode = rb->lcd_get_drawmode();
86 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
87 rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
88 rb->lcd_set_drawmode(oldmode);
91 /* Scroll right */
92 void xlcd_scroll_right(int count)
94 int bitcount, oldmode;
95 int blockcount, blocklen;
97 if ((unsigned) count >= LCD_WIDTH)
98 return;
100 #if LCD_DEPTH == 2
101 blockcount = count >> 2;
102 blocklen = LCD_FBWIDTH - blockcount;
103 bitcount = 2 * (count & 3);
104 #endif
106 if (blockcount)
108 unsigned char *data = rb->lcd_framebuffer;
109 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
113 rb->memmove(data + blockcount, data, blocklen);
114 data += LCD_FBWIDTH;
116 while (data < data_end);
118 if (bitcount)
120 int bx, y;
121 unsigned char *addr = rb->lcd_framebuffer + blockcount;
122 #if LCD_DEPTH == 2
123 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
124 #endif
126 for (y = 0; y < LCD_HEIGHT; y++)
128 unsigned char *row_addr = addr;
129 unsigned data = fill;
131 for (bx = 0; bx < blocklen; bx++)
133 data = (data << 8) | *row_addr;
134 *row_addr = data >> bitcount;
135 row_addr++;
137 addr += LCD_FBWIDTH;
140 oldmode = rb->lcd_get_drawmode();
141 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
142 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
143 rb->lcd_set_drawmode(oldmode);
146 #else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */
148 /* Scroll left */
149 void xlcd_scroll_left(int count)
151 fb_data *data, *data_end;
152 int length, oldmode;
154 if ((unsigned)count >= LCD_WIDTH)
155 return;
157 data = rb->lcd_framebuffer;
158 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
159 length = LCD_WIDTH - count;
163 rb->memmove(data, data + count, length * sizeof(fb_data));
164 data += LCD_WIDTH;
166 while (data < data_end);
168 oldmode = rb->lcd_get_drawmode();
169 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
170 rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
171 rb->lcd_set_drawmode(oldmode);
174 /* Scroll right */
175 void xlcd_scroll_right(int count)
177 fb_data *data, *data_end;
178 int length, oldmode;
180 if ((unsigned)count >= LCD_WIDTH)
181 return;
183 data = rb->lcd_framebuffer;
184 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
185 length = LCD_WIDTH - count;
189 rb->memmove(data + count, data, length * sizeof(fb_data));
190 data += LCD_WIDTH;
192 while (data < data_end);
194 oldmode = rb->lcd_get_drawmode();
195 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
196 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
197 rb->lcd_set_drawmode(oldmode);
200 #endif /* LCD_PIXELFORMAT, LCD_DEPTH */
202 #if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8)
204 /* Scroll up */
205 void xlcd_scroll_up(int count)
207 int length, oldmode;
209 if ((unsigned)count >= LCD_HEIGHT)
210 return;
212 length = LCD_HEIGHT - count;
214 rb->memmove(rb->lcd_framebuffer,
215 rb->lcd_framebuffer + count * LCD_FBWIDTH,
216 length * LCD_FBWIDTH * sizeof(fb_data));
218 oldmode = rb->lcd_get_drawmode();
219 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
220 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
221 rb->lcd_set_drawmode(oldmode);
224 /* Scroll down */
225 void xlcd_scroll_down(int count)
227 int length, oldmode;
229 if ((unsigned)count >= LCD_HEIGHT)
230 return;
232 length = LCD_HEIGHT - count;
234 rb->memmove(rb->lcd_framebuffer + count * LCD_FBWIDTH,
235 rb->lcd_framebuffer,
236 length * LCD_FBWIDTH * sizeof(fb_data));
238 oldmode = rb->lcd_get_drawmode();
239 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
240 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
241 rb->lcd_set_drawmode(oldmode);
244 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING,
245 LCD_PIXELFORMAT == VERTICAL_INTERLEAVED */
247 /* Scroll up */
248 void xlcd_scroll_up(int count)
250 int bitcount, oldmode;
251 int blockcount, blocklen;
253 if ((unsigned) count >= LCD_HEIGHT)
254 return;
256 #if (LCD_DEPTH == 1) \
257 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
258 blockcount = count >> 3;
259 bitcount = count & 7;
260 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
261 blockcount = count >> 2;
262 bitcount = 2 * (count & 3);
263 #endif
264 blocklen = LCD_FBHEIGHT - blockcount;
266 if (blockcount)
268 rb->memmove(rb->lcd_framebuffer,
269 rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
270 blocklen * LCD_FBWIDTH * sizeof(fb_data));
272 if (bitcount)
274 #if LCD_PIXELFORMAT == VERTICAL_PACKING
276 #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
277 asm (
278 "mov #0,r4 \n" /* x = 0 */
279 "mova .su_shifttbl,r0 \n" /* calculate jump destination for */
280 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
281 "bra .su_cloop \n" /* skip table */
282 "add r0,%[cnt] \n"
284 ".align 2 \n"
285 ".su_shifttbl: \n" /* shift jump offset table */
286 ".byte .su_shift0 - .su_shifttbl \n"
287 ".byte .su_shift1 - .su_shifttbl \n"
288 ".byte .su_shift2 - .su_shifttbl \n"
289 ".byte .su_shift3 - .su_shifttbl \n"
290 ".byte .su_shift4 - .su_shifttbl \n"
291 ".byte .su_shift5 - .su_shifttbl \n"
292 ".byte .su_shift6 - .su_shifttbl \n"
293 ".byte .su_shift7 - .su_shifttbl \n"
295 ".su_cloop: \n" /* repeat for every column */
296 "mov %[addr],r2 \n" /* get start address */
297 "mov #0,r3 \n" /* current_row = 0 */
298 "mov #0,r1 \n" /* fill with zero */
300 ".su_iloop: \n" /* repeat for all rows */
301 "sub %[wide],r2 \n" /* address -= width */
302 "mov.b @r2,r0 \n" /* get data byte */
303 "shll8 r1 \n" /* old data to 2nd byte */
304 "extu.b r0,r0 \n" /* extend unsigned */
305 "or r1,r0 \n" /* combine old data */
306 "jmp @%[cnt] \n" /* jump into shift "path" */
307 "extu.b r0,r1 \n" /* store data for next round */
309 ".su_shift6: \n" /* shift right by 0..7 bits */
310 "shll2 r0 \n"
311 "bra .su_shift0 \n"
312 "shlr8 r0 \n"
313 ".su_shift4: \n"
314 "shlr2 r0 \n"
315 ".su_shift2: \n"
316 "bra .su_shift0 \n"
317 "shlr2 r0 \n"
318 ".su_shift7: \n"
319 "shlr2 r0 \n"
320 ".su_shift5: \n"
321 "shlr2 r0 \n"
322 ".su_shift3: \n"
323 "shlr2 r0 \n"
324 ".su_shift1: \n"
325 "shlr r0 \n"
326 ".su_shift0: \n"
328 "mov.b r0,@r2 \n" /* store data */
329 "add #1,r3 \n" /* current_row++ */
330 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
331 "bt .su_iloop \n"
333 "add #1,%[addr] \n" /* start_address++ */
334 "add #1,r4 \n" /* x++ */
335 "cmp/hi r4,%[wide] \n" /* x < width ? */
336 "bt .su_cloop \n"
337 : /* outputs */
338 : /* inputs */
339 [addr]"r"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
340 [wide]"r"(LCD_FBWIDTH),
341 [rows]"r"(blocklen),
342 [cnt] "r"(bitcount)
343 : /* clobbers */
344 "r0", "r1", "r2", "r3", "r4"
346 #elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
347 asm (
348 "move.l %[wide],%%d3\n" /* columns = width */
350 ".su_cloop: \n" /* repeat for every column */
351 "move.l %[addr],%%a1\n" /* get start address */
352 "move.l %[rows],%%d2\n" /* rows = row_count */
353 "move.l %[bkg],%%d1 \n" /* fill with background */
355 ".su_iloop: \n" /* repeat for all rows */
356 "sub.l %[wide],%%a1\n" /* address -= width */
358 "clr.l %%d0 \n"
359 "move.b (%%a1),%%d0 \n" /* get data byte */
360 "lsl.l #8,%%d1 \n" /* old data to 2nd byte */
361 "or.l %%d1,%%d0 \n" /* combine old data */
362 "clr.l %%d1 \n"
363 "move.b %%d0,%%d1 \n" /* keep data for next round */
364 "lsr.l %[cnt],%%d0 \n" /* shift right */
365 "move.b %%d0,(%%a1) \n" /* store data */
367 "subq.l #1,%%d2 \n" /* rows-- */
368 "bne.b .su_iloop \n"
370 "addq.l #1,%[addr] \n" /* start_address++ */
371 "subq.l #1,%%d3 \n" /* columns-- */
372 "bne.b .su_cloop \n"
373 : /* outputs */
374 : /* inputs */
375 [wide]"r"(LCD_FBWIDTH),
376 [rows]"r"(blocklen),
377 [addr]"a"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
378 [cnt] "d"(bitcount),
379 [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
380 : /* clobbers */
381 "a1", "d0", "d1", "d2", "d3"
383 #else /* C version */
384 int x, by;
385 unsigned char *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
386 #if LCD_DEPTH == 2
387 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
388 #else
389 const unsigned fill = 0;
390 #endif
392 for (x = 0; x < LCD_WIDTH; x++)
394 unsigned char *col_addr = addr++;
395 unsigned data = fill;
397 for (by = 0; by < blocklen; by++)
399 col_addr -= LCD_FBWIDTH;
400 data = (data << 8) | *col_addr;
401 *col_addr = data >> bitcount;
404 #endif /* CPU, LCD_DEPTH */
406 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
408 #if LCD_DEPTH == 2
409 int x, by;
410 fb_data *addr = rb->lcd_framebuffer + blocklen * LCD_FBWIDTH;
411 unsigned fill, mask;
413 fill = patterns[rb->lcd_get_background() & 3] << 8;
414 mask = (0xFFu >> bitcount) << bitcount;
415 mask |= mask << 8;
417 for (x = 0; x < LCD_WIDTH; x++)
419 fb_data *col_addr = addr++;
420 unsigned olddata = fill;
421 unsigned data;
423 for (by = 0; by < blocklen; by++)
425 col_addr -= LCD_FBWIDTH;
426 data = *col_addr;
427 *col_addr = (olddata ^ ((data ^ olddata) & mask)) >> bitcount;
428 olddata = data << 8;
431 #endif /* LCD_DEPTH == 2 */
433 #endif /* LCD_PIXELFORMAT */
435 oldmode = rb->lcd_get_drawmode();
436 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
437 rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
438 rb->lcd_set_drawmode(oldmode);
441 /* Scroll up */
442 void xlcd_scroll_down(int count)
444 int bitcount, oldmode;
445 int blockcount, blocklen;
447 if ((unsigned) count >= LCD_HEIGHT)
448 return;
450 #if (LCD_DEPTH == 1) \
451 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
452 blockcount = count >> 3;
453 bitcount = count & 7;
454 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
455 blockcount = count >> 2;
456 bitcount = 2 * (count & 3);
457 #endif
458 blocklen = LCD_FBHEIGHT - blockcount;
460 if (blockcount)
462 rb->memmove(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
463 rb->lcd_framebuffer,
464 blocklen * LCD_FBWIDTH * sizeof(fb_data));
466 if (bitcount)
468 #if LCD_PIXELFORMAT == VERTICAL_PACKING
470 #if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
471 asm (
472 "mov #0,r4 \n" /* x = 0 */
473 "mova .sd_shifttbl,r0 \n" /* calculate jump destination for */
474 "mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
475 "bra .sd_cloop \n" /* skip table */
476 "add r0,%[cnt] \n"
478 ".align 2 \n"
479 ".sd_shifttbl: \n" /* shift jump offset table */
480 ".byte .sd_shift0 - .sd_shifttbl \n"
481 ".byte .sd_shift1 - .sd_shifttbl \n"
482 ".byte .sd_shift2 - .sd_shifttbl \n"
483 ".byte .sd_shift3 - .sd_shifttbl \n"
484 ".byte .sd_shift4 - .sd_shifttbl \n"
485 ".byte .sd_shift5 - .sd_shifttbl \n"
486 ".byte .sd_shift6 - .sd_shifttbl \n"
487 ".byte .sd_shift7 - .sd_shifttbl \n"
489 ".sd_cloop: \n" /* repeat for every column */
490 "mov %[addr],r2 \n" /* get start address */
491 "mov #0,r3 \n" /* current_row = 0 */
492 "mov #0,r1 \n" /* fill with zero */
494 ".sd_iloop: \n" /* repeat for all rows */
495 "shlr8 r1 \n" /* shift right to get residue */
496 "mov.b @r2,r0 \n" /* get data byte */
497 "jmp @%[cnt] \n" /* jump into shift "path" */
498 "extu.b r0,r0 \n" /* extend unsigned */
500 ".sd_shift6: \n" /* shift left by 0..7 bits */
501 "shll8 r0 \n"
502 "bra .sd_shift0 \n"
503 "shlr2 r0 \n"
504 ".sd_shift4: \n"
505 "shll2 r0 \n"
506 ".sd_shift2: \n"
507 "bra .sd_shift0 \n"
508 "shll2 r0 \n"
509 ".sd_shift7: \n"
510 "shll2 r0 \n"
511 ".sd_shift5: \n"
512 "shll2 r0 \n"
513 ".sd_shift3: \n"
514 "shll2 r0 \n"
515 ".sd_shift1: \n"
516 "shll r0 \n"
517 ".sd_shift0: \n"
519 "or r0,r1 \n" /* combine with last residue */
520 "mov.b r1,@r2 \n" /* store data */
521 "add %[wide],r2 \n" /* address += width */
522 "add #1,r3 \n" /* current_row++ */
523 "cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
524 "bt .sd_iloop \n"
526 "add #1,%[addr] \n" /* start_address++ */
527 "add #1,r4 \n" /* x++ */
528 "cmp/hi r4,%[wide] \n" /* x < width ? */
529 "bt .sd_cloop \n"
530 : /* outputs */
531 : /* inputs */
532 [addr]"r"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
533 [wide]"r"(LCD_WIDTH),
534 [rows]"r"(blocklen),
535 [cnt] "r"(bitcount)
536 : /* clobbers */
537 "r0", "r1", "r2", "r3", "r4"
539 #elif defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
540 asm (
541 "move.l %[wide],%%d3\n" /* columns = width */
543 ".sd_cloop: \n" /* repeat for every column */
544 "move.l %[addr],%%a1\n" /* get start address */
545 "move.l %[rows],%%d2\n" /* rows = row_count */
546 "move.l %[bkg],%%d1 \n" /* fill with background */
548 ".sd_iloop: \n" /* repeat for all rows */
549 "lsr.l #8,%%d1 \n" /* shift right to get residue */
550 "clr.l %%d0 \n"
551 "move.b (%%a1),%%d0 \n" /* get data byte */
552 "lsl.l %[cnt],%%d0 \n"
553 "or.l %%d0,%%d1 \n" /* combine with last residue */
554 "move.b %%d1,(%%a1) \n" /* store data */
556 "add.l %[wide],%%a1\n" /* address += width */
557 "subq.l #1,%%d2 \n" /* rows-- */
558 "bne.b .sd_iloop \n"
560 "lea.l (1,%[addr]),%[addr] \n" /* start_address++ */
561 "subq.l #1,%%d3 \n" /* columns-- */
562 "bne.b .sd_cloop \n"
563 : /* outputs */
564 : /* inputs */
565 [wide]"r"(LCD_WIDTH),
566 [rows]"r"(blocklen),
567 [addr]"a"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
568 [cnt] "d"(bitcount),
569 [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
570 : /* clobbers */
571 "a1", "d0", "d1", "d2", "d3"
573 #else /* C version */
574 int x, by;
575 unsigned char *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
576 #if LCD_DEPTH == 2
577 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
578 #else
579 const unsigned fill = 0;
580 #endif
582 for (x = 0; x < LCD_WIDTH; x++)
584 unsigned char *col_addr = addr++;
585 unsigned data = fill;
587 for (by = 0; by < blocklen; by++)
589 data = (data >> 8) | (*col_addr << bitcount);
590 *col_addr = data;
591 col_addr += LCD_FBWIDTH;
594 #endif /* CPU, LCD_DEPTH */
596 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
598 #if LCD_DEPTH == 2
599 int x, by;
600 fb_data *addr = rb->lcd_framebuffer + blockcount * LCD_FBWIDTH;
601 unsigned fill, mask;
603 fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount);
604 mask = (0xFFu >> bitcount) << bitcount;
605 mask |= mask << 8;
607 for (x = 0; x < LCD_WIDTH; x++)
609 fb_data *col_addr = addr++;
610 unsigned olddata = fill;
611 unsigned data;
613 for (by = 0; by < blocklen; by++)
615 data = *col_addr << bitcount;
616 *col_addr = olddata ^ ((data ^ olddata) & mask);
617 olddata = data >> 8;
618 col_addr += LCD_FBWIDTH;
621 #endif /* LCD_DEPTH == 2 */
623 #endif /* LCD_PIXELFORMAT */
625 oldmode = rb->lcd_get_drawmode();
626 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
627 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
628 rb->lcd_set_drawmode(oldmode);
631 #endif /* LCD_PIXELFORMAT, LCD_DEPTH */
633 #endif /* HAVE_LCD_BITMAP */