summaryrefslogtreecommitdiff
path: root/apps/plugins/oscilloscope.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/oscilloscope.c')
-rw-r--r--apps/plugins/oscilloscope.c1910
1 files changed, 1476 insertions, 434 deletions
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}