A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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* 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.
19*
20* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21* KIND, either express or implied.
22*
23****************************************************************************/
24
25#include "plugin.h"
26
27#include "xlcd.h"
28
29#if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
30static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
31#endif
32
33#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
34void xlcd_scroll_left(int count)
35{
36 /*size_t dst_stride;*/
37 /*struct viewport *vp_main = NULL;*/
38 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
39
40
41 int length, oldmode;
42
43 if ((unsigned)count >= LCD_WIDTH)
44 {
45 rb->lcd_clear_display();
46 return;
47 }
48
49 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
50
51 rb->memmove(lcd_fb, lcd_fb + LCD_HEIGHT*count, length * sizeof(fb_data));
52
53 oldmode = rb->lcd_get_drawmode();
54 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
55 rb->lcd_fillrect(LCD_WIDTH-count, 0, count, LCD_HEIGHT);
56 rb->lcd_set_drawmode(oldmode);
57}
58
59/* Scroll right */
60void xlcd_scroll_right(int count)
61{
62 /*size_t dst_stride;*/
63 /*struct viewport *vp_main = NULL;*/
64 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
65
66
67 int length, oldmode;
68
69 if ((unsigned)count >= LCD_WIDTH)
70 {
71 rb->lcd_clear_display();
72 return;
73 }
74
75 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
76
77 rb->memmove(lcd_fb + LCD_HEIGHT*count,
78 lcd_fb, length * sizeof(fb_data));
79
80 oldmode = rb->lcd_get_drawmode();
81 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
82 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
83 rb->lcd_set_drawmode(oldmode);
84}
85
86/* Scroll up */
87void xlcd_scroll_up(int count)
88{
89 /*size_t dst_stride;*/
90 /*struct viewport *vp_main = NULL;*/
91 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
92
93
94 int width, length, oldmode;
95
96 fb_data *data;
97
98 if ((unsigned)count >= LCD_HEIGHT)
99 {
100 rb->lcd_clear_display();
101 return;
102 }
103
104 length = LCD_HEIGHT - count;
105
106 width = LCD_WIDTH-1;
107 data = lcd_fb;
108
109 do {
110 rb->memmove(data,data + count,length * sizeof(fb_data));
111 data += LCD_HEIGHT;
112 } while(width--);
113
114 oldmode = rb->lcd_get_drawmode();
115 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
116 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
117 rb->lcd_set_drawmode(oldmode);
118}
119
120/* Scroll down */
121void xlcd_scroll_down(int count)
122{
123 /*size_t dst_stride;*/
124 /*struct viewport *vp_main = NULL;*/
125 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
126
127
128 int width, length, oldmode;
129
130 fb_data *data;
131
132 if ((unsigned)count >= LCD_HEIGHT)
133 {
134 rb->lcd_clear_display();
135 return;
136 }
137
138 length = LCD_HEIGHT - count;
139
140 width = LCD_WIDTH-1;
141 data = lcd_fb;
142
143 do {
144 rb->memmove(data + count, data, length * sizeof(fb_data));
145 data += LCD_HEIGHT;
146 } while(width--);
147
148 oldmode = rb->lcd_get_drawmode();
149 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
150 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
151 rb->lcd_set_drawmode(oldmode);
152}
153#else
154
155#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
156
157/* Scroll left */
158void xlcd_scroll_left(int count)
159{
160 /*size_t dst_stride;*/
161 /*struct viewport *vp_main = NULL;*/
162 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
163
164
165 int bitcount=0, oldmode;
166 int blockcount=0, blocklen;
167
168 if ((unsigned) count >= LCD_WIDTH)
169 {
170 rb->lcd_clear_display();
171 return;
172 }
173
174#if LCD_DEPTH == 2
175 blockcount = count >> 2;
176 blocklen = LCD_FBWIDTH - blockcount;
177 bitcount = 2 * (count & 3);
178#endif
179
180 if (blockcount)
181 {
182 unsigned char *data = lcd_fb;
183 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
184
185 do
186 {
187 rb->memmove(data, data + blockcount, blocklen);
188 data += LCD_FBWIDTH;
189 }
190 while (data < data_end);
191 }
192 if (bitcount)
193 {
194 int bx, y;
195 unsigned char *addr = lcd_fb + blocklen;
196#if LCD_DEPTH == 2
197 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
198#endif
199
200 for (y = 0; y < LCD_HEIGHT; y++)
201 {
202 unsigned char *row_addr = addr;
203 unsigned data = fill;
204
205 for (bx = 0; bx < blocklen; bx++)
206 {
207 --row_addr;
208 data = (data >> 8) | (*row_addr << bitcount);
209 *row_addr = data;
210 }
211 addr += LCD_FBWIDTH;
212 }
213 }
214 oldmode = rb->lcd_get_drawmode();
215 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
216 rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
217 rb->lcd_set_drawmode(oldmode);
218}
219
220/* Scroll right */
221void xlcd_scroll_right(int count)
222{
223 /*size_t dst_stride;*/
224 /*struct viewport *vp_main = NULL;*/
225 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
226
227
228 int bitcount=0, oldmode;
229 int blockcount=0, blocklen;
230
231 if ((unsigned) count >= LCD_WIDTH)
232 {
233 rb->lcd_clear_display();
234 return;
235 }
236
237#if LCD_DEPTH == 2
238 blockcount = count >> 2;
239 blocklen = LCD_FBWIDTH - blockcount;
240 bitcount = 2 * (count & 3);
241#endif
242
243 if (blockcount)
244 {
245 unsigned char *data = lcd_fb;
246 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
247
248 do
249 {
250 rb->memmove(data + blockcount, data, blocklen);
251 data += LCD_FBWIDTH;
252 }
253 while (data < data_end);
254 }
255 if (bitcount)
256 {
257 int bx, y;
258 unsigned char *addr = lcd_fb + blockcount;
259#if LCD_DEPTH == 2
260 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
261#endif
262
263 for (y = 0; y < LCD_HEIGHT; y++)
264 {
265 unsigned char *row_addr = addr;
266 unsigned data = fill;
267
268 for (bx = 0; bx < blocklen; bx++)
269 {
270 data = (data << 8) | *row_addr;
271 *row_addr = data >> bitcount;
272 row_addr++;
273 }
274 addr += LCD_FBWIDTH;
275 }
276 }
277 oldmode = rb->lcd_get_drawmode();
278 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
279 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
280 rb->lcd_set_drawmode(oldmode);
281}
282
283#else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */
284
285/* Scroll left */
286void xlcd_scroll_left(int count)
287{
288 /*size_t dst_stride;*/
289 /*struct viewport *vp_main = NULL;*/
290 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
291
292
293 fb_data *data, *data_end;
294 int length, oldmode;
295
296 if ((unsigned)count >= LCD_WIDTH)
297 {
298 rb->lcd_clear_display();
299 return;
300 }
301
302 data = lcd_fb;
303 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
304 length = LCD_WIDTH - count;
305
306 do
307 {
308 rb->memmove(data, data + count, length * sizeof(fb_data));
309 data += LCD_WIDTH;
310 }
311 while (data < data_end);
312
313 oldmode = rb->lcd_get_drawmode();
314 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
315 rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
316 rb->lcd_set_drawmode(oldmode);
317}
318
319/* Scroll right */
320void xlcd_scroll_right(int count)
321{
322 /*size_t dst_stride;*/
323 /*struct viewport *vp_main = NULL;*/
324 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
325
326
327 fb_data *data, *data_end;
328 int length, oldmode;
329
330 if ((unsigned)count >= LCD_WIDTH)
331 {
332 rb->lcd_clear_display();
333 return;
334 }
335
336 data = lcd_fb;
337 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
338 length = LCD_WIDTH - count;
339
340 do
341 {
342 rb->memmove(data + count, data, length * sizeof(fb_data));
343 data += LCD_WIDTH;
344 }
345 while (data < data_end);
346
347 oldmode = rb->lcd_get_drawmode();
348 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
349 rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
350 rb->lcd_set_drawmode(oldmode);
351}
352
353#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
354
355#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8)
356
357/* Scroll up */
358void xlcd_scroll_up(int count)
359{
360 /*size_t dst_stride;*/
361 /*struct viewport *vp_main = NULL;*/
362 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
363
364 int length, oldmode;
365
366 if ((unsigned)count >= LCD_HEIGHT)
367 {
368 rb->lcd_clear_display();
369 return;
370 }
371
372 length = LCD_HEIGHT - count;
373
374 rb->memmove(lcd_fb,
375 lcd_fb + count * LCD_FBWIDTH,
376 length * LCD_FBWIDTH * sizeof(fb_data));
377
378 oldmode = rb->lcd_get_drawmode();
379 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
380 rb->lcd_fillrect(0, length, LCD_WIDTH, count);
381 rb->lcd_set_drawmode(oldmode);
382}
383
384/* Scroll down */
385void xlcd_scroll_down(int count)
386{
387 /*size_t dst_stride;*/
388 /*struct viewport *vp_main = NULL;*/
389 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
390
391 int length, oldmode;
392
393 if ((unsigned)count >= LCD_HEIGHT)
394 {
395 rb->lcd_clear_display();
396 return;
397 }
398
399 length = LCD_HEIGHT - count;
400
401 rb->memmove(lcd_fb + count * LCD_FBWIDTH,
402 lcd_fb,
403 length * LCD_FBWIDTH * sizeof(fb_data));
404
405 oldmode = rb->lcd_get_drawmode();
406 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
407 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
408 rb->lcd_set_drawmode(oldmode);
409}
410
411#else /* LCD_PIXELFORMAT == VERTICAL_PACKING,
412 LCD_PIXELFORMAT == VERTICAL_INTERLEAVED */
413
414/* Scroll up */
415void xlcd_scroll_up(int count)
416{
417 /*size_t dst_stride;*/
418 /*struct viewport *vp_main = NULL;*/
419 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
420
421 int bitcount=0, oldmode;
422 int blockcount=0, blocklen;
423
424 if ((unsigned) count >= LCD_HEIGHT)
425 {
426 rb->lcd_clear_display();
427 return;
428 }
429
430#if (LCD_DEPTH == 1) \
431 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
432 blockcount = count >> 3;
433 bitcount = count & 7;
434#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
435 blockcount = count >> 2;
436 bitcount = 2 * (count & 3);
437#endif
438 blocklen = LCD_FBHEIGHT - blockcount;
439
440 if (blockcount)
441 {
442 rb->memmove(lcd_fb,
443 lcd_fb + blockcount * LCD_FBWIDTH,
444 blocklen * LCD_FBWIDTH * sizeof(fb_data));
445 }
446 if (bitcount)
447 {
448#if LCD_PIXELFORMAT == VERTICAL_PACKING
449
450#if defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
451 asm (
452 "move.l %[wide],%%d3\n" /* columns = width */
453
454 ".su_cloop: \n" /* repeat for every column */
455 "move.l %[addr],%%a1\n" /* get start address */
456 "move.l %[rows],%%d2\n" /* rows = row_count */
457 "move.l %[bkg],%%d1 \n" /* fill with background */
458
459 ".su_iloop: \n" /* repeat for all rows */
460 "sub.l %[wide],%%a1\n" /* address -= width */
461
462 "lsl.l #8,%%d1 \n" /* old data to 2nd byte */
463 "move.b (%%a1),%%d1 \n" /* combine with new data byte */
464 "move.l %%d1,%%d0 \n" /* keep data for next round */
465 "lsr.l %[cnt],%%d0 \n" /* shift right */
466 "move.b %%d0,(%%a1) \n" /* store data */
467
468 "subq.l #1,%%d2 \n" /* rows-- */
469 "bne.b .su_iloop \n"
470
471 "addq.l #1,%[addr] \n" /* start_address++ */
472 "subq.l #1,%%d3 \n" /* columns-- */
473 "bne.b .su_cloop \n"
474 : /* outputs */
475 : /* inputs */
476 [wide]"r"(LCD_FBWIDTH),
477 [rows]"r"(blocklen),
478 [addr]"a"(lcd_fb + blocklen * LCD_FBWIDTH),
479 [cnt] "d"(bitcount),
480 [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
481 : /* clobbers */
482 "a1", "d0", "d1", "d2", "d3"
483 );
484#else /* C version */
485 int x, by;
486 unsigned char *addr = lcd_fb + blocklen * LCD_FBWIDTH;
487#if LCD_DEPTH == 2
488 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
489#else
490 const unsigned fill = 0;
491#endif
492
493 for (x = 0; x < LCD_WIDTH; x++)
494 {
495 unsigned char *col_addr = addr++;
496 unsigned data = fill;
497
498 for (by = 0; by < blocklen; by++)
499 {
500 col_addr -= LCD_FBWIDTH;
501 data = (data << 8) | *col_addr;
502 *col_addr = data >> bitcount;
503 }
504 }
505#endif /* CPU, LCD_DEPTH */
506
507#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
508
509#if LCD_DEPTH == 2
510 int x, by;
511 fb_data *addr = lcd_fb + blocklen * LCD_FBWIDTH;
512 unsigned fill, mask;
513
514 fill = patterns[rb->lcd_get_background() & 3] << 8;
515 mask = (0xFFu >> bitcount) << bitcount;
516 mask |= mask << 8;
517
518 for (x = 0; x < LCD_WIDTH; x++)
519 {
520 fb_data *col_addr = addr++;
521 unsigned olddata = fill;
522 unsigned data;
523
524 for (by = 0; by < blocklen; by++)
525 {
526 col_addr -= LCD_FBWIDTH;
527 data = *col_addr;
528 *col_addr = (olddata ^ ((data ^ olddata) & mask)) >> bitcount;
529 olddata = data << 8;
530 }
531 }
532#endif /* LCD_DEPTH == 2 */
533
534#endif /* LCD_PIXELFORMAT */
535 }
536 oldmode = rb->lcd_get_drawmode();
537 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
538 rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
539 rb->lcd_set_drawmode(oldmode);
540}
541
542/* Scroll up */
543void xlcd_scroll_down(int count)
544{
545 /*size_t dst_stride;*/
546 /*struct viewport *vp_main = NULL;*/
547 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
548
549 int bitcount=0, oldmode;
550 int blockcount=0, blocklen;
551
552 if ((unsigned) count >= LCD_HEIGHT)
553 {
554 rb->lcd_clear_display();
555 return;
556 }
557
558#if (LCD_DEPTH == 1) \
559 || (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
560 blockcount = count >> 3;
561 bitcount = count & 7;
562#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
563 blockcount = count >> 2;
564 bitcount = 2 * (count & 3);
565#endif
566 blocklen = LCD_FBHEIGHT - blockcount;
567
568 if (blockcount)
569 {
570 rb->memmove(lcd_fb + blockcount * LCD_FBWIDTH,
571 lcd_fb,
572 blocklen * LCD_FBWIDTH * sizeof(fb_data));
573 }
574 if (bitcount)
575 {
576#if LCD_PIXELFORMAT == VERTICAL_PACKING
577
578#if defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
579 asm (
580 "move.l %[wide],%%d3\n" /* columns = width */
581
582 ".sd_cloop: \n" /* repeat for every column */
583 "move.l %[addr],%%a1\n" /* get start address */
584 "move.l %[rows],%%d2\n" /* rows = row_count */
585 "move.l %[bkg],%%d1 \n" /* fill with background */
586
587 ".sd_iloop: \n" /* repeat for all rows */
588 "lsr.l #8,%%d1 \n" /* shift right to get residue */
589 "clr.l %%d0 \n"
590 "move.b (%%a1),%%d0 \n" /* get data byte */
591 "lsl.l %[cnt],%%d0 \n"
592 "or.l %%d0,%%d1 \n" /* combine with last residue */
593 "move.b %%d1,(%%a1) \n" /* store data */
594
595 "add.l %[wide],%%a1\n" /* address += width */
596 "subq.l #1,%%d2 \n" /* rows-- */
597 "bne.b .sd_iloop \n"
598
599 "lea.l (1,%[addr]),%[addr] \n" /* start_address++ */
600 "subq.l #1,%%d3 \n" /* columns-- */
601 "bne.b .sd_cloop \n"
602 : /* outputs */
603 : /* inputs */
604 [wide]"r"(LCD_WIDTH),
605 [rows]"r"(blocklen),
606 [addr]"a"(lcd_fb + blockcount * LCD_FBWIDTH),
607 [cnt] "d"(bitcount),
608 [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
609 : /* clobbers */
610 "a1", "d0", "d1", "d2", "d3"
611 );
612#else /* C version */
613 int x, by;
614 unsigned char *addr = lcd_fb + blockcount * LCD_FBWIDTH;
615#if LCD_DEPTH == 2
616 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
617#else
618 const unsigned fill = 0;
619#endif
620
621 for (x = 0; x < LCD_WIDTH; x++)
622 {
623 unsigned char *col_addr = addr++;
624 unsigned data = fill;
625
626 for (by = 0; by < blocklen; by++)
627 {
628 data = (data >> 8) | (*col_addr << bitcount);
629 *col_addr = data;
630 col_addr += LCD_FBWIDTH;
631 }
632 }
633#endif /* CPU, LCD_DEPTH */
634
635#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
636
637#if LCD_DEPTH == 2
638 int x, by;
639 fb_data *addr = lcd_fb + blockcount * LCD_FBWIDTH;
640 unsigned fill, mask;
641
642 fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount);
643 mask = (0xFFu >> bitcount) << bitcount;
644 mask |= mask << 8;
645
646 for (x = 0; x < LCD_WIDTH; x++)
647 {
648 fb_data *col_addr = addr++;
649 unsigned olddata = fill;
650 unsigned data;
651
652 for (by = 0; by < blocklen; by++)
653 {
654 data = *col_addr << bitcount;
655 *col_addr = olddata ^ ((data ^ olddata) & mask);
656 olddata = data >> 8;
657 col_addr += LCD_FBWIDTH;
658 }
659 }
660#endif /* LCD_DEPTH == 2 */
661
662#endif /* LCD_PIXELFORMAT */
663 }
664 oldmode = rb->lcd_get_drawmode();
665 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
666 rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
667 rb->lcd_set_drawmode(oldmode);
668}
669
670#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
671#endif /* LCD_STRIDEFORMAT == VERTICAL_STRIDE */