Bring mpegplayer backlight fix to the other plugins, this also fixes some wrongly...
[Rockbox.git] / apps / plugins / oscilloscope.c
blob6ef398a5208750b1e43b05d8a90d9cfeb44ac2ad
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Oscilloscope, with many different modes of operation.
12 * Copyright (C) 2004-2006 Jens Arnold
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "helper.h"
25 #ifdef HAVE_LCD_BITMAP
26 #include "xlcd.h"
27 #include "configfile.h"
29 PLUGIN_HEADER
31 /* variable button definitions */
32 #if CONFIG_KEYPAD == RECORDER_PAD
33 #define OSCILLOSCOPE_QUIT BUTTON_OFF
34 #define OSCILLOSCOPE_DRAWMODE BUTTON_F1
35 #define OSCILLOSCOPE_ADVMODE BUTTON_F2
36 #define OSCILLOSCOPE_ORIENTATION BUTTON_F3
37 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
38 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
39 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
40 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
41 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
43 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
44 #define OSCILLOSCOPE_QUIT BUTTON_OFF
45 #define OSCILLOSCOPE_DRAWMODE BUTTON_F1
46 #define OSCILLOSCOPE_ADVMODE BUTTON_F2
47 #define OSCILLOSCOPE_ORIENTATION BUTTON_F3
48 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
49 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
50 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
51 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
52 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
54 #elif CONFIG_KEYPAD == ONDIO_PAD
55 #define OSCILLOSCOPE_QUIT BUTTON_OFF
56 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_MENU
57 #define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_REL)
58 #define OSCILLOSCOPE_ADVMODE (BUTTON_MENU | BUTTON_RIGHT)
59 #define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_LEFT)
60 #define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF)
61 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
62 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
63 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
64 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
66 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
67 #define OSCILLOSCOPE_QUIT BUTTON_OFF
68 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
69 #define OSCILLOSCOPE_ADVMODE BUTTON_MODE
70 #define OSCILLOSCOPE_ORIENTATION BUTTON_REC
71 #define OSCILLOSCOPE_PAUSE BUTTON_ON
72 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
73 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
74 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
75 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
76 #define OSCILLOSCOPE_RC_QUIT BUTTON_RC_STOP
78 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
79 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
80 #define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
81 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY)
82 #define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
83 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
84 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
85 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
86 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
87 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
88 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
90 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
91 #define OSCILLOSCOPE_QUIT BUTTON_POWER
92 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
93 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
94 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
95 #define OSCILLOSCOPE_PAUSE BUTTON_A
96 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
97 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
98 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
99 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
101 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
102 #define OSCILLOSCOPE_QUIT BUTTON_POWER
103 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
104 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
105 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
106 #define OSCILLOSCOPE_PAUSE BUTTON_REC
107 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
108 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
109 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_DOWN
110 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_UP
112 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
113 #define OSCILLOSCOPE_QUIT BUTTON_POWER
114 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
115 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
116 #define OSCILLOSCOPE_ADVMODE BUTTON_REC
117 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
118 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
119 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
120 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
121 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
122 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
123 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
125 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
126 #define OSCILLOSCOPE_QUIT BUTTON_POWER
127 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW
128 #define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL)
129 #define OSCILLOSCOPE_ADVMODE BUTTON_FF
130 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW
131 #define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT)
132 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
133 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
134 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
135 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP
136 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN
138 #endif
140 /* colours */
141 #if LCD_DEPTH > 1
142 #ifdef HAVE_LCD_COLOR
143 #define BACKG_COLOR LCD_BLACK
144 #define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
145 #define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
146 #else
147 #define BACKG_COLOR LCD_WHITE
148 #define GRAPH_COLOR LCD_BLACK
149 #define CURSOR_COLOR LCD_DARKGRAY
150 #endif
151 #endif
153 enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW };
154 enum { ADV_SCROLL, ADV_WRAP, MAX_ADV };
155 enum { OSC_HORIZ, OSC_VERT, MAX_OSC };
157 #define CFGFILE_VERSION 0 /* Current config file version */
158 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
161 #define MAX_PEAK 0x8000
163 #if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
164 #define mas_codec_readreg(x) rand()%MAX_PEAK
165 #endif
167 /* global variables */
169 struct plugin_api* rb; /* global api struct pointer */
171 /* settings */
172 struct osc_config {
173 int delay; /* in ticks */
174 int draw;
175 int advance;
176 int orientation;
179 struct osc_config osc_disk = { 2, DRAW_FILLED, ADV_SCROLL, OSC_HORIZ };
180 struct osc_config osc; /* running config */
182 static const char cfg_filename[] = "oscilloscope.cfg";
183 static char *draw_str[3] = { "filled", "line", "pixel" };
184 static char *advance_str[2] = { "scroll", "wrap" };
185 static char *orientation_str[2] = { "horizontal", "vertical" };
187 struct configdata disk_config[] = {
188 { TYPE_INT, 1, 99, &osc_disk.delay, "delay", NULL, NULL },
189 { TYPE_ENUM, 0, MAX_DRAW, &osc_disk.draw, "draw", draw_str, NULL },
190 { TYPE_ENUM, 0, MAX_ADV, &osc_disk.advance, "advance", advance_str, NULL },
191 { TYPE_ENUM, 0, MAX_OSC, &osc_disk.orientation, "orientation", orientation_str, NULL }
195 long last_tick = 0; /* time of last drawing */
196 int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */
197 int last_left; /* last channel values */
198 int last_right;
200 unsigned char message[16]; /* message to display */
201 bool displaymsg = false;
202 int font_height = 8;
204 /* implementation */
206 void anim_horizontal(int cur_left, int cur_right)
208 int cur_x, x;
209 int left, right, dl, dr;
210 long cur_tick = *rb->current_tick;
211 long d = (cur_tick - last_tick) / osc.delay;
212 bool full_update = false;
214 if (d == 0) /* too early, bail out */
215 return;
217 last_tick = cur_tick;
219 if (d > HZ) /* first call or too much delay, (re)start */
221 last_left = cur_left;
222 last_right = cur_right;
223 return;
225 cur_x = last_pos + d;
227 if (cur_x >= LCD_WIDTH)
229 if (osc.advance == ADV_SCROLL)
231 int shift = cur_x - (LCD_WIDTH-1);
232 xlcd_scroll_left(shift);
233 full_update = true;
234 cur_x -= shift;
235 last_pos -= shift;
237 else
239 cur_x -= LCD_WIDTH;
242 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
244 if (cur_x > last_pos)
246 rb->lcd_fillrect(last_pos + 1, 0, d, LCD_HEIGHT);
248 else
250 rb->lcd_fillrect(last_pos + 1, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
251 rb->lcd_fillrect(0, 0, cur_x + 1, LCD_HEIGHT);
253 rb->lcd_set_drawmode(DRMODE_SOLID);
255 switch (osc.draw)
257 case DRAW_FILLED:
258 left = last_left;
259 right = last_right;
260 dl = (cur_left - left) / d;
261 dr = (cur_right - right) / d;
263 for (x = last_pos + 1; d > 0; x++, d--)
265 if (x == LCD_WIDTH)
266 x = 0;
268 left += dl;
269 right += dr;
271 rb->lcd_vline(x, LCD_HEIGHT/2-1,
272 LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
273 rb->lcd_vline(x, LCD_HEIGHT/2+1,
274 LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
276 break;
278 case DRAW_LINE:
279 if (cur_x > last_pos)
281 rb->lcd_drawline(
282 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
283 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
285 rb->lcd_drawline(
286 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
287 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
290 else
292 left = last_left
293 + (LCD_WIDTH - last_pos) * (last_left - cur_left) / d;
294 right = last_right
295 + (LCD_WIDTH - last_pos) * (last_right - cur_right) / d;
297 rb->lcd_drawline(
298 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
299 LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16)
301 rb->lcd_drawline(
302 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
303 LCD_WIDTH, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16)
305 if (cur_x > 0)
307 rb->lcd_drawline(
308 0, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16),
309 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
311 rb->lcd_drawline(
312 0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16),
313 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
317 break;
319 case DRAW_PIXEL:
320 left = last_left;
321 right = last_right;
322 dl = (cur_left - left) / d;
323 dr = (cur_right - right) / d;
325 for (x = last_pos + 1; d > 0; x++, d--)
327 if (x == LCD_WIDTH)
328 x = 0;
330 left += dl;
331 right += dr;
333 rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
334 rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
336 break;
339 last_left = cur_left;
340 last_right = cur_right;
342 if (displaymsg)
344 int width;
346 rb->lcd_getstringsize(message, &width, NULL);
347 last_pos -= width - 1;
348 rb->lcd_putsxy(last_pos, 0, message);
349 displaymsg = false;
351 if (last_pos < 0)
352 last_pos = 0;
355 if (full_update)
357 rb->lcd_update();
359 else
361 #if LCD_DEPTH > 1 /* cursor bar */
362 rb->lcd_set_foreground(CURSOR_COLOR);
363 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
364 rb->lcd_set_foreground(GRAPH_COLOR);
365 #else
366 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
367 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
368 rb->lcd_set_drawmode(DRMODE_SOLID);
369 #endif
371 if (cur_x > last_pos)
373 rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT);
375 else
377 rb->lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
378 rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
381 last_pos = cur_x;
384 void anim_vertical(int cur_left, int cur_right)
386 int cur_y, y;
387 int left, right, dl, dr;
388 long cur_tick = *rb->current_tick;
389 long d = (cur_tick - last_tick) / osc.delay;
390 bool full_update = false;
392 if (d == 0) /* too early, bail out */
393 return;
395 last_tick = cur_tick;
397 if (d > HZ) /* first call or too much delay, (re)start */
399 last_left = cur_left;
400 last_right = cur_right;
401 return;
403 cur_y = last_pos + d;
405 if (cur_y >= LCD_HEIGHT)
407 if (osc.advance == ADV_SCROLL)
409 int shift = cur_y - (LCD_HEIGHT-1);
410 xlcd_scroll_up(shift);
411 full_update = true;
412 cur_y -= shift;
413 last_pos -= shift;
415 else
417 cur_y -= LCD_HEIGHT;
420 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
422 if (cur_y > last_pos)
424 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, d);
426 else
428 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, LCD_HEIGHT - last_pos);
429 rb->lcd_fillrect(0, 0, LCD_WIDTH, cur_y + 1);
431 rb->lcd_set_drawmode(DRMODE_SOLID);
433 switch (osc.draw)
435 case DRAW_FILLED:
436 left = last_left;
437 right = last_right;
438 dl = (cur_left - left) / d;
439 dr = (cur_right - right) / d;
441 for (y = last_pos + 1; d > 0; y++, d--)
443 if (y == LCD_HEIGHT)
444 y = 0;
446 left += dl;
447 right += dr;
449 rb->lcd_hline(LCD_WIDTH/2-1,
450 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
451 rb->lcd_hline(LCD_WIDTH/2+1,
452 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
454 break;
456 case DRAW_LINE:
457 if (cur_y > last_pos)
459 rb->lcd_drawline(
460 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
461 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
463 rb->lcd_drawline(
464 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
465 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
468 else
470 left = last_left
471 + (LCD_HEIGHT - last_pos) * (last_left - cur_left) / d;
472 right = last_right
473 + (LCD_HEIGHT - last_pos) * (last_right - cur_right) / d;
475 rb->lcd_drawline(
476 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
477 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), LCD_HEIGHT
479 rb->lcd_drawline(
480 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
481 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), LCD_HEIGHT
483 if (cur_y > 0)
485 rb->lcd_drawline(
486 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), 0,
487 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
489 rb->lcd_drawline(
490 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), 0,
491 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
495 break;
497 case DRAW_PIXEL:
498 left = last_left;
499 right = last_right;
500 dl = (cur_left - left) / d;
501 dr = (cur_right - right) / d;
503 for (y = last_pos + 1; d > 0; y++, d--)
505 if (y == LCD_HEIGHT)
506 y = 0;
508 left += dl;
509 right += dr;
511 rb->lcd_drawpixel(LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
512 rb->lcd_drawpixel(LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
514 break;
517 last_left = cur_left;
518 last_right = cur_right;
520 if (displaymsg)
522 last_pos -= font_height - 1;
523 rb->lcd_putsxy(0, last_pos, message);
524 displaymsg = false;
526 if (last_pos < 0)
527 last_pos = 0;
530 if (full_update)
532 rb->lcd_update();
534 else
536 #if LCD_DEPTH > 1 /* cursor bar */
537 rb->lcd_set_foreground(CURSOR_COLOR);
538 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
539 rb->lcd_set_foreground(GRAPH_COLOR);
540 #else
541 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
542 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
543 rb->lcd_set_drawmode(DRMODE_SOLID);
544 #endif
546 if (cur_y > last_pos)
548 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2);
550 else
552 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos);
553 rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2);
556 last_pos = cur_y;
559 void cleanup(void *parameter)
561 (void)parameter;
562 #if LCD_DEPTH > 1
563 rb->lcd_set_foreground(LCD_DEFAULT_FG);
564 rb->lcd_set_background(LCD_DEFAULT_BG);
565 #endif
566 /* Turn on backlight timeout (revert to settings) */
567 backlight_use_settings(); /* backlight control in lib/helper.c */
570 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
572 int button, vol;
573 int lastbutton = BUTTON_NONE;
574 bool exit = false;
575 bool paused = false;
576 bool tell_speed;
578 (void)parameter;
579 rb = api;
581 xlcd_init(rb);
582 configfile_init(rb);
584 configfile_load(cfg_filename, disk_config,
585 sizeof(disk_config) / sizeof(disk_config[0]),
586 CFGFILE_MINVERSION);
587 rb->memcpy(&osc, &osc_disk, sizeof(osc)); /* copy to running config */
589 #if LCD_DEPTH > 1
590 rb->lcd_set_foreground(GRAPH_COLOR);
591 rb->lcd_set_background(BACKG_COLOR);
592 rb->lcd_set_backdrop(NULL);
593 rb->lcd_clear_display();
594 rb->lcd_update();
595 #endif
597 /* Turn off backlight timeout */
598 backlight_force_on(); /* backlight control in lib/helper.c */
600 rb->lcd_getstringsize("A", NULL, &font_height);
602 while (!exit)
604 if (!paused)
606 int left, right;
608 rb->sleep(MAX(last_tick + osc.delay - *rb->current_tick - 1, 0));
610 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
611 left = rb->mas_codec_readreg(0xC);
612 right = rb->mas_codec_readreg(0xD);
613 #elif (CONFIG_CODEC == SWCODEC)
614 rb->pcm_calculate_peaks(&left, &right);
615 #endif
616 if (osc.orientation == OSC_HORIZ)
617 anim_horizontal(left, right);
618 else
619 anim_vertical(left, right);
622 tell_speed = false;
623 button = rb->button_get(paused);
624 switch (button)
626 #ifdef OSCILLOSCOPE_RC_QUIT
627 case OSCILLOSCOPE_RC_QUIT:
628 #endif
629 case OSCILLOSCOPE_QUIT:
630 exit = true;
631 break;
633 case OSCILLOSCOPE_ADVMODE:
634 if (++osc.advance >= MAX_ADV)
635 osc.advance = 0;
636 break;
638 case OSCILLOSCOPE_DRAWMODE:
639 #ifdef OSCILLOSCOPE_DRAWMODE_PRE
640 if (lastbutton != OSCILLOSCOPE_DRAWMODE_PRE)
641 break;
642 #endif
643 if (++osc.draw >= MAX_DRAW)
644 osc.draw = 0;
645 break;
647 case OSCILLOSCOPE_ORIENTATION:
648 #ifdef OSCILLOSCOPE_ORIENTATION_PRE
649 if (lastbutton != OSCILLOSCOPE_ORIENTATION_PRE)
650 break;
651 #endif
652 if (++osc.orientation >= MAX_OSC)
653 osc.orientation = 0;
654 last_pos = 0;
655 last_tick = 0;
656 displaymsg = false;
657 rb->lcd_clear_display();
658 rb->lcd_update();
659 break;
661 case OSCILLOSCOPE_PAUSE:
662 paused = !paused;
663 last_tick = 0;
664 break;
666 case OSCILLOSCOPE_SPEED_UP:
667 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
668 if (osc.delay > 1)
670 osc.delay--;
671 tell_speed = true;
673 break;
675 case OSCILLOSCOPE_SPEED_DOWN:
676 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
677 osc.delay++;
678 tell_speed = true;
679 break;
681 case OSCILLOSCOPE_VOL_UP:
682 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
683 vol = rb->global_settings->volume;
684 if (vol < rb->sound_max(SOUND_VOLUME))
686 vol++;
687 rb->sound_set(SOUND_VOLUME, vol);
688 rb->global_settings->volume = vol;
690 break;
692 case OSCILLOSCOPE_VOL_DOWN:
693 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
694 vol = rb->global_settings->volume;
695 if (vol > rb->sound_min(SOUND_VOLUME))
697 vol--;
698 rb->sound_set(SOUND_VOLUME, vol);
699 rb->global_settings->volume = vol;
701 break;
703 default:
704 if (rb->default_event_handler_ex(button, cleanup, NULL)
705 == SYS_USB_CONNECTED)
706 return PLUGIN_USB_CONNECTED;
707 break;
709 if (button != BUTTON_NONE)
710 lastbutton = button;
712 if (tell_speed)
714 rb->snprintf(message, sizeof(message), "%s%d",
715 (osc.orientation == OSC_VERT) ? "Speed: " : "",
716 100 / osc.delay);
717 displaymsg = true;
720 cleanup(NULL);
721 if (rb->memcmp(&osc, &osc_disk, sizeof(osc))) /* save settings if changed */
723 rb->memcpy(&osc_disk, &osc, sizeof(osc));
724 configfile_save(cfg_filename, disk_config,
725 sizeof(disk_config) / sizeof(disk_config[0]),
726 CFGFILE_VERSION);
728 return PLUGIN_OK;
730 #endif /* HAVE_LCD_BITMAP */