Fix yellow
[Rockbox.git] / apps / plugins / oscilloscope.c
blobe126ff57d0405b25d333246a10c329703a209617
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_FWD
110 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
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 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
150 #define OSCILLOSCOPE_QUIT BUTTON_BACK
151 #define OSCILLOSCOPE_DRAWMODE BUTTON_PREV
152 #define OSCILLOSCOPE_ADVMODE BUTTON_NEXT
153 #define OSCILLOSCOPE_ORIENTATION BUTTON_MENU
154 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
155 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
156 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
157 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
158 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
160 #elif (CONFIG_KEYPAD == MROBE100_PAD)
161 #define OSCILLOSCOPE_QUIT BUTTON_POWER
162 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
163 #define OSCILLOSCOPE_ADVMODE BUTTON_MENU
164 #define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY
165 #define OSCILLOSCOPE_PAUSE BUTTON_DISPLAY
166 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
167 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
168 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
169 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
171 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
172 #define OSCILLOSCOPE_QUIT BUTTON_RC_REC
173 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_RC_MODE
174 #define OSCILLOSCOPE_DRAWMODE (BUTTON_RC_MODE|BUTTON_REL)
175 #define OSCILLOSCOPE_ADVMODE BUTTON_RC_MENU
176 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_RC_MODE
177 #define OSCILLOSCOPE_ORIENTATION (BUTTON_RC_MODE|BUTTON_REPEAT)
178 #define OSCILLOSCOPE_PAUSE BUTTON_RC_PLAY
179 #define OSCILLOSCOPE_SPEED_UP BUTTON_RC_FF
180 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_RC_REW
181 #define OSCILLOSCOPE_VOL_UP BUTTON_RC_VOL_UP
182 #define OSCILLOSCOPE_VOL_DOWN BUTTON_RC_VOL_DOWN
184 #elif CONFIG_KEYPAD == COWOND2_PAD
185 #define OSCILLOSCOPE_QUIT BUTTON_POWER
186 #define OSCILLOSCOPE_VOL_UP BUTTON_PLUS
187 #define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS
189 #else
190 #error No keymap defined!
191 #endif
193 #ifdef HAVE_TOUCHPAD
194 #ifndef OSCILLOSCOPE_QUIT
195 #define OSCILLOSCOPE_QUIT BUTTON_TOPLEFT
196 #endif
197 #ifndef OSCILLOSCOPE_DRAWMODE
198 #define OSCILLOSCOPE_DRAWMODE BUTTON_TOPMIDDLE
199 #endif
200 #ifndef OSCILLOSCOPE_ADVMODE
201 #define OSCILLOSCOPE_ADVMODE BUTTON_BOTTOMMIDDLE
202 #endif
203 #ifndef OSCILLOSCOPE_ORIENTATION
204 #define OSCILLOSCOPE_ORIENTATION BUTTON_BOTTOMLEFT
205 #endif
206 #ifndef OSCILLOSCOPE_PAUSE
207 #define OSCILLOSCOPE_PAUSE BUTTON_CENTER
208 #endif
209 #ifndef OSCILLOSCOPE_SPEED_UP
210 #define OSCILLOSCOPE_SPEED_UP BUTTON_MIDRIGHT
211 #endif
212 #ifndef OSCILLOSCOPE_SPEED_DOWN
213 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_MIDLEFT
214 #endif
215 #ifndef OSCILLOSCOPE_VOL_UP
216 #define OSCILLOSCOPE_VOL_UP BUTTON_TOPRIGHT
217 #endif
218 #ifndef OSCILLOSCOPE_VOL_DOWN
219 #define OSCILLOSCOPE_VOL_DOWN BUTTON_BOTTOMRIGHT
220 #endif
221 #endif
223 /* colours */
224 #if LCD_DEPTH > 1
225 #ifdef HAVE_LCD_COLOR
226 #define BACKG_COLOR LCD_BLACK
227 #define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
228 #define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
229 #else
230 #define BACKG_COLOR LCD_WHITE
231 #define GRAPH_COLOR LCD_BLACK
232 #define CURSOR_COLOR LCD_DARKGRAY
233 #endif
234 #endif
236 enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW };
237 enum { ADV_SCROLL, ADV_WRAP, MAX_ADV };
238 enum { OSC_HORIZ, OSC_VERT, MAX_OSC };
240 #define CFGFILE_VERSION 0 /* Current config file version */
241 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
244 #define MAX_PEAK 0x8000
246 #if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
247 #define mas_codec_readreg(x) rand()%MAX_PEAK
248 #endif
250 /* global variables */
252 const struct plugin_api* rb; /* global api struct pointer */
254 /* settings */
255 struct osc_config {
256 int delay; /* in ticks */
257 int draw;
258 int advance;
259 int orientation;
262 struct osc_config osc_disk = { 2, DRAW_FILLED, ADV_SCROLL, OSC_HORIZ };
263 struct osc_config osc; /* running config */
265 static const char cfg_filename[] = "oscilloscope.cfg";
266 static char *draw_str[3] = { "filled", "line", "pixel" };
267 static char *advance_str[2] = { "scroll", "wrap" };
268 static char *orientation_str[2] = { "horizontal", "vertical" };
270 struct configdata disk_config[] = {
271 { TYPE_INT, 1, 99, &osc_disk.delay, "delay", NULL, NULL },
272 { TYPE_ENUM, 0, MAX_DRAW, &osc_disk.draw, "draw", draw_str, NULL },
273 { TYPE_ENUM, 0, MAX_ADV, &osc_disk.advance, "advance", advance_str, NULL },
274 { TYPE_ENUM, 0, MAX_OSC, &osc_disk.orientation, "orientation", orientation_str, NULL }
278 long last_tick = 0; /* time of last drawing */
279 int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */
280 int last_left; /* last channel values */
281 int last_right;
283 unsigned char message[16]; /* message to display */
284 bool displaymsg = false;
285 int font_height = 8;
287 /* implementation */
289 void anim_horizontal(int cur_left, int cur_right)
291 int cur_x, x;
292 int left, right, dl, dr;
293 long cur_tick = *rb->current_tick;
294 long d = (cur_tick - last_tick) / osc.delay;
295 bool full_update = false;
297 if (d == 0) /* too early, bail out */
298 return;
300 last_tick = cur_tick;
302 if (d > HZ) /* first call or too much delay, (re)start */
304 last_left = cur_left;
305 last_right = cur_right;
306 return;
308 cur_x = last_pos + d;
310 if (cur_x >= LCD_WIDTH)
312 if (osc.advance == ADV_SCROLL)
314 int shift = cur_x - (LCD_WIDTH-1);
315 xlcd_scroll_left(shift);
316 full_update = true;
317 cur_x -= shift;
318 last_pos -= shift;
320 else
322 cur_x -= LCD_WIDTH;
325 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
327 if (cur_x > last_pos)
329 rb->lcd_fillrect(last_pos + 1, 0, d, LCD_HEIGHT);
331 else
333 rb->lcd_fillrect(last_pos + 1, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
334 rb->lcd_fillrect(0, 0, cur_x + 1, LCD_HEIGHT);
336 rb->lcd_set_drawmode(DRMODE_SOLID);
338 switch (osc.draw)
340 case DRAW_FILLED:
341 left = last_left;
342 right = last_right;
343 dl = (cur_left - left) / d;
344 dr = (cur_right - right) / d;
346 for (x = last_pos + 1; d > 0; x++, d--)
348 if (x == LCD_WIDTH)
349 x = 0;
351 left += dl;
352 right += dr;
354 rb->lcd_vline(x, LCD_HEIGHT/2-1,
355 LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
356 rb->lcd_vline(x, LCD_HEIGHT/2+1,
357 LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
359 break;
361 case DRAW_LINE:
362 if (cur_x > last_pos)
364 rb->lcd_drawline(
365 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
366 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
368 rb->lcd_drawline(
369 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
370 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
373 else
375 left = last_left
376 + (LCD_WIDTH - last_pos) * (last_left - cur_left) / d;
377 right = last_right
378 + (LCD_WIDTH - last_pos) * (last_right - cur_right) / d;
380 rb->lcd_drawline(
381 last_pos, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_left) >> 16),
382 LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16)
384 rb->lcd_drawline(
385 last_pos, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_right) >> 16),
386 LCD_WIDTH, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16)
388 if (cur_x > 0)
390 rb->lcd_drawline(
391 0, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16),
392 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_left) >> 16)
394 rb->lcd_drawline(
395 0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16),
396 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_right) >> 16)
400 break;
402 case DRAW_PIXEL:
403 left = last_left;
404 right = last_right;
405 dl = (cur_left - left) / d;
406 dr = (cur_right - right) / d;
408 for (x = last_pos + 1; d > 0; x++, d--)
410 if (x == LCD_WIDTH)
411 x = 0;
413 left += dl;
414 right += dr;
416 rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * left) >> 16));
417 rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * right) >> 16));
419 break;
422 last_left = cur_left;
423 last_right = cur_right;
425 if (displaymsg)
427 int width;
429 rb->lcd_getstringsize(message, &width, NULL);
430 last_pos -= width - 1;
431 rb->lcd_putsxy(last_pos, 0, message);
432 displaymsg = false;
434 if (last_pos < 0)
435 last_pos = 0;
438 if (full_update)
440 rb->lcd_update();
442 else
444 #if LCD_DEPTH > 1 /* cursor bar */
445 rb->lcd_set_foreground(CURSOR_COLOR);
446 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
447 rb->lcd_set_foreground(GRAPH_COLOR);
448 #else
449 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
450 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
451 rb->lcd_set_drawmode(DRMODE_SOLID);
452 #endif
454 if (cur_x > last_pos)
456 rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT);
458 else
460 rb->lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
461 rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
464 last_pos = cur_x;
467 void anim_vertical(int cur_left, int cur_right)
469 int cur_y, y;
470 int left, right, dl, dr;
471 long cur_tick = *rb->current_tick;
472 long d = (cur_tick - last_tick) / osc.delay;
473 bool full_update = false;
475 if (d == 0) /* too early, bail out */
476 return;
478 last_tick = cur_tick;
480 if (d > HZ) /* first call or too much delay, (re)start */
482 last_left = cur_left;
483 last_right = cur_right;
484 return;
486 cur_y = last_pos + d;
488 if (cur_y >= LCD_HEIGHT)
490 if (osc.advance == ADV_SCROLL)
492 int shift = cur_y - (LCD_HEIGHT-1);
493 xlcd_scroll_up(shift);
494 full_update = true;
495 cur_y -= shift;
496 last_pos -= shift;
498 else
500 cur_y -= LCD_HEIGHT;
503 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
505 if (cur_y > last_pos)
507 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, d);
509 else
511 rb->lcd_fillrect(0, last_pos + 1, LCD_WIDTH, LCD_HEIGHT - last_pos);
512 rb->lcd_fillrect(0, 0, LCD_WIDTH, cur_y + 1);
514 rb->lcd_set_drawmode(DRMODE_SOLID);
516 switch (osc.draw)
518 case DRAW_FILLED:
519 left = last_left;
520 right = last_right;
521 dl = (cur_left - left) / d;
522 dr = (cur_right - right) / d;
524 for (y = last_pos + 1; d > 0; y++, d--)
526 if (y == LCD_HEIGHT)
527 y = 0;
529 left += dl;
530 right += dr;
532 rb->lcd_hline(LCD_WIDTH/2-1,
533 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
534 rb->lcd_hline(LCD_WIDTH/2+1,
535 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
537 break;
539 case DRAW_LINE:
540 if (cur_y > last_pos)
542 rb->lcd_drawline(
543 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
544 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
546 rb->lcd_drawline(
547 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
548 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
551 else
553 left = last_left
554 + (LCD_HEIGHT - last_pos) * (last_left - cur_left) / d;
555 right = last_right
556 + (LCD_HEIGHT - last_pos) * (last_right - cur_right) / d;
558 rb->lcd_drawline(
559 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * last_left) >> 16), last_pos,
560 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), LCD_HEIGHT
562 rb->lcd_drawline(
563 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * last_right) >> 16), last_pos,
564 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), LCD_HEIGHT
566 if (cur_y > 0)
568 rb->lcd_drawline(
569 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), 0,
570 LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * cur_left) >> 16), cur_y
572 rb->lcd_drawline(
573 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), 0,
574 LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * cur_right) >> 16), cur_y
578 break;
580 case DRAW_PIXEL:
581 left = last_left;
582 right = last_right;
583 dl = (cur_left - left) / d;
584 dr = (cur_right - right) / d;
586 for (y = last_pos + 1; d > 0; y++, d--)
588 if (y == LCD_HEIGHT)
589 y = 0;
591 left += dl;
592 right += dr;
594 rb->lcd_drawpixel(LCD_WIDTH/2-1 - (((LCD_WIDTH-2) * left) >> 16), y);
595 rb->lcd_drawpixel(LCD_WIDTH/2+1 + (((LCD_WIDTH-2) * right) >> 16), y);
597 break;
600 last_left = cur_left;
601 last_right = cur_right;
603 if (displaymsg)
605 last_pos -= font_height - 1;
606 rb->lcd_putsxy(0, last_pos, message);
607 displaymsg = false;
609 if (last_pos < 0)
610 last_pos = 0;
613 if (full_update)
615 rb->lcd_update();
617 else
619 #if LCD_DEPTH > 1 /* cursor bar */
620 rb->lcd_set_foreground(CURSOR_COLOR);
621 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
622 rb->lcd_set_foreground(GRAPH_COLOR);
623 #else
624 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
625 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1);
626 rb->lcd_set_drawmode(DRMODE_SOLID);
627 #endif
629 if (cur_y > last_pos)
631 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2);
633 else
635 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos);
636 rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2);
639 last_pos = cur_y;
642 void cleanup(void *parameter)
644 (void)parameter;
645 #if LCD_DEPTH > 1
646 rb->lcd_set_foreground(LCD_DEFAULT_FG);
647 rb->lcd_set_background(LCD_DEFAULT_BG);
648 #endif
649 /* Turn on backlight timeout (revert to settings) */
650 backlight_use_settings(rb); /* backlight control in lib/helper.c */
653 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
655 int button, vol;
656 int lastbutton = BUTTON_NONE;
657 bool exit = false;
658 bool paused = false;
659 bool tell_speed;
661 (void)parameter;
662 rb = api;
664 xlcd_init(rb);
665 configfile_init(rb);
667 configfile_load(cfg_filename, disk_config,
668 sizeof(disk_config) / sizeof(disk_config[0]),
669 CFGFILE_MINVERSION);
670 rb->memcpy(&osc, &osc_disk, sizeof(osc)); /* copy to running config */
672 #if LCD_DEPTH > 1
673 rb->lcd_set_foreground(GRAPH_COLOR);
674 rb->lcd_set_background(BACKG_COLOR);
675 rb->lcd_set_backdrop(NULL);
676 rb->lcd_clear_display();
677 rb->lcd_update();
678 #endif
680 /* Turn off backlight timeout */
681 backlight_force_on(rb); /* backlight control in lib/helper.c */
683 rb->lcd_getstringsize("A", NULL, &font_height);
685 while (!exit)
687 if (!paused)
689 int left, right;
691 rb->sleep(MAX(last_tick + osc.delay - *rb->current_tick - 1, 0));
693 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
694 left = rb->mas_codec_readreg(0xC);
695 right = rb->mas_codec_readreg(0xD);
696 #elif (CONFIG_CODEC == SWCODEC)
697 rb->pcm_calculate_peaks(&left, &right);
698 #endif
699 if (osc.orientation == OSC_HORIZ)
700 anim_horizontal(left, right);
701 else
702 anim_vertical(left, right);
705 tell_speed = false;
706 button = rb->button_get(paused);
707 switch (button)
709 #ifdef OSCILLOSCOPE_RC_QUIT
710 case OSCILLOSCOPE_RC_QUIT:
711 #endif
712 case OSCILLOSCOPE_QUIT:
713 exit = true;
714 break;
716 case OSCILLOSCOPE_ADVMODE:
717 if (++osc.advance >= MAX_ADV)
718 osc.advance = 0;
719 break;
721 case OSCILLOSCOPE_DRAWMODE:
722 #ifdef OSCILLOSCOPE_DRAWMODE_PRE
723 if (lastbutton != OSCILLOSCOPE_DRAWMODE_PRE)
724 break;
725 #endif
726 if (++osc.draw >= MAX_DRAW)
727 osc.draw = 0;
728 break;
730 case OSCILLOSCOPE_ORIENTATION:
731 #ifdef OSCILLOSCOPE_ORIENTATION_PRE
732 if (lastbutton != OSCILLOSCOPE_ORIENTATION_PRE)
733 break;
734 #endif
735 if (++osc.orientation >= MAX_OSC)
736 osc.orientation = 0;
737 last_pos = 0;
738 last_tick = 0;
739 displaymsg = false;
740 rb->lcd_clear_display();
741 rb->lcd_update();
742 break;
744 case OSCILLOSCOPE_PAUSE:
745 paused = !paused;
746 last_tick = 0;
747 break;
749 case OSCILLOSCOPE_SPEED_UP:
750 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
751 if (osc.delay > 1)
753 osc.delay--;
754 tell_speed = true;
756 break;
758 case OSCILLOSCOPE_SPEED_DOWN:
759 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
760 osc.delay++;
761 tell_speed = true;
762 break;
764 case OSCILLOSCOPE_VOL_UP:
765 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
766 vol = rb->global_settings->volume;
767 if (vol < rb->sound_max(SOUND_VOLUME))
769 vol++;
770 rb->sound_set(SOUND_VOLUME, vol);
771 rb->global_settings->volume = vol;
773 break;
775 case OSCILLOSCOPE_VOL_DOWN:
776 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
777 vol = rb->global_settings->volume;
778 if (vol > rb->sound_min(SOUND_VOLUME))
780 vol--;
781 rb->sound_set(SOUND_VOLUME, vol);
782 rb->global_settings->volume = vol;
784 break;
786 default:
787 if (rb->default_event_handler_ex(button, cleanup, NULL)
788 == SYS_USB_CONNECTED)
789 return PLUGIN_USB_CONNECTED;
790 break;
792 if (button != BUTTON_NONE)
793 lastbutton = button;
795 if (tell_speed)
797 rb->snprintf(message, sizeof(message), "%s%d",
798 (osc.orientation == OSC_VERT) ? "Speed: " : "",
799 100 / osc.delay);
800 displaymsg = true;
803 cleanup(NULL);
804 if (rb->memcmp(&osc, &osc_disk, sizeof(osc))) /* save settings if changed */
806 rb->memcpy(&osc_disk, &osc, sizeof(osc));
807 configfile_save(cfg_filename, disk_config,
808 sizeof(disk_config) / sizeof(disk_config[0]),
809 CFGFILE_VERSION);
811 return PLUGIN_OK;
813 #endif /* HAVE_LCD_BITMAP */