summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/lib/SOURCES1
-rw-r--r--apps/plugins/lib/osd.c470
-rw-r--r--apps/plugins/lib/osd.h94
-rw-r--r--apps/plugins/oscilloscope.c1910
4 files changed, 2041 insertions, 434 deletions
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES
index 4b33901088..d49605f1ad 100644
--- a/apps/plugins/lib/SOURCES
+++ b/apps/plugins/lib/SOURCES
@@ -52,6 +52,7 @@ pluginlib_jpeg_load.c
52#endif 52#endif
53 53
54checkbox.c 54checkbox.c
55osd.c
55picture.c 56picture.c
56xlcd_core.c 57xlcd_core.c
57xlcd_draw.c 58xlcd_draw.c
diff --git a/apps/plugins/lib/osd.c b/apps/plugins/lib/osd.c
new file mode 100644
index 0000000000..ff0533a898
--- /dev/null
+++ b/apps/plugins/lib/osd.c
@@ -0,0 +1,470 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Floating on-screen display
11*
12* Copyright (C) 2012 Michael Sevakis
13*
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.
18*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22****************************************************************************/
23#include "plugin.h"
24#include "osd.h"
25
26#if 1
27#undef DEBUGF
28#define DEBUGF(...)
29#endif
30
31/* At this time: assumes use of the default viewport for normal drawing */
32
33/* If multiple OSD's are wanted, could convert to caller-allocated */
34static struct osd
35{
36 enum osd_status
37 {
38 OSD_DISABLED = 0, /* Disabled entirely */
39 OSD_HIDDEN, /* Hidden from view */
40 OSD_VISIBLE, /* Visible on screen */
41 OSD_ERASED, /* Erased in preparation for regular drawing */
42 } status; /* View status */
43 struct viewport vp; /* Clipping viewport */
44 struct bitmap lcd_bitmap; /* The main LCD fb bitmap */
45 struct bitmap back_bitmap; /* The OSD backbuffer fb bitmap */
46 int maxwidth; /* How wide may it be at most? */
47 int maxheight; /* How high may it be at most? */
48 long timeout; /* Current popup stay duration */
49 long hide_tick; /* Tick when it should be hidden */
50 osd_draw_cb_fn_t draw_cb; /* Draw update callback */
51} osd;
52
53/* Framebuffer allocation macros */
54#if LCD_DEPTH == 1
55# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
56# define LCD_WIDTH2BYTES(w) (((w)+7)/8)
57# define LCD_BYTES2WIDTH(b) ((b)*8)
58# elif LCD_PIXELFORMAT == VERTICAL_PACKING
59# define LCD_HEIGHT2BYTES(h) (((h)+7)/8)
60# define LCD_BYTES2HEIGHT(b) ((b)*8)
61# else
62# error Unknown 1-bit format; please define macros
63# endif /* LCD_PIXELFORMAT */
64#elif LCD_DEPTH == 2
65# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
66# define LCD_WIDTH2BYTES(w) (((w)+3)/4)
67# define LCD_BYTES2WIDTH(b) ((b)*4)
68# elif LCD_PIXELFORMAT == VERTICAL_PACKING
69# define LCD_HEIGHT2BYTES(h) (((h)+3)/4)
70# define LCD_BYTES2HEIGHT(b) ((b)*4)
71# elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
72# define LCD_WIDTH2BYTES(w) ((w)*2)
73# define LCD_BYTES2WIDTH(b) ((b)/2)
74# define LCD_HEIGHT2BYTES(h) (((h)+7)/8*2)
75# define LCD_BYTES2HEIGHT(b) ((b)/2*8)
76# else
77# error Unknown 2-bit format; please define macros
78# endif /* LCD_PIXELFORMAT */
79#elif LCD_DEPTH == 16
80# define LCD_WIDTH2BYTES(w) ((w)*2)
81# define LCD_BYTES2WIDTH(b) ((b)/2)
82#else
83# error Unknown LCD depth; please define macros
84#endif /* LCD_DEPTH */
85/* Set defaults if not defined different yet. */
86#ifndef LCD_WIDTH2BYTES
87# define LCD_WIDTH2BYTES(w) (w)
88#endif
89#ifndef LCD_BYTES2WIDTH
90# define LCD_BYTES2WIDTH(b) (b)
91#endif
92#ifndef LCD_HEIGHT2BYTES
93# define LCD_HEIGHT2BYTES(h) (h)
94#endif
95#ifndef LCD_BYTES2HEIGHT
96# define LCD_BYTES2HEIGHT(b) (b)
97#endif
98
99/* Create a bitmap framebuffer from a buffer */
100static fb_data * buf_to_fb_bitmap(void *buf, size_t bufsize,
101 int *width, int *height)
102{
103 /* Used as dest, the LCD functions cannot deal with alternate
104 strides as of now - the stride guides the calulations. If
105 that is no longer the case, then width or height can be
106 used instead (and less memory needed for a small surface!).
107 */
108 DEBUGF("buf: %p bufsize: %lu\n", buf, (unsigned long)bufsize);
109
110#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
111 int h = LCD_BYTES2HEIGHT(LCD_HEIGHT2BYTES(LCD_HEIGHT));
112 int w = bufsize / LCD_HEIGHT2BYTES(h);
113
114 if (w == 0)
115 {
116 DEBUGF("OSD: not enough buffer\n");
117 return NULL; /* not enough buffer */
118 }
119#else
120 int w = LCD_BYTES2WIDTH(LCD_WIDTH2BYTES(LCD_WIDTH));
121 int h = bufsize / LCD_WIDTH2BYTES(w);
122
123 if (h == 0)
124 {
125 DEBUGF("OSD: not enough buffer\n");
126 return NULL; /* not enough buffer */
127 }
128#endif
129
130 DEBUGF("fbw:%d fbh:%d\n", w, h);
131
132 *width = w;
133 *height = h;
134
135 return (fb_data *)buf;
136}
137
138static inline void osd_set_vp_pos(int x, int y, int width, int height)
139{
140 osd.vp.x = x;
141 osd.vp.y = y;
142 osd.vp.width = width;
143 osd.vp.height = height;
144}
145
146/* Sync the backbuffer to the on-screen image */
147static void osd_lcd_update_back_buffer(void)
148{
149 rb->lcd_set_framebuffer((fb_data *)osd.back_bitmap.data);
150 rb->lcd_bmp_part(&osd.lcd_bitmap, osd.vp.x, osd.vp.y,
151 0, 0, osd.vp.width, osd.vp.height);
152 /* Assume it was on default framebuffer for now */
153 rb->lcd_set_framebuffer(NULL);
154}
155
156/* Erase the OSD to restore the framebuffer */
157static void osd_lcd_erase(void)
158{
159 rb->lcd_bmp_part(&osd.back_bitmap, 0, 0, osd.vp.x, osd.vp.y,
160 osd.vp.width, osd.vp.height);
161}
162
163/* Draw the OSD image portion using the callback */
164static void osd_lcd_draw_rect(int x, int y, int width, int height)
165{
166 rb->lcd_set_viewport(&osd.vp);
167 osd.draw_cb(x, y, width, height);
168 rb->lcd_set_viewport(NULL);
169}
170
171/* Draw the OSD image using the callback */
172static void osd_lcd_draw(void)
173{
174 osd_lcd_draw_rect(0, 0, osd.vp.width, osd.vp.height);
175}
176
177
178/** Public APIs **/
179
180/* Initialized the OSD and set its backbuffer */
181bool osd_init(void *backbuf, size_t backbuf_size,
182 osd_draw_cb_fn_t draw_cb)
183{
184 osd_show(OSD_HIDE);
185
186 osd.status = OSD_DISABLED; /* Disabled unless all is okay */
187 osd_set_vp_pos(0, 0, 0, 0);
188 osd.maxwidth = osd.maxheight = 0;
189 osd.timeout = 0;
190
191 if (!draw_cb)
192 return false;
193
194 if (!backbuf)
195 return false;
196
197 ALIGN_BUFFER(backbuf, backbuf_size, FB_DATA_SZ);
198
199 if (!backbuf_size)
200 return false;
201
202 rb->viewport_set_fullscreen(&osd.vp, SCREEN_MAIN);
203
204 fb_data *backfb = buf_to_fb_bitmap(backbuf, backbuf_size,
205 &osd.maxwidth, &osd.maxheight);
206
207 if (!backfb)
208 return false;
209
210 osd.draw_cb = draw_cb;
211
212 /* LCD framebuffer bitmap */
213 osd.lcd_bitmap.width = LCD_BYTES2WIDTH(LCD_WIDTH2BYTES(LCD_WIDTH));
214 osd.lcd_bitmap.height = LCD_BYTES2HEIGHT(LCD_HEIGHT2BYTES(LCD_HEIGHT));
215#if LCD_DEPTH > 1
216 osd.lcd_bitmap.format = FORMAT_NATIVE;
217 osd.lcd_bitmap.maskdata = NULL;
218#endif
219#ifdef HAVE_LCD_COLOR
220 osd.lcd_bitmap.alpha_offset = 0;
221#endif
222 osd.lcd_bitmap.data = (void *)rb->lcd_framebuffer;
223
224 /* Backbuffer bitmap */
225 osd.back_bitmap.width = osd.maxwidth;
226 osd.back_bitmap.height = osd.maxheight;
227#if LCD_DEPTH > 1
228 osd.back_bitmap.format = FORMAT_NATIVE;
229 osd.back_bitmap.maskdata = NULL;
230#endif
231#ifdef HAVE_LCD_COLOR
232 osd.back_bitmap.alpha_offset = 0;
233#endif
234 osd.back_bitmap.data = (void *)backfb;
235
236 DEBUGF("FB:%p BB:%p\n", osd.lcd_bitmap.data, osd.back_bitmap.data);
237
238 /* Set the default position to the whole thing */
239 osd_set_vp_pos(0, 0, osd.maxwidth, osd.maxheight);
240
241 osd.status = OSD_HIDDEN; /* Ready when you are */
242 return true;
243}
244
245/* Show/Hide the OSD on screen */
246bool osd_show(unsigned flags)
247{
248 if (flags & OSD_SHOW)
249 {
250 switch (osd.status)
251 {
252 case OSD_DISABLED:
253 break; /* No change */
254
255 case OSD_HIDDEN:
256 osd_lcd_update_back_buffer();
257 osd.status = OSD_VISIBLE;
258 osd_update();
259 osd.hide_tick = *rb->current_tick + osd.timeout;
260 break;
261
262 case OSD_VISIBLE:
263 if (flags & OSD_UPDATENOW)
264 osd_update();
265 /* Fall-through */
266 case OSD_ERASED:
267 osd.hide_tick = *rb->current_tick + osd.timeout;
268 return true;
269 }
270 }
271 else
272 {
273 switch (osd.status)
274 {
275 case OSD_DISABLED:
276 case OSD_HIDDEN:
277 break;
278
279 case OSD_VISIBLE:
280 osd_lcd_erase();
281 rb->lcd_update_rect(osd.vp.x, osd.vp.y, osd.vp.width,
282 osd.vp.height);
283 /* Fall-through */
284 case OSD_ERASED:
285 osd.status = OSD_HIDDEN;
286 return true;
287 }
288 }
289
290 return false;
291}
292
293/* Redraw the entire OSD */
294bool osd_update(void)
295{
296 if (osd.status != OSD_VISIBLE)
297 return false;
298
299 osd_lcd_draw();
300
301 rb->lcd_update_rect(osd.vp.x, osd.vp.y, osd.vp.width,
302 osd.vp.height);
303
304 return true;
305}
306
307/* Redraw part of the OSD (viewport-relative coordinates) */
308bool osd_update_rect(int x, int y, int width, int height)
309{
310 if (osd.status != OSD_VISIBLE)
311 return false;
312
313 osd_lcd_draw_rect(x, y, width, height);
314
315 if (x + width > osd.vp.width)
316 width = osd.vp.width - x;
317
318 if (x < 0)
319 {
320 width += x;
321 x = 0;
322 }
323
324 if (width <= 0)
325 return false;
326
327 if (y + height > osd.vp.height)
328 height = osd.vp.height - y;
329
330 if (y < 0)
331 {
332 height += y;
333 y = 0;
334 }
335
336 if (height <= 0)
337 return false;
338
339 rb->lcd_update_rect(osd.vp.x + x, osd.vp.y + y, width, height);
340
341 return true;
342}
343
344/* Set a new screen location and size (screen coordinates) */
345bool osd_update_pos(int x, int y, int width, int height)
346{
347 if (osd.status == OSD_DISABLED)
348 return false;
349
350 if (width < 0)
351 width = 0;
352 else if (width > osd.maxwidth)
353 width = osd.maxwidth;
354
355 if (height < 0)
356 height = 0;
357 else if (height > osd.maxheight)
358 height = osd.maxheight;
359
360 if (x == osd.vp.x && y == osd.vp.y &&
361 width == osd.vp.width && height == osd.vp.height)
362 return false; /* No change */
363
364 if (osd.status != OSD_VISIBLE)
365 {
366 /* Not visible - just update pos */
367 osd_set_vp_pos(x, y, width, height);
368 return false;
369 }
370
371 /* Visible area has changed */
372 osd_lcd_erase();
373
374 /* Update the smallest rectangle that encloses both the old and new
375 regions to make the change free of flicker (they may overlap) */
376 int xu = MIN(osd.vp.x, x);
377 int yu = MIN(osd.vp.y, y);
378 int wu = MAX(osd.vp.x + osd.vp.width, x + width) - xu;
379 int hu = MAX(osd.vp.y + osd.vp.height, y + height) - yu;
380
381 osd_set_vp_pos(x, y, width, height);
382 osd_lcd_update_back_buffer();
383 osd_lcd_draw();
384
385 rb->lcd_update_rect(xu, yu, wu, hu);
386 return true;
387}
388
389/* Call periodically to have the OSD timeout and hide itself */
390void osd_monitor_timeout(void)
391{
392 if (osd.status <= OSD_HIDDEN)
393 return; /* Already hidden/disabled */
394
395 if (osd.timeout > 0 && TIME_AFTER(*rb->current_tick, osd.hide_tick))
396 osd_show(OSD_HIDE);
397}
398
399/* Set the OSD timeout value. <= 0 = never timeout */
400void osd_set_timeout(long timeout)
401{
402 if (osd.status == OSD_DISABLED)
403 return;
404
405 osd.timeout = timeout;
406 osd_monitor_timeout();
407}
408
409/* Use the OSD viewport context */
410struct viewport * osd_get_viewport(void)
411{
412 return &osd.vp;
413}
414
415/* Get the maximum dimensions calculated by osd_init() */
416void osd_get_max_dims(int *maxwidth, int *maxheight)
417{
418 if (maxwidth)
419 *maxwidth = osd.maxwidth;
420
421 if (maxheight)
422 *maxheight = osd.maxheight;
423}
424
425/* Is the OSD enabled? */
426bool osd_enabled(void)
427{
428 return osd.status != OSD_DISABLED;
429}
430
431
432/** LCD update substitutes **/
433
434/* Prepare LCD framebuffer for regular drawing */
435void osd_lcd_update_prepare(void)
436{
437 if (osd.status == OSD_VISIBLE)
438 {
439 osd.status = OSD_ERASED;
440 osd_lcd_erase();
441 }
442}
443
444/* Update the whole screen */
445void osd_lcd_update(void)
446{
447 if (osd.status == OSD_ERASED)
448 {
449 /* Save the screen image underneath and restore the OSD image */
450 osd.status = OSD_VISIBLE;
451 osd_lcd_update_back_buffer();
452 osd_lcd_draw();
453 }
454
455 rb->lcd_update();
456}
457
458/* Update a part of the screen */
459void osd_lcd_update_rect(int x, int y, int width, int height)
460{
461 if (osd.status == OSD_ERASED)
462 {
463 /* Save the screen image underneath and restore the OSD image */
464 osd.status = OSD_VISIBLE;
465 osd_lcd_update_back_buffer();
466 osd_lcd_draw();
467 }
468
469 rb->lcd_update_rect(x, y, width, height);
470}
diff --git a/apps/plugins/lib/osd.h b/apps/plugins/lib/osd.h
new file mode 100644
index 0000000000..89441ae273
--- /dev/null
+++ b/apps/plugins/lib/osd.h
@@ -0,0 +1,94 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Floating on-screen display
11*
12* Copyright (C) 2012 Michael Sevakis
13*
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.
18*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22****************************************************************************/
23#ifndef OSD_H
24#define OSD_H
25
26/* At this time: assumes use of the default viewport for normal drawing */
27
28/* Callback implemented by user. Paramters are OSD vp-relative coordinates */
29typedef void (* osd_draw_cb_fn_t)(int x, int y, int width, int height);
30
31/* Initialize the OSD, set its backbuffer, update callback and enable it if
32 * the call succeeded. */
33bool osd_init(void *backbuf, size_t backbuf_size,
34 osd_draw_cb_fn_t draw_cb);
35
36enum
37{
38 OSD_HIDE = 0x0, /* Hide from view */
39 OSD_SHOW = 0x1, /* Bring into view, updating if needed */
40 OSD_UPDATENOW = 0x2, /* Force update even if nothing changed */
41};
42
43/* Show/Hide the OSD on screen returning previous status */
44bool osd_show(unsigned flags);
45
46/* Redraw the entire OSD returning true if screen update occurred */
47bool osd_update(void);
48
49/* Redraw part of the OSD (OSD viewport-relative coordinates) returning true
50 if any screen update occurred */
51bool osd_update_rect(int x, int y, int width, int height);
52
53/* Set a new screen location and size (screen coordinates) */
54bool osd_update_pos(int x, int y, int width, int height);
55
56/* Call periodically to have the OSD timeout and hide itself */
57void osd_monitor_timeout(void);
58
59/* Set the OSD timeout value. 'timeout' <= 0 == never timeout */
60void osd_set_timeout(long timeout);
61
62/* Use the OSD viewport context */
63struct viewport * osd_get_viewport(void);
64
65/* Get the maximum buffer dimensions calculated by osd_init() */
66void osd_get_max_dims(int *maxwidth, int *maxheight);
67
68/* Is the OSD enabled? */
69bool osd_enabled(void);
70
71/** Functions that must be used in lieu of regular LCD functions for this
72 ** to work.
73 **
74 ** To be efficient, as much drawing as possible should be combined between
75 ** *prepare and *update.
76 **
77 ** osd_lcd_update_prepare();
78 ** <draw stuff using lcd_* routines>
79 ** osd_lcd_update[_rect]();
80 **
81 ** TODO: Make it work seamlessly with greylib and regular LCD functions.
82 **/
83
84/* Prepare LCD frambuffer for regular drawing - call before any other LCD
85 function */
86void osd_lcd_update_prepare(void);
87
88/* Update the whole screen and restore OSD if it is visible */
89void osd_lcd_update(void);
90
91/* Update a part of the screen and restore OSD if it is visible */
92void osd_lcd_update_rect(int x, int y, int width, int height);
93
94#endif /* OSD_H */
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index af2c821037..66ebb43774 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -27,353 +27,435 @@
27 27
28#include "lib/xlcd.h" 28#include "lib/xlcd.h"
29#include "lib/configfile.h" 29#include "lib/configfile.h"
30 30#include "fixedpoint.h"
31 31#include "lib/fixedpoint.h"
32#include "lib/osd.h"
32 33
33/* variable button definitions */ 34/* variable button definitions */
34#if CONFIG_KEYPAD == RECORDER_PAD 35#if CONFIG_KEYPAD == RECORDER_PAD
35#define OSCILLOSCOPE_QUIT BUTTON_OFF 36#define OSCILLOSCOPE_QUIT BUTTON_OFF
36#define OSCILLOSCOPE_DRAWMODE BUTTON_F1 37#define OSCILLOSCOPE_DRAWMODE BUTTON_F1
37#define OSCILLOSCOPE_ADVMODE BUTTON_F2 38#define OSCILLOSCOPE_ADVMODE BUTTON_F2
38#define OSCILLOSCOPE_ORIENTATION BUTTON_F3 39#define OSCILLOSCOPE_ORIENTATION BUTTON_F3
39#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 40#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
40#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 41#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
41#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 42#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
42#define OSCILLOSCOPE_VOL_UP BUTTON_UP 43#define OSCILLOSCOPE_VOL_UP BUTTON_UP
43#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 44#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
44 45
45#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD 46#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
46#define OSCILLOSCOPE_QUIT BUTTON_OFF 47#define OSCILLOSCOPE_QUIT BUTTON_OFF
47#define OSCILLOSCOPE_DRAWMODE BUTTON_F1 48#define OSCILLOSCOPE_DRAWMODE BUTTON_F1
48#define OSCILLOSCOPE_ADVMODE BUTTON_F2 49#define OSCILLOSCOPE_ADVMODE BUTTON_F2
49#define OSCILLOSCOPE_ORIENTATION BUTTON_F3 50#define OSCILLOSCOPE_ORIENTATION BUTTON_F3
50#define OSCILLOSCOPE_PAUSE BUTTON_SELECT 51#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
51#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 52#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
52#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 53#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
53#define OSCILLOSCOPE_VOL_UP BUTTON_UP 54#define OSCILLOSCOPE_VOL_UP BUTTON_UP
54#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 55#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
55 56
56#elif CONFIG_KEYPAD == ONDIO_PAD 57#elif CONFIG_KEYPAD == ONDIO_PAD
57#define OSCILLOSCOPE_QUIT BUTTON_OFF 58#define OSCILLOSCOPE_QUIT BUTTON_OFF
58#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_MENU 59#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_MENU
59#define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_REL) 60#define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_REL)
60#define OSCILLOSCOPE_ADVMODE (BUTTON_MENU | BUTTON_RIGHT) 61#define OSCILLOSCOPE_ADVMODE (BUTTON_MENU | BUTTON_RIGHT)
61#define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_LEFT) 62#define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_LEFT)
62#define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF) 63#define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF)
63#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 64#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
64#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 65#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
65#define OSCILLOSCOPE_VOL_UP BUTTON_UP 66#define OSCILLOSCOPE_VOL_UP BUTTON_UP
66#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 67#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
68#define NEED_LASTBUTTON
67 69
68#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) 70#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
69#define OSCILLOSCOPE_QUIT BUTTON_OFF 71#define OSCILLOSCOPE_QUIT BUTTON_OFF
70#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 72#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
71#define OSCILLOSCOPE_ADVMODE BUTTON_MODE 73#define OSCILLOSCOPE_ADVMODE BUTTON_MODE
72#define OSCILLOSCOPE_ORIENTATION BUTTON_REC 74#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REC
73#define OSCILLOSCOPE_PAUSE BUTTON_ON 75#define OSCILLOSCOPE_ORIENTATION (BUTTON_REC | BUTTON_REL)
74#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 76#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_REC
75#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 77#define OSCILLOSCOPE_GRAPHMODE (BUTTON_REC | BUTTON_REPEAT)
76#define OSCILLOSCOPE_VOL_UP BUTTON_UP 78#define OSCILLOSCOPE_PAUSE BUTTON_ON
77#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 79#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
78#define OSCILLOSCOPE_RC_QUIT BUTTON_RC_STOP 80#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
81#define OSCILLOSCOPE_VOL_UP BUTTON_UP
82#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
83#define OSCILLOSCOPE_RC_QUIT BUTTON_RC_STOP
84#define NEED_LASTBUTTON
79 85
80#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 86#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
81 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 87 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
82#define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU) 88#define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
83#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY) 89#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY)
84#define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT) 90#define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
85#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT) 91#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
86#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 92#define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
87#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 93#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
88#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 94#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
89#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD 95#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
90#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK 96#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
97#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
98/* Need GRAPHMODE */
91 99
92#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 100#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
93#define OSCILLOSCOPE_QUIT BUTTON_POWER 101#define OSCILLOSCOPE_QUIT BUTTON_POWER
94#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 102#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
95#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN 103#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
96#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 104#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
97#define OSCILLOSCOPE_PAUSE BUTTON_A 105#define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
98#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 106#define OSCILLOSCOPE_PAUSE BUTTON_A
99#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 107#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
100#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 108#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
101#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 109#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
110#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
102 111
103#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 112#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
104#define OSCILLOSCOPE_QUIT BUTTON_POWER 113#define OSCILLOSCOPE_QUIT BUTTON_POWER
105#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 114#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
106#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN 115#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
107#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 116#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
108#define OSCILLOSCOPE_PAUSE BUTTON_REC 117#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
109#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 118#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
110#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 119#define OSCILLOSCOPE_PAUSE_PRE BUTTON_UP
111#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD 120#define OSCILLOSCOPE_PAUSE (BUTTON_UP | BUTTON_REL)
112#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK 121#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
122#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
123#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
124#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
125#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
126#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
127#define NEED_LASTBUTTON
113 128
114#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 129#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
115#define OSCILLOSCOPE_QUIT (BUTTON_HOME|BUTTON_REPEAT) 130#define OSCILLOSCOPE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
116#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL) 131#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
117#define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT) 132#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
118#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT) 133#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
119#define OSCILLOSCOPE_PAUSE BUTTON_UP 134#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
120#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 135#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
121#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 136#define OSCILLOSCOPE_PAUSE_PRE BUTTON_UP
122#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD 137#define OSCILLOSCOPE_PAUSE (BUTTON_UP | BUTTON_REL)
123#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK 138#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
139#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
140#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
141#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
142#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
143#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
144#define NEED_LASTBUTTON
124 145
125#elif (CONFIG_KEYPAD == SANSA_C200_PAD) 146#elif (CONFIG_KEYPAD == SANSA_C200_PAD)
126#define OSCILLOSCOPE_QUIT BUTTON_POWER 147#define OSCILLOSCOPE_QUIT BUTTON_POWER
127#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 148#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
128#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN 149#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
129#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 150#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
130#define OSCILLOSCOPE_PAUSE BUTTON_REC 151#define OSCILLOSCOPE_PAUSE BUTTON_REC
131#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 152#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
132#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 153#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
133#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 154#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
134#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 155#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
156/* v1 - Need GRAPHMODE */
157/* v2 - Not enough plugin RAM for waveform view */
135 158
136#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD) 159#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
137#define OSCILLOSCOPE_QUIT BUTTON_POWER 160#define OSCILLOSCOPE_QUIT BUTTON_POWER
138#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 161#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
139#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN 162#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
140#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 163#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
141#define OSCILLOSCOPE_PAUSE BUTTON_HOME 164#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
142#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 165#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
143#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 166#define OSCILLOSCOPE_PAUSE BUTTON_UP
144#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 167#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
145#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 168#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
169#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
170#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
171#define NEED_LASTBUTTON
172/* Not enough plugin RAM for waveform view */
146 173
147#elif (CONFIG_KEYPAD == SANSA_M200_PAD) 174#elif (CONFIG_KEYPAD == SANSA_M200_PAD)
148#define OSCILLOSCOPE_QUIT BUTTON_POWER 175#define OSCILLOSCOPE_QUIT BUTTON_POWER
149#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL) 176#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
150#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN 177#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
151#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 178#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
152#define OSCILLOSCOPE_PAUSE (BUTTON_SELECT | BUTTON_UP) 179#define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
153#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 180#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
154#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 181#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
155#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 182#define OSCILLOSCOPE_PAUSE (BUTTON_SELECT | BUTTON_UP)
156#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 183#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
184#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
185#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
186#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
187#define NEED_LASTBUTTON
157 188
158#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD 189#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
159#define OSCILLOSCOPE_QUIT BUTTON_POWER 190#define OSCILLOSCOPE_QUIT BUTTON_POWER
160#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT 191#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
161#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL) 192#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
162#define OSCILLOSCOPE_ADVMODE BUTTON_REC 193#define OSCILLOSCOPE_ADVMODE BUTTON_REC
163#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT 194#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
164#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT) 195#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
165#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 196#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_PLAY
166#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 197#define OSCILLOSCOPE_GRAPHMODE (BUTTON_PLAY | BUTTON_REPEAT)
167#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 198#define OSCILLOSCOPE_PAUSE_PRE BUTTON_PLAY
168#define OSCILLOSCOPE_VOL_UP BUTTON_UP 199#define OSCILLOSCOPE_PAUSE (BUTTON_PLAY | BUTTON_REL)
169#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 200#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
201#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
202#define OSCILLOSCOPE_VOL_UP BUTTON_UP
203#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
204#define NEED_LASTBUTTON
170 205
171#elif CONFIG_KEYPAD == IRIVER_H10_PAD 206#elif CONFIG_KEYPAD == IRIVER_H10_PAD
172#define OSCILLOSCOPE_QUIT BUTTON_POWER 207#define OSCILLOSCOPE_QUIT BUTTON_POWER
173#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW 208#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW
174#define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL) 209#define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL)
175#define OSCILLOSCOPE_ADVMODE BUTTON_FF 210#define OSCILLOSCOPE_ADVMODE BUTTON_FF
176#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW 211#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW
177#define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT) 212#define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT)
178#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 213#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_PLAY
179#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 214#define OSCILLOSCOPE_GRAPHMODE (BUTTON_PLAY | BUTTON_REPEAT)
180#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 215#define OSCILLOSCOPE_PAUSE_PRE BUTTON_PLAY
181#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP 216#define OSCILLOSCOPE_PAUSE (BUTTON_PLAY | BUTTON_REL)
182#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN 217#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
218#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
219#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP
220#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN
221#define NEED_LASTBUTTON
183 222
184#elif CONFIG_KEYPAD == GIGABEAT_S_PAD 223#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
185#define OSCILLOSCOPE_QUIT BUTTON_BACK 224#define OSCILLOSCOPE_QUIT BUTTON_BACK
186#define OSCILLOSCOPE_DRAWMODE BUTTON_PREV 225#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
187#define OSCILLOSCOPE_ADVMODE BUTTON_NEXT 226#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
188#define OSCILLOSCOPE_ORIENTATION BUTTON_MENU 227#define OSCILLOSCOPE_ORIENTATION BUTTON_UP
189#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 228#define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
190#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 229#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
191#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 230#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
192#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 231#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
193#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 232#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
233#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
194 234
195#elif (CONFIG_KEYPAD == MROBE100_PAD) 235#elif (CONFIG_KEYPAD == MROBE100_PAD)
196#define OSCILLOSCOPE_QUIT BUTTON_POWER 236#define OSCILLOSCOPE_QUIT BUTTON_POWER
197#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 237#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
198#define OSCILLOSCOPE_ADVMODE BUTTON_MENU 238#define OSCILLOSCOPE_ADVMODE BUTTON_MENU
199#define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY 239#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_PLAY
200#define OSCILLOSCOPE_PAUSE BUTTON_DISPLAY 240#define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY | BUTTON_REL)
201#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 241#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_PLAY
202#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 242#define OSCILLOSCOPE_GRAPHMODE (BUTTON_PLAY | BUTTON_REPEAT)
203#define OSCILLOSCOPE_VOL_UP BUTTON_UP 243#define OSCILLOSCOPE_PAUSE BUTTON_DISPLAY
204#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 244#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
245#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
246#define OSCILLOSCOPE_VOL_UP BUTTON_UP
247#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
248#define NEED_LASTBUTTON
205 249
206#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 250#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
207#define OSCILLOSCOPE_QUIT BUTTON_RC_REC 251#define OSCILLOSCOPE_QUIT BUTTON_RC_REC
208#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_RC_MODE 252#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_RC_MODE
209#define OSCILLOSCOPE_DRAWMODE (BUTTON_RC_MODE|BUTTON_REL) 253#define OSCILLOSCOPE_DRAWMODE (BUTTON_RC_MODE|BUTTON_REL)
210#define OSCILLOSCOPE_ADVMODE BUTTON_RC_MENU 254#define OSCILLOSCOPE_ADVMODE BUTTON_RC_MENU
211#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_RC_MODE 255#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_RC_MODE
212#define OSCILLOSCOPE_ORIENTATION (BUTTON_RC_MODE|BUTTON_REPEAT) 256#define OSCILLOSCOPE_ORIENTATION (BUTTON_RC_MODE|BUTTON_REPEAT)
213#define OSCILLOSCOPE_PAUSE BUTTON_RC_PLAY 257#define OSCILLOSCOPE_PAUSE_PRE BUTTON_RC_PLAY
214#define OSCILLOSCOPE_SPEED_UP BUTTON_RC_FF 258#define OSCILLOSCOPE_PAUSE (BUTTON_RC_PLAY|BUTTON_REL)
215#define OSCILLOSCOPE_SPEED_DOWN BUTTON_RC_REW 259#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_RC_PLAY
216#define OSCILLOSCOPE_VOL_UP BUTTON_RC_VOL_UP 260#define SCILLLOSCOPE_GRAPHMODE (BUTTON_RC_PLAY|BUTTON_REPEAT)
217#define OSCILLOSCOPE_VOL_DOWN BUTTON_RC_VOL_DOWN 261#define OSCILLOSCOPE_SPEED_UP BUTTON_RC_FF
262#define OSCILLOSCOPE_SPEED_DOWN BUTTON_RC_REW
263#define OSCILLOSCOPE_VOL_UP BUTTON_RC_VOL_UP
264#define OSCILLOSCOPE_VOL_DOWN BUTTON_RC_VOL_DOWN
265#define NEED_LASTBUTTON
218 266
219#elif CONFIG_KEYPAD == COWON_D2_PAD 267#elif CONFIG_KEYPAD == COWON_D2_PAD
220#define OSCILLOSCOPE_QUIT BUTTON_POWER 268#define OSCILLOSCOPE_QUIT BUTTON_POWER
221#define OSCILLOSCOPE_VOL_UP BUTTON_PLUS 269#define OSCILLOSCOPE_VOL_UP BUTTON_PLUS
222#define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS 270#define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS
223 271
224#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 272#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
225#define OSCILLOSCOPE_QUIT BUTTON_BACK 273#define OSCILLOSCOPE_QUIT BUTTON_BACK
226#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 274#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
227#define OSCILLOSCOPE_ADVMODE BUTTON_CUSTOM 275#define OSCILLOSCOPE_ADVMODE BUTTON_CUSTOM
228#define OSCILLOSCOPE_ORIENTATION BUTTON_MENU 276#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_MENU
229#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 277#define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_REL)
230#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 278#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_MENU
231#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 279#define OSCILLOSCOPE_GRAPHMODE (BUTTON_MENU | BUTTON_REPEAT)
232#define OSCILLOSCOPE_VOL_UP BUTTON_UP 280#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
233#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 281#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
282#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
283#define OSCILLOSCOPE_VOL_UP BUTTON_UP
284#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
285#define NEED_LASTBUTTON
234 286
235#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 287#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
236#define OSCILLOSCOPE_QUIT BUTTON_POWER 288#define OSCILLOSCOPE_QUIT BUTTON_POWER
237#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU 289#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
238#define OSCILLOSCOPE_ADVMODE BUTTON_VIEW 290#define OSCILLOSCOPE_ADVMODE BUTTON_VIEW
239#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 291#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
240#define OSCILLOSCOPE_PAUSE BUTTON_SELECT 292#define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
241#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 293#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
242#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 294#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
243#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 295#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
244#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 296#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
297#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
298#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
299#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
300#define NEED_LASTBUTTON
245 301
246#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 302#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
247#define OSCILLOSCOPE_QUIT BUTTON_POWER 303#define OSCILLOSCOPE_QUIT BUTTON_POWER
248#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU 304#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
249#define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT 305#define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT
250#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 306#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
251#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 307#define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
252#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT 308#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
253#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV 309#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
254#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 310#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
255#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 311#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
312#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
313#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
314#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
315#define NEED_LASTBUTTON
256 316
257#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 317#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
258#define OSCILLOSCOPE_QUIT BUTTON_POWER 318#define OSCILLOSCOPE_QUIT BUTTON_POWER
259#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU 319#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
260#define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT 320#define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT
261#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 321#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
262#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 322#define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
263#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT 323#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
264#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV 324#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
265#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 325#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
266#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 326#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
327#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
328#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
329#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
330#define NEED_LASTBUTTON
267 331
268#elif CONFIG_KEYPAD == ONDAVX747_PAD 332#elif CONFIG_KEYPAD == ONDAVX747_PAD
269#define OSCILLOSCOPE_QUIT BUTTON_POWER 333#define OSCILLOSCOPE_QUIT BUTTON_POWER
270#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 334#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
271#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 335#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
272 336
273#elif CONFIG_KEYPAD == ONDAVX777_PAD 337#elif CONFIG_KEYPAD == ONDAVX777_PAD
274#define OSCILLOSCOPE_QUIT BUTTON_POWER 338#define OSCILLOSCOPE_QUIT BUTTON_POWER
275 339
276#elif CONFIG_KEYPAD == MROBE500_PAD 340#elif CONFIG_KEYPAD == MROBE500_PAD
277#define OSCILLOSCOPE_QUIT BUTTON_POWER 341#define OSCILLOSCOPE_QUIT BUTTON_POWER
278 342
279#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD 343#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
280#define OSCILLOSCOPE_QUIT BUTTON_REC 344#define OSCILLOSCOPE_QUIT BUTTON_REC
281#define OSCILLOSCOPE_DRAWMODE (BUTTON_PLAY|BUTTON_LEFT) 345#define OSCILLOSCOPE_DRAWMODE (BUTTON_PLAY|BUTTON_LEFT)
282#define OSCILLOSCOPE_ADVMODE (BUTTON_PLAY|BUTTON_RIGHT) 346#define OSCILLOSCOPE_ADVMODE (BUTTON_PLAY|BUTTON_RIGHT)
283#define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY|BUTTON_UP) 347#define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY|BUTTON_UP)
284#define OSCILLOSCOPE_PAUSE (BUTTON_PLAY|BUTTON_DOWN) 348#define OSCILLOSCOPE_PAUSE (BUTTON_PLAY|BUTTON_DOWN)
285#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 349#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
286#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 350#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
287#define OSCILLOSCOPE_VOL_UP BUTTON_UP 351#define OSCILLOSCOPE_VOL_UP BUTTON_UP
288#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 352#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
353/* Need GRAPHMODE */
289 354
290#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 355#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
291#define OSCILLOSCOPE_QUIT BUTTON_REC 356#define OSCILLOSCOPE_QUIT BUTTON_REC
292#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU 357#define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
293#define OSCILLOSCOPE_ADVMODE BUTTON_CANCEL 358#define OSCILLOSCOPE_ADVMODE BUTTON_CANCEL
294#define OSCILLOSCOPE_ORIENTATION BUTTON_OK 359#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_OK
295#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 360#define OSCILLOSCOPE_ORIENTATION (BUTTON_OK | BUTTON_REL)
296#define OSCILLOSCOPE_SPEED_UP BUTTON_PREV 361#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_OK
297#define OSCILLOSCOPE_SPEED_DOWN BUTTON_NEXT 362#define OSCILLOSCOPE_GRAPHMODE (BUTTON_OK | BUTTON_REPEAT)
298#define OSCILLOSCOPE_VOL_UP BUTTON_UP 363#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
299#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 364#define OSCILLOSCOPE_SPEED_UP BUTTON_PREV
365#define OSCILLOSCOPE_SPEED_DOWN BUTTON_NEXT
366#define OSCILLOSCOPE_VOL_UP BUTTON_UP
367#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
368#define NEED_LASTBUTTON
300 369
301#elif CONFIG_KEYPAD == MPIO_HD200_PAD 370#elif CONFIG_KEYPAD == MPIO_HD200_PAD
302#define OSCILLOSCOPE_QUIT (BUTTON_REC | BUTTON_PLAY) 371#define OSCILLOSCOPE_QUIT (BUTTON_REC | BUTTON_PLAY)
303#define OSCILLOSCOPE_DRAWMODE BUTTON_FUNC 372#define OSCILLOSCOPE_DRAWMODE BUTTON_FUNC
304#define OSCILLOSCOPE_ADVMODE BUTTON_REC 373#define OSCILLOSCOPE_ADVMODE BUTTON_REC
305#define OSCILLOSCOPE_ORIENTATION (BUTTON_FUNC|BUTTON_REPEAT) 374#define OSCILLOSCOPE_ORIENTATION (BUTTON_FUNC | BUTTON_REPEAT)
306#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 375#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
307#define OSCILLOSCOPE_SPEED_UP BUTTON_FF 376#define OSCILLOSCOPE_SPEED_UP BUTTON_FF
308#define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW 377#define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW
309#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 378#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
310#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 379#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
380/* Need GRAPHMODE */
311 381
312#elif CONFIG_KEYPAD == MPIO_HD300_PAD 382#elif CONFIG_KEYPAD == MPIO_HD300_PAD
313#define OSCILLOSCOPE_QUIT (BUTTON_MENU | BUTTON_REPEAT) 383#define OSCILLOSCOPE_QUIT (BUTTON_MENU | BUTTON_REPEAT)
314#define OSCILLOSCOPE_DRAWMODE BUTTON_ENTER 384#define OSCILLOSCOPE_DRAWMODE BUTTON_ENTER
315#define OSCILLOSCOPE_ADVMODE BUTTON_REC 385#define OSCILLOSCOPE_ADVMODE BUTTON_REC
316#define OSCILLOSCOPE_ORIENTATION BUTTON_MENU 386#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_MENU
317#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 387#define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_REL)
318#define OSCILLOSCOPE_SPEED_UP BUTTON_FF 388#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_MENU
319#define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW 389#define OSCILLOSCOPE_GRAPHMODE (BUTTON_MENU | BUTTON_REPEAT)
320#define OSCILLOSCOPE_VOL_UP BUTTON_UP 390#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
321#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 391#define OSCILLOSCOPE_SPEED_UP BUTTON_FF
392#define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW
393#define OSCILLOSCOPE_VOL_UP BUTTON_UP
394#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
395#define NEED_LASTBUTTON
322 396
323#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 397#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
324#define OSCILLOSCOPE_QUIT BUTTON_POWER 398#define OSCILLOSCOPE_QUIT BUTTON_POWER
325#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 399#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
326#define OSCILLOSCOPE_ADVMODE BUTTON_BACK 400#define OSCILLOSCOPE_ADVMODE BUTTON_BACK
327#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 401#define OSCILLOSCOPE_ORIENTATION (BUTTON_BACK|BUTTON_REPEAT)
328#define OSCILLOSCOPE_PAUSE BUTTON_PLAYPAUSE 402#define OSCILLOSCOPE_PAUSE BUTTON_PLAYPAUSE
329#define OSCILLOSCOPE_SPEED_UP BUTTON_LEFT 403#define OSCILLOSCOPE_SPEED_UP BUTTON_LEFT
330#define OSCILLOSCOPE_SPEED_DOWN BUTTON_RIGHT 404#define OSCILLOSCOPE_SPEED_DOWN BUTTON_RIGHT
331#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 405#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
332#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 406#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
407/* Need GRAPHMODE */
333 408
334#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD) 409#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
335#define OSCILLOSCOPE_QUIT BUTTON_POWER 410#define OSCILLOSCOPE_QUIT BUTTON_POWER
336#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT 411#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
337#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN 412#define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
338#define OSCILLOSCOPE_ORIENTATION BUTTON_UP 413#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
339#define OSCILLOSCOPE_PAUSE BUTTON_NEXT 414#define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
340#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 415#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
341#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 416#define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
342#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 417#define OSCILLOSCOPE_PAUSE BUTTON_NEXT
343#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 418#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
419#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
420#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
421#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
422#define NEED_LASTBUTTON
344 423
345#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) 424#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
346#define OSCILLOSCOPE_QUIT BUTTON_BACK 425#define OSCILLOSCOPE_QUIT BUTTON_BACK
347#define OSCILLOSCOPE_DRAWMODE BUTTON_USER 426#define OSCILLOSCOPE_DRAWMODE BUTTON_USER
348#define OSCILLOSCOPE_ADVMODE BUTTON_MENU 427#define OSCILLOSCOPE_ADVMODE BUTTON_MENU
349#define OSCILLOSCOPE_ORIENTATION BUTTON_POWER 428#define OSCILLOSCOPE_ORIENTATION BUTTON_POWER
350#define OSCILLOSCOPE_PAUSE BUTTON_SELECT 429#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
351#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT 430#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
352#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT 431#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
353#define OSCILLOSCOPE_VOL_UP BUTTON_UP 432#define OSCILLOSCOPE_VOL_UP BUTTON_UP
354#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 433#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
434/* Need GRAPHMODE */
355 435
356#elif (CONFIG_KEYPAD == HM60X_PAD) 436#elif (CONFIG_KEYPAD == HM60X_PAD)
357#define OSCILLOSCOPE_QUIT BUTTON_POWER 437#define OSCILLOSCOPE_QUIT BUTTON_POWER
358#define OSCILLOSCOPE_DRAWMODE (BUTTON_POWER | BUTTON_SELECT) 438#define OSCILLOSCOPE_DRAWMODE (BUTTON_POWER | BUTTON_SELECT)
359#define OSCILLOSCOPE_ADVMODE (BUTTON_POWER | BUTTON_RIGHT) 439#define OSCILLOSCOPE_ADVMODE (BUTTON_POWER | BUTTON_RIGHT)
360#define OSCILLOSCOPE_ORIENTATION (BUTTON_POWER | BUTTON_LEFT) 440#define OSCILLOSCOPE_ORIENTATION (BUTTON_POWER | BUTTON_LEFT)
361#define OSCILLOSCOPE_PAUSE BUTTON_SELECT 441#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
362#define OSCILLOSCOPE_SPEED_UP BUTTON_UP 442#define OSCILLOSCOPE_SPEED_UP BUTTON_UP
363#define OSCILLOSCOPE_SPEED_DOWN BUTTON_DOWN 443#define OSCILLOSCOPE_SPEED_DOWN BUTTON_DOWN
364#define OSCILLOSCOPE_VOL_UP BUTTON_RIGHT 444#define OSCILLOSCOPE_VOL_UP BUTTON_RIGHT
365#define OSCILLOSCOPE_VOL_DOWN BUTTON_LEFT 445#define OSCILLOSCOPE_VOL_DOWN BUTTON_LEFT
446/* Need GRAPHMODE */
366 447
367#elif (CONFIG_KEYPAD == HM801_PAD) 448#elif (CONFIG_KEYPAD == HM801_PAD)
368#define OSCILLOSCOPE_QUIT BUTTON_POWER 449#define OSCILLOSCOPE_QUIT BUTTON_POWER
369#define OSCILLOSCOPE_DRAWMODE BUTTON_PREV 450#define OSCILLOSCOPE_DRAWMODE BUTTON_PREV
370#define OSCILLOSCOPE_ADVMODE BUTTON_NEXT 451#define OSCILLOSCOPE_ADVMODE BUTTON_NEXT
371#define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY 452#define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY
372#define OSCILLOSCOPE_PAUSE BUTTON_SELECT 453#define OSCILLOSCOPE_PAUSE BUTTON_SELECT
373#define OSCILLOSCOPE_SPEED_UP BUTTON_UP 454#define OSCILLOSCOPE_SPEED_UP BUTTON_UP
374#define OSCILLOSCOPE_SPEED_DOWN BUTTON_DOWN 455#define OSCILLOSCOPE_SPEED_DOWN BUTTON_DOWN
375#define OSCILLOSCOPE_VOL_UP BUTTON_RIGHT 456#define OSCILLOSCOPE_VOL_UP BUTTON_RIGHT
376#define OSCILLOSCOPE_VOL_DOWN BUTTON_LEFT 457#define OSCILLOSCOPE_VOL_DOWN BUTTON_LEFT
458/* Need GRAPHMODE */
377 459
378#else 460#else
379#error No keymap defined! 461#error No keymap defined!
@@ -381,119 +463,419 @@
381 463
382#ifdef HAVE_TOUCHSCREEN 464#ifdef HAVE_TOUCHSCREEN
383#ifndef OSCILLOSCOPE_QUIT 465#ifndef OSCILLOSCOPE_QUIT
384#define OSCILLOSCOPE_QUIT BUTTON_TOPLEFT 466#define OSCILLOSCOPE_QUIT BUTTON_TOPLEFT
385#endif 467#endif
386#ifndef OSCILLOSCOPE_DRAWMODE 468#ifndef OSCILLOSCOPE_DRAWMODE
387#define OSCILLOSCOPE_DRAWMODE BUTTON_TOPMIDDLE 469#define OSCILLOSCOPE_DRAWMODE BUTTON_TOPMIDDLE
388#endif 470#endif
389#ifndef OSCILLOSCOPE_ADVMODE 471#ifndef OSCILLOSCOPE_ADVMODE
390#define OSCILLOSCOPE_ADVMODE BUTTON_BOTTOMMIDDLE 472#define OSCILLOSCOPE_ADVMODE BUTTON_BOTTOMMIDDLE
391#endif 473#endif
392#ifndef OSCILLOSCOPE_ORIENTATION 474#ifndef OSCILLOSCOPE_ORIENTATION
393#define OSCILLOSCOPE_ORIENTATION BUTTON_BOTTOMLEFT 475#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_BOTTOMLEFT
476#define OSCILLOSCOPE_ORIENTATION (BUTTON_BOTTOMLEFT|BUTTON_REL)
477#endif
478#ifndef OSCILLOSCOPE_GRAPHMODE
479#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_BOTTOMLEFT
480#define OSCILLOSCOPE_GRAPHMODE (BUTTON_BOTTOMLEFT|BUTTON_REPEAT)
394#endif 481#endif
395#ifndef OSCILLOSCOPE_PAUSE 482#ifndef OSCILLOSCOPE_PAUSE
396#define OSCILLOSCOPE_PAUSE BUTTON_CENTER 483#define OSCILLOSCOPE_PAUSE BUTTON_CENTER
397#endif 484#endif
398#ifndef OSCILLOSCOPE_SPEED_UP 485#ifndef OSCILLOSCOPE_SPEED_UP
399#define OSCILLOSCOPE_SPEED_UP BUTTON_MIDRIGHT 486#define OSCILLOSCOPE_SPEED_UP BUTTON_MIDRIGHT
400#endif 487#endif
401#ifndef OSCILLOSCOPE_SPEED_DOWN 488#ifndef OSCILLOSCOPE_SPEED_DOWN
402#define OSCILLOSCOPE_SPEED_DOWN BUTTON_MIDLEFT 489#define OSCILLOSCOPE_SPEED_DOWN BUTTON_MIDLEFT
403#endif 490#endif
404#ifndef OSCILLOSCOPE_VOL_UP 491#ifndef OSCILLOSCOPE_VOL_UP
405#define OSCILLOSCOPE_VOL_UP BUTTON_TOPRIGHT 492#define OSCILLOSCOPE_VOL_UP BUTTON_TOPRIGHT
406#endif 493#endif
407#ifndef OSCILLOSCOPE_VOL_DOWN 494#ifndef OSCILLOSCOPE_VOL_DOWN
408#define OSCILLOSCOPE_VOL_DOWN BUTTON_BOTTOMRIGHT 495#define OSCILLOSCOPE_VOL_DOWN BUTTON_BOTTOMRIGHT
409#endif
410#endif 496#endif
497#define NEED_LASTBUTTON
498#endif /* HAVE_TOUCHSCREEN */
411 499
412/* colours */ 500/* colours */
413#if LCD_DEPTH > 1 501#if LCD_DEPTH > 1
414#ifdef HAVE_LCD_COLOR 502#ifdef HAVE_LCD_COLOR
415#define BACKG_COLOR LCD_BLACK 503#define BACKG_COLOR LCD_BLACK
416#define GRAPH_COLOR LCD_RGBPACK(128, 255, 0) 504#define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
417#define CURSOR_COLOR LCD_RGBPACK(255, 0, 0) 505#define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
506#define GRID_COLOR LCD_RGBPACK(192, 255, 64)
507#define OSD_TEXT_COLOR LCD_WHITE
508#define OSD_BACKG_COLOR LCD_BLACK
509#define OSD_BORDER_COLOR LCD_RGBPACK(255, 0, 0)
510#define OSC_OSD_MARGIN_SIZE 0 /* Border and text are different */
418#else 511#else
419#define BACKG_COLOR LCD_WHITE 512#define BACKG_COLOR LCD_WHITE
420#define GRAPH_COLOR LCD_BLACK 513#define GRAPH_COLOR LCD_BLACK
421#define CURSOR_COLOR LCD_DARKGRAY 514#define CURSOR_COLOR LCD_DARKGRAY
515#define GRID_COLOR LCD_DARKGRAY
516#define OSD_TEXT_COLOR LCD_BLACK
517#define OSD_BACKG_COLOR LCD_WHITE
518#define OSD_BORDER_COLOR LCD_BLACK
519#endif
422#endif 520#endif
521
522#ifndef OSC_OSD_MARGIN_SIZE
523#define OSC_OSD_MARGIN_SIZE 1
423#endif 524#endif
424 525
526#define MIN_SPEED 1
527#define MAX_SPEED 100
528
425enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW }; 529enum { DRAW_FILLED, DRAW_LINE, DRAW_PIXEL, MAX_DRAW };
426enum { ADV_SCROLL, ADV_WRAP, MAX_ADV }; 530enum { ADV_SCROLL, ADV_WRAP, MAX_ADV };
427enum { OSC_HORIZ, OSC_VERT, MAX_OSC }; 531enum { OSC_HORIZ, OSC_VERT, MAX_OSC };
532enum
533{
534 GRAPH_PEAKS,
535#ifdef OSCILLOSCOPE_GRAPHMODE
536 GRAPH_WAVEFORM,
537#endif
538 MAX_GRAPH
539};
428 540
429#define CFGFILE_VERSION 0 /* Current config file version */ 541#define CFGFILE_VERSION 1 /* Current config file version */
430#define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */ 542#define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
431 543
544/* global variables */
432 545
433#define MAX_PEAK 0x8000 546/*
434 547 * / 99*[e ^ ((100 - x) / z) - 1] \
435#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) 548 * osc_delay = HZ * | ---------------------------- + 1 |
436#define mas_codec_readreg(x) rand()%MAX_PEAK 549 * \ [e ^ (99 / z) - 1] /
437#endif 550 *
551 * x: 1 .. 100, z: 15, delay: 100.00 .. 1.00
552 */
553static const unsigned short osc_delay_tbl[100] =
554{
555 10000, 9361, 8763, 8205, 7682, 7192, 6735, 6307, 5906, 5532,
556 5181, 4853, 4546, 4259, 3991, 3739, 3504, 3285, 3079, 2886,
557 2706, 2538, 2380, 2233, 2095, 1966, 1845, 1732, 1627, 1528,
558 1435, 1349, 1268, 1192, 1121, 1055, 993, 935, 880, 830,
559 782, 737, 696, 657, 620, 586, 554, 524, 497, 470,
560 446, 423, 402, 381, 363, 345, 329, 313, 299, 285,
561 273, 261, 250, 239, 230, 221, 212, 204, 197, 190,
562 183, 177, 171, 166, 161, 156, 152, 147, 144, 140,
563 136, 133, 130, 127, 125, 122, 120, 118, 116, 114,
564 112, 110, 108, 107, 106, 104, 103, 102, 101, 100
565};
438 566
439/* global variables */ 567#define GRAPH_PEAKS_DEFAULT 68
568#define GRAPH_WAVEFORM_DEFAULT 50
440 569
441/* settings */ 570/* settings */
442struct osc_config { 571static struct osc_config
443 int delay; /* in ticks */ 572{
573 int speed[MAX_GRAPH];
444 int draw; 574 int draw;
445 int advance; 575 int advance;
446 int orientation; 576 int orientation;
577 int graphmode;
578} osc_disk =
579{
580 .speed =
581 {
582 [GRAPH_PEAKS] = GRAPH_PEAKS_DEFAULT,
583#ifdef OSCILLOSCOPE_GRAPHMODE
584 [GRAPH_WAVEFORM] = GRAPH_WAVEFORM_DEFAULT,
585#endif
586 },
587 .draw = DRAW_FILLED,
588 .advance = ADV_SCROLL,
589 .orientation = OSC_HORIZ,
590#ifdef OSCILLOSCOPE_GRAPHMODE
591 .graphmode = GRAPH_PEAKS,
592#endif
447}; 593};
448 594
449struct osc_config osc_disk = { 2, DRAW_FILLED, ADV_SCROLL, OSC_HORIZ }; 595static struct osc_config osc; /* running config */
450struct osc_config osc; /* running config */
451 596
452static const char cfg_filename[] = "oscilloscope.cfg"; 597static const char cfg_filename[] = "oscilloscope.cfg";
453static char *draw_str[3] = { "filled", "line", "pixel" }; 598static char *draw_str[3] = { "filled", "line", "pixel" };
454static char *advance_str[2] = { "scroll", "wrap" }; 599static char *advance_str[2] = { "scroll", "wrap" };
455static char *orientation_str[2] = { "horizontal", "vertical" }; 600static char *orientation_str[2] = { "horizontal", "vertical" };
601#ifdef OSCILLOSCOPE_GRAPHMODE
602static char *graphmode_str[2] = { "peaks", "waveform" };
603#endif
456 604
457struct configdata disk_config[] = { 605struct configdata disk_config[] =
458 { TYPE_INT, 1, 99, { .int_p = &osc_disk.delay }, "delay", NULL }, 606{
607 { TYPE_INT, MIN_SPEED, MAX_SPEED,
608 { .int_p = &osc_disk.speed[GRAPH_PEAKS] }, "speed", NULL },
459 { TYPE_ENUM, 0, MAX_DRAW, { .int_p = &osc_disk.draw }, "draw", draw_str }, 609 { TYPE_ENUM, 0, MAX_DRAW, { .int_p = &osc_disk.draw }, "draw", draw_str },
460 { TYPE_ENUM, 0, MAX_ADV, { .int_p = &osc_disk.advance }, "advance", 610 { TYPE_ENUM, 0, MAX_ADV, { .int_p = &osc_disk.advance }, "advance",
461 advance_str }, 611 advance_str },
462 { TYPE_ENUM, 0, MAX_OSC, { .int_p = &osc_disk.orientation }, "orientation", 612 { TYPE_ENUM, 0, MAX_OSC, { .int_p = &osc_disk.orientation }, "orientation",
463 orientation_str } 613 orientation_str },
614#ifdef OSCILLOSCOPE_GRAPHMODE
615 { TYPE_INT, MAX_SPEED, MAX_SPEED,
616 { .int_p = &osc_disk.speed[GRAPH_WAVEFORM] }, "wavespeed", NULL },
617 { TYPE_ENUM, 0, MAX_GRAPH, { .int_p = &osc_disk.graphmode }, "graphmode",
618 graphmode_str },
619#endif
464}; 620};
465 621
622enum osc_message_ids
623{
624 OSC_MSG_ADVMODE,
625 OSC_MSG_DRAWMODE,
626#ifdef OSCILLOSCOPE_GRAPHMODE
627 OSC_MSG_GRAPHMODE,
628#endif
629 OSC_MSG_ORIENTATION,
630 OSC_MSG_PAUSED,
631 OSC_MSG_SPEED,
632 OSC_MSG_VOLUME,
633};
466 634
467long last_tick = 0; /* time of last drawing */ 635static long (*anim_draw)(void);
468int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */ 636static int message = -1, msgval = 0; /* popup message */
469int last_left; /* last channel values */ 637static bool paused = false;
470int last_right; 638static bool one_frame_paused = false; /* Allow one frame to be drawn when paused if
471 639 view is erased */
472unsigned char message[16]; /* message to display */ 640static long osc_delay; /* delay in 100ths of a tick */
473bool displaymsg = false; 641static long osc_delay_error; /* delay fraction error accumulator */
474int font_height = 8;
475 642
476/* implementation */ 643/* implementation */
477 644
478static void anim_horizontal(int cur_left, int cur_right) 645
646/** Messages **/
647
648static unsigned char osc_osd_message[16]; /* message to display (formatted) */
649
650static inline void osc_popupmsg(int msg, int val)
651{
652 message = msg; msgval = val;
653}
654
655/* Format a message to display */
656static void osc_osd_format_message(enum osc_message_ids id, int val)
479{ 657{
658 const char *msg = "";
659
660 switch (id)
661 {
662 case OSC_MSG_ADVMODE:
663 msg = val == ADV_WRAP ? "Wrap" : "Scroll";
664 break;
665
666 case OSC_MSG_DRAWMODE:
667 switch (val)
668 {
669 case DRAW_PIXEL: msg = "Pixel"; break;
670 case DRAW_LINE: msg = "Line"; break;
671 default: msg = "Filled";
672 }
673 break;
674
675#ifdef OSCILLOSCOPE_GRAPHMODE
676 case OSC_MSG_GRAPHMODE:
677 msg = val == GRAPH_WAVEFORM ? "Waveform" : "Peaks";
678 break;
679#endif
680
681 case OSC_MSG_ORIENTATION:
682 msg = val == OSC_VERT ? "Vertical" : "Horizontal";
683 break;
684
685 case OSC_MSG_PAUSED:
686 msg = val ? "Paused" : "Running";
687 break;
688
689 case OSC_MSG_SPEED:
690 msg = "Speed: %d";
691 break;
692
693 case OSC_MSG_VOLUME:
694 rb->snprintf(osc_osd_message, sizeof (osc_osd_message),
695 "Volume: %d%s",
696 rb->sound_val2phys(SOUND_VOLUME, val),
697 rb->sound_unit(SOUND_VOLUME));
698 return;
699 }
700
701 /* Default action: format integer */
702 rb->snprintf(osc_osd_message, sizeof (osc_osd_message), msg, val);
703}
704
705
706/** OSD **/
707
708/* Actually draw the OSD within the OSD viewport */
709extern void osd_lcd_draw_cb(int x, int y, int width, int height)
710{
711#if LCD_DEPTH > 1
712 rb->lcd_set_foreground(OSD_TEXT_COLOR);
713 rb->lcd_set_background(OSD_BACKG_COLOR);
714#endif
715#if OSC_OSD_MARGIN_SIZE != 0
716 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
717 rb->lcd_fillrect(1, 1, width - 2, height - 2);
718 rb->lcd_set_drawmode(DRMODE_SOLID);
719#endif
720 rb->lcd_putsxy(1+OSC_OSD_MARGIN_SIZE, 1+OSC_OSD_MARGIN_SIZE,
721 osc_osd_message);
722#if LCD_DEPTH > 1
723 rb->lcd_set_foreground(OSD_BORDER_COLOR);
724#endif
725 rb->lcd_drawrect(0, 0, width, height);
726
727 (void)x; (void)y;
728}
729
730/* Perform all necessary basic setup tasks for the OSD */
731static void osc_osd_init(void)
732{
733 /* Grab the plugin buffer for the OSD back buffer */
734 size_t bufsize;
735 void *buf = rb->plugin_get_buffer(&bufsize);
736 osd_init(buf, bufsize, osd_lcd_draw_cb);
737}
738
739/* Format a message by ID and show the OSD */
740static void osc_osd_show_message(int id, int val)
741{
742 osc_osd_format_message(id, val);
743
744 if (!osd_enabled())
745 return;
746
747 int width, height;
748 int maxwidth, maxheight;
749
750 rb->lcd_set_viewport(osd_get_viewport());
751 osd_get_max_dims(&maxwidth, &maxheight);
752 rb->lcd_getstringsize(osc_osd_message, &width, &height);
753 rb->lcd_set_viewport(NULL); /* to regular viewport */
754
755 width += 2 + 2*OSC_OSD_MARGIN_SIZE;
756 if (width > maxwidth)
757 width = maxwidth;
758
759 height += 2 + 2*OSC_OSD_MARGIN_SIZE;
760 if (height > maxheight)
761 height = maxheight;
762
763 /* Center it on the screen */
764 bool drawn = osd_update_pos((LCD_WIDTH - width) / 2,
765 (LCD_HEIGHT - height) / 2,
766 width, height);
767
768 osd_show(OSD_SHOW | (drawn ? 0 : OSD_UPDATENOW));
769}
770
771/* Draw cursor bar for horizontal views */
772static void anim_draw_cursor_h(int x)
773{
774#if LCD_DEPTH > 1
775 rb->lcd_set_foreground(CURSOR_COLOR);
776 rb->lcd_vline(x, 0, LCD_HEIGHT-1);
777 rb->lcd_set_foreground(GRAPH_COLOR);
778#else
779 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
780 rb->lcd_vline(x, 0, LCD_HEIGHT-1);
781 rb->lcd_set_drawmode(DRMODE_SOLID);
782#endif
783}
784
785/* Draw cursor bar for vertical views */
786static void anim_draw_cursor_v(int y)
787{
788#if LCD_DEPTH > 1 /* cursor bar */
789 rb->lcd_set_foreground(CURSOR_COLOR);
790 rb->lcd_hline(0, LCD_WIDTH-1, y);
791 rb->lcd_set_foreground(GRAPH_COLOR);
792#else
793 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
794 rb->lcd_hline(0, LCD_WIDTH-1, y);
795 rb->lcd_set_drawmode(DRMODE_SOLID);
796#endif
797}
798
799
800/** Peaks View **/
801
802static long last_tick = 0; /* time of last drawing */
803static long last_delay = 0; /* last delay value used */
804static int last_pos = 0; /* last x or y drawing position. Reset for aspect switch. */
805static int last_left; /* last channel values */
806static int last_right;
807
808static void get_peaks(int *left, int *right)
809{
810#if CONFIG_CODEC == SWCODEC
811 static struct pcm_peaks peaks;
812 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
813 &peaks);
814 *left = peaks.left;
815 *right = peaks.right;
816#elif defined (SIMULATOR)
817 *left = rand() % 0x8000;
818 *right = rand() % 0x8000;
819#elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
820 *left = rb->mas_codec_readreg(0xC);
821 *right = rb->mas_codec_readreg(0xD);
822#else
823 *left = 0;
824 *right = 0;
825#endif
826}
827
828static long get_next_delay(void)
829{
830 long delay = osc_delay / 100;
831 osc_delay_error += osc_delay - delay * 100;
832
833 if (osc_delay_error >= 100)
834 {
835 delay++;
836 osc_delay_error -= 100;
837 }
838
839 return delay;
840}
841
842static long anim_peaks_horizontal(void)
843{
844 long cur_tick = *rb->current_tick;
480 int cur_x, x; 845 int cur_x, x;
481 int left, right, dl, dr; 846 int left, right, dl, dr;
482 long cur_tick = *rb->current_tick; 847 long d = (cur_tick - last_tick) / last_delay;
483 long d = (cur_tick - last_tick) / osc.delay;
484 bool full_update = false; 848 bool full_update = false;
485 849
486 if (d == 0) /* too early, bail out */ 850 if (paused)
487 return; 851 {
852 one_frame_paused = false;
853 osd_lcd_update_prepare();
854 anim_draw_cursor_h(0);
855 osd_lcd_update_rect(0, 0, 1, LCD_HEIGHT);
856 last_pos = -1;
857 return cur_tick + HZ/5;
858 }
859
860 if (d <= 0) /* too early, bail out */
861 return last_tick + last_delay;
488 862
489 last_tick = cur_tick; 863 last_tick = cur_tick;
490 864
865 int cur_left, cur_right;
866 get_peaks(&cur_left, &cur_right);
867
491 if (d > HZ) /* first call or too much delay, (re)start */ 868 if (d > HZ) /* first call or too much delay, (re)start */
492 { 869 {
493 last_left = cur_left; 870 last_left = cur_left;
494 last_right = cur_right; 871 last_right = cur_right;
495 return; 872 return cur_tick + last_delay;
496 } 873 }
874
875 one_frame_paused = false;
876
877 osd_lcd_update_prepare();
878
497 cur_x = last_pos + d; 879 cur_x = last_pos + d;
498 880
499 if (cur_x >= LCD_WIDTH) 881 if (cur_x >= LCD_WIDTH)
@@ -608,70 +990,71 @@ static void anim_horizontal(int cur_left, int cur_right)
608 break; 990 break;
609 991
610 } 992 }
993
611 last_left = cur_left; 994 last_left = cur_left;
612 last_right = cur_right; 995 last_right = cur_right;
613 996
614 if (displaymsg)
615 {
616 int width;
617
618 rb->lcd_getstringsize(message, &width, NULL);
619 last_pos -= width - 1;
620 rb->lcd_putsxy(last_pos, 0, message);
621 displaymsg = false;
622
623 if (last_pos < 0)
624 last_pos = 0;
625 }
626
627 if (full_update) 997 if (full_update)
628 { 998 {
629 rb->lcd_update(); 999 osd_lcd_update();
630 } 1000 }
631 else 1001 else
632 { 1002 {
633#if LCD_DEPTH > 1 /* cursor bar */ 1003 anim_draw_cursor_h(cur_x + 1); /* cursor bar */
634 rb->lcd_set_foreground(CURSOR_COLOR);
635 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
636 rb->lcd_set_foreground(GRAPH_COLOR);
637#else
638 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
639 rb->lcd_vline(cur_x + 1, 0, LCD_HEIGHT-1);
640 rb->lcd_set_drawmode(DRMODE_SOLID);
641#endif
642 1004
643 if (cur_x > last_pos) 1005 if (cur_x > last_pos)
644 { 1006 {
645 rb->lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT); 1007 osd_lcd_update_rect(last_pos, 0, cur_x - last_pos + 2, LCD_HEIGHT);
646 } 1008 }
647 else 1009 else
648 { 1010 {
649 rb->lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT); 1011 osd_lcd_update_rect(last_pos, 0, LCD_WIDTH - last_pos, LCD_HEIGHT);
650 rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT); 1012 osd_lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
651 } 1013 }
652 } 1014 }
653 last_pos = cur_x; 1015 last_pos = cur_x;
1016
1017 last_delay = get_next_delay();
1018 return cur_tick + last_delay;
654} 1019}
655 1020
656static void anim_vertical(int cur_left, int cur_right) 1021static long anim_peaks_vertical(void)
657{ 1022{
1023 long cur_tick = *rb->current_tick;
658 int cur_y, y; 1024 int cur_y, y;
659 int left, right, dl, dr; 1025 int left, right, dl, dr;
660 long cur_tick = *rb->current_tick;
661 long d = (cur_tick - last_tick) / osc.delay;
662 bool full_update = false; 1026 bool full_update = false;
1027 long d = (cur_tick - last_tick) / last_delay;
1028
1029 if (paused)
1030 {
1031 one_frame_paused = false;
1032 osd_lcd_update_prepare();
1033 anim_draw_cursor_v(0);
1034 osd_lcd_update_rect(0, 0, LCD_WIDTH, 1);
1035 last_pos = -1;
1036 return cur_tick + HZ/5;
1037 }
663 1038
664 if (d == 0) /* too early, bail out */ 1039 if (d == 0) /* too early, bail out */
665 return; 1040 return last_tick + last_delay;
666 1041
667 last_tick = cur_tick; 1042 last_tick = cur_tick;
668 1043
1044 int cur_left, cur_right;
1045 get_peaks(&cur_left, &cur_right);
1046
669 if (d > HZ) /* first call or too much delay, (re)start */ 1047 if (d > HZ) /* first call or too much delay, (re)start */
670 { 1048 {
671 last_left = cur_left; 1049 last_left = cur_left;
672 last_right = cur_right; 1050 last_right = cur_right;
673 return; 1051 return cur_tick + last_delay;
674 } 1052 }
1053
1054 one_frame_paused = false;
1055
1056 osd_lcd_update_prepare();
1057
675 cur_y = last_pos + d; 1058 cur_y = last_pos + d;
676 1059
677 if (cur_y >= LCD_HEIGHT) 1060 if (cur_y >= LCD_HEIGHT)
@@ -786,114 +1169,736 @@ static void anim_vertical(int cur_left, int cur_right)
786 break; 1169 break;
787 1170
788 } 1171 }
1172
789 last_left = cur_left; 1173 last_left = cur_left;
790 last_right = cur_right; 1174 last_right = cur_right;
791 1175
792 if (displaymsg) 1176 if (full_update)
1177 {
1178 osd_lcd_update();
1179 }
1180 else
793 { 1181 {
794 last_pos -= font_height - 1; 1182 anim_draw_cursor_v(cur_y + 1); /* cursor bar */
795 rb->lcd_putsxy(0, last_pos, message);
796 displaymsg = false;
797 1183
798 if (last_pos < 0) 1184 if (cur_y > last_pos)
799 last_pos = 0; 1185 {
1186 osd_lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2);
1187 }
1188 else
1189 {
1190 osd_lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos);
1191 osd_lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2);
1192 }
800 } 1193 }
1194 last_pos = cur_y;
801 1195
802 if (full_update) 1196 last_delay = get_next_delay();
1197 return cur_tick + last_delay;
1198}
1199
1200
1201/** Waveform View **/
1202
1203#ifdef OSCILLOSCOPE_GRAPHMODE
1204static int16_t waveform_buffer[2*ALIGN_UP(NATIVE_FREQUENCY, 2048)+2*2048]
1205 MEM_ALIGN_ATTR;
1206static size_t waveform_buffer_threshold = 0;
1207static size_t volatile waveform_buffer_have = 0;
1208static size_t waveform_buffer_break = 0;
1209#define PCM_SAMPLESIZE (2*sizeof(int16_t))
1210#define PCM_BYTERATE (NATIVE_FREQUENCY*PCM_SAMPLESIZE)
1211
1212#define WAVEFORM_SCALE_PCM(full_scale, sample) \
1213 ((((full_scale) * (sample)) + (1 << 14)) >> 15)
1214
1215static void waveform_buffer_set_threshold(size_t threshold)
1216{
1217 if (threshold > sizeof (waveform_buffer))
1218 threshold = sizeof (waveform_buffer);
1219
1220 if (threshold == waveform_buffer_threshold)
1221 return;
1222
1223 /* Avoid changing it in the middle of buffer callback */
1224 rb->pcm_play_lock();
1225
1226 waveform_buffer_threshold = threshold;
1227
1228 rb->pcm_play_unlock();
1229}
1230
1231static inline bool waveform_buffer_have_enough(void)
1232{
1233 return waveform_buffer_have >= waveform_buffer_threshold;
1234}
1235
1236static void waveform_buffer_done(void)
1237{
1238 /* This is safe because buffer callback won't add more data unless the
1239 treshold is changed or data is removed below the threshold. This isn't
1240 called until after the threshold is already met. */
1241 size_t threshold = waveform_buffer_threshold;
1242 size_t have = 0;
1243
1244 if (threshold != 0)
1245 {
1246 have = waveform_buffer_have;
1247 size_t slide = (have - 1) / threshold * threshold;
1248
1249 if (slide == 0)
1250 slide = threshold;
1251
1252 have -= slide;
1253
1254 if (have > 0)
1255 {
1256 /* memcpy: the slide >= threshold and have <= threshold */
1257 memcpy(waveform_buffer, (void *)waveform_buffer + slide, have);
1258 }
1259 }
1260
1261 waveform_buffer_have = have;
1262}
1263
1264/* where the samples are obtained and buffered */
1265static void waveform_buffer_callback(const void *start, size_t size)
1266{
1267 size_t threshold = waveform_buffer_threshold;
1268 size_t have = waveform_buffer_have;
1269
1270 if (have >= threshold)
803 { 1271 {
804 rb->lcd_update(); 1272 waveform_buffer_break += size;
1273 return;
1274 }
1275
1276 if (waveform_buffer_break > 0)
1277 {
1278 /* Previosly missed a part or all of a frame and the break would
1279 happen within the data threshold area. Start where frame would
1280 end up if all had been processed fully. This might mean a period
1281 of resynchronization will have to happen first before the buffer
1282 is filled to the threshold or even begins filling. Maintaining
1283 scan phase relationship is important to proper appearance or else
1284 the waveform display looks sloppy. */
1285 size_t brk = have + waveform_buffer_break;
1286 waveform_buffer_have = have = 0;
1287
1288 brk %= threshold;
1289
1290 if (brk != 0)
1291 {
1292 brk += size;
1293
1294 if (brk <= threshold)
1295 {
1296 waveform_buffer_break = brk;
1297 return;
1298 }
1299
1300 brk -= threshold;
1301 start += size - brk;
1302 size = brk;
1303 }
1304
1305 waveform_buffer_break = 0;
1306 }
1307
1308 size_t remaining = sizeof (waveform_buffer) - have;
1309 size_t copy = size;
1310
1311 if (copy > remaining)
1312 {
1313 waveform_buffer_break = copy - remaining;
1314 copy = remaining;
1315 }
1316
1317 memcpy((void *)waveform_buffer + have, start, copy);
1318
1319 waveform_buffer_have = have + copy;
1320}
1321
1322static void waveform_buffer_reset(void)
1323{
1324 /* only called when callback is off */
1325 waveform_buffer_have = 0;
1326 waveform_buffer_threshold = 0;
1327 waveform_buffer_break = 0;
1328}
1329
1330static void anim_waveform_plot_filled_h(int x, int x_prev,
1331 int vmin, int vmax,
1332 int vmin_prev, int vmax_prev)
1333{
1334 if (vmin != vmax || vmin_prev != vmax_prev)
1335 {
1336 /* Graph compression */
1337 if (vmax > vmin_prev)
1338 vmax = vmin_prev;
1339 else if (vmin < vmax_prev)
1340 vmin = vmax_prev;
1341
1342 rb->lcd_vline(x, vmax, vmin);
805 } 1343 }
806 else 1344 else
807 { 1345 {
808#if LCD_DEPTH > 1 /* cursor bar */ 1346 /* 1:1 or stretch */
809 rb->lcd_set_foreground(CURSOR_COLOR); 1347 rb->lcd_drawline(x_prev, vmin_prev, x, vmin);
810 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1); 1348 }
811 rb->lcd_set_foreground(GRAPH_COLOR); 1349}
812#else 1350
813 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); 1351static void anim_waveform_plot_lines_h(int x, int x_prev,
814 rb->lcd_hline(0, LCD_WIDTH-1, cur_y + 1); 1352 int vmin, int vmax,
815 rb->lcd_set_drawmode(DRMODE_SOLID); 1353 int vmin_prev, int vmax_prev)
1354{
1355 rb->lcd_drawline(x_prev, vmin_prev, x, vmin);
1356
1357 if (vmax_prev != vmin_prev || vmax != vmin)
1358 rb->lcd_drawline(x_prev, vmax_prev, x, vmax);
1359}
1360
1361static void anim_waveform_plot_pixel_h(int x, int x_prev,
1362 int vmin, int vmax,
1363 int vmin_prev, int vmax_prev)
1364{
1365 rb->lcd_drawpixel(x, vmin);
1366
1367 if (vmax != vmin)
1368 rb->lcd_drawpixel(x, vmax);
1369
1370 (void)x_prev; (void)vmin_prev; (void)vmax_prev;
1371}
1372
1373static long anim_waveform_horizontal(void)
1374{
1375 static void (* const plot[MAX_DRAW])(int, int, int, int, int, int) =
1376 {
1377 [DRAW_FILLED] = anim_waveform_plot_filled_h,
1378 [DRAW_LINE] = anim_waveform_plot_lines_h,
1379 [DRAW_PIXEL] = anim_waveform_plot_pixel_h,
1380 };
1381
1382 long cur_tick = *rb->current_tick;
1383
1384 if (rb->mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK) != CHANNEL_PLAYING)
1385 {
1386 osd_lcd_update_prepare();
1387 rb->lcd_hline(0, LCD_WIDTH-1, 1*LCD_HEIGHT/4);
1388 rb->lcd_hline(0, LCD_WIDTH-1, 3*LCD_HEIGHT/4);
1389 osd_lcd_update();
1390 one_frame_paused = false;
1391 return cur_tick + HZ/5;
1392 }
1393
1394 int count = (NATIVE_FREQUENCY*osc_delay + 100*HZ - 1) / (100*HZ);
1395
1396 waveform_buffer_set_threshold(count*PCM_SAMPLESIZE);
1397
1398 if (!waveform_buffer_have_enough())
1399 return cur_tick + HZ/100;
1400
1401 one_frame_paused = false;
1402
1403 osd_lcd_update_prepare();
1404
1405 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1406 rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT);
1407 rb->lcd_set_drawmode(DRMODE_SOLID);
1408#if LCD_DEPTH > 1
1409 rb->lcd_set_foreground(GRAPH_COLOR);
816#endif 1410#endif
817 1411
818 if (cur_y > last_pos) 1412 int x = 0, x_prev = count - 1;
1413 int x_step = (LCD_WIDTH-1) / x_prev;
1414 int x_a_step = (LCD_WIDTH-1) - x_step * x_prev;
1415 int x_a = 0;
1416
1417 int idx_step = (count / LCD_WIDTH) * 2;
1418 int idx_a_step = count - idx_step * (LCD_WIDTH/2);
1419 int idx = idx_step, idx_prev = 0;
1420 int idx_a = idx_a_step;
1421
1422 int a_lim = MIN(x_prev, LCD_WIDTH-1);
1423
1424 int lmin, lmin_prev = 0;
1425 int rmin, rmin_prev = 0;
1426 int lmax, lmax_prev = 0;
1427 int rmax, rmax_prev = 0;
1428
1429 if (osc.draw == DRAW_PIXEL)
1430 goto plot_start_noprev; /* Doesn't need previous points */
1431
1432 lmax = lmin = waveform_buffer[0];
1433 rmax = rmin = waveform_buffer[1];
1434
1435 /* Find min-max envelope for interval */
1436 for (int i = 2; i < idx; i += 2)
1437 {
1438 int sl = waveform_buffer[i + 0];
1439 int sr = waveform_buffer[i + 1];
1440
1441 if (sl < lmin)
1442 lmin = sl;
1443 if (sl > lmax)
1444 lmax = sl;
1445
1446 if (sr < rmin)
1447 rmin = sr;
1448 if (sr > rmax)
1449 rmax = sr;
1450 }
1451
1452 lmin = (1*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, lmin);
1453 lmax = (1*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, lmax);
1454 rmin = (3*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, rmin);
1455 rmax = (3*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, rmax);
1456
1457 while (1)
1458 {
1459 x_prev = x;
1460 x += x_step;
1461 x_a += x_a_step;
1462
1463 if (x_a >= a_lim)
819 { 1464 {
820 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, cur_y - last_pos + 2); 1465 x_a -= a_lim;
1466 x++;
821 } 1467 }
822 else 1468
1469 if (x >= LCD_WIDTH)
1470 break;
1471
1472 idx_prev = idx;
1473 idx += idx_step;
1474 idx_a += idx_a_step;
1475
1476 if (idx_a > a_lim)
823 { 1477 {
824 rb->lcd_update_rect(0, last_pos, LCD_WIDTH, LCD_HEIGHT - last_pos); 1478 idx_a -= a_lim + 1;
825 rb->lcd_update_rect(0, 0, LCD_WIDTH, cur_y + 2); 1479 idx += 2;
826 } 1480 }
1481
1482 lmin_prev = lmin, lmax_prev = lmax;
1483 rmin_prev = rmin, rmax_prev = rmax;
1484
1485 plot_start_noprev:
1486 lmax = lmin = waveform_buffer[idx_prev + 0];
1487 rmax = rmin = waveform_buffer[idx_prev + 1];
1488
1489 /* Find min-max envelope for interval */
1490 for (int i = idx_prev + 2; i < idx; i += 2)
1491 {
1492 int sl = waveform_buffer[i + 0];
1493 int sr = waveform_buffer[i + 1];
1494
1495 if (sl < lmin)
1496 lmin = sl;
1497 if (sl > lmax)
1498 lmax = sl;
1499
1500 if (sr < rmin)
1501 rmin = sr;
1502 if (sr > rmax)
1503 rmax = sr;
1504 }
1505
1506 lmin = (1*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, lmin);
1507 lmax = (1*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, lmax);
1508 rmin = (3*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, rmin);
1509 rmax = (3*LCD_HEIGHT/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT/4-1, rmax);
1510
1511 plot[osc.draw](x, x_prev, lmin, lmax, lmin_prev, lmax_prev);
1512 plot[osc.draw](x, x_prev, rmin, rmax, rmin_prev, rmax_prev);
827 } 1513 }
828 last_pos = cur_y; 1514
1515 waveform_buffer_done();
1516
1517 osd_lcd_update();
1518
1519 long delay = get_next_delay();
1520 return cur_tick + delay - waveform_buffer_have * HZ / PCM_BYTERATE;
1521}
1522
1523static void anim_waveform_plot_filled_v(int y, int y_prev,
1524 int vmin, int vmax,
1525 int vmin_prev, int vmax_prev)
1526{
1527 if (vmin != vmax || vmin_prev != vmax_prev)
1528 {
1529 /* Graph compression */
1530 if (vmax < vmin_prev)
1531 vmax = vmin_prev;
1532 else if (vmin > vmax_prev)
1533 vmin = vmax_prev;
1534
1535 rb->lcd_hline(vmin, vmax, y);
1536 }
1537 else
1538 {
1539 /* 1:1 or stretch */
1540 rb->lcd_drawline(vmin_prev, y_prev, vmin, y);
1541 }
1542}
1543
1544static void anim_waveform_plot_lines_v(int y, int y_prev,
1545 int vmin, int vmax,
1546 int vmin_prev, int vmax_prev)
1547{
1548 rb->lcd_drawline(vmin_prev, y_prev, vmin, y);
1549
1550 if (vmax_prev != vmin_prev || vmax != vmin)
1551 rb->lcd_drawline(vmax_prev, y_prev, vmax, y);
1552}
1553
1554static void anim_waveform_plot_pixel_v(int y, int y_prev,
1555 int vmin, int vmax,
1556 int vmin_prev, int vmax_prev)
1557{
1558 rb->lcd_drawpixel(vmin, y);
1559
1560 if (vmax != vmin)
1561 rb->lcd_drawpixel(vmax, y);
1562
1563 (void)y_prev; (void)vmin_prev; (void)vmax_prev;
1564}
1565
1566static long anim_waveform_vertical(void)
1567{
1568 static void (* const plot[MAX_DRAW])(int, int, int, int, int, int) =
1569 {
1570 [DRAW_FILLED] = anim_waveform_plot_filled_v,
1571 [DRAW_LINE] = anim_waveform_plot_lines_v,
1572 [DRAW_PIXEL] = anim_waveform_plot_pixel_v,
1573 };
1574
1575 long cur_tick = *rb->current_tick;
1576
1577 if (rb->mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK) != CHANNEL_PLAYING)
1578 {
1579 osd_lcd_update_prepare();
1580 rb->lcd_vline(1*LCD_WIDTH/4, 0, LCD_HEIGHT-1);
1581 rb->lcd_vline(3*LCD_WIDTH/4, 0, LCD_HEIGHT-1);
1582 osd_lcd_update();
1583 one_frame_paused = false;
1584 return cur_tick + HZ/5;
1585 }
1586
1587 int count = (NATIVE_FREQUENCY*osc_delay + 100*HZ - 1) / (100*HZ);
1588
1589 waveform_buffer_set_threshold(count*PCM_SAMPLESIZE);
1590
1591 if (!waveform_buffer_have_enough())
1592 return cur_tick + HZ/100;
1593
1594 one_frame_paused = false;
1595
1596 osd_lcd_update_prepare();
1597
1598 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1599 rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT);
1600 rb->lcd_set_drawmode(DRMODE_SOLID);
1601#if LCD_DEPTH > 1
1602 rb->lcd_set_foreground(GRAPH_COLOR);
1603#endif
1604
1605 int y = 0, y_prev = count - 1;
1606 int y_step = (LCD_HEIGHT-1) / y_prev;
1607 int y_a_step = (LCD_HEIGHT-1) - y_step * y_prev;
1608 int y_a = 0;
1609
1610 int idx_step = (count / LCD_HEIGHT) * 2;
1611 int idx_a_step = count - idx_step * (LCD_HEIGHT/2);
1612 int idx = idx_step, idx_prev = 0;
1613 int idx_a = idx_a_step;
1614
1615 int a_lim = MIN(y_prev, LCD_HEIGHT-1);
1616
1617 int lmin, lmin_prev = 0;
1618 int rmin, rmin_prev = 0;
1619 int lmax, lmax_prev = 0;
1620 int rmax, rmax_prev = 0;
1621
1622 if (osc.draw == DRAW_PIXEL)
1623 goto plot_start_noprev; /* Doesn't need previous points */
1624
1625 lmax = lmin = waveform_buffer[0];
1626 rmax = rmin = waveform_buffer[1];
1627
1628 /* Find min-max envelope for interval */
1629 for (int i = 2; i < idx; i += 2)
1630 {
1631 int sl = waveform_buffer[i + 0];
1632 int sr = waveform_buffer[i + 1];
1633
1634 if (sl < lmin)
1635 lmin = sl;
1636 if (sl > lmax)
1637 lmax = sl;
1638
1639 if (sr < rmin)
1640 rmin = sr;
1641 if (sr > rmax)
1642 rmax = sr;
1643 }
1644
1645 lmin = (1*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, lmin);
1646 lmax = (1*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, lmax);
1647 rmin = (3*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, rmin);
1648 rmax = (3*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, rmax);
1649
1650 while (1)
1651 {
1652 y_prev = y;
1653 y += y_step;
1654 y_a += y_a_step;
1655
1656 if (y_a >= a_lim)
1657 {
1658 y_a -= a_lim;
1659 y++;
1660 }
1661
1662 if (y >= LCD_HEIGHT)
1663 break;
1664
1665 idx_prev = idx;
1666 idx += idx_step;
1667 idx_a += idx_a_step;
1668
1669 if (idx_a > a_lim)
1670 {
1671 idx_a -= a_lim + 1;
1672 idx += 2;
1673 }
1674
1675 lmin_prev = lmin, lmax_prev = lmax;
1676 rmin_prev = rmin, rmax_prev = rmax;
1677
1678 plot_start_noprev:
1679 lmax = lmin = waveform_buffer[idx_prev + 0];
1680 rmax = rmin = waveform_buffer[idx_prev + 1];
1681
1682 /* Find min-max envelope for interval */
1683 for (int i = idx_prev + 2; i < idx; i += 2)
1684 {
1685 int sl = waveform_buffer[i + 0];
1686 int sr = waveform_buffer[i + 1];
1687
1688 if (sl < lmin)
1689 lmin = sl;
1690 if (sl > lmax)
1691 lmax = sl;
1692
1693 if (sr < rmin)
1694 rmin = sr;
1695 if (sr > rmax)
1696 rmax = sr;
1697 }
1698
1699 lmin = (1*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, lmin);
1700 lmax = (1*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, lmax);
1701 rmin = (3*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, rmin);
1702 rmax = (3*LCD_WIDTH/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH/4-1, rmax);
1703
1704 plot[osc.draw](y, y_prev, lmin, lmax, lmin_prev, lmax_prev);
1705 plot[osc.draw](y, y_prev, rmin, rmax, rmin_prev, rmax_prev);
1706 }
1707
1708 waveform_buffer_done();
1709
1710 osd_lcd_update();
1711
1712 long delay = get_next_delay();
1713 return cur_tick + delay - waveform_buffer_have * HZ / PCM_BYTERATE;
1714}
1715
1716static void anim_waveform_exit(void)
1717{
1718 /* Remove any buffer hook */
1719 rb->mixer_channel_set_buffer_hook(PCM_MIXER_CHAN_PLAYBACK, NULL);
1720#ifdef HAVE_SCHEDULER_BOOSTCTRL
1721 /* Remove our boost */
1722 rb->cancel_cpu_boost();
1723#endif
1724}
1725#endif /* OSCILLOSCOPE_GRAPHMODE */
1726
1727static void graphmode_reset(void)
1728{
1729 static long (* const fns[MAX_GRAPH][MAX_OSC])(void) =
1730 {
1731 [GRAPH_PEAKS] =
1732 {
1733 [OSC_HORIZ] = anim_peaks_horizontal,
1734 [OSC_VERT] = anim_peaks_vertical,
1735 },
1736#ifdef OSCILLOSCOPE_GRAPHMODE
1737 [GRAPH_WAVEFORM] =
1738 {
1739 [OSC_HORIZ] = anim_waveform_horizontal,
1740 [OSC_VERT] = anim_waveform_vertical,
1741 },
1742#endif /* OSCILLOSCOPE_GRAPHMODE */
1743 };
1744
1745 /* For peaks view */
1746 last_left = 0;
1747 last_right = 0;
1748 last_pos = 0;
1749 last_tick = *rb->current_tick;
1750 last_delay = 1;
1751
1752 /* General */
1753 osd_lcd_update_prepare();
1754 rb->lcd_clear_display();
1755 osd_lcd_update();
1756
1757 one_frame_paused = true;
1758 osd_set_timeout(paused ? 4*HZ : HZ);
1759 anim_draw = fns[osc.graphmode][osc.orientation];
1760}
1761
1762static void graphmode_pause_unpause(bool paused)
1763{
1764 if (paused)
1765 return;
1766
1767 last_tick = *rb->current_tick;
1768 osd_set_timeout(HZ);
1769 one_frame_paused = false;
1770#ifdef OSCILLOSCOPE_GRAPHMODE
1771 if (osc.graphmode == GRAPH_WAVEFORM)
1772 waveform_buffer_done();
1773#endif /* OSCILLOSCOPE_GRAPHMODE */
1774}
1775
1776static void update_osc_delay(int value)
1777{
1778 osc_delay = osc_delay_tbl[value - 1];
1779 osc_delay_error = 0;
829} 1780}
830 1781
831static void cleanup(void) 1782static void graphmode_setup(void)
832{ 1783{
1784#ifdef OSCILLOSCOPE_GRAPHMODE
1785 if (osc.graphmode == GRAPH_WAVEFORM)
1786 {
1787 rb->mixer_channel_set_buffer_hook(PCM_MIXER_CHAN_PLAYBACK,
1788 waveform_buffer_callback);
1789#ifdef HAVE_SCHEDULER_BOOSTCTRL
1790 rb->trigger_cpu_boost(); /* Just looks better */
1791#endif
1792 }
1793 else
1794 {
1795 rb->mixer_channel_set_buffer_hook(PCM_MIXER_CHAN_PLAYBACK,
1796 NULL);
1797#ifdef HAVE_SCHEDULER_BOOSTCTRL
1798 rb->cancel_cpu_boost();
1799#endif
1800 waveform_buffer_reset();
1801 }
1802#endif /* OSCILLOSCOPE_GRAPHMODE */
1803
1804 update_osc_delay(osc.speed[osc.graphmode]);
1805 graphmode_reset();
1806}
1807
1808static long oscilloscope_draw(void)
1809{
1810 if (message != -1)
1811 {
1812 osc_osd_show_message((enum osc_message_ids)message, msgval);
1813 message = -1;
1814 }
1815 else
1816 {
1817 osd_monitor_timeout();
1818 }
1819
1820 long delay = HZ/5;
1821
1822 if (!paused || one_frame_paused)
1823 {
1824 delay = anim_draw() - *rb->current_tick;
1825
1826 if (delay > HZ/5)
1827 delay = HZ/5;
1828 }
1829
1830 return delay;
1831}
1832
1833static void osc_cleanup(void)
1834{
1835 osd_init(NULL, 0, NULL);
1836
1837#ifdef OSCILLOSCOPE_GRAPHMODE
1838 anim_waveform_exit();
1839#endif
1840
833#if LCD_DEPTH > 1 1841#if LCD_DEPTH > 1
834 rb->lcd_set_foreground(LCD_DEFAULT_FG); 1842 rb->lcd_set_foreground(LCD_DEFAULT_FG);
835 rb->lcd_set_background(LCD_DEFAULT_BG); 1843 rb->lcd_set_background(LCD_DEFAULT_BG);
836#endif 1844#endif
837 /* Turn on backlight timeout (revert to settings) */ 1845 /* Turn on backlight timeout (revert to settings) */
838 backlight_use_settings(); 1846 backlight_use_settings();
839}
840 1847
841enum plugin_status plugin_start(const void* parameter)
842{
843 int button, vol;
844#if defined(OSCILLOSCOPE_DRAWMODE_PRE) || defined(OSCILLOSCOPE_ORIENTATION_PRE)
845 int lastbutton = BUTTON_NONE;
846#endif
847 bool exit = false;
848 bool paused = false;
849 bool tell_speed;
850 1848
851 (void)parameter; 1849 /* save settings if changed */
1850 if (rb->memcmp(&osc, &osc_disk, sizeof(osc)))
1851 {
1852 rb->memcpy(&osc_disk, &osc, sizeof(osc));
1853 configfile_save(cfg_filename, disk_config, ARRAYLEN(disk_config),
1854 CFGFILE_VERSION);
1855 }
1856}
852 1857
853 atexit(cleanup); 1858static void osc_setup(void)
854 configfile_load(cfg_filename, disk_config, 1859{
855 sizeof(disk_config) / sizeof(disk_config[0]), 1860 atexit(osc_cleanup);
1861 configfile_load(cfg_filename, disk_config, ARRAYLEN(disk_config),
856 CFGFILE_MINVERSION); 1862 CFGFILE_MINVERSION);
857 rb->memcpy(&osc, &osc_disk, sizeof(osc)); /* copy to running config */ 1863 osc = osc_disk; /* copy to running config */
1864
1865 osc_osd_init();
858 1866
859#if LCD_DEPTH > 1 1867#if LCD_DEPTH > 1
1868 osd_lcd_update_prepare();
860 rb->lcd_set_foreground(GRAPH_COLOR); 1869 rb->lcd_set_foreground(GRAPH_COLOR);
861 rb->lcd_set_background(BACKG_COLOR); 1870 rb->lcd_set_background(BACKG_COLOR);
862 rb->lcd_set_backdrop(NULL); 1871 rb->lcd_set_backdrop(NULL);
863 rb->lcd_clear_display(); 1872 rb->lcd_clear_display();
864 rb->lcd_update(); 1873 osd_lcd_update();
865#endif 1874#endif
866 1875
867 /* Turn off backlight timeout */ 1876 /* Turn off backlight timeout */
868 backlight_ignore_timeout(); 1877 backlight_ignore_timeout();
1878 graphmode_setup();
1879}
1880
1881enum plugin_status plugin_start(const void* parameter)
1882{
1883 bool exit = false;
1884#ifdef NEED_LASTBUTTON
1885 int lastbutton = BUTTON_NONE;
1886#endif
869 1887
870 rb->lcd_getstringsize("A", NULL, &font_height); 1888 osc_setup();
871 1889
872 while (!exit) 1890 while (!exit)
873 { 1891 {
874 if (!paused) 1892 long delay = oscilloscope_draw();
875 {
876 int left, right;
877
878 rb->sleep(MAX(last_tick + osc.delay - *rb->current_tick - 1, 0));
879 1893
880#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 1894 if (delay <= 0)
881 left = rb->mas_codec_readreg(0xC); 1895 {
882 right = rb->mas_codec_readreg(0xD); 1896 delay = 0;
883#elif (CONFIG_CODEC == SWCODEC) 1897 rb->yield(); /* tmo = 0 won't yield */
884 static struct pcm_peaks peaks;
885 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
886 &peaks);
887 left = peaks.left; right = peaks.right;
888#endif
889 if (osc.orientation == OSC_HORIZ)
890 anim_horizontal(left, right);
891 else
892 anim_vertical(left, right);
893 } 1898 }
894 1899
895 tell_speed = false; 1900 int button = rb->button_get_w_tmo(delay);
896 button = rb->button_get(paused); 1901
897 switch (button) 1902 switch (button)
898 { 1903 {
899#ifdef OSCILLOSCOPE_RC_QUIT 1904#ifdef OSCILLOSCOPE_RC_QUIT
@@ -904,8 +1909,14 @@ enum plugin_status plugin_start(const void* parameter)
904 break; 1909 break;
905 1910
906 case OSCILLOSCOPE_ADVMODE: 1911 case OSCILLOSCOPE_ADVMODE:
1912#ifdef OSCILLOSCOPE_GRAPHMODE
1913 if (osc.graphmode == GRAPH_WAVEFORM)
1914 break; /* Not applicable */
1915#endif
907 if (++osc.advance >= MAX_ADV) 1916 if (++osc.advance >= MAX_ADV)
908 osc.advance = 0; 1917 osc.advance = 0;
1918
1919 osc_popupmsg(OSC_MSG_ADVMODE, osc.advance);
909 break; 1920 break;
910 1921
911 case OSCILLOSCOPE_DRAWMODE: 1922 case OSCILLOSCOPE_DRAWMODE:
@@ -915,7 +1926,26 @@ enum plugin_status plugin_start(const void* parameter)
915#endif 1926#endif
916 if (++osc.draw >= MAX_DRAW) 1927 if (++osc.draw >= MAX_DRAW)
917 osc.draw = 0; 1928 osc.draw = 0;
1929
1930 osc_popupmsg(OSC_MSG_DRAWMODE, osc.draw);
918 break; 1931 break;
1932
1933 /* Need all keymaps for this (remove extra condition when
1934 completed) */
1935#ifdef OSCILLOSCOPE_GRAPHMODE
1936 case OSCILLOSCOPE_GRAPHMODE:
1937#ifdef OSCILLOSCOPE_GRAPHMODE_PRE
1938 if (lastbutton != OSCILLOSCOPE_GRAPHMODE_PRE)
1939 break;
1940#endif
1941 if (++osc.graphmode >= MAX_GRAPH)
1942 osc.graphmode = 0;
1943
1944 graphmode_setup();
1945
1946 osc_popupmsg(OSC_MSG_GRAPHMODE, osc.graphmode);
1947 break;
1948#endif /* OSCILLOSCOPE_GRAPHMODE */
919 1949
920 case OSCILLOSCOPE_ORIENTATION: 1950 case OSCILLOSCOPE_ORIENTATION:
921#ifdef OSCILLOSCOPE_ORIENTATION_PRE 1951#ifdef OSCILLOSCOPE_ORIENTATION_PRE
@@ -924,78 +1954,90 @@ enum plugin_status plugin_start(const void* parameter)
924#endif 1954#endif
925 if (++osc.orientation >= MAX_OSC) 1955 if (++osc.orientation >= MAX_OSC)
926 osc.orientation = 0; 1956 osc.orientation = 0;
927 last_pos = 0; 1957
928 last_tick = 0; 1958 graphmode_reset();
929 displaymsg = false; 1959 osc_popupmsg(OSC_MSG_ORIENTATION, osc.orientation);
930 rb->lcd_clear_display();
931 rb->lcd_update();
932 break; 1960 break;
933 1961
934 case OSCILLOSCOPE_PAUSE: 1962 case OSCILLOSCOPE_PAUSE:
1963#ifdef OSCILLOSCOPE_PAUSE_PRE
1964 if (lastbutton != OSCILLOSCOPE_PAUSE_PRE)
1965 break;
1966#endif
935 paused = !paused; 1967 paused = !paused;
936 last_tick = 0; 1968 graphmode_pause_unpause(paused);
1969 osc_popupmsg(OSC_MSG_PAUSED, paused ? 1 : 0);
937 break; 1970 break;
938 1971
939 case OSCILLOSCOPE_SPEED_UP: 1972 case OSCILLOSCOPE_SPEED_UP:
940 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT: 1973 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
941 if (osc.delay > 1) 1974 {
942 { 1975 int *val = &osc.speed[osc.graphmode];
943 osc.delay--; 1976
944 tell_speed = true; 1977 if (*val < MAX_SPEED)
945 } 1978 ++*val;
1979
1980 update_osc_delay(*val);
1981 osc_popupmsg(OSC_MSG_SPEED, *val);
946 break; 1982 break;
1983 }
947 1984
948 case OSCILLOSCOPE_SPEED_DOWN: 1985 case OSCILLOSCOPE_SPEED_DOWN:
949 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT: 1986 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
950 osc.delay++; 1987 {
951 tell_speed = true; 1988 int *val = &osc.speed[osc.graphmode];
1989
1990 if (*val > MIN_SPEED)
1991 --*val;
1992
1993 update_osc_delay(*val);
1994 osc_popupmsg(OSC_MSG_SPEED, *val);
952 break; 1995 break;
1996 }
953 1997
954 case OSCILLOSCOPE_VOL_UP: 1998 case OSCILLOSCOPE_VOL_UP:
955 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT: 1999 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
956 vol = rb->global_settings->volume; 2000 {
2001 int vol = rb->global_settings->volume;
2002
957 if (vol < rb->sound_max(SOUND_VOLUME)) 2003 if (vol < rb->sound_max(SOUND_VOLUME))
958 { 2004 {
959 vol++; 2005 vol++;
960 rb->sound_set(SOUND_VOLUME, vol); 2006 rb->sound_set(SOUND_VOLUME, vol);
961 rb->global_settings->volume = vol; 2007 rb->global_settings->volume = vol;
962 } 2008 }
2009
2010 osc_popupmsg(OSC_MSG_VOLUME, vol);
963 break; 2011 break;
2012 }
964 2013
965 case OSCILLOSCOPE_VOL_DOWN: 2014 case OSCILLOSCOPE_VOL_DOWN:
966 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT: 2015 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
967 vol = rb->global_settings->volume; 2016 {
2017 int vol = rb->global_settings->volume;
2018
968 if (vol > rb->sound_min(SOUND_VOLUME)) 2019 if (vol > rb->sound_min(SOUND_VOLUME))
969 { 2020 {
970 vol--; 2021 vol--;
971 rb->sound_set(SOUND_VOLUME, vol); 2022 rb->sound_set(SOUND_VOLUME, vol);
972 rb->global_settings->volume = vol; 2023 rb->global_settings->volume = vol;
973 } 2024 }
2025
2026 osc_popupmsg(OSC_MSG_VOLUME, vol);
974 break; 2027 break;
2028 }
975 2029
976 default: 2030 default:
977 exit_on_usb(button); 2031 exit_on_usb(button);
978 break; 2032 break;
979 } 2033 }
980#if defined(OSCILLOSCOPE_DRAWMODE_PRE) || defined(OSCILLOSCOPE_ORIENTATION_PRE) 2034
2035#ifdef NEED_LASTBUTTON
981 if (button != BUTTON_NONE) 2036 if (button != BUTTON_NONE)
982 lastbutton = button; 2037 lastbutton = button;
983#endif 2038#endif
2039 } /* while */
984 2040
985 if (tell_speed)
986 {
987 rb->snprintf(message, sizeof(message), "%s%d",
988 (osc.orientation == OSC_VERT) ? "Speed: " : "",
989 100 / osc.delay);
990 displaymsg = true;
991 }
992 }
993 if (rb->memcmp(&osc, &osc_disk, sizeof(osc))) /* save settings if changed */
994 {
995 rb->memcpy(&osc_disk, &osc, sizeof(osc));
996 configfile_save(cfg_filename, disk_config,
997 sizeof(disk_config) / sizeof(disk_config[0]),
998 CFGFILE_VERSION);
999 }
1000 return PLUGIN_OK; 2041 return PLUGIN_OK;
2042 (void)parameter;
1001} 2043}