Introduce Rockbox Utility to the manual as automated installation option. Only rather...
[Rockbox.git] / apps / plugins / oscilloscope.c
blobee4b089ac1324d1ae5615b3356eb7415502330de
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 == SANSA_C200_PAD)
113 #define OSCILLOSCOPE_QUIT BUTTON_POWER
114 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
115 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
116 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
117 #define OSCILLOSCOPE_PAUSE BUTTON_REC
118 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
119 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
120 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
121 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
123 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
124 #define OSCILLOSCOPE_QUIT BUTTON_POWER
125 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
126 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
127 #define OSCILLOSCOPE_ADVMODE BUTTON_REC
128 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
129 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
130 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
131 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
132 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
133 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
134 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
136 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
137 #define OSCILLOSCOPE_QUIT BUTTON_POWER
138 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW
139 #define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL)
140 #define OSCILLOSCOPE_ADVMODE BUTTON_FF
141 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW
142 #define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT)
143 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
144 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
145 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
146 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP
147 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN
149 #endif
151 /* colours */
152 #if LCD_DEPTH > 1
153 #ifdef HAVE_LCD_COLOR
154 #define BACKG_COLOR LCD_BLACK
155 #define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
156 #define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
157 #else
158 #define BACKG_COLOR LCD_WHITE
159 #define GRAPH_COLOR LCD_BLACK
160 #define CURSOR_COLOR LCD_DARKGRAY
161 #endif
162 #endif
164 enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW };
165 enum { ADV_SCROLL, ADV_WRAP, MAX_ADV };
166 enum { OSC_HORIZ, OSC_VERT, MAX_OSC };
168 #define CFGFILE_VERSION 0 /* Current config file version */
169 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
172 #define MAX_PEAK 0x8000
174 #if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
175 #define mas_codec_readreg(x) rand()%MAX_PEAK
176 #endif
178 /* global variables */
180 struct plugin_api* rb; /* global api struct pointer */
182 /* settings */
183 struct osc_config {
184 int delay; /* in ticks */
185 int draw;
186 int advance;
187 int orientation;
190 struct osc_config osc_disk = { 2, DRAW_FILLED, ADV_SCROLL, OSC_HORIZ };
191 struct osc_config osc; /* running config */
193 static const char cfg_filename[] = "oscilloscope.cfg";
194 static char *draw_str[3] = { "filled", "line", "pixel" };
195 static char *advance_str[2] = { "scroll", "wrap" };
196 static char *orientation_str[2] = { "horizontal", "vertical" };
198 struct configdata disk_config[] = {
199 { TYPE_INT, 1, 99, &osc_disk.delay, "delay", NULL, NULL },
200 { TYPE_ENUM, 0, MAX_DRAW, &osc_disk.draw, "draw", draw_str, NULL },
201 { TYPE_ENUM, 0, MAX_ADV, &osc_disk.advance, "advance", advance_str, NULL },
202 { TYPE_ENUM, 0, MAX_OSC, &osc_disk.orientation, "orientation", orientation_str, NULL }
206 long last_tick = 0; /* time of last drawing */
207 int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */
208 int last_left; /* last channel values */
209 int last_right;
211 unsigned char message[16]; /* message to display */
212 bool displaymsg = false;
213 int font_height = 8;
215 /* implementation */
217 void anim_horizontal(int cur_left, int cur_right)
219 int cur_x, x;
220 int left, right, dl, dr;
221 long cur_tick = *rb->current_tick;
222 long d = (cur_tick - last_tick) / osc.delay;
223 bool full_update = false;
225 if (d == 0) /* too early, bail out */
226 return;
228 last_tick = cur_tick;
230 if (d > HZ) /* first call or too much delay, (re)start */
232 last_left = cur_left;
233 last_right = cur_right;
234 return;
236 cur_x = last_pos + d;
238 if (cur_x >= LCD_WIDTH)
240 if (osc.advance == ADV_SCROLL)
242 int shift = cur_x - (LCD_WIDTH-1);
243 xlcd_scroll_left(shift);
244 full_update = true;
245 cur_x -= shift;
246 last_pos -= shift;
248 else
250 cur_x -= LCD_WIDTH;
253 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
255 if (cur_x > last_pos)
257 rb->lcd_fillrect(last_pos + 1, 0, d, LCD_HEIGHT);
259 else
261 rb->lcd_fillrect(last_pos + 1, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
262 rb->lcd_fillrect(0, 0, cur_x + 1, LCD_HEIGHT);
264 rb->lcd_set_drawmode(DRMODE_SOLID);
266 switch (osc.draw)
268 case DRAW_FILLED:
269 left = last_left;
270 right = last_right;
271 dl = (cur_left - left) / d;
272 dr = (cur_right - right) / d;
274 for (x = last_pos + 1; d > 0; x++, d--)
276 if (x == LCD_WIDTH)
277 x = 0;
279 left += dl;
280 right += dr;
282 rb->lcd_vline(x, LCD_HEIGHT/2-1,
283 LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
284 rb->lcd_vline(x, LCD_HEIGHT/2+1,
285 LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
287 break;
289 case DRAW_LINE:
290 if (cur_x > last_pos)
292 rb->lcd_drawline(
293 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
294 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
296 rb->lcd_drawline(
297 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
298 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
301 else
303 left = last_left
304 + (LCD_WIDTH - last_pos) * (last_left - cur_left) / d;
305 right = last_right
306 + (LCD_WIDTH - last_pos) * (last_right - cur_right) / d;
308 rb->lcd_drawline(
309 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
310 LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16)
312 rb->lcd_drawline(
313 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
314 LCD_WIDTH, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16)
316 if (cur_x > 0)
318 rb->lcd_drawline(
319 0, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16),
320 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
322 rb->lcd_drawline(
323 0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16),
324 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
328 break;
330 case DRAW_PIXEL:
331 left = last_left;
332 right = last_right;
333 dl = (cur_left - left) / d;
334 dr = (cur_right - right) / d;
336 for (x = last_pos + 1; d > 0; x++, d--)
338 if (x == LCD_WIDTH)
339 x = 0;
341 left += dl;
342 right += dr;
344 rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
345 rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
347 break;
350 last_left = cur_left;
351 last_right = cur_right;
353 if (displaymsg)
355 int width;
357 rb->lcd_getstringsize(message, &width, NULL);
358 last_pos -= width - 1;
359 rb->lcd_putsxy(last_pos, 0, message);
360 displaymsg = false;
362 if (last_pos < 0)
363 last_pos = 0;
366 if (full_update)
368 rb->lcd_update();
370 else
372 #if LCD_DEPTH > 1 /* cursor bar */
373 rb->lcd_set_foreground(CURSOR_COLOR);
374 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
375 rb->lcd_set_foreground(GRAPH_COLOR);
376 #else
377 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
378 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
379 rb->lcd_set_drawmode(DRMODE_SOLID);
380 #endif
382 if (cur_x > last_pos)
384 rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT);
386 else
388 rb->lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
389 rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
392 last_pos = cur_x;
395 void anim_vertical(int cur_left, int cur_right)
397 int cur_y, y;
398 int left, right, dl, dr;
399 long cur_tick = *rb->current_tick;
400 long d = (cur_tick - last_tick) / osc.delay;
401 bool full_update = false;
403 if (d == 0) /* too early, bail out */
404 return;
406 last_tick = cur_tick;
408 if (d > HZ) /* first call or too much delay, (re)start */
410 last_left = cur_left;
411 last_right = cur_right;
412 return;
414 cur_y = last_pos + d;
416 if (cur_y >= LCD_HEIGHT)
418 if (osc.advance == ADV_SCROLL)
420 int shift = cur_y - (LCD_HEIGHT-1);
421 xlcd_scroll_up(shift);
422 full_update = true;
423 cur_y -= shift;
424 last_pos -= shift;
426 else
428 cur_y -= LCD_HEIGHT;
431 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
433 if (cur_y > last_pos)
435 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, d);
437 else
439 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, LCD_HEIGHT - last_pos);
440 rb->lcd_fillrect(0, 0, LCD_WIDTH, cur_y + 1);
442 rb->lcd_set_drawmode(DRMODE_SOLID);
444 switch (osc.draw)
446 case DRAW_FILLED:
447 left = last_left;
448 right = last_right;
449 dl = (cur_left - left) / d;
450 dr = (cur_right - right) / d;
452 for (y = last_pos + 1; d > 0; y++, d--)
454 if (y == LCD_HEIGHT)
455 y = 0;
457 left += dl;
458 right += dr;
460 rb->lcd_hline(LCD_WIDTH/2-1,
461 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
462 rb->lcd_hline(LCD_WIDTH/2+1,
463 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
465 break;
467 case DRAW_LINE:
468 if (cur_y > last_pos)
470 rb->lcd_drawline(
471 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
472 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
474 rb->lcd_drawline(
475 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
476 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
479 else
481 left = last_left
482 + (LCD_HEIGHT - last_pos) * (last_left - cur_left) / d;
483 right = last_right
484 + (LCD_HEIGHT - last_pos) * (last_right - cur_right) / d;
486 rb->lcd_drawline(
487 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
488 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), LCD_HEIGHT
490 rb->lcd_drawline(
491 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
492 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), LCD_HEIGHT
494 if (cur_y > 0)
496 rb->lcd_drawline(
497 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), 0,
498 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
500 rb->lcd_drawline(
501 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), 0,
502 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
506 break;
508 case DRAW_PIXEL:
509 left = last_left;
510 right = last_right;
511 dl = (cur_left - left) / d;
512 dr = (cur_right - right) / d;
514 for (y = last_pos + 1; d > 0; y++, d--)
516 if (y == LCD_HEIGHT)
517 y = 0;
519 left += dl;
520 right += dr;
522 rb->lcd_drawpixel(LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
523 rb->lcd_drawpixel(LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
525 break;
528 last_left = cur_left;
529 last_right = cur_right;
531 if (displaymsg)
533 last_pos -= font_height - 1;
534 rb->lcd_putsxy(0, last_pos, message);
535 displaymsg = false;
537 if (last_pos < 0)
538 last_pos = 0;
541 if (full_update)
543 rb->lcd_update();
545 else
547 #if LCD_DEPTH > 1 /* cursor bar */
548 rb->lcd_set_foreground(CURSOR_COLOR);
549 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
550 rb->lcd_set_foreground(GRAPH_COLOR);
551 #else
552 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
553 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
554 rb->lcd_set_drawmode(DRMODE_SOLID);
555 #endif
557 if (cur_y > last_pos)
559 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2);
561 else
563 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos);
564 rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2);
567 last_pos = cur_y;
570 void cleanup(void *parameter)
572 (void)parameter;
573 #if LCD_DEPTH > 1
574 rb->lcd_set_foreground(LCD_DEFAULT_FG);
575 rb->lcd_set_background(LCD_DEFAULT_BG);
576 #endif
577 /* Turn on backlight timeout (revert to settings) */
578 backlight_use_settings(rb); /* backlight control in lib/helper.c */
581 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
583 int button, vol;
584 int lastbutton = BUTTON_NONE;
585 bool exit = false;
586 bool paused = false;
587 bool tell_speed;
589 (void)parameter;
590 rb = api;
592 xlcd_init(rb);
593 configfile_init(rb);
595 configfile_load(cfg_filename, disk_config,
596 sizeof(disk_config) / sizeof(disk_config[0]),
597 CFGFILE_MINVERSION);
598 rb->memcpy(&osc, &osc_disk, sizeof(osc)); /* copy to running config */
600 #if LCD_DEPTH > 1
601 rb->lcd_set_foreground(GRAPH_COLOR);
602 rb->lcd_set_background(BACKG_COLOR);
603 rb->lcd_set_backdrop(NULL);
604 rb->lcd_clear_display();
605 rb->lcd_update();
606 #endif
608 /* Turn off backlight timeout */
609 backlight_force_on(rb); /* backlight control in lib/helper.c */
611 rb->lcd_getstringsize("A", NULL, &font_height);
613 while (!exit)
615 if (!paused)
617 int left, right;
619 rb->sleep(MAX(last_tick + osc.delay - *rb->current_tick - 1, 0));
621 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
622 left = rb->mas_codec_readreg(0xC);
623 right = rb->mas_codec_readreg(0xD);
624 #elif (CONFIG_CODEC == SWCODEC)
625 rb->pcm_calculate_peaks(&left, &right);
626 #endif
627 if (osc.orientation == OSC_HORIZ)
628 anim_horizontal(left, right);
629 else
630 anim_vertical(left, right);
633 tell_speed = false;
634 button = rb->button_get(paused);
635 switch (button)
637 #ifdef OSCILLOSCOPE_RC_QUIT
638 case OSCILLOSCOPE_RC_QUIT:
639 #endif
640 case OSCILLOSCOPE_QUIT:
641 exit = true;
642 break;
644 case OSCILLOSCOPE_ADVMODE:
645 if (++osc.advance >= MAX_ADV)
646 osc.advance = 0;
647 break;
649 case OSCILLOSCOPE_DRAWMODE:
650 #ifdef OSCILLOSCOPE_DRAWMODE_PRE
651 if (lastbutton != OSCILLOSCOPE_DRAWMODE_PRE)
652 break;
653 #endif
654 if (++osc.draw >= MAX_DRAW)
655 osc.draw = 0;
656 break;
658 case OSCILLOSCOPE_ORIENTATION:
659 #ifdef OSCILLOSCOPE_ORIENTATION_PRE
660 if (lastbutton != OSCILLOSCOPE_ORIENTATION_PRE)
661 break;
662 #endif
663 if (++osc.orientation >= MAX_OSC)
664 osc.orientation = 0;
665 last_pos = 0;
666 last_tick = 0;
667 displaymsg = false;
668 rb->lcd_clear_display();
669 rb->lcd_update();
670 break;
672 case OSCILLOSCOPE_PAUSE:
673 paused = !paused;
674 last_tick = 0;
675 break;
677 case OSCILLOSCOPE_SPEED_UP:
678 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
679 if (osc.delay > 1)
681 osc.delay--;
682 tell_speed = true;
684 break;
686 case OSCILLOSCOPE_SPEED_DOWN:
687 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
688 osc.delay++;
689 tell_speed = true;
690 break;
692 case OSCILLOSCOPE_VOL_UP:
693 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
694 vol = rb->global_settings->volume;
695 if (vol < rb->sound_max(SOUND_VOLUME))
697 vol++;
698 rb->sound_set(SOUND_VOLUME, vol);
699 rb->global_settings->volume = vol;
701 break;
703 case OSCILLOSCOPE_VOL_DOWN:
704 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
705 vol = rb->global_settings->volume;
706 if (vol > rb->sound_min(SOUND_VOLUME))
708 vol--;
709 rb->sound_set(SOUND_VOLUME, vol);
710 rb->global_settings->volume = vol;
712 break;
714 default:
715 if (rb->default_event_handler_ex(button, cleanup, NULL)
716 == SYS_USB_CONNECTED)
717 return PLUGIN_USB_CONNECTED;
718 break;
720 if (button != BUTTON_NONE)
721 lastbutton = button;
723 if (tell_speed)
725 rb->snprintf(message, sizeof(message), "%s%d",
726 (osc.orientation == OSC_VERT) ? "Speed: " : "",
727 100 / osc.delay);
728 displaymsg = true;
731 cleanup(NULL);
732 if (rb->memcmp(&osc, &osc_disk, sizeof(osc))) /* save settings if changed */
734 rb->memcpy(&osc_disk, &osc, sizeof(osc));
735 configfile_save(cfg_filename, disk_config,
736 sizeof(disk_config) / sizeof(disk_config[0]),
737 CFGFILE_VERSION);
739 return PLUGIN_OK;
741 #endif /* HAVE_LCD_BITMAP */