very minor code police. also fix a possible but unlikely missed cpu_boost(false)
[Rockbox.git] / apps / plugins / oscilloscope.c
blob76ff5f5744196d1e195b6606dfc34f94f4ef54b9
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 * 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 ****************************************************************************/
24 #include "plugin.h"
25 #include "helper.h"
27 #ifdef HAVE_LCD_BITMAP
28 #include "xlcd.h"
29 #include "configfile.h"
31 PLUGIN_HEADER
33 /* variable button definitions */
34 #if CONFIG_KEYPAD == RECORDER_PAD
35 #define OSCILLOSCOPE_QUIT BUTTON_OFF
36 #define OSCILLOSCOPE_DRAWMODE BUTTON_F1
37 #define OSCILLOSCOPE_ADVMODE BUTTON_F2
38 #define OSCILLOSCOPE_ORIENTATION BUTTON_F3
39 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
40 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
41 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
42 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
43 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
45 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
46 #define OSCILLOSCOPE_QUIT BUTTON_OFF
47 #define OSCILLOSCOPE_DRAWMODE BUTTON_F1
48 #define OSCILLOSCOPE_ADVMODE BUTTON_F2
49 #define OSCILLOSCOPE_ORIENTATION BUTTON_F3
50 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
51 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
52 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
53 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
54 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
56 #elif CONFIG_KEYPAD == ONDIO_PAD
57 #define OSCILLOSCOPE_QUIT BUTTON_OFF
58 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_MENU
59 #define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_REL)
60 #define OSCILLOSCOPE_ADVMODE (BUTTON_MENU | BUTTON_RIGHT)
61 #define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_LEFT)
62 #define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF)
63 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
64 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
65 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
66 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
68 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
69 #define OSCILLOSCOPE_QUIT BUTTON_OFF
70 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
71 #define OSCILLOSCOPE_ADVMODE BUTTON_MODE
72 #define OSCILLOSCOPE_ORIENTATION BUTTON_REC
73 #define OSCILLOSCOPE_PAUSE BUTTON_ON
74 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
75 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
76 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
77 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
78 #define OSCILLOSCOPE_RC_QUIT BUTTON_RC_STOP
80 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
81 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
82 #define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
83 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY)
84 #define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
85 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
86 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
87 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
88 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
89 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
90 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
92 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
93 #define OSCILLOSCOPE_QUIT BUTTON_POWER
94 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
95 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
96 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
97 #define OSCILLOSCOPE_PAUSE BUTTON_A
98 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
99 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
100 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
101 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
103 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
104 #define OSCILLOSCOPE_QUIT BUTTON_POWER
105 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
106 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
107 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
108 #define OSCILLOSCOPE_PAUSE BUTTON_REC
109 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
110 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
111 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
112 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
114 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
115 #define OSCILLOSCOPE_QUIT BUTTON_POWER
116 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
117 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
118 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
119 #define OSCILLOSCOPE_PAUSE BUTTON_REC
120 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
121 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
122 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
123 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
125 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
126 #define OSCILLOSCOPE_QUIT BUTTON_POWER
127 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
128 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
129 #define OSCILLOSCOPE_ADVMODE BUTTON_REC
130 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
131 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | 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_UP
136 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
138 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
139 #define OSCILLOSCOPE_QUIT BUTTON_POWER
140 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW
141 #define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL)
142 #define OSCILLOSCOPE_ADVMODE BUTTON_FF
143 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW
144 #define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT)
145 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
146 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
147 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
148 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP
149 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN
151 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
152 #define OSCILLOSCOPE_QUIT BUTTON_BACK
153 #define OSCILLOSCOPE_DRAWMODE BUTTON_PREV
154 #define OSCILLOSCOPE_ADVMODE BUTTON_NEXT
155 #define OSCILLOSCOPE_ORIENTATION BUTTON_MENU
156 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
157 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
158 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
159 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
160 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
162 #elif (CONFIG_KEYPAD == MROBE100_PAD)
163 #define OSCILLOSCOPE_QUIT BUTTON_POWER
164 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
165 #define OSCILLOSCOPE_ADVMODE BUTTON_MENU
166 #define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY
167 #define OSCILLOSCOPE_PAUSE BUTTON_DISPLAY
168 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
169 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
170 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
171 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
173 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
174 #define OSCILLOSCOPE_QUIT BUTTON_RC_REC
175 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_RC_MODE
176 #define OSCILLOSCOPE_DRAWMODE (BUTTON_RC_MODE|BUTTON_REL)
177 #define OSCILLOSCOPE_ADVMODE BUTTON_RC_MENU
178 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_RC_MODE
179 #define OSCILLOSCOPE_ORIENTATION (BUTTON_RC_MODE|BUTTON_REPEAT)
180 #define OSCILLOSCOPE_PAUSE BUTTON_RC_PLAY
181 #define OSCILLOSCOPE_SPEED_UP BUTTON_RC_FF
182 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_RC_REW
183 #define OSCILLOSCOPE_VOL_UP BUTTON_RC_VOL_UP
184 #define OSCILLOSCOPE_VOL_DOWN BUTTON_RC_VOL_DOWN
186 #elif CONFIG_KEYPAD == COWOND2_PAD
187 #define OSCILLOSCOPE_QUIT BUTTON_POWER
188 #define OSCILLOSCOPE_VOL_UP BUTTON_PLUS
189 #define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS
191 #else
192 #error No keymap defined!
193 #endif
195 #ifdef HAVE_TOUCHPAD
196 #ifndef OSCILLOSCOPE_QUIT
197 #define OSCILLOSCOPE_QUIT BUTTON_TOPLEFT
198 #endif
199 #ifndef OSCILLOSCOPE_DRAWMODE
200 #define OSCILLOSCOPE_DRAWMODE BUTTON_TOPMIDDLE
201 #endif
202 #ifndef OSCILLOSCOPE_ADVMODE
203 #define OSCILLOSCOPE_ADVMODE BUTTON_BOTTOMMIDDLE
204 #endif
205 #ifndef OSCILLOSCOPE_ORIENTATION
206 #define OSCILLOSCOPE_ORIENTATION BUTTON_BOTTOMLEFT
207 #endif
208 #ifndef OSCILLOSCOPE_PAUSE
209 #define OSCILLOSCOPE_PAUSE BUTTON_CENTER
210 #endif
211 #ifndef OSCILLOSCOPE_SPEED_UP
212 #define OSCILLOSCOPE_SPEED_UP BUTTON_MIDRIGHT
213 #endif
214 #ifndef OSCILLOSCOPE_SPEED_DOWN
215 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_MIDLEFT
216 #endif
217 #ifndef OSCILLOSCOPE_VOL_UP
218 #define OSCILLOSCOPE_VOL_UP BUTTON_TOPRIGHT
219 #endif
220 #ifndef OSCILLOSCOPE_VOL_DOWN
221 #define OSCILLOSCOPE_VOL_DOWN BUTTON_BOTTOMRIGHT
222 #endif
223 #endif
225 /* colours */
226 #if LCD_DEPTH > 1
227 #ifdef HAVE_LCD_COLOR
228 #define BACKG_COLOR LCD_BLACK
229 #define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
230 #define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
231 #else
232 #define BACKG_COLOR LCD_WHITE
233 #define GRAPH_COLOR LCD_BLACK
234 #define CURSOR_COLOR LCD_DARKGRAY
235 #endif
236 #endif
238 enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW };
239 enum { ADV_SCROLL, ADV_WRAP, MAX_ADV };
240 enum { OSC_HORIZ, OSC_VERT, MAX_OSC };
242 #define CFGFILE_VERSION 0 /* Current config file version */
243 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
246 #define MAX_PEAK 0x8000
248 #if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
249 #define mas_codec_readreg(x) rand()%MAX_PEAK
250 #endif
252 /* global variables */
254 const struct plugin_api* rb; /* global api struct pointer */
256 /* settings */
257 struct osc_config {
258 int delay; /* in ticks */
259 int draw;
260 int advance;
261 int orientation;
264 struct osc_config osc_disk = { 2, DRAW_FILLED, ADV_SCROLL, OSC_HORIZ };
265 struct osc_config osc; /* running config */
267 static const char cfg_filename[] = "oscilloscope.cfg";
268 static char *draw_str[3] = { "filled", "line", "pixel" };
269 static char *advance_str[2] = { "scroll", "wrap" };
270 static char *orientation_str[2] = { "horizontal", "vertical" };
272 struct configdata disk_config[] = {
273 { TYPE_INT, 1, 99, &osc_disk.delay, "delay", NULL, NULL },
274 { TYPE_ENUM, 0, MAX_DRAW, &osc_disk.draw, "draw", draw_str, NULL },
275 { TYPE_ENUM, 0, MAX_ADV, &osc_disk.advance, "advance", advance_str, NULL },
276 { TYPE_ENUM, 0, MAX_OSC, &osc_disk.orientation, "orientation", orientation_str, NULL }
280 long last_tick = 0; /* time of last drawing */
281 int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */
282 int last_left; /* last channel values */
283 int last_right;
285 unsigned char message[16]; /* message to display */
286 bool displaymsg = false;
287 int font_height = 8;
289 /* implementation */
291 void anim_horizontal(int cur_left, int cur_right)
293 int cur_x, x;
294 int left, right, dl, dr;
295 long cur_tick = *rb->current_tick;
296 long d = (cur_tick - last_tick) / osc.delay;
297 bool full_update = false;
299 if (d == 0) /* too early, bail out */
300 return;
302 last_tick = cur_tick;
304 if (d > HZ) /* first call or too much delay, (re)start */
306 last_left = cur_left;
307 last_right = cur_right;
308 return;
310 cur_x = last_pos + d;
312 if (cur_x >= LCD_WIDTH)
314 if (osc.advance == ADV_SCROLL)
316 int shift = cur_x - (LCD_WIDTH-1);
317 xlcd_scroll_left(shift);
318 full_update = true;
319 cur_x -= shift;
320 last_pos -= shift;
322 else
324 cur_x -= LCD_WIDTH;
327 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
329 if (cur_x > last_pos)
331 rb->lcd_fillrect(last_pos + 1, 0, d, LCD_HEIGHT);
333 else
335 rb->lcd_fillrect(last_pos + 1, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
336 rb->lcd_fillrect(0, 0, cur_x + 1, LCD_HEIGHT);
338 rb->lcd_set_drawmode(DRMODE_SOLID);
340 switch (osc.draw)
342 case DRAW_FILLED:
343 left = last_left;
344 right = last_right;
345 dl = (cur_left - left) / d;
346 dr = (cur_right - right) / d;
348 for (x = last_pos + 1; d > 0; x++, d--)
350 if (x == LCD_WIDTH)
351 x = 0;
353 left += dl;
354 right += dr;
356 rb->lcd_vline(x, LCD_HEIGHT/2-1,
357 LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
358 rb->lcd_vline(x, LCD_HEIGHT/2+1,
359 LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
361 break;
363 case DRAW_LINE:
364 if (cur_x > last_pos)
366 rb->lcd_drawline(
367 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
368 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
370 rb->lcd_drawline(
371 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
372 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
375 else
377 left = last_left
378 + (LCD_WIDTH - last_pos) * (last_left - cur_left) / d;
379 right = last_right
380 + (LCD_WIDTH - last_pos) * (last_right - cur_right) / d;
382 rb->lcd_drawline(
383 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
384 LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16)
386 rb->lcd_drawline(
387 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
388 LCD_WIDTH, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16)
390 if (cur_x > 0)
392 rb->lcd_drawline(
393 0, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16),
394 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
396 rb->lcd_drawline(
397 0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16),
398 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
402 break;
404 case DRAW_PIXEL:
405 left = last_left;
406 right = last_right;
407 dl = (cur_left - left) / d;
408 dr = (cur_right - right) / d;
410 for (x = last_pos + 1; d > 0; x++, d--)
412 if (x == LCD_WIDTH)
413 x = 0;
415 left += dl;
416 right += dr;
418 rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
419 rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
421 break;
424 last_left = cur_left;
425 last_right = cur_right;
427 if (displaymsg)
429 int width;
431 rb->lcd_getstringsize(message, &width, NULL);
432 last_pos -= width - 1;
433 rb->lcd_putsxy(last_pos, 0, message);
434 displaymsg = false;
436 if (last_pos < 0)
437 last_pos = 0;
440 if (full_update)
442 rb->lcd_update();
444 else
446 #if LCD_DEPTH > 1 /* cursor bar */
447 rb->lcd_set_foreground(CURSOR_COLOR);
448 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
449 rb->lcd_set_foreground(GRAPH_COLOR);
450 #else
451 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
452 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
453 rb->lcd_set_drawmode(DRMODE_SOLID);
454 #endif
456 if (cur_x > last_pos)
458 rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT);
460 else
462 rb->lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
463 rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
466 last_pos = cur_x;
469 void anim_vertical(int cur_left, int cur_right)
471 int cur_y, y;
472 int left, right, dl, dr;
473 long cur_tick = *rb->current_tick;
474 long d = (cur_tick - last_tick) / osc.delay;
475 bool full_update = false;
477 if (d == 0) /* too early, bail out */
478 return;
480 last_tick = cur_tick;
482 if (d > HZ) /* first call or too much delay, (re)start */
484 last_left = cur_left;
485 last_right = cur_right;
486 return;
488 cur_y = last_pos + d;
490 if (cur_y >= LCD_HEIGHT)
492 if (osc.advance == ADV_SCROLL)
494 int shift = cur_y - (LCD_HEIGHT-1);
495 xlcd_scroll_up(shift);
496 full_update = true;
497 cur_y -= shift;
498 last_pos -= shift;
500 else
502 cur_y -= LCD_HEIGHT;
505 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
507 if (cur_y > last_pos)
509 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, d);
511 else
513 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, LCD_HEIGHT - last_pos);
514 rb->lcd_fillrect(0, 0, LCD_WIDTH, cur_y + 1);
516 rb->lcd_set_drawmode(DRMODE_SOLID);
518 switch (osc.draw)
520 case DRAW_FILLED:
521 left = last_left;
522 right = last_right;
523 dl = (cur_left - left) / d;
524 dr = (cur_right - right) / d;
526 for (y = last_pos + 1; d > 0; y++, d--)
528 if (y == LCD_HEIGHT)
529 y = 0;
531 left += dl;
532 right += dr;
534 rb->lcd_hline(LCD_WIDTH/2-1,
535 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
536 rb->lcd_hline(LCD_WIDTH/2+1,
537 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
539 break;
541 case DRAW_LINE:
542 if (cur_y > last_pos)
544 rb->lcd_drawline(
545 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
546 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
548 rb->lcd_drawline(
549 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
550 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
553 else
555 left = last_left
556 + (LCD_HEIGHT - last_pos) * (last_left - cur_left) / d;
557 right = last_right
558 + (LCD_HEIGHT - last_pos) * (last_right - cur_right) / d;
560 rb->lcd_drawline(
561 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
562 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), LCD_HEIGHT
564 rb->lcd_drawline(
565 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
566 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), LCD_HEIGHT
568 if (cur_y > 0)
570 rb->lcd_drawline(
571 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), 0,
572 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
574 rb->lcd_drawline(
575 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), 0,
576 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
580 break;
582 case DRAW_PIXEL:
583 left = last_left;
584 right = last_right;
585 dl = (cur_left - left) / d;
586 dr = (cur_right - right) / d;
588 for (y = last_pos + 1; d > 0; y++, d--)
590 if (y == LCD_HEIGHT)
591 y = 0;
593 left += dl;
594 right += dr;
596 rb->lcd_drawpixel(LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
597 rb->lcd_drawpixel(LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
599 break;
602 last_left = cur_left;
603 last_right = cur_right;
605 if (displaymsg)
607 last_pos -= font_height - 1;
608 rb->lcd_putsxy(0, last_pos, message);
609 displaymsg = false;
611 if (last_pos < 0)
612 last_pos = 0;
615 if (full_update)
617 rb->lcd_update();
619 else
621 #if LCD_DEPTH > 1 /* cursor bar */
622 rb->lcd_set_foreground(CURSOR_COLOR);
623 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
624 rb->lcd_set_foreground(GRAPH_COLOR);
625 #else
626 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
627 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
628 rb->lcd_set_drawmode(DRMODE_SOLID);
629 #endif
631 if (cur_y > last_pos)
633 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2);
635 else
637 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos);
638 rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2);
641 last_pos = cur_y;
644 void cleanup(void *parameter)
646 (void)parameter;
647 #if LCD_DEPTH > 1
648 rb->lcd_set_foreground(LCD_DEFAULT_FG);
649 rb->lcd_set_background(LCD_DEFAULT_BG);
650 #endif
651 /* Turn on backlight timeout (revert to settings) */
652 backlight_use_settings(rb); /* backlight control in lib/helper.c */
655 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
657 int button, vol;
658 int lastbutton = BUTTON_NONE;
659 bool exit = false;
660 bool paused = false;
661 bool tell_speed;
663 (void)parameter;
664 rb = api;
666 xlcd_init(rb);
667 configfile_init(rb);
669 configfile_load(cfg_filename, disk_config,
670 sizeof(disk_config) / sizeof(disk_config[0]),
671 CFGFILE_MINVERSION);
672 rb->memcpy(&osc, &osc_disk, sizeof(osc)); /* copy to running config */
674 #if LCD_DEPTH > 1
675 rb->lcd_set_foreground(GRAPH_COLOR);
676 rb->lcd_set_background(BACKG_COLOR);
677 rb->lcd_set_backdrop(NULL);
678 rb->lcd_clear_display();
679 rb->lcd_update();
680 #endif
682 /* Turn off backlight timeout */
683 backlight_force_on(rb); /* backlight control in lib/helper.c */
685 rb->lcd_getstringsize("A", NULL, &font_height);
687 while (!exit)
689 if (!paused)
691 int left, right;
693 rb->sleep(MAX(last_tick + osc.delay - *rb->current_tick - 1, 0));
695 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
696 left = rb->mas_codec_readreg(0xC);
697 right = rb->mas_codec_readreg(0xD);
698 #elif (CONFIG_CODEC == SWCODEC)
699 rb->pcm_calculate_peaks(&left, &right);
700 #endif
701 if (osc.orientation == OSC_HORIZ)
702 anim_horizontal(left, right);
703 else
704 anim_vertical(left, right);
707 tell_speed = false;
708 button = rb->button_get(paused);
709 switch (button)
711 #ifdef OSCILLOSCOPE_RC_QUIT
712 case OSCILLOSCOPE_RC_QUIT:
713 #endif
714 case OSCILLOSCOPE_QUIT:
715 exit = true;
716 break;
718 case OSCILLOSCOPE_ADVMODE:
719 if (++osc.advance >= MAX_ADV)
720 osc.advance = 0;
721 break;
723 case OSCILLOSCOPE_DRAWMODE:
724 #ifdef OSCILLOSCOPE_DRAWMODE_PRE
725 if (lastbutton != OSCILLOSCOPE_DRAWMODE_PRE)
726 break;
727 #endif
728 if (++osc.draw >= MAX_DRAW)
729 osc.draw = 0;
730 break;
732 case OSCILLOSCOPE_ORIENTATION:
733 #ifdef OSCILLOSCOPE_ORIENTATION_PRE
734 if (lastbutton != OSCILLOSCOPE_ORIENTATION_PRE)
735 break;
736 #endif
737 if (++osc.orientation >= MAX_OSC)
738 osc.orientation = 0;
739 last_pos = 0;
740 last_tick = 0;
741 displaymsg = false;
742 rb->lcd_clear_display();
743 rb->lcd_update();
744 break;
746 case OSCILLOSCOPE_PAUSE:
747 paused = !paused;
748 last_tick = 0;
749 break;
751 case OSCILLOSCOPE_SPEED_UP:
752 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
753 if (osc.delay > 1)
755 osc.delay--;
756 tell_speed = true;
758 break;
760 case OSCILLOSCOPE_SPEED_DOWN:
761 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
762 osc.delay++;
763 tell_speed = true;
764 break;
766 case OSCILLOSCOPE_VOL_UP:
767 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
768 vol = rb->global_settings->volume;
769 if (vol < rb->sound_max(SOUND_VOLUME))
771 vol++;
772 rb->sound_set(SOUND_VOLUME, vol);
773 rb->global_settings->volume = vol;
775 break;
777 case OSCILLOSCOPE_VOL_DOWN:
778 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
779 vol = rb->global_settings->volume;
780 if (vol > rb->sound_min(SOUND_VOLUME))
782 vol--;
783 rb->sound_set(SOUND_VOLUME, vol);
784 rb->global_settings->volume = vol;
786 break;
788 default:
789 if (rb->default_event_handler_ex(button, cleanup, NULL)
790 == SYS_USB_CONNECTED)
791 return PLUGIN_USB_CONNECTED;
792 break;
794 if (button != BUTTON_NONE)
795 lastbutton = button;
797 if (tell_speed)
799 rb->snprintf(message, sizeof(message), "%s%d",
800 (osc.orientation == OSC_VERT) ? "Speed: " : "",
801 100 / osc.delay);
802 displaymsg = true;
805 cleanup(NULL);
806 if (rb->memcmp(&osc, &osc_disk, sizeof(osc))) /* save settings if changed */
808 rb->memcpy(&osc_disk, &osc, sizeof(osc));
809 configfile_save(cfg_filename, disk_config,
810 sizeof(disk_config) / sizeof(disk_config[0]),
811 CFGFILE_VERSION);
813 return PLUGIN_OK;
815 #endif /* HAVE_LCD_BITMAP */