1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Oscilloscope, with many different modes of operation.
12 * Copyright (C) 2004-2006 Jens Arnold
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "lib/helper.h"
26 #include "lib/pluginlib_exit.h"
29 #include "lib/configfile.h"
30 #include "fixedpoint.h"
31 #include "lib/fixedpoint.h"
34 /* variable button definitions */
35 #if CONFIG_KEYPAD == RECORDER_PAD
36 #define OSCILLOSCOPE_QUIT BUTTON_OFF
37 #define OSCILLOSCOPE_DRAWMODE BUTTON_F1
38 #define OSCILLOSCOPE_ADVMODE BUTTON_F2
39 #define OSCILLOSCOPE_ORIENTATION BUTTON_F3
40 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
41 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
42 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
43 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
44 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
46 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
47 #define OSCILLOSCOPE_QUIT BUTTON_OFF
48 #define OSCILLOSCOPE_DRAWMODE BUTTON_F1
49 #define OSCILLOSCOPE_ADVMODE BUTTON_F2
50 #define OSCILLOSCOPE_ORIENTATION BUTTON_F3
51 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
52 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
53 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
54 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
55 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
57 #elif CONFIG_KEYPAD == ONDIO_PAD
58 #define OSCILLOSCOPE_QUIT BUTTON_OFF
59 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_MENU
60 #define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_REL)
61 #define OSCILLOSCOPE_ADVMODE (BUTTON_MENU | BUTTON_RIGHT)
62 #define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_LEFT)
63 #define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF)
64 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
65 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
66 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
67 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
68 #define NEED_LASTBUTTON
70 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
71 #define OSCILLOSCOPE_QUIT BUTTON_OFF
72 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
73 #define OSCILLOSCOPE_ADVMODE BUTTON_MODE
74 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REC
75 #define OSCILLOSCOPE_ORIENTATION (BUTTON_REC | BUTTON_REL)
76 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_REC
77 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_REC | BUTTON_REPEAT)
78 #define OSCILLOSCOPE_PAUSE BUTTON_ON
79 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
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
86 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
87 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
88 #define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
89 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY)
90 #define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
91 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
92 #define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
93 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
94 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
95 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
96 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
97 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
100 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
101 #define OSCILLOSCOPE_QUIT BUTTON_POWER
102 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
103 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
104 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
105 #define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
106 #define OSCILLOSCOPE_PAUSE BUTTON_A
107 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
108 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
109 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
110 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
112 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
113 #define OSCILLOSCOPE_QUIT BUTTON_POWER
114 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
115 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
116 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
117 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
118 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
119 #define OSCILLOSCOPE_PAUSE_PRE BUTTON_UP
120 #define OSCILLOSCOPE_PAUSE (BUTTON_UP | BUTTON_REL)
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
129 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
130 #define OSCILLOSCOPE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
131 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
132 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
133 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
134 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
135 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
136 #define OSCILLOSCOPE_PAUSE_PRE BUTTON_UP
137 #define OSCILLOSCOPE_PAUSE (BUTTON_UP | BUTTON_REL)
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
146 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
147 #define OSCILLOSCOPE_QUIT BUTTON_POWER
148 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
149 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
150 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
151 #define OSCILLOSCOPE_PAUSE BUTTON_REC
152 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
153 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
154 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
155 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
156 /* v1 - Need GRAPHMODE */
157 /* v2 - Not enough plugin RAM for waveform view */
159 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
160 #define OSCILLOSCOPE_QUIT BUTTON_POWER
161 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
162 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
163 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
164 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
165 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
166 #define OSCILLOSCOPE_PAUSE BUTTON_UP
167 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
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 */
174 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
175 #define OSCILLOSCOPE_QUIT BUTTON_POWER
176 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
177 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
178 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
179 #define OSCILLOSCOPE_PAUSE (BUTTON_SELECT | BUTTON_UP)
180 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
181 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
182 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
183 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
184 /* Not enough plugin RAM for waveform view */
186 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
187 #define OSCILLOSCOPE_QUIT BUTTON_POWER
188 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
189 #define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REL)
190 #define OSCILLOSCOPE_ADVMODE BUTTON_REC
191 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_SELECT
192 #define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_REPEAT)
193 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_PLAY
194 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_PLAY | BUTTON_REPEAT)
195 #define OSCILLOSCOPE_PAUSE_PRE BUTTON_PLAY
196 #define OSCILLOSCOPE_PAUSE (BUTTON_PLAY | BUTTON_REL)
197 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
198 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
199 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
200 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
201 #define NEED_LASTBUTTON
203 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
204 #define OSCILLOSCOPE_QUIT BUTTON_POWER
205 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_REW
206 #define OSCILLOSCOPE_DRAWMODE (BUTTON_REW | BUTTON_REL)
207 #define OSCILLOSCOPE_ADVMODE BUTTON_FF
208 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_REW
209 #define OSCILLOSCOPE_ORIENTATION (BUTTON_REW | BUTTON_REPEAT)
210 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_PLAY
211 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_PLAY | BUTTON_REPEAT)
212 #define OSCILLOSCOPE_PAUSE_PRE BUTTON_PLAY
213 #define OSCILLOSCOPE_PAUSE (BUTTON_PLAY | BUTTON_REL)
214 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
215 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
216 #define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_UP
217 #define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_DOWN
218 #define NEED_LASTBUTTON
220 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
221 #define OSCILLOSCOPE_QUIT BUTTON_BACK
222 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
223 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
224 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
225 #define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
226 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
227 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
228 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
229 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
230 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
232 #elif (CONFIG_KEYPAD == MROBE100_PAD)
233 #define OSCILLOSCOPE_QUIT BUTTON_POWER
234 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
235 #define OSCILLOSCOPE_ADVMODE BUTTON_MENU
236 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_PLAY
237 #define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY | BUTTON_REL)
238 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_PLAY
239 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_PLAY | BUTTON_REPEAT)
240 #define OSCILLOSCOPE_PAUSE BUTTON_DISPLAY
241 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
242 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
243 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
244 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
245 #define NEED_LASTBUTTON
247 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
248 #define OSCILLOSCOPE_QUIT BUTTON_RC_REC
249 #define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_RC_MODE
250 #define OSCILLOSCOPE_DRAWMODE (BUTTON_RC_MODE|BUTTON_REL)
251 #define OSCILLOSCOPE_ADVMODE BUTTON_RC_MENU
252 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_RC_MODE
253 #define OSCILLOSCOPE_ORIENTATION (BUTTON_RC_MODE|BUTTON_REPEAT)
254 #define OSCILLOSCOPE_PAUSE_PRE BUTTON_RC_PLAY
255 #define OSCILLOSCOPE_PAUSE (BUTTON_RC_PLAY|BUTTON_REL)
256 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_RC_PLAY
257 #define SCILLLOSCOPE_GRAPHMODE (BUTTON_RC_PLAY|BUTTON_REPEAT)
258 #define OSCILLOSCOPE_SPEED_UP BUTTON_RC_FF
259 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_RC_REW
260 #define OSCILLOSCOPE_VOL_UP BUTTON_RC_VOL_UP
261 #define OSCILLOSCOPE_VOL_DOWN BUTTON_RC_VOL_DOWN
262 #define NEED_LASTBUTTON
264 #elif CONFIG_KEYPAD == COWON_D2_PAD
265 #define OSCILLOSCOPE_QUIT BUTTON_POWER
266 #define OSCILLOSCOPE_VOL_UP BUTTON_PLUS
267 #define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS
269 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
270 #define OSCILLOSCOPE_QUIT BUTTON_BACK
271 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
272 #define OSCILLOSCOPE_ADVMODE BUTTON_CUSTOM
273 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_MENU
274 #define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_REL)
275 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_MENU
276 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_MENU | BUTTON_REPEAT)
277 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
278 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
279 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
280 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
281 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
282 #define NEED_LASTBUTTON
284 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
285 #define OSCILLOSCOPE_QUIT BUTTON_POWER
286 #define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
287 #define OSCILLOSCOPE_ADVMODE BUTTON_VIEW
288 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
289 #define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
290 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
291 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
292 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
293 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
294 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
295 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
296 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
297 #define NEED_LASTBUTTON
299 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
300 #define OSCILLOSCOPE_QUIT BUTTON_POWER
301 #define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
302 #define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT
303 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
304 #define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
305 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
306 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
307 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
308 #define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
309 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
310 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
311 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
312 #define NEED_LASTBUTTON
314 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
315 #define OSCILLOSCOPE_QUIT BUTTON_POWER
316 #define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
317 #define OSCILLOSCOPE_ADVMODE BUTTON_RIGHT
318 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
319 #define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
320 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
321 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
322 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
323 #define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
324 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
325 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
326 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
327 #define NEED_LASTBUTTON
329 #elif CONFIG_KEYPAD == ONDAVX747_PAD
330 #define OSCILLOSCOPE_QUIT BUTTON_POWER
331 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
332 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
334 #elif CONFIG_KEYPAD == ONDAVX777_PAD
335 #define OSCILLOSCOPE_QUIT BUTTON_POWER
337 #elif CONFIG_KEYPAD == MROBE500_PAD
338 #define OSCILLOSCOPE_QUIT BUTTON_POWER
340 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
341 #define OSCILLOSCOPE_QUIT BUTTON_REC
342 #define OSCILLOSCOPE_DRAWMODE (BUTTON_PLAY|BUTTON_LEFT)
343 #define OSCILLOSCOPE_ADVMODE (BUTTON_PLAY|BUTTON_RIGHT)
344 #define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY|BUTTON_UP)
345 #define OSCILLOSCOPE_PAUSE (BUTTON_PLAY|BUTTON_DOWN)
346 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
347 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
348 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
349 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
352 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
353 #define OSCILLOSCOPE_QUIT BUTTON_REC
354 #define OSCILLOSCOPE_DRAWMODE BUTTON_MENU
355 #define OSCILLOSCOPE_ADVMODE BUTTON_CANCEL
356 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_OK
357 #define OSCILLOSCOPE_ORIENTATION (BUTTON_OK | BUTTON_REL)
358 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_OK
359 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_OK | BUTTON_REPEAT)
360 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
361 #define OSCILLOSCOPE_SPEED_UP BUTTON_PREV
362 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_NEXT
363 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
364 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
365 #define NEED_LASTBUTTON
367 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
368 #define OSCILLOSCOPE_QUIT (BUTTON_REC | BUTTON_PLAY)
369 #define OSCILLOSCOPE_DRAWMODE BUTTON_FUNC
370 #define OSCILLOSCOPE_ADVMODE BUTTON_REC
371 #define OSCILLOSCOPE_ORIENTATION (BUTTON_FUNC | BUTTON_REPEAT)
372 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
373 #define OSCILLOSCOPE_SPEED_UP BUTTON_FF
374 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW
375 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
376 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
379 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
380 #define OSCILLOSCOPE_QUIT (BUTTON_MENU | BUTTON_REPEAT)
381 #define OSCILLOSCOPE_DRAWMODE BUTTON_ENTER
382 #define OSCILLOSCOPE_ADVMODE BUTTON_REC
383 #define OSCILLOSCOPE_ORIENTATION BUTTON_MENU
384 #define OSCILLOSCOPE_PAUSE BUTTON_PLAY
385 #define OSCILLOSCOPE_SPEED_UP BUTTON_FF
386 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_REW
387 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
388 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
391 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
392 #define OSCILLOSCOPE_QUIT BUTTON_POWER
393 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
394 #define OSCILLOSCOPE_ADVMODE BUTTON_BACK
395 #define OSCILLOSCOPE_ORIENTATION BUTTON_UP
396 #define OSCILLOSCOPE_PAUSE BUTTON_PLAYPAUSE
397 #define OSCILLOSCOPE_SPEED_UP BUTTON_LEFT
398 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_RIGHT
399 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
400 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
403 #elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
404 #define OSCILLOSCOPE_QUIT BUTTON_POWER
405 #define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT
406 #define OSCILLOSCOPE_ADVMODE BUTTON_DOWN
407 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_UP
408 #define OSCILLOSCOPE_ORIENTATION (BUTTON_UP | BUTTON_REL)
409 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_UP
410 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_UP | BUTTON_REPEAT)
411 #define OSCILLOSCOPE_PAUSE BUTTON_NEXT
412 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
413 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
414 #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
415 #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
416 #define NEED_LASTBUTTON
418 #elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
419 #define OSCILLOSCOPE_QUIT BUTTON_BACK
420 #define OSCILLOSCOPE_DRAWMODE BUTTON_USER
421 #define OSCILLOSCOPE_ADVMODE BUTTON_MENU
422 #define OSCILLOSCOPE_ORIENTATION BUTTON_POWER
423 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
424 #define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
425 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
426 #define OSCILLOSCOPE_VOL_UP BUTTON_UP
427 #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
430 #elif (CONFIG_KEYPAD == HM60X_PAD)
431 #define OSCILLOSCOPE_QUIT BUTTON_POWER
432 #define OSCILLOSCOPE_DRAWMODE (BUTTON_POWER | BUTTON_SELECT)
433 #define OSCILLOSCOPE_ADVMODE (BUTTON_POWER | BUTTON_RIGHT)
434 #define OSCILLOSCOPE_ORIENTATION (BUTTON_POWER | BUTTON_LEFT)
435 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
436 #define OSCILLOSCOPE_SPEED_UP BUTTON_UP
437 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_DOWN
438 #define OSCILLOSCOPE_VOL_UP BUTTON_RIGHT
439 #define OSCILLOSCOPE_VOL_DOWN BUTTON_LEFT
442 #elif (CONFIG_KEYPAD == HM801_PAD)
443 #define OSCILLOSCOPE_QUIT BUTTON_POWER
444 #define OSCILLOSCOPE_DRAWMODE BUTTON_PREV
445 #define OSCILLOSCOPE_ADVMODE BUTTON_NEXT
446 #define OSCILLOSCOPE_ORIENTATION BUTTON_PLAY
447 #define OSCILLOSCOPE_PAUSE BUTTON_SELECT
448 #define OSCILLOSCOPE_SPEED_UP BUTTON_UP
449 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_DOWN
450 #define OSCILLOSCOPE_VOL_UP BUTTON_RIGHT
451 #define OSCILLOSCOPE_VOL_DOWN BUTTON_LEFT
455 #error No keymap defined!
458 #ifdef HAVE_TOUCHSCREEN
459 #ifndef OSCILLOSCOPE_QUIT
460 #define OSCILLOSCOPE_QUIT BUTTON_TOPLEFT
462 #ifndef OSCILLOSCOPE_DRAWMODE
463 #define OSCILLOSCOPE_DRAWMODE BUTTON_TOPMIDDLE
465 #ifndef OSCILLOSCOPE_ADVMODE
466 #define OSCILLOSCOPE_ADVMODE BUTTON_BOTTOMMIDDLE
468 #ifndef OSCILLOSCOPE_ORIENTATION
469 #define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_BOTTOMLEFT
470 #define OSCILLOSCOPE_ORIENTATION (BUTTON_BOTTOMLEFT|BUTTON_REL)
472 #ifndef OSCILLOSCOPE_GRAPHMODE
473 #define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_BOTTOMLEFT
474 #define OSCILLOSCOPE_GRAPHMODE (BUTTON_BOTTOMLEFT|BUTTON_REPEAT)
476 #ifndef OSCILLOSCOPE_PAUSE
477 #define OSCILLOSCOPE_PAUSE BUTTON_CENTER
479 #ifndef OSCILLOSCOPE_SPEED_UP
480 #define OSCILLOSCOPE_SPEED_UP BUTTON_MIDRIGHT
482 #ifndef OSCILLOSCOPE_SPEED_DOWN
483 #define OSCILLOSCOPE_SPEED_DOWN BUTTON_MIDLEFT
485 #ifndef OSCILLOSCOPE_VOL_UP
486 #define OSCILLOSCOPE_VOL_UP BUTTON_TOPRIGHT
488 #ifndef OSCILLOSCOPE_VOL_DOWN
489 #define OSCILLOSCOPE_VOL_DOWN BUTTON_BOTTOMRIGHT
491 #define NEED_LASTBUTTON
492 #endif /* HAVE_TOUCHSCREEN */
496 #ifdef HAVE_LCD_COLOR
497 #define BACKG_COLOR LCD_BLACK
498 #define GRAPH_COLOR LCD_RGBPACK(128, 255, 0)
499 #define CURSOR_COLOR LCD_RGBPACK(255, 0, 0)
500 #define GRID_COLOR LCD_RGBPACK(192, 255, 64)
501 #define OSD_TEXT_COLOR LCD_WHITE
502 #define OSD_BACKG_COLOR LCD_BLACK
503 #define OSD_BORDER_COLOR LCD_RGBPACK(255, 0, 0)
504 #define OSC_OSD_MARGIN_SIZE 0 /* Border and text are different */
506 #define BACKG_COLOR LCD_WHITE
507 #define GRAPH_COLOR LCD_BLACK
508 #define CURSOR_COLOR LCD_DARKGRAY
509 #define GRID_COLOR LCD_DARKGRAY
510 #define OSD_TEXT_COLOR LCD_BLACK
511 #define OSD_BACKG_COLOR LCD_WHITE
512 #define OSD_BORDER_COLOR LCD_BLACK
516 #ifndef OSC_OSD_MARGIN_SIZE
517 #define OSC_OSD_MARGIN_SIZE 1
521 #define MAX_SPEED 100
523 enum { DRAW_FILLED
, DRAW_LINE
, DRAW_PIXEL
, MAX_DRAW
};
524 enum { ADV_SCROLL
, ADV_WRAP
, MAX_ADV
};
525 enum { OSC_HORIZ
, OSC_VERT
, MAX_OSC
};
529 #ifdef OSCILLOSCOPE_GRAPHMODE
535 #define CFGFILE_VERSION 1 /* Current config file version */
536 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
538 /* global variables */
541 * / 99*[e ^ ((100 - x) / z) - 1] \
542 * osc_delay = HZ * | ---------------------------- + 1 |
543 * \ [e ^ (99 / z) - 1] /
545 * x: 1 .. 100, z: 15, delay: 100.00 .. 1.00
547 static const unsigned short osc_delay_tbl
[100] =
549 10000, 9361, 8763, 8205, 7682, 7192, 6735, 6307, 5906, 5532,
550 5181, 4853, 4546, 4259, 3991, 3739, 3504, 3285, 3079, 2886,
551 2706, 2538, 2380, 2233, 2095, 1966, 1845, 1732, 1627, 1528,
552 1435, 1349, 1268, 1192, 1121, 1055, 993, 935, 880, 830,
553 782, 737, 696, 657, 620, 586, 554, 524, 497, 470,
554 446, 423, 402, 381, 363, 345, 329, 313, 299, 285,
555 273, 261, 250, 239, 230, 221, 212, 204, 197, 190,
556 183, 177, 171, 166, 161, 156, 152, 147, 144, 140,
557 136, 133, 130, 127, 125, 122, 120, 118, 116, 114,
558 112, 110, 108, 107, 106, 104, 103, 102, 101, 100
561 #define GRAPH_PEAKS_DEFAULT 68
562 #define GRAPH_WAVEFORM_DEFAULT 50
565 static struct osc_config
567 int speed
[MAX_GRAPH
];
576 [GRAPH_PEAKS
] = GRAPH_PEAKS_DEFAULT
,
577 #ifdef OSCILLOSCOPE_GRAPHMODE
578 [GRAPH_WAVEFORM
] = GRAPH_WAVEFORM_DEFAULT
,
582 .advance
= ADV_SCROLL
,
583 .orientation
= OSC_HORIZ
,
584 #ifdef OSCILLOSCOPE_GRAPHMODE
585 .graphmode
= GRAPH_PEAKS
,
589 static struct osc_config osc
; /* running config */
591 static const char cfg_filename
[] = "oscilloscope.cfg";
592 static char *draw_str
[3] = { "filled", "line", "pixel" };
593 static char *advance_str
[2] = { "scroll", "wrap" };
594 static char *orientation_str
[2] = { "horizontal", "vertical" };
595 #ifdef OSCILLOSCOPE_GRAPHMODE
596 static char *graphmode_str
[2] = { "peaks", "waveform" };
599 struct configdata disk_config
[] =
601 { TYPE_INT
, MIN_SPEED
, MAX_SPEED
,
602 { .int_p
= &osc_disk
.speed
[GRAPH_PEAKS
] }, "speed", NULL
},
603 { TYPE_ENUM
, 0, MAX_DRAW
, { .int_p
= &osc_disk
.draw
}, "draw", draw_str
},
604 { TYPE_ENUM
, 0, MAX_ADV
, { .int_p
= &osc_disk
.advance
}, "advance",
606 { TYPE_ENUM
, 0, MAX_OSC
, { .int_p
= &osc_disk
.orientation
}, "orientation",
608 #ifdef OSCILLOSCOPE_GRAPHMODE
609 { TYPE_INT
, MAX_SPEED
, MAX_SPEED
,
610 { .int_p
= &osc_disk
.speed
[GRAPH_WAVEFORM
] }, "wavespeed", NULL
},
611 { TYPE_ENUM
, 0, MAX_GRAPH
, { .int_p
= &osc_disk
.graphmode
}, "graphmode",
620 #ifdef OSCILLOSCOPE_GRAPHMODE
629 static long (*anim_draw
)(void);
630 static int message
= -1, msgval
= 0; /* popup message */
631 static bool paused
= false;
632 static bool one_frame_paused
= false; /* Allow one frame to be drawn when paused if
634 static long osc_delay
; /* delay in 100ths of a tick */
635 static long osc_delay_error
; /* delay fraction error accumulator */
642 static unsigned char osc_osd_message
[16]; /* message to display (formatted) */
644 static inline void osc_popupmsg(int msg
, int val
)
646 message
= msg
; msgval
= val
;
649 /* Format a message to display */
650 static void osc_osd_format_message(enum osc_message_ids id
, int val
)
652 const char *msg
= "";
656 case OSC_MSG_ADVMODE
:
657 msg
= val
== ADV_WRAP
? "Wrap" : "Scroll";
660 case OSC_MSG_DRAWMODE
:
663 case DRAW_PIXEL
: msg
= "Pixel"; break;
664 case DRAW_LINE
: msg
= "Line"; break;
665 default: msg
= "Filled";
669 #ifdef OSCILLOSCOPE_GRAPHMODE
670 case OSC_MSG_GRAPHMODE
:
671 msg
= val
== GRAPH_WAVEFORM
? "Waveform" : "Peaks";
675 case OSC_MSG_ORIENTATION
:
676 msg
= val
== OSC_VERT
? "Vertical" : "Horizontal";
680 msg
= val
? "Paused" : "Running";
688 rb
->snprintf(osc_osd_message
, sizeof (osc_osd_message
),
690 rb
->sound_val2phys(SOUND_VOLUME
, val
),
691 rb
->sound_unit(SOUND_VOLUME
));
695 /* Default action: format integer */
696 rb
->snprintf(osc_osd_message
, sizeof (osc_osd_message
), msg
, val
);
702 /* Actually draw the OSD within the OSD viewport */
703 extern void osd_lcd_draw_cb(int x
, int y
, int width
, int height
)
706 rb
->lcd_set_foreground(OSD_TEXT_COLOR
);
707 rb
->lcd_set_background(OSD_BACKG_COLOR
);
709 #if OSC_OSD_MARGIN_SIZE != 0
710 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
711 rb
->lcd_fillrect(1, 1, width
- 2, height
- 2);
712 rb
->lcd_set_drawmode(DRMODE_SOLID
);
714 rb
->lcd_putsxy(1+OSC_OSD_MARGIN_SIZE
, 1+OSC_OSD_MARGIN_SIZE
,
717 rb
->lcd_set_foreground(OSD_BORDER_COLOR
);
719 rb
->lcd_drawrect(0, 0, width
, height
);
724 /* Perform all necessary basic setup tasks for the OSD */
725 static void osc_osd_init(void)
727 /* Grab the plugin buffer for the OSD back buffer */
729 void *buf
= rb
->plugin_get_buffer(&bufsize
);
732 rb
->lcd_setfont(FONT_UI
);
733 rb
->lcd_getstringsize("M", NULL
, &height
);
735 height
+= 2 + 2*OSC_OSD_MARGIN_SIZE
;
736 osd_init(OSD_INIT_MAJOR_HEIGHT
| OSD_INIT_MINOR_MAX
, buf
, bufsize
,
737 osd_lcd_draw_cb
, &width
, &height
, NULL
);
740 /* Format a message by ID and show the OSD */
741 static void osc_osd_show_message(int id
, int val
)
743 osc_osd_format_message(id
, val
);
749 int maxwidth
, maxheight
;
751 rb
->lcd_set_viewport(osd_get_viewport());
752 osd_get_max_dims(&maxwidth
, &maxheight
);
753 rb
->lcd_getstringsize(osc_osd_message
, &width
, &height
);
754 rb
->lcd_set_viewport(NULL
); /* to regular viewport */
756 width
+= 2 + 2*OSC_OSD_MARGIN_SIZE
;
757 if (width
> maxwidth
)
760 height
+= 2 + 2*OSC_OSD_MARGIN_SIZE
;
761 if (height
> maxheight
)
764 /* Center it on the screen */
765 bool drawn
= osd_update_pos((LCD_WIDTH
- width
) / 2,
766 (LCD_HEIGHT
- height
) / 2,
769 osd_show(OSD_SHOW
| (drawn
? 0 : OSD_UPDATENOW
));
772 /* Draw cursor bar for horizontal views */
773 static void anim_draw_cursor_h(int x
)
776 rb
->lcd_set_foreground(CURSOR_COLOR
);
777 rb
->lcd_vline(x
, 0, LCD_HEIGHT
-1);
778 rb
->lcd_set_foreground(GRAPH_COLOR
);
780 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
781 rb
->lcd_vline(x
, 0, LCD_HEIGHT
-1);
782 rb
->lcd_set_drawmode(DRMODE_SOLID
);
786 /* Draw cursor bar for vertical views */
787 static void anim_draw_cursor_v(int y
)
789 #if LCD_DEPTH > 1 /* cursor bar */
790 rb
->lcd_set_foreground(CURSOR_COLOR
);
791 rb
->lcd_hline(0, LCD_WIDTH
-1, y
);
792 rb
->lcd_set_foreground(GRAPH_COLOR
);
794 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
795 rb
->lcd_hline(0, LCD_WIDTH
-1, y
);
796 rb
->lcd_set_drawmode(DRMODE_SOLID
);
803 static long last_tick
= 0; /* time of last drawing */
804 static long last_delay
= 0; /* last delay value used */
805 static int last_pos
= 0; /* last x or y drawing position. Reset for aspect switch. */
806 static int last_left
; /* last channel values */
807 static int last_right
;
809 static void get_peaks(int *left
, int *right
)
811 #if CONFIG_CODEC == SWCODEC
812 static struct pcm_peaks peaks
;
813 rb
->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK
,
816 *right
= peaks
.right
;
817 #elif defined (SIMULATOR)
818 *left
= rand() % 0x8000;
819 *right
= rand() % 0x8000;
820 #elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
821 *left
= rb
->mas_codec_readreg(0xC);
822 *right
= rb
->mas_codec_readreg(0xD);
829 static long get_next_delay(void)
831 long delay
= osc_delay
/ 100;
832 osc_delay_error
+= osc_delay
- delay
* 100;
834 if (osc_delay_error
>= 100)
837 osc_delay_error
-= 100;
843 static long anim_peaks_horizontal(void)
845 long cur_tick
= *rb
->current_tick
;
847 int left
, right
, dl
, dr
;
848 long d
= (cur_tick
- last_tick
) / last_delay
;
849 bool full_update
= false;
853 one_frame_paused
= false;
854 osd_lcd_update_prepare();
855 anim_draw_cursor_h(0);
856 osd_lcd_update_rect(0, 0, 1, LCD_HEIGHT
);
858 return cur_tick
+ HZ
/5;
861 if (d
<= 0) /* too early, bail out */
862 return last_tick
+ last_delay
;
864 last_tick
= cur_tick
;
866 int cur_left
, cur_right
;
867 get_peaks(&cur_left
, &cur_right
);
869 if (d
> HZ
) /* first call or too much delay, (re)start */
871 last_left
= cur_left
;
872 last_right
= cur_right
;
873 return cur_tick
+ last_delay
;
876 one_frame_paused
= false;
878 osd_lcd_update_prepare();
880 cur_x
= last_pos
+ d
;
882 if (cur_x
>= LCD_WIDTH
)
884 if (osc
.advance
== ADV_SCROLL
)
886 int shift
= cur_x
- (LCD_WIDTH
-1);
887 xlcd_scroll_left(shift
);
897 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
899 if (cur_x
> last_pos
)
901 rb
->lcd_fillrect(last_pos
+ 1, 0, d
, LCD_HEIGHT
);
905 rb
->lcd_fillrect(last_pos
+ 1, 0, LCD_WIDTH
- last_pos
, LCD_HEIGHT
);
906 rb
->lcd_fillrect(0, 0, cur_x
+ 1, LCD_HEIGHT
);
908 rb
->lcd_set_drawmode(DRMODE_SOLID
);
915 dl
= (cur_left
- left
) / d
;
916 dr
= (cur_right
- right
) / d
;
918 for (x
= last_pos
+ 1; d
> 0; x
++, d
--)
926 rb
->lcd_vline(x
, LCD_HEIGHT
/2-1,
927 LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * left
) >> 16));
928 rb
->lcd_vline(x
, LCD_HEIGHT
/2+1,
929 LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * right
) >> 16));
934 if (cur_x
> last_pos
)
937 last_pos
, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * last_left
) >> 16),
938 cur_x
, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * cur_left
) >> 16)
941 last_pos
, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * last_right
) >> 16),
942 cur_x
, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * cur_right
) >> 16)
948 + (LCD_WIDTH
- last_pos
) * (last_left
- cur_left
) / d
;
950 + (LCD_WIDTH
- last_pos
) * (last_right
- cur_right
) / d
;
953 last_pos
, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * last_left
) >> 16),
954 LCD_WIDTH
, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * left
) >> 16)
957 last_pos
, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * last_right
) >> 16),
958 LCD_WIDTH
, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * right
) >> 16)
963 0, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * left
) >> 16),
964 cur_x
, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * cur_left
) >> 16)
967 0, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * right
) >> 16),
968 cur_x
, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * cur_right
) >> 16)
977 dl
= (cur_left
- left
) / d
;
978 dr
= (cur_right
- right
) / d
;
980 for (x
= last_pos
+ 1; d
> 0; x
++, d
--)
988 rb
->lcd_drawpixel(x
, LCD_HEIGHT
/2-1 - (((LCD_HEIGHT
-2) * left
) >> 16));
989 rb
->lcd_drawpixel(x
, LCD_HEIGHT
/2+1 + (((LCD_HEIGHT
-2) * right
) >> 16));
995 last_left
= cur_left
;
996 last_right
= cur_right
;
1004 anim_draw_cursor_h(cur_x
+ 1); /* cursor bar */
1006 if (cur_x
> last_pos
)
1008 osd_lcd_update_rect(last_pos
, 0, cur_x
- last_pos
+ 2, LCD_HEIGHT
);
1012 osd_lcd_update_rect(last_pos
, 0, LCD_WIDTH
- last_pos
, LCD_HEIGHT
);
1013 osd_lcd_update_rect(0, 0, cur_x
+ 2, LCD_HEIGHT
);
1018 last_delay
= get_next_delay();
1019 return cur_tick
+ last_delay
;
1022 static long anim_peaks_vertical(void)
1024 long cur_tick
= *rb
->current_tick
;
1026 int left
, right
, dl
, dr
;
1027 bool full_update
= false;
1028 long d
= (cur_tick
- last_tick
) / last_delay
;
1032 one_frame_paused
= false;
1033 osd_lcd_update_prepare();
1034 anim_draw_cursor_v(0);
1035 osd_lcd_update_rect(0, 0, LCD_WIDTH
, 1);
1037 return cur_tick
+ HZ
/5;
1040 if (d
== 0) /* too early, bail out */
1041 return last_tick
+ last_delay
;
1043 last_tick
= cur_tick
;
1045 int cur_left
, cur_right
;
1046 get_peaks(&cur_left
, &cur_right
);
1048 if (d
> HZ
) /* first call or too much delay, (re)start */
1050 last_left
= cur_left
;
1051 last_right
= cur_right
;
1052 return cur_tick
+ last_delay
;
1055 one_frame_paused
= false;
1057 osd_lcd_update_prepare();
1059 cur_y
= last_pos
+ d
;
1061 if (cur_y
>= LCD_HEIGHT
)
1063 if (osc
.advance
== ADV_SCROLL
)
1065 int shift
= cur_y
- (LCD_HEIGHT
-1);
1066 xlcd_scroll_up(shift
);
1073 cur_y
-= LCD_HEIGHT
;
1076 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1078 if (cur_y
> last_pos
)
1080 rb
->lcd_fillrect(0, last_pos
+ 1, LCD_WIDTH
, d
);
1084 rb
->lcd_fillrect(0, last_pos
+ 1, LCD_WIDTH
, LCD_HEIGHT
- last_pos
);
1085 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, cur_y
+ 1);
1087 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1094 dl
= (cur_left
- left
) / d
;
1095 dr
= (cur_right
- right
) / d
;
1097 for (y
= last_pos
+ 1; d
> 0; y
++, d
--)
1099 if (y
== LCD_HEIGHT
)
1105 rb
->lcd_hline(LCD_WIDTH
/2-1,
1106 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * left
) >> 16), y
);
1107 rb
->lcd_hline(LCD_WIDTH
/2+1,
1108 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * right
) >> 16), y
);
1113 if (cur_y
> last_pos
)
1116 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * last_left
) >> 16), last_pos
,
1117 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * cur_left
) >> 16), cur_y
1120 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * last_right
) >> 16), last_pos
,
1121 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * cur_right
) >> 16), cur_y
1127 + (LCD_HEIGHT
- last_pos
) * (last_left
- cur_left
) / d
;
1129 + (LCD_HEIGHT
- last_pos
) * (last_right
- cur_right
) / d
;
1132 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * last_left
) >> 16), last_pos
,
1133 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * left
) >> 16), LCD_HEIGHT
1136 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * last_right
) >> 16), last_pos
,
1137 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * right
) >> 16), LCD_HEIGHT
1142 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * left
) >> 16), 0,
1143 LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * cur_left
) >> 16), cur_y
1146 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * right
) >> 16), 0,
1147 LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * cur_right
) >> 16), cur_y
1156 dl
= (cur_left
- left
) / d
;
1157 dr
= (cur_right
- right
) / d
;
1159 for (y
= last_pos
+ 1; d
> 0; y
++, d
--)
1161 if (y
== LCD_HEIGHT
)
1167 rb
->lcd_drawpixel(LCD_WIDTH
/2-1 - (((LCD_WIDTH
-2) * left
) >> 16), y
);
1168 rb
->lcd_drawpixel(LCD_WIDTH
/2+1 + (((LCD_WIDTH
-2) * right
) >> 16), y
);
1174 last_left
= cur_left
;
1175 last_right
= cur_right
;
1183 anim_draw_cursor_v(cur_y
+ 1); /* cursor bar */
1185 if (cur_y
> last_pos
)
1187 osd_lcd_update_rect(0, last_pos
, LCD_WIDTH
, cur_y
- last_pos
+ 2);
1191 osd_lcd_update_rect(0, last_pos
, LCD_WIDTH
, LCD_HEIGHT
- last_pos
);
1192 osd_lcd_update_rect(0, 0, LCD_WIDTH
, cur_y
+ 2);
1197 last_delay
= get_next_delay();
1198 return cur_tick
+ last_delay
;
1202 /** Waveform View **/
1204 #ifdef OSCILLOSCOPE_GRAPHMODE
1205 static int16_t waveform_buffer
[2*ALIGN_UP(NATIVE_FREQUENCY
, 2048)+2*2048]
1207 static size_t waveform_buffer_threshold
= 0;
1208 static size_t volatile waveform_buffer_have
= 0;
1209 static size_t waveform_buffer_break
= 0;
1210 #define PCM_SAMPLESIZE (2*sizeof(int16_t))
1211 #define PCM_BYTERATE (NATIVE_FREQUENCY*PCM_SAMPLESIZE)
1213 #define WAVEFORM_SCALE_PCM(full_scale, sample) \
1214 ((((full_scale) * (sample)) + (1 << 14)) >> 15)
1216 static void waveform_buffer_set_threshold(size_t threshold
)
1218 if (threshold
> sizeof (waveform_buffer
))
1219 threshold
= sizeof (waveform_buffer
);
1221 if (threshold
== waveform_buffer_threshold
)
1224 /* Avoid changing it in the middle of buffer callback */
1225 rb
->pcm_play_lock();
1227 waveform_buffer_threshold
= threshold
;
1229 rb
->pcm_play_unlock();
1232 static inline bool waveform_buffer_have_enough(void)
1234 return waveform_buffer_have
>= waveform_buffer_threshold
;
1237 static void waveform_buffer_done(void)
1239 /* This is safe because buffer callback won't add more data unless the
1240 treshold is changed or data is removed below the threshold. This isn't
1241 called until after the threshold is already met. */
1242 size_t threshold
= waveform_buffer_threshold
;
1247 have
= waveform_buffer_have
;
1248 size_t slide
= (have
- 1) / threshold
* threshold
;
1257 /* memcpy: the slide >= threshold and have <= threshold */
1258 memcpy(waveform_buffer
, (void *)waveform_buffer
+ slide
, have
);
1262 waveform_buffer_have
= have
;
1265 /* where the samples are obtained and buffered */
1266 static void waveform_buffer_callback(const void *start
, size_t size
)
1268 size_t threshold
= waveform_buffer_threshold
;
1269 size_t have
= waveform_buffer_have
;
1271 if (have
>= threshold
)
1273 waveform_buffer_break
+= size
;
1277 if (waveform_buffer_break
> 0)
1279 /* Previosly missed a part or all of a frame and the break would
1280 happen within the data threshold area. Start where frame would
1281 end up if all had been processed fully. This might mean a period
1282 of resynchronization will have to happen first before the buffer
1283 is filled to the threshold or even begins filling. Maintaining
1284 scan phase relationship is important to proper appearance or else
1285 the waveform display looks sloppy. */
1286 size_t brk
= have
+ waveform_buffer_break
;
1287 waveform_buffer_have
= have
= 0;
1295 if (brk
<= threshold
)
1297 waveform_buffer_break
= brk
;
1302 start
+= size
- brk
;
1306 waveform_buffer_break
= 0;
1309 size_t remaining
= sizeof (waveform_buffer
) - have
;
1312 if (copy
> remaining
)
1314 waveform_buffer_break
= copy
- remaining
;
1318 memcpy((void *)waveform_buffer
+ have
, start
, copy
);
1320 waveform_buffer_have
= have
+ copy
;
1323 static void waveform_buffer_reset(void)
1325 /* only called when callback is off */
1326 waveform_buffer_have
= 0;
1327 waveform_buffer_threshold
= 0;
1328 waveform_buffer_break
= 0;
1331 static void anim_waveform_plot_filled_h(int x
, int x_prev
,
1333 int vmin_prev
, int vmax_prev
)
1335 if (vmin
!= vmax
|| vmin_prev
!= vmax_prev
)
1337 /* Graph compression */
1338 if (vmax
> vmin_prev
)
1340 else if (vmin
< vmax_prev
)
1343 rb
->lcd_vline(x
, vmax
, vmin
);
1347 /* 1:1 or stretch */
1348 rb
->lcd_drawline(x_prev
, vmin_prev
, x
, vmin
);
1352 static void anim_waveform_plot_lines_h(int x
, int x_prev
,
1354 int vmin_prev
, int vmax_prev
)
1356 rb
->lcd_drawline(x_prev
, vmin_prev
, x
, vmin
);
1358 if (vmax_prev
!= vmin_prev
|| vmax
!= vmin
)
1359 rb
->lcd_drawline(x_prev
, vmax_prev
, x
, vmax
);
1362 static void anim_waveform_plot_pixel_h(int x
, int x_prev
,
1364 int vmin_prev
, int vmax_prev
)
1366 rb
->lcd_drawpixel(x
, vmin
);
1369 rb
->lcd_drawpixel(x
, vmax
);
1371 (void)x_prev
; (void)vmin_prev
; (void)vmax_prev
;
1374 static long anim_waveform_horizontal(void)
1376 static void (* const plot
[MAX_DRAW
])(int, int, int, int, int, int) =
1378 [DRAW_FILLED
] = anim_waveform_plot_filled_h
,
1379 [DRAW_LINE
] = anim_waveform_plot_lines_h
,
1380 [DRAW_PIXEL
] = anim_waveform_plot_pixel_h
,
1383 long cur_tick
= *rb
->current_tick
;
1385 if (rb
->mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK
) != CHANNEL_PLAYING
)
1387 osd_lcd_update_prepare();
1388 rb
->lcd_hline(0, LCD_WIDTH
-1, 1*LCD_HEIGHT
/4);
1389 rb
->lcd_hline(0, LCD_WIDTH
-1, 3*LCD_HEIGHT
/4);
1391 one_frame_paused
= false;
1392 return cur_tick
+ HZ
/5;
1395 int count
= (NATIVE_FREQUENCY
*osc_delay
+ 100*HZ
- 1) / (100*HZ
);
1397 waveform_buffer_set_threshold(count
*PCM_SAMPLESIZE
);
1399 if (!waveform_buffer_have_enough())
1400 return cur_tick
+ HZ
/100;
1402 one_frame_paused
= false;
1404 osd_lcd_update_prepare();
1406 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1407 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, LCD_HEIGHT
);
1408 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1410 rb
->lcd_set_foreground(GRAPH_COLOR
);
1413 int x
= 0, x_prev
= count
- 1;
1414 int x_step
= (LCD_WIDTH
-1) / x_prev
;
1415 int x_a_step
= (LCD_WIDTH
-1) - x_step
* x_prev
;
1418 int idx_step
= (count
/ LCD_WIDTH
) * 2;
1419 int idx_a_step
= count
- idx_step
* (LCD_WIDTH
/2);
1420 int idx
= idx_step
, idx_prev
= 0;
1421 int idx_a
= idx_a_step
;
1423 int a_lim
= MIN(x_prev
, LCD_WIDTH
-1);
1425 int lmin
, lmin_prev
= 0;
1426 int rmin
, rmin_prev
= 0;
1427 int lmax
, lmax_prev
= 0;
1428 int rmax
, rmax_prev
= 0;
1430 if (osc
.draw
== DRAW_PIXEL
)
1431 goto plot_start_noprev
; /* Doesn't need previous points */
1433 lmax
= lmin
= waveform_buffer
[0];
1434 rmax
= rmin
= waveform_buffer
[1];
1436 /* Find min-max envelope for interval */
1437 for (int i
= 2; i
< idx
; i
+= 2)
1439 int sl
= waveform_buffer
[i
+ 0];
1440 int sr
= waveform_buffer
[i
+ 1];
1453 lmin
= (1*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, lmin
);
1454 lmax
= (1*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, lmax
);
1455 rmin
= (3*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, rmin
);
1456 rmax
= (3*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, rmax
);
1475 idx_a
+= idx_a_step
;
1483 lmin_prev
= lmin
, lmax_prev
= lmax
;
1484 rmin_prev
= rmin
, rmax_prev
= rmax
;
1487 lmax
= lmin
= waveform_buffer
[idx_prev
+ 0];
1488 rmax
= rmin
= waveform_buffer
[idx_prev
+ 1];
1490 /* Find min-max envelope for interval */
1491 for (int i
= idx_prev
+ 2; i
< idx
; i
+= 2)
1493 int sl
= waveform_buffer
[i
+ 0];
1494 int sr
= waveform_buffer
[i
+ 1];
1507 lmin
= (1*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, lmin
);
1508 lmax
= (1*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, lmax
);
1509 rmin
= (3*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, rmin
);
1510 rmax
= (3*LCD_HEIGHT
/4) - WAVEFORM_SCALE_PCM(LCD_HEIGHT
/4-1, rmax
);
1512 plot
[osc
.draw
](x
, x_prev
, lmin
, lmax
, lmin_prev
, lmax_prev
);
1513 plot
[osc
.draw
](x
, x_prev
, rmin
, rmax
, rmin_prev
, rmax_prev
);
1516 waveform_buffer_done();
1520 long delay
= get_next_delay();
1521 return cur_tick
+ delay
- waveform_buffer_have
* HZ
/ PCM_BYTERATE
;
1524 static void anim_waveform_plot_filled_v(int y
, int y_prev
,
1526 int vmin_prev
, int vmax_prev
)
1528 if (vmin
!= vmax
|| vmin_prev
!= vmax_prev
)
1530 /* Graph compression */
1531 if (vmax
< vmin_prev
)
1533 else if (vmin
> vmax_prev
)
1536 rb
->lcd_hline(vmin
, vmax
, y
);
1540 /* 1:1 or stretch */
1541 rb
->lcd_drawline(vmin_prev
, y_prev
, vmin
, y
);
1545 static void anim_waveform_plot_lines_v(int y
, int y_prev
,
1547 int vmin_prev
, int vmax_prev
)
1549 rb
->lcd_drawline(vmin_prev
, y_prev
, vmin
, y
);
1551 if (vmax_prev
!= vmin_prev
|| vmax
!= vmin
)
1552 rb
->lcd_drawline(vmax_prev
, y_prev
, vmax
, y
);
1555 static void anim_waveform_plot_pixel_v(int y
, int y_prev
,
1557 int vmin_prev
, int vmax_prev
)
1559 rb
->lcd_drawpixel(vmin
, y
);
1562 rb
->lcd_drawpixel(vmax
, y
);
1564 (void)y_prev
; (void)vmin_prev
; (void)vmax_prev
;
1567 static long anim_waveform_vertical(void)
1569 static void (* const plot
[MAX_DRAW
])(int, int, int, int, int, int) =
1571 [DRAW_FILLED
] = anim_waveform_plot_filled_v
,
1572 [DRAW_LINE
] = anim_waveform_plot_lines_v
,
1573 [DRAW_PIXEL
] = anim_waveform_plot_pixel_v
,
1576 long cur_tick
= *rb
->current_tick
;
1578 if (rb
->mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK
) != CHANNEL_PLAYING
)
1580 osd_lcd_update_prepare();
1581 rb
->lcd_vline(1*LCD_WIDTH
/4, 0, LCD_HEIGHT
-1);
1582 rb
->lcd_vline(3*LCD_WIDTH
/4, 0, LCD_HEIGHT
-1);
1584 one_frame_paused
= false;
1585 return cur_tick
+ HZ
/5;
1588 int count
= (NATIVE_FREQUENCY
*osc_delay
+ 100*HZ
- 1) / (100*HZ
);
1590 waveform_buffer_set_threshold(count
*PCM_SAMPLESIZE
);
1592 if (!waveform_buffer_have_enough())
1593 return cur_tick
+ HZ
/100;
1595 one_frame_paused
= false;
1597 osd_lcd_update_prepare();
1599 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1600 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, LCD_HEIGHT
);
1601 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1603 rb
->lcd_set_foreground(GRAPH_COLOR
);
1606 int y
= 0, y_prev
= count
- 1;
1607 int y_step
= (LCD_HEIGHT
-1) / y_prev
;
1608 int y_a_step
= (LCD_HEIGHT
-1) - y_step
* y_prev
;
1611 int idx_step
= (count
/ LCD_HEIGHT
) * 2;
1612 int idx_a_step
= count
- idx_step
* (LCD_HEIGHT
/2);
1613 int idx
= idx_step
, idx_prev
= 0;
1614 int idx_a
= idx_a_step
;
1616 int a_lim
= MIN(y_prev
, LCD_HEIGHT
-1);
1618 int lmin
, lmin_prev
= 0;
1619 int rmin
, rmin_prev
= 0;
1620 int lmax
, lmax_prev
= 0;
1621 int rmax
, rmax_prev
= 0;
1623 if (osc
.draw
== DRAW_PIXEL
)
1624 goto plot_start_noprev
; /* Doesn't need previous points */
1626 lmax
= lmin
= waveform_buffer
[0];
1627 rmax
= rmin
= waveform_buffer
[1];
1629 /* Find min-max envelope for interval */
1630 for (int i
= 2; i
< idx
; i
+= 2)
1632 int sl
= waveform_buffer
[i
+ 0];
1633 int sr
= waveform_buffer
[i
+ 1];
1646 lmin
= (1*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, lmin
);
1647 lmax
= (1*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, lmax
);
1648 rmin
= (3*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, rmin
);
1649 rmax
= (3*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, rmax
);
1663 if (y
>= LCD_HEIGHT
)
1668 idx_a
+= idx_a_step
;
1676 lmin_prev
= lmin
, lmax_prev
= lmax
;
1677 rmin_prev
= rmin
, rmax_prev
= rmax
;
1680 lmax
= lmin
= waveform_buffer
[idx_prev
+ 0];
1681 rmax
= rmin
= waveform_buffer
[idx_prev
+ 1];
1683 /* Find min-max envelope for interval */
1684 for (int i
= idx_prev
+ 2; i
< idx
; i
+= 2)
1686 int sl
= waveform_buffer
[i
+ 0];
1687 int sr
= waveform_buffer
[i
+ 1];
1700 lmin
= (1*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, lmin
);
1701 lmax
= (1*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, lmax
);
1702 rmin
= (3*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, rmin
);
1703 rmax
= (3*LCD_WIDTH
/4) + WAVEFORM_SCALE_PCM(LCD_WIDTH
/4-1, rmax
);
1705 plot
[osc
.draw
](y
, y_prev
, lmin
, lmax
, lmin_prev
, lmax_prev
);
1706 plot
[osc
.draw
](y
, y_prev
, rmin
, rmax
, rmin_prev
, rmax_prev
);
1709 waveform_buffer_done();
1713 long delay
= get_next_delay();
1714 return cur_tick
+ delay
- waveform_buffer_have
* HZ
/ PCM_BYTERATE
;
1717 static void anim_waveform_exit(void)
1719 /* Remove any buffer hook */
1720 rb
->mixer_channel_set_buffer_hook(PCM_MIXER_CHAN_PLAYBACK
, NULL
);
1721 #ifdef HAVE_SCHEDULER_BOOSTCTRL
1722 /* Remove our boost */
1723 rb
->cancel_cpu_boost();
1726 #endif /* OSCILLOSCOPE_GRAPHMODE */
1728 static void graphmode_reset(void)
1730 static long (* const fns
[MAX_GRAPH
][MAX_OSC
])(void) =
1734 [OSC_HORIZ
] = anim_peaks_horizontal
,
1735 [OSC_VERT
] = anim_peaks_vertical
,
1737 #ifdef OSCILLOSCOPE_GRAPHMODE
1740 [OSC_HORIZ
] = anim_waveform_horizontal
,
1741 [OSC_VERT
] = anim_waveform_vertical
,
1743 #endif /* OSCILLOSCOPE_GRAPHMODE */
1746 /* For peaks view */
1750 last_tick
= *rb
->current_tick
;
1754 osd_lcd_update_prepare();
1755 rb
->lcd_clear_display();
1758 one_frame_paused
= true;
1759 osd_set_timeout(paused
? 4*HZ
: HZ
);
1760 anim_draw
= fns
[osc
.graphmode
][osc
.orientation
];
1763 static void graphmode_pause_unpause(bool paused
)
1768 last_tick
= *rb
->current_tick
;
1769 osd_set_timeout(HZ
);
1770 one_frame_paused
= false;
1771 #ifdef OSCILLOSCOPE_GRAPHMODE
1772 if (osc
.graphmode
== GRAPH_WAVEFORM
)
1773 waveform_buffer_done();
1774 #endif /* OSCILLOSCOPE_GRAPHMODE */
1777 static void update_osc_delay(int value
)
1779 osc_delay
= osc_delay_tbl
[value
- 1];
1780 osc_delay_error
= 0;
1783 static void graphmode_setup(void)
1785 #ifdef OSCILLOSCOPE_GRAPHMODE
1786 if (osc
.graphmode
== GRAPH_WAVEFORM
)
1788 rb
->mixer_channel_set_buffer_hook(PCM_MIXER_CHAN_PLAYBACK
,
1789 waveform_buffer_callback
);
1790 #ifdef HAVE_SCHEDULER_BOOSTCTRL
1791 rb
->trigger_cpu_boost(); /* Just looks better */
1796 rb
->mixer_channel_set_buffer_hook(PCM_MIXER_CHAN_PLAYBACK
,
1798 #ifdef HAVE_SCHEDULER_BOOSTCTRL
1799 rb
->cancel_cpu_boost();
1801 waveform_buffer_reset();
1803 #endif /* OSCILLOSCOPE_GRAPHMODE */
1805 update_osc_delay(osc
.speed
[osc
.graphmode
]);
1809 static long oscilloscope_draw(void)
1813 osc_osd_show_message((enum osc_message_ids
)message
, msgval
);
1818 osd_monitor_timeout();
1823 if (!paused
|| one_frame_paused
)
1825 delay
= anim_draw() - *rb
->current_tick
;
1834 static void osc_cleanup(void)
1838 #ifdef OSCILLOSCOPE_GRAPHMODE
1839 anim_waveform_exit();
1843 rb
->lcd_set_foreground(LCD_DEFAULT_FG
);
1844 rb
->lcd_set_background(LCD_DEFAULT_BG
);
1846 /* Turn on backlight timeout (revert to settings) */
1847 backlight_use_settings();
1850 /* save settings if changed */
1851 if (rb
->memcmp(&osc
, &osc_disk
, sizeof(osc
)))
1853 rb
->memcpy(&osc_disk
, &osc
, sizeof(osc
));
1854 configfile_save(cfg_filename
, disk_config
, ARRAYLEN(disk_config
),
1859 static void osc_setup(void)
1861 atexit(osc_cleanup
);
1862 configfile_load(cfg_filename
, disk_config
, ARRAYLEN(disk_config
),
1863 CFGFILE_MINVERSION
);
1864 osc
= osc_disk
; /* copy to running config */
1869 osd_lcd_update_prepare();
1870 rb
->lcd_set_foreground(GRAPH_COLOR
);
1871 rb
->lcd_set_background(BACKG_COLOR
);
1872 rb
->lcd_set_backdrop(NULL
);
1873 rb
->lcd_clear_display();
1877 /* Turn off backlight timeout */
1878 backlight_ignore_timeout();
1882 enum plugin_status
plugin_start(const void* parameter
)
1885 #ifdef NEED_LASTBUTTON
1886 int lastbutton
= BUTTON_NONE
;
1893 long delay
= oscilloscope_draw();
1898 rb
->yield(); /* tmo = 0 won't yield */
1901 int button
= rb
->button_get_w_tmo(delay
);
1905 #ifdef OSCILLOSCOPE_RC_QUIT
1906 case OSCILLOSCOPE_RC_QUIT
:
1908 case OSCILLOSCOPE_QUIT
:
1912 case OSCILLOSCOPE_ADVMODE
:
1913 #ifdef OSCILLOSCOPE_GRAPHMODE
1914 if (osc
.graphmode
== GRAPH_WAVEFORM
)
1915 break; /* Not applicable */
1917 if (++osc
.advance
>= MAX_ADV
)
1920 osc_popupmsg(OSC_MSG_ADVMODE
, osc
.advance
);
1923 case OSCILLOSCOPE_DRAWMODE
:
1924 #ifdef OSCILLOSCOPE_DRAWMODE_PRE
1925 if (lastbutton
!= OSCILLOSCOPE_DRAWMODE_PRE
)
1928 if (++osc
.draw
>= MAX_DRAW
)
1931 osc_popupmsg(OSC_MSG_DRAWMODE
, osc
.draw
);
1934 /* Need all keymaps for this (remove extra condition when
1936 #ifdef OSCILLOSCOPE_GRAPHMODE
1937 case OSCILLOSCOPE_GRAPHMODE
:
1938 #ifdef OSCILLOSCOPE_GRAPHMODE_PRE
1939 if (lastbutton
!= OSCILLOSCOPE_GRAPHMODE_PRE
)
1942 if (++osc
.graphmode
>= MAX_GRAPH
)
1947 osc_popupmsg(OSC_MSG_GRAPHMODE
, osc
.graphmode
);
1949 #endif /* OSCILLOSCOPE_GRAPHMODE */
1951 case OSCILLOSCOPE_ORIENTATION
:
1952 #ifdef OSCILLOSCOPE_ORIENTATION_PRE
1953 if (lastbutton
!= OSCILLOSCOPE_ORIENTATION_PRE
)
1956 if (++osc
.orientation
>= MAX_OSC
)
1957 osc
.orientation
= 0;
1960 osc_popupmsg(OSC_MSG_ORIENTATION
, osc
.orientation
);
1963 case OSCILLOSCOPE_PAUSE
:
1964 #ifdef OSCILLOSCOPE_PAUSE_PRE
1965 if (lastbutton
!= OSCILLOSCOPE_PAUSE_PRE
)
1969 graphmode_pause_unpause(paused
);
1970 osc_popupmsg(OSC_MSG_PAUSED
, paused
? 1 : 0);
1973 case OSCILLOSCOPE_SPEED_UP
:
1974 case OSCILLOSCOPE_SPEED_UP
| BUTTON_REPEAT
:
1976 int *val
= &osc
.speed
[osc
.graphmode
];
1978 if (*val
< MAX_SPEED
)
1981 update_osc_delay(*val
);
1982 osc_popupmsg(OSC_MSG_SPEED
, *val
);
1986 case OSCILLOSCOPE_SPEED_DOWN
:
1987 case OSCILLOSCOPE_SPEED_DOWN
| BUTTON_REPEAT
:
1989 int *val
= &osc
.speed
[osc
.graphmode
];
1991 if (*val
> MIN_SPEED
)
1994 update_osc_delay(*val
);
1995 osc_popupmsg(OSC_MSG_SPEED
, *val
);
1999 case OSCILLOSCOPE_VOL_UP
:
2000 case OSCILLOSCOPE_VOL_UP
| BUTTON_REPEAT
:
2002 int vol
= rb
->global_settings
->volume
;
2004 if (vol
< rb
->sound_max(SOUND_VOLUME
))
2007 rb
->sound_set(SOUND_VOLUME
, vol
);
2008 rb
->global_settings
->volume
= vol
;
2011 osc_popupmsg(OSC_MSG_VOLUME
, vol
);
2015 case OSCILLOSCOPE_VOL_DOWN
:
2016 case OSCILLOSCOPE_VOL_DOWN
| BUTTON_REPEAT
:
2018 int vol
= rb
->global_settings
->volume
;
2020 if (vol
> rb
->sound_min(SOUND_VOLUME
))
2023 rb
->sound_set(SOUND_VOLUME
, vol
);
2024 rb
->global_settings
->volume
= vol
;
2027 osc_popupmsg(OSC_MSG_VOLUME
, vol
);
2032 exit_on_usb(button
);
2036 #ifdef NEED_LASTBUTTON
2037 if (button
!= BUTTON_NONE
)
2038 lastbutton
= button
;