New makefile solution: A single invocation of 'make' to build the entire tree. Fully...
[kugel-rb.git] / apps / plugins / cube.c
blobec1930f547d7cc2d94e12127d8bf6d38571341f2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Damien Teney
11 * modified to use int instead of float math by Andreas Zwirtes
12 * heavily extended by Jens Arnold
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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
23 #include "plugin.h"
24 #include "lib/grey.h"
25 #include "lib/playergfx.h"
26 #include "lib/xlcd.h"
27 #include "lib/fixedpoint.h"
29 PLUGIN_HEADER
31 /* Loops that the values are displayed */
32 #define DISP_TIME 30
34 /* variable button definitions */
35 #if CONFIG_KEYPAD == RECORDER_PAD
36 #define CUBE_QUIT BUTTON_OFF
37 #define CUBE_NEXT BUTTON_RIGHT
38 #define CUBE_PREV BUTTON_LEFT
39 #define CUBE_INC BUTTON_UP
40 #define CUBE_DEC BUTTON_DOWN
41 #define CUBE_MODE BUTTON_F1
42 #define CUBE_PAUSE BUTTON_PLAY
43 #define CUBE_HIGHSPEED BUTTON_ON
45 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
46 #define CUBE_QUIT BUTTON_OFF
47 #define CUBE_NEXT BUTTON_RIGHT
48 #define CUBE_PREV BUTTON_LEFT
49 #define CUBE_INC BUTTON_UP
50 #define CUBE_DEC BUTTON_DOWN
51 #define CUBE_MODE BUTTON_F1
52 #define CUBE_PAUSE BUTTON_SELECT
53 #define CUBE_HIGHSPEED BUTTON_ON
55 #elif CONFIG_KEYPAD == PLAYER_PAD
56 #define CUBE_QUIT BUTTON_STOP
57 #define CUBE_INC BUTTON_RIGHT
58 #define CUBE_DEC BUTTON_LEFT
59 #define CUBE_NEXT (BUTTON_ON | BUTTON_RIGHT)
60 #define CUBE_PREV (BUTTON_ON | BUTTON_LEFT)
61 #define CUBE_MODE BUTTON_MENU
62 #define CUBE_PAUSE BUTTON_PLAY
63 #define CUBE_HIGHSPEED_PRE BUTTON_ON
64 #define CUBE_HIGHSPEED (BUTTON_ON | BUTTON_REL)
66 #elif CONFIG_KEYPAD == ONDIO_PAD
67 #define CUBE_QUIT BUTTON_OFF
68 #define CUBE_NEXT BUTTON_RIGHT
69 #define CUBE_PREV BUTTON_LEFT
70 #define CUBE_INC BUTTON_UP
71 #define CUBE_DEC BUTTON_DOWN
72 #define CUBE_MODE_PRE BUTTON_MENU
73 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
74 #define CUBE_PAUSE (BUTTON_MENU | BUTTON_LEFT)
75 #define CUBE_HIGHSPEED (BUTTON_MENU | BUTTON_RIGHT)
77 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
78 (CONFIG_KEYPAD == IRIVER_H300_PAD)
79 #define CUBE_QUIT BUTTON_OFF
80 #define CUBE_NEXT BUTTON_RIGHT
81 #define CUBE_PREV BUTTON_LEFT
82 #define CUBE_INC BUTTON_UP
83 #define CUBE_DEC BUTTON_DOWN
84 #define CUBE_MODE BUTTON_MODE
85 #define CUBE_PAUSE BUTTON_ON
86 #define CUBE_HIGHSPEED BUTTON_SELECT
88 #define CUBE_RC_QUIT BUTTON_RC_STOP
90 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
91 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
92 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
93 #define CUBE_QUIT (BUTTON_SELECT | BUTTON_MENU)
94 #define CUBE_NEXT BUTTON_RIGHT
95 #define CUBE_PREV BUTTON_LEFT
96 #define CUBE_INC BUTTON_SCROLL_FWD
97 #define CUBE_DEC BUTTON_SCROLL_BACK
98 #define CUBE_MODE BUTTON_MENU
99 #define CUBE_PAUSE BUTTON_PLAY
100 #define CUBE_HIGHSPEED_PRE BUTTON_SELECT
101 #define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REL)
103 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
104 #define CUBE_QUIT BUTTON_PLAY
105 #define CUBE_NEXT BUTTON_RIGHT
106 #define CUBE_PREV BUTTON_LEFT
107 #define CUBE_INC BUTTON_UP
108 #define CUBE_DEC BUTTON_DOWN
109 #define CUBE_MODE BUTTON_MODE
110 #define CUBE_PAUSE BUTTON_SELECT
111 #define CUBE_HIGHSPEED BUTTON_EQ
113 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
114 #define CUBE_QUIT BUTTON_POWER
115 #define CUBE_NEXT BUTTON_RIGHT
116 #define CUBE_PREV BUTTON_LEFT
117 #define CUBE_INC BUTTON_UP
118 #define CUBE_DEC BUTTON_DOWN
119 #define CUBE_MODE BUTTON_REC
120 #define CUBE_PAUSE BUTTON_PLAY
121 #define CUBE_HIGHSPEED BUTTON_SELECT
123 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
124 #define CUBE_QUIT BUTTON_POWER
125 #define CUBE_NEXT BUTTON_RIGHT
126 #define CUBE_PREV BUTTON_LEFT
127 #define CUBE_INC BUTTON_UP
128 #define CUBE_DEC BUTTON_DOWN
129 #define CUBE_MODE BUTTON_MENU
130 #define CUBE_PAUSE BUTTON_SELECT
131 #define CUBE_HIGHSPEED BUTTON_A
133 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
134 #define CUBE_QUIT BUTTON_POWER
135 #define CUBE_NEXT BUTTON_RIGHT
136 #define CUBE_PREV BUTTON_LEFT
137 #define CUBE_INC BUTTON_SCROLL_FWD
138 #define CUBE_DEC BUTTON_SCROLL_BACK
139 #define CUBE_MODE BUTTON_DOWN
140 #define CUBE_PAUSE BUTTON_UP
141 #define CUBE_HIGHSPEED BUTTON_SELECT
143 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
144 #define CUBE_QUIT BUTTON_POWER
145 #define CUBE_NEXT BUTTON_RIGHT
146 #define CUBE_PREV BUTTON_LEFT
147 #define CUBE_INC BUTTON_VOL_UP
148 #define CUBE_DEC BUTTON_VOL_DOWN
149 #define CUBE_MODE BUTTON_DOWN
150 #define CUBE_PAUSE BUTTON_UP
151 #define CUBE_HIGHSPEED BUTTON_SELECT
154 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
155 #define CUBE_QUIT BUTTON_POWER
156 #define CUBE_NEXT BUTTON_RIGHT
157 #define CUBE_PREV BUTTON_LEFT
158 #define CUBE_INC BUTTON_SCROLL_UP
159 #define CUBE_DEC BUTTON_SCROLL_DOWN
160 #define CUBE_MODE BUTTON_REW
161 #define CUBE_PAUSE BUTTON_PLAY
162 #define CUBE_HIGHSPEED BUTTON_FF
164 #elif CONFIG_KEYPAD == MROBE500_PAD
165 #define CUBE_QUIT BUTTON_POWER
166 #define CUBE_NEXT BUTTON_RIGHT
167 #define CUBE_PREV BUTTON_LEFT
168 #define CUBE_INC BUTTON_RC_VOL_UP
169 #define CUBE_DEC BUTTON_RC_VOL_DOWN
170 #define CUBE_MODE BUTTON_RC_MODE
171 #define CUBE_PAUSE_PRE BUTTON_RC_HEART
172 #define CUBE_PAUSE (BUTTON_RC_HEART | BUTTON_REL)
173 #define CUBE_HIGHSPEED BUTTON_RC_HEART /* fixme: clashes with pause */
175 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
176 #define CUBE_QUIT BUTTON_BACK
177 #define CUBE_NEXT BUTTON_RIGHT
178 #define CUBE_PREV BUTTON_LEFT
179 #define CUBE_INC BUTTON_UP
180 #define CUBE_DEC BUTTON_DOWN
181 #define CUBE_MODE BUTTON_MENU
182 #define CUBE_PAUSE BUTTON_PLAY
183 #define CUBE_HIGHSPEED BUTTON_SELECT
185 #elif (CONFIG_KEYPAD == MROBE100_PAD)
186 #define CUBE_QUIT BUTTON_POWER
187 #define CUBE_NEXT BUTTON_RIGHT
188 #define CUBE_PREV BUTTON_LEFT
189 #define CUBE_INC BUTTON_UP
190 #define CUBE_DEC BUTTON_DOWN
191 #define CUBE_MODE BUTTON_MENU
192 #define CUBE_PAUSE BUTTON_PLAY
193 #define CUBE_HIGHSPEED BUTTON_SELECT
195 #elif (CONFIG_KEYPAD == IAUDIO_M3_PAD)
196 #define CUBE_QUIT BUTTON_RC_REC
197 #define CUBE_NEXT BUTTON_RC_FF
198 #define CUBE_PREV BUTTON_RC_REW
199 #define CUBE_INC BUTTON_RC_VOL_UP
200 #define CUBE_DEC BUTTON_RC_VOL_DOWN
201 #define CUBE_MODE BUTTON_RC_MODE
202 #define CUBE_PAUSE BUTTON_RC_PLAY
203 #define CUBE_HIGHSPEED BUTTON_RC_MENU
205 #elif CONFIG_KEYPAD == COWOND2_PAD
206 #define CUBE_QUIT BUTTON_POWER
208 #elif (CONFIG_KEYPAD == IAUDIO67_PAD)
209 #define CUBE_QUIT BUTTON_POWER
210 #define CUBE_NEXT BUTTON_RIGHT
211 #define CUBE_PREV BUTTON_LEFT
212 #define CUBE_INC BUTTON_VOLUP
213 #define CUBE_DEC BUTTON_VOLDOWN
214 #define CUBE_MODE BUTTON_MENU
215 #define CUBE_PAUSE BUTTON_PLAY
216 #define CUBE_HIGHSPEED BUTTON_STOP
218 #else
219 #error No keymap defined!
220 #endif
222 #ifdef HAVE_TOUCHSCREEN
223 #ifndef CUBE_QUIT
224 #define CUBE_QUIT BUTTON_TOPLEFT
225 #endif
226 #ifndef CUBE_NEXT
227 #define CUBE_NEXT BUTTON_MIDRIGHT
228 #endif
229 #ifndef CUBE_PREV
230 #define CUBE_PREV BUTTON_MIDLEFT
231 #endif
232 #ifndef CUBE_INC
233 #define CUBE_INC BUTTON_TOPMIDDLE
234 #endif
235 #ifndef CUBE_DEC
236 #define CUBE_DEC BUTTON_BOTTOMMIDDLE
237 #endif
238 #ifndef CUBE_MODE
239 #define CUBE_MODE BUTTON_TOPRIGHT
240 #endif
241 #ifndef CUBE_PAUSE
242 #define CUBE_PAUSE BUTTON_CENTER
243 #endif
244 #ifndef CUBE_HIGHSPEED
245 #define CUBE_HIGHSPEED BUTTON_BOTTOMRIGHT
246 #endif
247 #endif
250 #ifdef HAVE_LCD_BITMAP
252 #define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
253 static int x_off = LCD_WIDTH/2;
254 static int y_off = LCD_HEIGHT/2;
256 #if LCD_DEPTH == 1
257 #define USE_GSLIB
258 GREY_INFO_STRUCT
259 struct my_lcd {
260 void (*update)(void);
261 void (*clear_display)(void);
262 void (*drawline)(int x1, int y1, int x2, int y2);
263 void (*putsxy)(int x, int y, const unsigned char *string);
266 static struct my_lcd greyfuncs = {
267 grey_update, grey_clear_display, grey_drawline, grey_putsxy
269 static struct my_lcd lcdfuncs; /* initialised at runtime */
270 static struct my_lcd *mylcd = &greyfuncs;
272 #define MYLCD(fn) mylcd->fn
273 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) grey_filltriangle(x1, y1, x2, y2, x3, y3)
274 #define MY_SET_FOREGROUND(fg) grey_set_foreground(fg)
275 #define MY_GET_FOREGROUND() grey_get_foreground()
277 #else
278 #define MYLCD(fn) rb->lcd_ ## fn
279 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) xlcd_filltriangle(x1, y1, x2, y2, x3, y3)
280 #define MY_SET_FOREGROUND(fg) rb->lcd_set_foreground(fg)
281 #define MY_GET_FOREGROUND() rb->lcd_get_foreground()
282 #endif
284 #if CONFIG_LCD == LCD_SSD1815
285 #define ASPECT 320 /* = 1.25 (fixed point 24.8) */
286 #else
287 #define ASPECT 256 /* = 1.00 */
288 #endif
290 #else /* !LCD_BITMAP */
292 #define MYLCD(fn) pgfx_ ## fn
293 #define DIST 9
294 static int x_off = 10;
295 static int y_off = 7;
296 #define ASPECT 300 /* = 1.175 */
298 #endif /* !LCD_BITMAP */
300 struct point_3D {
301 long x, y, z;
304 struct point_2D {
305 long x, y;
308 struct line {
309 int start, end;
312 struct face {
313 int corner[4];
314 int line[4];
317 /* initial, unrotated cube corners */
318 static const struct point_3D sommet[8] =
320 {-DIST, -DIST, -DIST},
321 { DIST, -DIST, -DIST},
322 { DIST, DIST, -DIST},
323 {-DIST, DIST, -DIST},
324 {-DIST, -DIST, DIST},
325 { DIST, -DIST, DIST},
326 { DIST, DIST, DIST},
327 {-DIST, DIST, DIST}
330 /* The 12 lines forming the edges */
331 static const struct line lines[12] =
333 {0, 1}, {1, 2}, {2, 3}, {3, 0},
334 {4, 7}, {7, 6}, {6, 5}, {5, 4},
335 {0, 4}, {1, 5}, {2, 6}, {3, 7}
338 static bool lines_drawn[12];
340 /* The 6 faces of the cube; points are in clockwise order when viewed
341 from the outside */
342 static const struct face faces[6] =
344 {{0, 1, 2, 3}, {0, 1, 2, 3}},
345 {{4, 7, 6, 5}, {4, 5, 6, 7}},
346 {{0, 4, 5, 1}, {8, 7, 9, 0}},
347 {{2, 6, 7, 3}, {10, 5, 11, 2}},
348 {{0, 3, 7, 4}, {3, 11, 4, 8}},
349 {{1, 5, 6, 2}, {9, 6, 10, 1}}
352 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
353 static const unsigned face_colors[6] =
355 #ifdef HAVE_LCD_COLOR
356 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
357 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
358 #elif defined(USE_GSLIB)
359 #ifdef MROBE_100
360 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
361 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE
362 #else
363 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
364 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
365 #endif
366 #else
367 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
368 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
369 #endif
371 #endif
373 enum {
374 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
375 SOLID,
376 #endif
377 HIDDEN_LINES,
378 WIREFRAME,
379 NUM_MODES
382 static int mode = 0;
384 struct counter {
385 const char *label;
386 short speed;
387 short angle;
390 static struct counter axes[] = {
391 {"x-axis", 1, 0},
392 {"y-axis", 3, 0},
393 {"z-axis", 2, 0}
396 static struct point_3D point3D[8];
397 static struct point_2D point2D[8];
398 static long matrice[3][3];
400 static const int nb_points = 8;
401 static long z_off = 600;
403 static const struct plugin_api* rb;
405 static void cube_rotate(int xa, int ya, int za)
407 int i;
408 /* Just to prevent unnecessary lookups */
409 long sxa, cxa, sya, cya, sza, cza;
411 sxa = sin_int(xa);
412 cxa = cos_int(xa);
413 sya = sin_int(ya);
414 cya = cos_int(ya);
415 sza = sin_int(za);
416 cza = cos_int(za);
418 /* calculate overall translation matrix */
419 matrice[0][0] = (cza * cya) >> 14;
420 matrice[1][0] = (sza * cya) >> 14;
421 matrice[2][0] = -sya;
423 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
424 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
425 matrice[2][1] = (sxa * cya) >> 14;
427 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
428 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
429 matrice[2][2] = (cxa * cya) >> 14;
431 /* apply translation matrix to all points */
432 for (i = 0; i < nb_points; i++)
434 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
435 + matrice[2][0] * sommet[i].z;
437 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
438 + matrice[2][1] * sommet[i].z;
440 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
441 + matrice[2][2] * sommet[i].z;
445 static void cube_viewport(void)
447 int i;
449 /* Do viewport transformation for all points */
450 for (i = 0; i < nb_points; i++)
452 #if ASPECT != 256
453 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
454 + x_off;
455 #else
456 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
457 + x_off;
458 #endif
459 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
460 + y_off;
464 static void cube_draw(void)
466 int i, j, line;
467 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
468 unsigned old_foreground;
469 #endif
471 switch (mode)
473 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
474 case SOLID:
476 old_foreground = MY_GET_FOREGROUND();
477 for (i = 0; i < 6; i++)
479 /* backface culling; if the shape winds counter-clockwise, we are
480 * looking at the backface, and the (simplified) cross product
481 * is < 0. Do not draw it. */
482 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
483 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
484 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
485 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
486 continue;
488 MY_SET_FOREGROUND(face_colors[i]);
489 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
490 point2D[faces[i].corner[0]].y,
491 point2D[faces[i].corner[1]].x,
492 point2D[faces[i].corner[1]].y,
493 point2D[faces[i].corner[2]].x,
494 point2D[faces[i].corner[2]].y);
495 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
496 point2D[faces[i].corner[0]].y,
497 point2D[faces[i].corner[2]].x,
498 point2D[faces[i].corner[2]].y,
499 point2D[faces[i].corner[3]].x,
500 point2D[faces[i].corner[3]].y);
503 MY_SET_FOREGROUND(old_foreground);
504 break;
505 #endif /* (LCD_DEPTH > 1) || GSLIB */
507 case HIDDEN_LINES:
509 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
510 for (i = 0; i < 6; i++)
512 /* backface culling; if the shape winds counter-clockwise, we are
513 * looking at the backface, and the (simplified) cross product
514 * is < 0. Do not draw it. */
515 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
516 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
517 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
518 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
519 continue;
521 for (j = 0; j < 4; j++)
523 line = faces[i].line[j];
524 if (!lines_drawn[line])
526 lines_drawn[line] = true;
527 MYLCD(drawline)(point2D[lines[line].start].x,
528 point2D[lines[line].start].y,
529 point2D[lines[line].end].x,
530 point2D[lines[line].end].y);
534 break;
536 case WIREFRAME:
538 for (i = 0; i < 12; i++)
539 MYLCD(drawline)(point2D[lines[i].start].x,
540 point2D[lines[i].start].y,
541 point2D[lines[i].end].x,
542 point2D[lines[i].end].y);
543 break;
547 void cleanup(void *parameter)
549 (void)parameter;
551 #ifdef USE_GSLIB
552 grey_release();
553 #elif defined HAVE_LCD_CHARCELLS
554 pgfx_release();
555 #endif
558 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
560 char buffer[30];
561 int t_disp = 0;
562 #ifdef USE_GSLIB
563 unsigned char *gbuf;
564 size_t gbuf_size = 0;
565 bool mode_switch = true;
566 #endif
568 int button;
569 int lastbutton = BUTTON_NONE;
570 int curr = 0;
571 bool highspeed = false;
572 bool paused = false;
573 bool redraw = true;
574 bool exit = false;
576 (void)(parameter);
577 rb = api;
579 #ifdef HAVE_LCD_BITMAP
580 #if LCD_DEPTH > 1
581 xlcd_init(rb);
582 #elif defined(USE_GSLIB)
583 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
584 if (!grey_init(rb, gbuf, gbuf_size, GREY_BUFFERED,
585 LCD_WIDTH, LCD_HEIGHT, NULL))
587 rb->splash(HZ, "Couldn't init greyscale display");
588 return PLUGIN_ERROR;
590 /* init lcd_ function pointers */
591 lcdfuncs.update = rb->lcd_update;
592 lcdfuncs.clear_display = rb->lcd_clear_display;
593 lcdfuncs.drawline = rb->lcd_drawline;
594 lcdfuncs.putsxy = rb->lcd_putsxy;
596 #ifdef MROBE_100
597 grey_set_background(GREY_BLACK);
598 #endif
600 grey_setfont(FONT_SYSFIXED);
601 #endif
602 rb->lcd_setfont(FONT_SYSFIXED);
603 #else /* LCD_CHARCELLS */
604 if (!pgfx_init(rb, 4, 2))
606 rb->splash(HZ*2, "Old LCD :(");
607 return PLUGIN_OK;
609 pgfx_display(0, 0);
610 #endif
612 while(!exit)
614 if (redraw)
616 MYLCD(clear_display)();
617 cube_rotate(axes[0].angle, axes[1].angle, axes[2].angle);
618 cube_viewport();
619 cube_draw();
620 redraw = false;
623 #ifdef HAVE_LCD_BITMAP
624 if (t_disp > 0)
626 t_disp--;
627 rb->snprintf(buffer, sizeof(buffer), "%s: %d %s",
628 axes[curr].label,
629 paused ? axes[curr].angle : axes[curr].speed,
630 highspeed ? "(hs)" : "");
631 MYLCD(putsxy)(0, LCD_HEIGHT-8, buffer);
632 if (t_disp == 0)
633 redraw = true;
635 #else
636 if (t_disp > 0)
638 if (t_disp == DISP_TIME)
640 rb->lcd_puts(5, 0, axes[curr].label);
641 rb->snprintf(buffer, sizeof(buffer), "%d %c",
642 paused ? axes[curr].angle : axes[curr].speed,
643 highspeed ? 'H' : ' ');
644 rb->lcd_puts(5, 1, buffer);
646 t_disp--;
647 if (t_disp == 0)
649 rb->lcd_clear_display();
650 pgfx_display(0, 0);
653 #endif
654 #ifdef USE_GSLIB
655 if (mode_switch)
657 grey_show(mode == SOLID);
658 mode_switch = false;
660 #endif
661 MYLCD(update)();
663 if (!paused)
665 int i;
667 for (i = 0; i < 3; i++)
669 axes[i].angle += axes[i].speed;
670 if (axes[i].angle > 359)
671 axes[i].angle -= 360;
672 else if (axes[i].angle < 0)
673 axes[i].angle += 360;
675 redraw = true;
677 if (highspeed)
678 rb->yield();
679 else
680 rb->sleep(HZ/25);
681 button = rb->button_get(false);
683 else
685 button = rb->button_get_w_tmo(HZ/25);
688 switch (button)
690 case CUBE_INC:
691 case CUBE_INC|BUTTON_REPEAT:
692 if (!paused)
694 if (axes[curr].speed < 10)
695 axes[curr].speed++;
697 else
699 if (++axes[curr].angle > 359)
700 axes[curr].angle -= 360;
702 t_disp = DISP_TIME;
703 redraw = true;
704 break;
706 case CUBE_DEC:
707 case CUBE_DEC|BUTTON_REPEAT:
708 if (!paused)
710 if (axes[curr].speed > -10)
711 axes[curr].speed--;
713 else
715 if (--axes[curr].angle < 0)
716 axes[curr].angle += 360;
718 t_disp = DISP_TIME;
719 redraw = true;
720 break;
722 case CUBE_NEXT:
723 if (++curr > 2)
724 curr = 0;
725 t_disp = DISP_TIME;
726 break;
728 case CUBE_PREV:
729 if (--curr < 0)
730 curr = 2;
731 t_disp = DISP_TIME;
732 break;
734 case CUBE_MODE:
735 #ifdef CUBE_MODE_PRE
736 if (lastbutton != CUBE_MODE_PRE)
737 break;
738 #endif
739 if (++mode >= NUM_MODES)
740 mode = 0;
741 #ifdef USE_GSLIB
742 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
743 mode_switch = true;
744 #endif
745 redraw = true;
746 break;
748 case CUBE_PAUSE:
749 #ifdef CUBE_PAUSE_PRE
750 if (lastbutton != CUBE_PAUSE_PRE)
751 break;
752 #endif
753 paused = !paused;
754 break;
756 case CUBE_HIGHSPEED:
757 #ifdef CUBE_HIGHSPEED_PRE
758 if (lastbutton != CUBE_HIGHSPEED_PRE)
759 break;
760 #endif
761 highspeed = !highspeed;
762 t_disp = DISP_TIME;
763 break;
765 #ifdef CUBE_RC_QUIT
766 case CUBE_RC_QUIT:
767 #endif
768 case CUBE_QUIT:
769 exit = true;
770 break;
772 default:
773 if (rb->default_event_handler_ex(button, cleanup, NULL)
774 == SYS_USB_CONNECTED)
775 return PLUGIN_USB_CONNECTED;
776 break;
778 if (button != BUTTON_NONE)
779 lastbutton = button;
782 #ifdef USE_GSLIB
783 grey_release();
784 #elif defined(HAVE_LCD_CHARCELLS)
785 pgfx_release();
786 #endif
787 return PLUGIN_OK;