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* Copyright (C) 2002 Damien Teney
11* modified to use int instead of float math by Andreas Zwirtes
12* heavily extended by Jens Arnold
13*
14* This program is free software; you can redistribute it and/or
15* modify it under the terms of the GNU General Public License
16* as published by the Free Software Foundation; either version 2
17* of the License, or (at your option) any later version.
18*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22***************************************************************************/
23#include "plugin.h"
24#include "fixedpoint.h"
25#include "lib/pluginlib_exit.h"
26#if LCD_DEPTH > 1
27#include "lib/mylcd.h" /* MYLCD_CFG_RB_XLCD or MYLCD_CFG_PGFX */
28#include "lib/grey.h"
29#else
30#include "lib/grey.h"
31#include "lib/mylcd.h" /* MYLCD_CFG_GREYLIB or MYLCD_CFG_PGFX */
32#endif
33#include "lib/xlcd.h"
34
35/* Loops that the values are displayed */
36#define DISP_TIME 30
37
38/* variable button definitions */
39#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
40 (CONFIG_KEYPAD == IRIVER_H300_PAD)
41#define CUBE_QUIT BUTTON_OFF
42#define CUBE_NEXT BUTTON_RIGHT
43#define CUBE_PREV BUTTON_LEFT
44#define CUBE_INC BUTTON_UP
45#define CUBE_DEC BUTTON_DOWN
46#define CUBE_MODE BUTTON_MODE
47#define CUBE_PAUSE BUTTON_ON
48#define CUBE_HIGHSPEED BUTTON_SELECT
49
50#define CUBE_RC_QUIT BUTTON_RC_STOP
51
52#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
53 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
54 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
55#define CUBE_QUIT_PRE BUTTON_MENU
56#define CUBE_QUIT (BUTTON_MENU | BUTTON_REL)
57#define CUBE_NEXT BUTTON_RIGHT
58#define CUBE_PREV BUTTON_LEFT
59#define CUBE_INC BUTTON_SCROLL_FWD
60#define CUBE_DEC BUTTON_SCROLL_BACK
61#define CUBE_MODE_PRE BUTTON_MENU
62#define CUBE_MODE (BUTTON_MENU | BUTTON_REPEAT)
63#define CUBE_PAUSE BUTTON_PLAY
64#define CUBE_HIGHSPEED_PRE BUTTON_SELECT
65#define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REL)
66
67#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
68#define CUBE_QUIT BUTTON_POWER
69#define CUBE_NEXT BUTTON_RIGHT
70#define CUBE_PREV BUTTON_LEFT
71#define CUBE_INC BUTTON_UP
72#define CUBE_DEC BUTTON_DOWN
73#define CUBE_MODE BUTTON_REC
74#define CUBE_PAUSE BUTTON_PLAY
75#define CUBE_HIGHSPEED BUTTON_SELECT
76
77#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
78#define CUBE_QUIT BUTTON_POWER
79#define CUBE_NEXT BUTTON_RIGHT
80#define CUBE_PREV BUTTON_LEFT
81#define CUBE_INC BUTTON_UP
82#define CUBE_DEC BUTTON_DOWN
83#define CUBE_MODE BUTTON_MENU
84#define CUBE_PAUSE BUTTON_SELECT
85#define CUBE_HIGHSPEED BUTTON_A
86
87#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
88#define CUBE_QUIT BUTTON_POWER
89#define CUBE_NEXT BUTTON_RIGHT
90#define CUBE_PREV BUTTON_LEFT
91#define CUBE_INC BUTTON_SCROLL_FWD
92#define CUBE_DEC BUTTON_SCROLL_BACK
93#define CUBE_MODE BUTTON_DOWN
94#define CUBE_PAUSE BUTTON_UP
95#define CUBE_HIGHSPEED BUTTON_SELECT
96
97#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
98#define CUBE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
99#define CUBE_NEXT BUTTON_RIGHT
100#define CUBE_PREV BUTTON_LEFT
101#define CUBE_INC BUTTON_SCROLL_FWD
102#define CUBE_DEC BUTTON_SCROLL_BACK
103#define CUBE_MODE BUTTON_DOWN
104#define CUBE_PAUSE BUTTON_UP
105#define CUBE_HIGHSPEED BUTTON_SELECT
106
107#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
108(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
109(CONFIG_KEYPAD == SANSA_M200_PAD)
110#define CUBE_QUIT BUTTON_POWER
111#define CUBE_NEXT BUTTON_RIGHT
112#define CUBE_PREV BUTTON_LEFT
113#define CUBE_INC BUTTON_VOL_UP
114#define CUBE_DEC BUTTON_VOL_DOWN
115#define CUBE_MODE BUTTON_DOWN
116#define CUBE_PAUSE BUTTON_UP
117#define CUBE_HIGHSPEED BUTTON_SELECT
118
119
120#elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
121#define CUBE_QUIT BUTTON_POWER
122#define CUBE_NEXT BUTTON_RIGHT
123#define CUBE_PREV BUTTON_LEFT
124#define CUBE_INC BUTTON_SCROLL_UP
125#define CUBE_DEC BUTTON_SCROLL_DOWN
126#define CUBE_MODE BUTTON_REW
127#define CUBE_PAUSE BUTTON_PLAY
128#define CUBE_HIGHSPEED BUTTON_FF
129
130#elif CONFIG_KEYPAD == MROBE500_PAD
131#define CUBE_QUIT BUTTON_POWER
132
133#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
134#define CUBE_QUIT BUTTON_BACK
135#define CUBE_NEXT BUTTON_RIGHT
136#define CUBE_PREV BUTTON_LEFT
137#define CUBE_INC BUTTON_UP
138#define CUBE_DEC BUTTON_DOWN
139#define CUBE_MODE BUTTON_MENU
140#define CUBE_PAUSE BUTTON_PLAY
141#define CUBE_HIGHSPEED BUTTON_SELECT
142
143#elif (CONFIG_KEYPAD == MROBE100_PAD)
144#define CUBE_QUIT BUTTON_POWER
145#define CUBE_NEXT BUTTON_RIGHT
146#define CUBE_PREV BUTTON_LEFT
147#define CUBE_INC BUTTON_UP
148#define CUBE_DEC BUTTON_DOWN
149#define CUBE_MODE BUTTON_MENU
150#define CUBE_PAUSE BUTTON_PLAY
151#define CUBE_HIGHSPEED BUTTON_SELECT
152
153#elif (CONFIG_KEYPAD == IAUDIO_M3_PAD)
154#define CUBE_QUIT BUTTON_RC_REC
155#define CUBE_NEXT BUTTON_RC_FF
156#define CUBE_PREV BUTTON_RC_REW
157#define CUBE_INC BUTTON_RC_VOL_UP
158#define CUBE_DEC BUTTON_RC_VOL_DOWN
159#define CUBE_MODE BUTTON_RC_MODE
160#define CUBE_PAUSE BUTTON_RC_PLAY
161#define CUBE_HIGHSPEED BUTTON_RC_MENU
162
163#elif CONFIG_KEYPAD == COWON_D2_PAD
164#define CUBE_QUIT BUTTON_POWER
165
166#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
167#define CUBE_QUIT BUTTON_BACK
168#define CUBE_NEXT BUTTON_RIGHT
169#define CUBE_PREV BUTTON_LEFT
170#define CUBE_INC BUTTON_UP
171#define CUBE_DEC BUTTON_DOWN
172#define CUBE_MODE BUTTON_MENU
173#define CUBE_PAUSE BUTTON_PLAY
174#define CUBE_HIGHSPEED BUTTON_SELECT
175
176#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
177#define CUBE_QUIT BUTTON_POWER
178#define CUBE_NEXT BUTTON_UP
179#define CUBE_PREV BUTTON_DOWN
180#define CUBE_INC BUTTON_VOL_UP
181#define CUBE_DEC BUTTON_VOL_DOWN
182#define CUBE_MODE BUTTON_MENU
183#define CUBE_PAUSE (BUTTON_PLAY|BUTTON_REL)
184#define CUBE_HIGHSPEED BUTTON_BACK
185
186#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
187#define CUBE_QUIT BUTTON_POWER
188#define CUBE_NEXT BUTTON_RIGHT
189#define CUBE_PREV BUTTON_LEFT
190#define CUBE_INC BUTTON_UP
191#define CUBE_DEC BUTTON_DOWN
192#define CUBE_MODE BUTTON_MENU
193#define CUBE_PAUSE BUTTON_SELECT
194#define CUBE_HIGHSPEED BUTTON_VIEW
195
196#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
197#define CUBE_QUIT BUTTON_POWER
198#define CUBE_NEXT BUTTON_NEXT
199#define CUBE_PREV BUTTON_PREV
200#define CUBE_INC BUTTON_UP
201#define CUBE_DEC BUTTON_DOWN
202#define CUBE_MODE BUTTON_MENU
203#define CUBE_PAUSE BUTTON_PLAY
204#define CUBE_HIGHSPEED BUTTON_RIGHT
205
206#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
207#define CUBE_QUIT BUTTON_POWER
208#define CUBE_NEXT BUTTON_NEXT
209#define CUBE_PREV BUTTON_PREV
210#define CUBE_INC BUTTON_UP
211#define CUBE_DEC BUTTON_DOWN
212#define CUBE_MODE BUTTON_MENU
213#define CUBE_PAUSE BUTTON_PLAY
214#define CUBE_HIGHSPEED BUTTON_RIGHT
215
216#elif CONFIG_KEYPAD == ONDAVX747_PAD
217#define CUBE_QUIT BUTTON_POWER
218#elif CONFIG_KEYPAD == ONDAVX777_PAD
219#define CUBE_QUIT BUTTON_POWER
220
221#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
222 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
223#define CUBE_QUIT BUTTON_REW
224#define CUBE_NEXT BUTTON_RIGHT
225#define CUBE_PREV BUTTON_LEFT
226#define CUBE_INC BUTTON_UP
227#define CUBE_DEC BUTTON_DOWN
228#define CUBE_MODE (BUTTON_FFWD|BUTTON_REL)
229#define CUBE_MODE_PRE BUTTON_FFWD
230#define CUBE_PAUSE BUTTON_PLAY
231#define CUBE_HIGHSPEED (BUTTON_FFWD|BUTTON_REPEAT)
232#define CUBE_HIGHSPEED_PRE BUTTON_FFWD
233
234#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
235#define CUBE_QUIT BUTTON_REC
236#define CUBE_NEXT BUTTON_NEXT
237#define CUBE_PREV BUTTON_PREV
238#define CUBE_INC BUTTON_UP
239#define CUBE_DEC BUTTON_DOWN
240#define CUBE_MODE BUTTON_MENU
241#define CUBE_PAUSE BUTTON_PLAY
242#define CUBE_HIGHSPEED BUTTON_OK
243
244#elif CONFIG_KEYPAD == MPIO_HD200_PAD
245#define CUBE_QUIT (BUTTON_REC | BUTTON_PLAY)
246#define CUBE_NEXT BUTTON_FF
247#define CUBE_PREV BUTTON_REW
248#define CUBE_INC BUTTON_VOL_UP
249#define CUBE_DEC BUTTON_VOL_DOWN
250#define CUBE_MODE BUTTON_REC
251#define CUBE_PAUSE BUTTON_PLAY
252#define CUBE_HIGHSPEED BUTTON_FUNC
253
254#elif CONFIG_KEYPAD == MPIO_HD300_PAD
255#define CUBE_QUIT (BUTTON_MENU | BUTTON_REPEAT)
256#define CUBE_NEXT BUTTON_FF
257#define CUBE_PREV BUTTON_REW
258#define CUBE_INC BUTTON_UP
259#define CUBE_DEC BUTTON_DOWN
260#define CUBE_MODE BUTTON_MENU
261#define CUBE_PAUSE BUTTON_PLAY
262#define CUBE_HIGHSPEED BUTTON_ENTER
263
264#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
265#define CUBE_QUIT BUTTON_POWER
266#define CUBE_NEXT BUTTON_RIGHT
267#define CUBE_PREV BUTTON_LEFT
268#define CUBE_INC BUTTON_UP
269#define CUBE_DEC BUTTON_DOWN
270#define CUBE_MODE BUTTON_SELECT
271#define CUBE_PAUSE BUTTON_PLAYPAUSE
272#define CUBE_HIGHSPEED BUTTON_BACK
273
274#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
275#define CUBE_QUIT BUTTON_POWER
276#define CUBE_NEXT BUTTON_NEXT
277#define CUBE_PREV BUTTON_PREV
278#define CUBE_INC BUTTON_VOL_UP
279#define CUBE_DEC BUTTON_VOL_DOWN
280#define CUBE_MODE BUTTON_SELECT
281#define CUBE_PAUSE BUTTON_DOWN
282#define CUBE_HIGHSPEED BUTTON_LEFT
283
284#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
285#define CUBE_QUIT BUTTON_BACK
286#define CUBE_NEXT BUTTON_RIGHT
287#define CUBE_PREV BUTTON_LEFT
288#define CUBE_INC BUTTON_UP
289#define CUBE_DEC BUTTON_DOWN
290#define CUBE_MODE BUTTON_MENU
291#define CUBE_PAUSE BUTTON_USER
292#define CUBE_HIGHSPEED BUTTON_SELECT
293
294#elif (CONFIG_KEYPAD == HM60X_PAD)
295#define CUBE_QUIT BUTTON_POWER
296#define CUBE_NEXT BUTTON_RIGHT
297#define CUBE_PREV BUTTON_LEFT
298#define CUBE_INC BUTTON_UP
299#define CUBE_DEC BUTTON_DOWN
300#define CUBE_MODE (BUTTON_SELECT|BUTTON_POWER)
301#define CUBE_PAUSE BUTTON_SELECT
302#define CUBE_HIGHSPEED (BUTTON_UP|BUTTON_POWER)
303
304#elif (CONFIG_KEYPAD == HM801_PAD)
305#define CUBE_QUIT BUTTON_POWER
306#define CUBE_NEXT BUTTON_RIGHT
307#define CUBE_PREV BUTTON_LEFT
308#define CUBE_INC BUTTON_UP
309#define CUBE_DEC BUTTON_DOWN
310#define CUBE_MODE BUTTON_PREV
311#define CUBE_PAUSE BUTTON_SELECT
312#define CUBE_HIGHSPEED BUTTON_NEXT
313
314#elif (CONFIG_KEYPAD == SONY_NWZ_PAD)
315#define CUBE_QUIT BUTTON_BACK
316#define CUBE_NEXT BUTTON_RIGHT
317#define CUBE_PREV BUTTON_LEFT
318#define CUBE_INC BUTTON_UP
319#define CUBE_DEC BUTTON_DOWN
320#define CUBE_MODE (BUTTON_POWER|BUTTON_UP)
321#define CUBE_PAUSE BUTTON_PLAY
322#define CUBE_HIGHSPEED (BUTTON_POWER|BUTTON_DOWN)
323
324#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD)
325#define CUBE_QUIT BUTTON_BACK
326#define CUBE_NEXT BUTTON_RIGHT
327#define CUBE_PREV BUTTON_LEFT
328#define CUBE_INC BUTTON_UP
329#define CUBE_DEC BUTTON_DOWN
330#define CUBE_MODE BUTTON_MENU
331#define CUBE_PAUSE BUTTON_PLAYPAUSE
332#define CUBE_HIGHSPEED BUTTON_SHORTCUT
333
334#elif (CONFIG_KEYPAD == DX50_PAD)
335#define CUBE_QUIT (BUTTON_POWER|BUTTON_REL)
336#define CUBE_NEXT BUTTON_RIGHT
337#define CUBE_PREV BUTTON_LEFT
338#define CUBE_INC BUTTON_VOL_UP
339#define CUBE_DEC BUTTON_VOL_DOWN
340#define CUBE_MODE BUTTON_PLAY
341
342#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
343#define CUBE_QUIT BUTTON_POWER
344
345#elif (CONFIG_KEYPAD == AGPTEK_ROCKER_PAD)
346#define CUBE_QUIT (BUTTON_POWER|BUTTON_REL)
347#define CUBE_NEXT BUTTON_RIGHT
348#define CUBE_PREV BUTTON_LEFT
349#define CUBE_INC BUTTON_VOLUP
350#define CUBE_DEC BUTTON_VOLDOWN
351#define CUBE_MODE BUTTON_SELECT
352#define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REPEAT)
353#define CUBE_PAUSE (BUTTON_LEFT | BUTTON_REPEAT)
354
355#elif (CONFIG_KEYPAD == XDUOO_X3_PAD) || (CONFIG_KEYPAD == XDUOO_X3II_PAD) || (CONFIG_KEYPAD == XDUOO_X20_PAD)
356#define CUBE_QUIT BUTTON_POWER
357#define CUBE_NEXT BUTTON_NEXT
358#define CUBE_PREV BUTTON_PREV
359#define CUBE_INC BUTTON_VOL_UP
360#define CUBE_DEC BUTTON_VOL_DOWN
361#define CUBE_MODE BUTTON_OPTION
362#define CUBE_PAUSE BUTTON_HOME
363#define CUBE_HIGHSPEED BUTTON_PLAY
364
365#elif (CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD)
366#define CUBE_QUIT BUTTON_POWER
367#define CUBE_NEXT BUTTON_NEXT
368#define CUBE_PREV BUTTON_PREV
369#define CUBE_INC BUTTON_VOL_UP
370#define CUBE_DEC BUTTON_VOL_DOWN
371#define CUBE_MODE BUTTON_OPTION
372#define CUBE_PAUSE BUTTON_HOME
373#define CUBE_HIGHSPEED BUTTON_PLAY
374
375#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD)
376#define CUBE_QUIT BUTTON_POWER
377#define CUBE_NEXT BUTTON_NEXT
378#define CUBE_PREV BUTTON_PREV
379#define CUBE_INC BUTTON_VOL_UP
380#define CUBE_DEC BUTTON_VOL_DOWN
381#define CUBE_MODE (BUTTON_HOME | BUTTON_POWER)
382#define CUBE_PAUSE BUTTON_HOME
383#define CUBE_HIGHSPEED BUTTON_PLAY
384
385#elif CONFIG_KEYPAD == EROSQ_PAD
386#define CUBE_QUIT BUTTON_POWER
387#define CUBE_NEXT BUTTON_NEXT
388#define CUBE_PREV BUTTON_PREV
389#define CUBE_INC BUTTON_SCROLL_FWD
390#define CUBE_DEC BUTTON_SCROLL_BACK
391#define CUBE_MODE BUTTON_MENU
392#define CUBE_PAUSE BUTTON_BACK
393#define CUBE_HIGHSPEED BUTTON_PLAY
394
395#elif CONFIG_KEYPAD == FIIO_M3K_PAD
396#define CUBE_QUIT BUTTON_POWER
397#define CUBE_NEXT BUTTON_RIGHT
398#define CUBE_PREV BUTTON_LEFT
399#define CUBE_INC BUTTON_SCROLL_FWD
400#define CUBE_DEC BUTTON_SCROLL_BACK
401#define CUBE_MODE BUTTON_MENU
402#define CUBE_PAUSE BUTTON_PLAY
403#define CUBE_HIGHSPEED BUTTON_BACK
404
405#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
406/* use touchscreen */
407
408
409#elif CONFIG_KEYPAD == SDL_PAD
410/* use touchscreen */
411#elif CONFIG_KEYPAD == MA_PAD
412#define CUBE_QUIT BUTTON_BACK
413#define CUBE_NEXT BUTTON_RIGHT
414#define CUBE_PREV BUTTON_LEFT
415#define CUBE_INC BUTTON_UP
416#define CUBE_DEC BUTTON_DOWN
417#define CUBE_MODE BUTTON_MENU
418#define CUBE_PAUSE BUTTON_PLAY
419#define CUBE_HIGHSPEED (BUTTON_PLAY|BUTTON_REPEAT)
420
421#elif CONFIG_KEYPAD == RG_NANO_PAD
422#define CUBE_QUIT BUTTON_START
423#define CUBE_NEXT BUTTON_RIGHT
424#define CUBE_PREV BUTTON_LEFT
425#define CUBE_INC BUTTON_UP
426#define CUBE_DEC BUTTON_DOWN
427#define CUBE_MODE BUTTON_X
428#define CUBE_PAUSE BUTTON_A
429#define CUBE_HIGHSPEED BUTTON_Y
430
431#else
432#error No keymap defined!
433#endif
434
435#ifdef HAVE_TOUCHSCREEN
436#ifndef CUBE_QUIT
437#define CUBE_QUIT BUTTON_TOPLEFT
438#endif
439#ifndef CUBE_NEXT
440#define CUBE_NEXT BUTTON_MIDRIGHT
441#endif
442#ifndef CUBE_PREV
443#define CUBE_PREV BUTTON_MIDLEFT
444#endif
445#ifndef CUBE_INC
446#define CUBE_INC BUTTON_TOPMIDDLE
447#endif
448#ifndef CUBE_DEC
449#define CUBE_DEC BUTTON_BOTTOMMIDDLE
450#endif
451#ifndef CUBE_MODE
452#define CUBE_MODE BUTTON_TOPRIGHT
453#endif
454#ifndef CUBE_PAUSE
455#define CUBE_PAUSE BUTTON_CENTER
456#endif
457#ifndef CUBE_HIGHSPEED
458#define CUBE_HIGHSPEED BUTTON_BOTTOMRIGHT
459#endif
460#endif
461
462#define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
463static int x_off = LCD_WIDTH/2;
464static int y_off = LCD_HEIGHT/2;
465
466#if LCD_DEPTH == 1
467#define USEGSLIB
468GREY_INFO_STRUCT
469struct my_lcd {
470 void (*update)(void);
471 void (*clear_display)(void);
472 void (*drawline)(int x1, int y1, int x2, int y2);
473 void (*putsxy)(int x, int y, const unsigned char *string);
474};
475
476static struct my_lcd greyfuncs = {
477 grey_update, grey_clear_display, grey_drawline, grey_putsxy
478};
479static struct my_lcd lcdfuncs; /* initialised at runtime */
480static struct my_lcd *mylcd = &greyfuncs;
481
482#define MYLCD(fn) mylcd->fn
483
484#else
485#define MYLCD(fn) rb->lcd_ ## fn
486#endif
487
488#if CONFIG_LCD == LCD_SSD1815
489#define ASPECT 320 /* = 1.25 (fixed point 24.8) */
490#else
491#define ASPECT 256 /* = 1.00 */
492#endif
493
494struct point_3D {
495 long x, y, z;
496};
497
498struct point_2D {
499 long x, y;
500};
501
502struct line {
503 int start, end;
504};
505
506struct face {
507 int corner[4];
508 int line[4];
509};
510
511/* initial, unrotated cube corners */
512static const struct point_3D sommet[8] =
513{
514 {-DIST, -DIST, -DIST},
515 { DIST, -DIST, -DIST},
516 { DIST, DIST, -DIST},
517 {-DIST, DIST, -DIST},
518 {-DIST, -DIST, DIST},
519 { DIST, -DIST, DIST},
520 { DIST, DIST, DIST},
521 {-DIST, DIST, DIST}
522};
523
524/* The 12 lines forming the edges */
525static const struct line lines[12] =
526{
527 {0, 1}, {1, 2}, {2, 3}, {3, 0},
528 {4, 7}, {7, 6}, {6, 5}, {5, 4},
529 {0, 4}, {1, 5}, {2, 6}, {3, 7}
530};
531
532static bool lines_drawn[12];
533
534/* The 6 faces of the cube; points are in clockwise order when viewed
535 from the outside */
536static const struct face faces[6] =
537{
538 {{0, 1, 2, 3}, {0, 1, 2, 3}},
539 {{4, 7, 6, 5}, {4, 5, 6, 7}},
540 {{0, 4, 5, 1}, {8, 7, 9, 0}},
541 {{2, 6, 7, 3}, {10, 5, 11, 2}},
542 {{0, 3, 7, 4}, {3, 11, 4, 8}},
543 {{1, 5, 6, 2}, {9, 6, 10, 1}}
544};
545
546#if LCD_DEPTH > 1 || defined(USEGSLIB)
547static const unsigned face_colors[6] =
548{
549#ifdef HAVE_LCD_COLOR
550 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
551 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
552#elif defined(USEGSLIB)
553#ifdef MROBE_100
554 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
555 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE
556#else
557 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
558 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
559#endif
560#else
561 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
562 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
563#endif
564};
565#endif
566
567enum {
568#if LCD_DEPTH > 1 || defined(USEGSLIB)
569 SOLID,
570#endif
571 HIDDEN_LINES,
572 WIREFRAME,
573 NUM_MODES
574};
575
576static int mode = 0;
577
578struct counter {
579 const char *label;
580 short speed;
581 short angle;
582};
583
584static struct counter axes[] = {
585 {"x-axis", 1, 0},
586 {"y-axis", 3, 0},
587 {"z-axis", 2, 0}
588};
589
590static struct point_3D point3D[8];
591static struct point_2D point2D[8];
592static long matrice[3][3];
593
594static const int nb_points = 8;
595static long z_off = 600;
596
597static void cube_rotate(int xa, int ya, int za)
598{
599 int i;
600 /* Just to prevent unnecessary lookups */
601 long sxa, cxa, sya, cya, sza, cza;
602
603 sxa = fp14_sin(xa);
604 cxa = fp14_cos(xa);
605 sya = fp14_sin(ya);
606 cya = fp14_cos(ya);
607 sza = fp14_sin(za);
608 cza = fp14_cos(za);
609
610 /* calculate overall translation matrix */
611 matrice[0][0] = (cza * cya) >> 14;
612 matrice[1][0] = (sza * cya) >> 14;
613 matrice[2][0] = -sya;
614
615 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
616 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
617 matrice[2][1] = (sxa * cya) >> 14;
618
619 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
620 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
621 matrice[2][2] = (cxa * cya) >> 14;
622
623 /* apply translation matrix to all points */
624 for (i = 0; i < nb_points; i++)
625 {
626 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
627 + matrice[2][0] * sommet[i].z;
628
629 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
630 + matrice[2][1] * sommet[i].z;
631
632 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
633 + matrice[2][2] * sommet[i].z;
634 }
635}
636
637static void cube_viewport(void)
638{
639 int i;
640
641 /* Do viewport transformation for all points */
642 for (i = 0; i < nb_points; i++)
643 {
644#if ASPECT != 256
645 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
646 + x_off;
647#else
648 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
649 + x_off;
650#endif
651 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
652 + y_off;
653 }
654}
655
656static void cube_draw(void)
657{
658 int i, j, line;
659#if LCD_DEPTH > 1 || defined(USEGSLIB)
660 unsigned old_foreground;
661#endif
662
663 switch (mode)
664 {
665#if LCD_DEPTH > 1 || defined(USEGSLIB)
666 case SOLID:
667
668 old_foreground = mylcd_get_foreground();
669 for (i = 0; i < 6; i++)
670 {
671 /* backface culling; if the shape winds counter-clockwise, we are
672 * looking at the backface, and the (simplified) cross product
673 * is < 0. Do not draw it. */
674 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
675 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
676 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
677 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
678 continue;
679
680 mylcd_set_foreground(face_colors[i]);
681 mylcd_filltriangle(point2D[faces[i].corner[0]].x,
682 point2D[faces[i].corner[0]].y,
683 point2D[faces[i].corner[1]].x,
684 point2D[faces[i].corner[1]].y,
685 point2D[faces[i].corner[2]].x,
686 point2D[faces[i].corner[2]].y);
687 mylcd_filltriangle(point2D[faces[i].corner[0]].x,
688 point2D[faces[i].corner[0]].y,
689 point2D[faces[i].corner[2]].x,
690 point2D[faces[i].corner[2]].y,
691 point2D[faces[i].corner[3]].x,
692 point2D[faces[i].corner[3]].y);
693
694 }
695 mylcd_set_foreground(old_foreground);
696 break;
697#endif /* (LCD_DEPTH > 1) || GSLIB */
698
699 case HIDDEN_LINES:
700
701 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
702 for (i = 0; i < 6; i++)
703 {
704 /* backface culling; if the shape winds counter-clockwise, we are
705 * looking at the backface, and the (simplified) cross product
706 * is < 0. Do not draw it. */
707 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
708 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
709 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
710 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
711 continue;
712
713 for (j = 0; j < 4; j++)
714 {
715 line = faces[i].line[j];
716 if (!lines_drawn[line])
717 {
718 lines_drawn[line] = true;
719 MYLCD(drawline)(point2D[lines[line].start].x,
720 point2D[lines[line].start].y,
721 point2D[lines[line].end].x,
722 point2D[lines[line].end].y);
723 }
724 }
725 }
726 break;
727
728 case WIREFRAME:
729
730 for (i = 0; i < 12; i++)
731 MYLCD(drawline)(point2D[lines[i].start].x,
732 point2D[lines[i].start].y,
733 point2D[lines[i].end].x,
734 point2D[lines[i].end].y);
735 break;
736 }
737}
738
739static void cleanup(void)
740{
741#ifdef USEGSLIB
742 grey_release();
743#endif
744}
745
746enum plugin_status plugin_start(const void* parameter)
747{
748 int t_disp = 0;
749#ifdef USEGSLIB
750 unsigned char *gbuf;
751 size_t gbuf_size = 0;
752 bool mode_switch = true;
753#endif
754
755 int button;
756#if defined(CUBE_MODE_PRE) || \
757 defined(CUBE_QUIT_PRE) || \
758 defined(CUBE_PAUSE_PRE) || \
759 defined(CUBE_HIGHSPEED_PRE)
760 int lastbutton = BUTTON_NONE;
761#endif
762 int curr = 0;
763 bool highspeed = false;
764 bool paused = false;
765 bool redraw = true;
766 bool quit = false;
767
768 (void)(parameter);
769
770#if defined(USEGSLIB)
771 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
772 if (!grey_init(gbuf, gbuf_size, GREY_BUFFERED,
773 LCD_WIDTH, LCD_HEIGHT, NULL))
774 {
775 rb->splash(HZ, "Couldn't init greyscale display");
776 return PLUGIN_ERROR;
777 }
778
779 /* init lcd_ function pointers */
780 lcdfuncs.update = rb->lcd_update;
781 lcdfuncs.clear_display = rb->lcd_clear_display;
782 lcdfuncs.drawline = rb->lcd_drawline;
783 lcdfuncs.putsxy = rb->lcd_putsxy;
784
785#ifdef MROBE_100
786 grey_set_background(GREY_BLACK);
787#endif
788
789 grey_setfont(FONT_SYSFIXED);
790#endif
791 rb->lcd_setfont(FONT_SYSFIXED);
792
793 atexit(cleanup);
794 while(!quit)
795 {
796 if (redraw)
797 {
798 MYLCD(clear_display)();
799 cube_rotate(axes[0].angle, axes[1].angle, axes[2].angle);
800 cube_viewport();
801 cube_draw();
802 redraw = false;
803 }
804
805 if (t_disp > 0)
806 {
807 char buffer[30];
808 t_disp--;
809 rb->snprintf(buffer, sizeof(buffer), "%s: %d %s",
810 axes[curr].label,
811 paused ? axes[curr].angle : axes[curr].speed,
812 highspeed ? "(hs)" : "");
813 MYLCD(putsxy)(0, LCD_HEIGHT-SYSFONT_HEIGHT, buffer);
814 if (t_disp == 0)
815 redraw = true;
816 }
817#ifdef USEGSLIB
818 if (mode_switch)
819 {
820 grey_show(mode == SOLID);
821 mode_switch = false;
822 }
823#endif
824 MYLCD(update)();
825
826 if (!paused)
827 {
828 int i;
829
830 for (i = 0; i < 3; i++)
831 {
832 axes[i].angle += axes[i].speed;
833 if (axes[i].angle > 359)
834 axes[i].angle -= 360;
835 else if (axes[i].angle < 0)
836 axes[i].angle += 360;
837 }
838 redraw = true;
839
840 if (highspeed)
841 rb->yield();
842 else
843 rb->sleep(HZ/25);
844 button = rb->button_get(false);
845 }
846 else
847 {
848 button = rb->button_get_w_tmo(HZ/25);
849 }
850
851 switch (button)
852 {
853 case CUBE_INC:
854 case CUBE_INC|BUTTON_REPEAT:
855 if (!paused)
856 {
857 if (axes[curr].speed < 10)
858 axes[curr].speed++;
859 }
860 else
861 {
862 if (++axes[curr].angle > 359)
863 axes[curr].angle -= 360;
864 }
865 t_disp = DISP_TIME;
866 redraw = true;
867 break;
868
869 case CUBE_DEC:
870 case CUBE_DEC|BUTTON_REPEAT:
871 if (!paused)
872 {
873 if (axes[curr].speed > -10)
874 axes[curr].speed--;
875 }
876 else
877 {
878 if (--axes[curr].angle < 0)
879 axes[curr].angle += 360;
880 }
881 t_disp = DISP_TIME;
882 redraw = true;
883 break;
884
885 case CUBE_NEXT:
886 if (++curr > 2)
887 curr = 0;
888 t_disp = DISP_TIME;
889 break;
890
891 case CUBE_PREV:
892 if (--curr < 0)
893 curr = 2;
894 t_disp = DISP_TIME;
895 break;
896
897 case CUBE_MODE:
898#ifdef CUBE_MODE_PRE
899 if (lastbutton != CUBE_MODE_PRE)
900 break;
901#endif
902 if (++mode >= NUM_MODES)
903 mode = 0;
904#ifdef USEGSLIB
905 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
906 mode_switch = true;
907#endif
908 redraw = true;
909 break;
910
911 case CUBE_PAUSE:
912#ifdef CUBE_PAUSE_PRE
913 if (lastbutton != CUBE_PAUSE_PRE)
914 break;
915#endif
916 paused = !paused;
917 break;
918
919 case CUBE_HIGHSPEED:
920#ifdef CUBE_HIGHSPEED_PRE
921 if (lastbutton != CUBE_HIGHSPEED_PRE)
922 break;
923#endif
924 highspeed = !highspeed;
925 t_disp = DISP_TIME;
926 break;
927
928#ifdef CUBE_RC_QUIT
929 case CUBE_RC_QUIT:
930#endif
931 case CUBE_QUIT:
932#ifdef CUBE_QUIT_PRE
933 if (lastbutton != CUBE_QUIT_PRE)
934 break;
935#endif
936 quit = true;
937 break;
938
939 default:
940 exit_on_usb(button);
941 break;
942 }
943#if defined(CUBE_MODE_PRE) || \
944 defined(CUBE_QUIT_PRE) || \
945 defined(CUBE_PAUSE_PRE) || \
946 defined(CUBE_HIGHSPEED_PRE)
947 if (button != BUTTON_NONE)
948 lastbutton = button;
949#endif
950 }
951
952 return PLUGIN_OK;
953}