summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-03-09 07:52:26 +0000
committerJens Arnold <amiconn@rockbox.org>2006-03-09 07:52:26 +0000
commitb318b3e84f4dad767a9c386954357357964cff38 (patch)
tree13538de6ffb164f6f4e7facdc3db80d9fd4a128c
parentc11a68aee2f0993777d72212241f91ecc99911af (diff)
downloadrockbox-b318b3e84f4dad767a9c386954357357964cff38.tar.gz
rockbox-b318b3e84f4dad767a9c386954357357964cff38.zip
Rewrite of oscilloscope plugin: * Doesn't use a timer isr anymore, ported to swcodec targets. * Added speed adjustment.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8969 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/oscilloscope.c337
1 files changed, 249 insertions, 88 deletions
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index de85dc3950..e215f78efe 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -9,7 +9,7 @@
9* 9*
10* Oscilloscope, with the thought-to-be impossible horizontal aspect! 10* Oscilloscope, with the thought-to-be impossible horizontal aspect!
11* 11*
12* Copyright (C) 2004 Jens Arnold 12* Copyright (C) 2004-2006 Jens Arnold
13* 13*
14* All files in this archive are subject to the GNU General Public License. 14* All files in this archive are subject to the GNU General Public License.
15* See the file COPYING in the source tree root for full license agreement. 15* See the file COPYING in the source tree root for full license agreement.
@@ -19,134 +19,269 @@
19* 19*
20****************************************************************************/ 20****************************************************************************/
21 21
22#ifndef SIMULATOR /* not for simulator by now */
23#include "plugin.h" 22#include "plugin.h"
24 23
25#ifdef HAVE_LCD_BITMAP /* and also not for the Player */ 24#ifdef HAVE_LCD_BITMAP
26#if CONFIG_CODEC != SWCODEC /* only for MAS-targets */
27#include "xlcd.h" 25#include "xlcd.h"
28 26
29PLUGIN_HEADER 27PLUGIN_HEADER
30 28
31/* The different drawing modes */ 29/* The different drawing modes */
32#define DRAW_MODE_FILLED 0 30#define OSC_MODE_FILLED 0
33#define DRAW_MODE_OUTLINE 1 31#define OSC_MODE_OUTLINE 1
34#define DRAW_MODE_PIXEL 2 32#define OSC_MODE_PIXEL 2
35#define DRAW_MODE_COUNT 3 33#define OSC_MODE_COUNT 3
36 34
37#define MAX_PEAK 0x8000 35#define MAX_PEAK 0x8000
38 36
39/* variable button definitions */ 37/* variable button definitions */
40#if CONFIG_KEYPAD == RECORDER_PAD 38#if CONFIG_KEYPAD == RECORDER_PAD
41#define OSCILLOSCOPE_QUIT BUTTON_OFF 39#define OSCILLOSCOPE_QUIT BUTTON_OFF
42#define OSCILLOSCOPE_SCROLL BUTTON_F1 40#define OSCILLOSCOPE_MODE BUTTON_F1
43#define OSCILLOSCOPE_MODE BUTTON_F2 41#define OSCILLOSCOPE_SCROLL BUTTON_F2
44#define OSCILLOSCOPE_PAUSE BUTTON_PLAY 42#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
43#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
44#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
45#define OSCILLOSCOPE_VOL_UP BUTTON_UP 45#define OSCILLOSCOPE_VOL_UP BUTTON_UP
46#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 46#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
47 47
48#elif CONFIG_KEYPAD == ONDIO_PAD 48#elif CONFIG_KEYPAD == ONDIO_PAD
49#define OSCILLOSCOPE_QUIT BUTTON_OFF 49#define OSCILLOSCOPE_QUIT BUTTON_OFF
50#define OSCILLOSCOPE_SCROLL BUTTON_RIGHT 50#define OSCILLOSCOPE_MODE_PRE BUTTON_MENU
51#define OSCILLOSCOPE_MODE BUTTON_MENU 51#define OSCILLOSCOPE_MODE (BUTTON_MENU | BUTTON_REL)
52#define OSCILLOSCOPE_PAUSE BUTTON_LEFT 52#define OSCILLOSCOPE_SCROLL (BUTTON_MENU | BUTTON_RIGHT)
53#define OSCILLOSCOPE_PAUSE (BUTTON_MENU | BUTTON_OFF)
54#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
55#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
56#define OSCILLOSCOPE_VOL_UP BUTTON_UP
57#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
58
59#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
60#define OSCILLOSCOPE_QUIT BUTTON_OFF
61#define OSCILLOSCOPE_MODE BUTTON_SELECT
62#define OSCILLOSCOPE_SCROLL BUTTON_MODE
63#define OSCILLOSCOPE_PAUSE BUTTON_ON
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
69#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
70#define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
71#define OSCILLOSCOPE_MODE (BUTTON_SELECT | BUTTON_PLAY)
72#define OSCILLOSCOPE_SCROLL (BUTTON_SELECT | BUTTON_RIGHT)
73#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
74#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
75#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
76#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
77#define OSCILLOSCOPE_VOL_DOWN BUTTON_SCROLL_BACK
78
79#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
80#define OSCILLOSCOPE_QUIT BUTTON_POWER
81#define OSCILLOSCOPE_MODE BUTTON_SELECT
82#define OSCILLOSCOPE_SCROLL BUTTON_MENU
83#define OSCILLOSCOPE_PAUSE BUTTON_A
84#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
85#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
86#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
87#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
88
89#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
90#define OSCILLOSCOPE_QUIT BUTTON_POWER
91#define OSCILLOSCOPE_MODE BUTTON_SELECT
92#define OSCILLOSCOPE_SCROLL BUTTON_REC
93#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
94#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
95#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
53#define OSCILLOSCOPE_VOL_UP BUTTON_UP 96#define OSCILLOSCOPE_VOL_UP BUTTON_UP
54#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN 97#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
55 98
56#endif 99#endif
57 100
58/* unsigned 16 bit multiplication (a single instruction on the SH) */ 101#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
59#define MULU16(a, b) ((unsigned long) \ 102#define mas_codec_readreg(x) rand()%MAX_PEAK
60 (((unsigned short) (a)) * ((unsigned short) (b)))) 103#endif
61 104
62/* global variables */ 105/* global variables */
63 106
64struct plugin_api* rb; /* global api struct pointer */ 107struct plugin_api* rb; /* global api struct pointer */
65int x = 0;
66int draw_mode = DRAW_MODE_FILLED;
67bool scroll = true;
68int left_val;
69int right_val;
70bool new_val = false;
71 108
72/* prototypes */ 109int osc_mode = OSC_MODE_FILLED;
73 110int osc_delay = 1; /* in ticks */
74void lcd_scroll_left(int count, bool black_border); 111bool osc_scroll = true;
75void timer_isr(void); 112long last_tick = 0;
76void cleanup(void *parameter);
77enum plugin_status plugin_start(struct plugin_api* api, void* parameter);
78 113
79/* implementation */ 114/* implementation */
80 115
81void timer_isr(void) 116void animate(int cur_left, int cur_right)
82{ 117{
118 static int last_x = 0;
83 static int last_left, last_right; 119 static int last_left, last_right;
120
121 int cur_x, x;
122 int left, right, dl, dr;
123 long cur_tick = *rb->current_tick;
124 long d = (cur_tick - last_tick) / osc_delay;
84 bool full_update = false; 125 bool full_update = false;
85 126
86 if (new_val) 127 if (d == 0) /* too early, bail out */
87 { 128 return;
88 if ((unsigned)x >= LCD_WIDTH) 129
130 last_tick = cur_tick;
131
132 if (d > HZ) /* first call or too much delay, (re)start */
133 {
134 last_left = cur_left;
135 last_right = cur_right;
136 return;
137 }
138 cur_x = last_x + d;
139
140 if (cur_x >= LCD_WIDTH)
141 {
142 if (osc_scroll) /* scroll */
143 {
144 int shift = cur_x - (LCD_WIDTH-1);
145 xlcd_scroll_left(shift);
146 full_update = true;
147 cur_x -= shift;
148 last_x -= shift;
149 }
150 else /* wrap */
89 { 151 {
90 if (scroll) 152 cur_x -= LCD_WIDTH;
153 }
154 }
155 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
156
157 if (cur_x > last_x)
158 {
159 rb->lcd_fillrect(last_x + 1, 0, d + 2, LCD_HEIGHT);
160 }
161 else
162 {
163 rb->lcd_fillrect(last_x + 1, 0, (LCD_WIDTH-1) - last_x, LCD_HEIGHT);
164 rb->lcd_fillrect(0, 0, cur_x + 2, LCD_HEIGHT);
165 }
166 rb->lcd_set_drawmode(DRMODE_SOLID);
167
168 switch (osc_mode)
169 {
170 case OSC_MODE_FILLED:
171 left = last_left;
172 right = last_right;
173 dl = (cur_left - left) / d;
174 dr = (cur_right - right) / d;
175
176 for (x = last_x + 1; d > 0; x++, d--)
91 { 177 {
92 xlcd_scroll_left(1); 178 if (x == LCD_WIDTH)
93 x = LCD_WIDTH-1; 179 x = 0;
94 full_update = true; 180
181 left += dl;
182 right += dr;
183
184 rb->lcd_vline(x, LCD_HEIGHT/2+1,
185 LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * left) >> 16));
186 rb->lcd_vline(x, LCD_HEIGHT/2-1,
187 LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * right) >> 16));
188 }
189 break;
190
191 case OSC_MODE_OUTLINE:
192 if (cur_x > last_x)
193 {
194 rb->lcd_drawline(
195 last_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_left) >> 16),
196 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_left) >> 16)
197 );
198 rb->lcd_drawline(
199 last_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_right) >> 16),
200 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_right) >> 16)
201 );
95 } 202 }
96 else 203 else
97 x = 0; 204 {
98 } 205 left = last_left
206 + (LCD_WIDTH - last_x) * (last_left - cur_left) / d;
207 right = last_right
208 + (LCD_WIDTH - last_x) * (last_right - cur_right) / d;
209
210 rb->lcd_drawline(
211 last_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * last_left) >> 16),
212 LCD_WIDTH, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * left) >> 16)
213 );
214 rb->lcd_drawline(
215 last_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * last_right) >> 16),
216 LCD_WIDTH, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * right) >> 16)
217 );
218 rb->lcd_drawline(
219 0, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * left) >> 16),
220 cur_x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * cur_left) >> 16)
221 );
222 rb->lcd_drawline(
223 0, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * right) >> 16),
224 cur_x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * cur_right) >> 16)
225 );
226 }
227 break;
228
229 case OSC_MODE_PIXEL:
230 left = last_left;
231 right = last_right;
232 dl = (cur_left - left) / d;
233 dr = (cur_right - right) / d;
234
235 for (x = last_x + 1; d > 0; x++, d--)
236 {
237 if (x == LCD_WIDTH)
238 x = 0;
239
240 left += dl;
241 right += dr;
242
243 rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + (((LCD_HEIGHT-2) * left) >> 16));
244 rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - (((LCD_HEIGHT-2) * right) >> 16));
245 }
246 break;
99 247
100 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 248 }
101 rb->lcd_vline(x, 0, LCD_HEIGHT-1); 249 last_left = cur_left;
102 rb->lcd_set_drawmode(DRMODE_SOLID); 250 last_right = cur_right;
103 251
104 switch (draw_mode) 252 if (full_update)
253 {
254 rb->lcd_update();
255 }
256 else
257 {
258 if (cur_x > last_x)
105 { 259 {
106 case DRAW_MODE_FILLED: 260 rb->lcd_update_rect(last_x, 0, cur_x - last_x + 2, LCD_HEIGHT);
107 rb->lcd_vline(x, LCD_HEIGHT/2+1, LCD_HEIGHT/2+1 + left_val);
108 rb->lcd_vline(x, LCD_HEIGHT/2-1, LCD_HEIGHT/2-1 - right_val);
109 break;
110
111 case DRAW_MODE_OUTLINE:
112 if (x > 0)
113 {
114 rb->lcd_drawline(x - 1, LCD_HEIGHT/2+1 + last_left,
115 x, LCD_HEIGHT/2+1 + left_val);
116 rb->lcd_drawline(x - 1, LCD_HEIGHT/2-1 - last_right,
117 x, LCD_HEIGHT/2-1 - right_val);
118 break;
119 }
120 /* else fall through */
121
122 case DRAW_MODE_PIXEL:
123 rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + left_val);
124 rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - right_val);
125 break;
126 } 261 }
127
128 if (full_update)
129 rb->lcd_update();
130 else 262 else
131 rb->lcd_update_rect(MAX(x - 1, 0), 0, 2, LCD_HEIGHT); 263 {
132 264 rb->lcd_update_rect(last_x, 0, (LCD_WIDTH-1) - last_x, LCD_HEIGHT);
133 last_left = left_val; 265 rb->lcd_update_rect(0, 0, cur_x + 2, LCD_HEIGHT);
134 last_right = right_val; 266 }
135 x++;
136 new_val = false;
137 } 267 }
268 last_x = cur_x;
138} 269}
139 270
140void cleanup(void *parameter) 271void cleanup(void *parameter)
141{ 272{
142 (void)parameter; 273 (void)parameter;
143 274#ifdef HAVE_LCD_COLOR
144 rb->timer_unregister(); 275 rb->lcd_set_foreground(LCD_DEFAULT_FG);
276 rb->lcd_set_background(LCD_DEFAULT_BG);
277 rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
278#endif
145} 279}
146 280
147enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 281enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
148{ 282{
149 int button, vol; 283 int button, vol;
284 int lastbutton = BUTTON_NONE;
150 bool exit = false; 285 bool exit = false;
151 bool paused = false; 286 bool paused = false;
152 287
@@ -155,18 +290,30 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
155 290
156 xlcd_init(rb); 291 xlcd_init(rb);
157 292
158 rb->timer_register(1, NULL, FREQ / 67, 1, timer_isr); 293#ifdef HAVE_LCD_COLOR
159 294 rb->lcd_set_foreground(LCD_RGBPACK(128, 255, 0));
295 rb->lcd_set_background(LCD_BLACK);
296 rb->lcd_clear_display();
297 rb->lcd_update();
298 rb->backlight_set_timeout(1); /* keep the light on */
299#endif
300
160 while (!exit) 301 while (!exit)
161 { 302 {
162 if (!paused) 303 if (!paused)
163 { 304 {
164 /* read the volume info from MAS */ 305 int left, right;
165 left_val = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_HEIGHT/2-2)); 306
166 right_val = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_HEIGHT/2-2)); 307 rb->sleep(MAX(last_tick + osc_delay - *rb->current_tick - 1, 0));
167 new_val = true; 308
309#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
310 left = rb->mas_codec_readreg(0xC);
311 right = rb->mas_codec_readreg(0xD);
312#elif (CONFIG_CODEC == SWCODEC)
313 rb->pcm_calculate_peaks(&left, &right);
314#endif
315 animate(left, right);
168 } 316 }
169 rb->yield();
170 317
171 button = rb->button_get(paused); 318 button = rb->button_get(paused);
172 switch (button) 319 switch (button)
@@ -176,18 +323,34 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
176 break; 323 break;
177 324
178 case OSCILLOSCOPE_SCROLL: 325 case OSCILLOSCOPE_SCROLL:
179 scroll = !scroll; 326 osc_scroll = !osc_scroll;
180 break; 327 break;
181 328
182 case OSCILLOSCOPE_MODE: 329 case OSCILLOSCOPE_MODE:
183 draw_mode++; 330#ifdef OSCILLOSCOPE_MODE_PRE
184 draw_mode = draw_mode % DRAW_MODE_COUNT; 331 if (lastbutton != OSCILLOSCOPE_MODE_PRE)
332 break;
333#endif
334 if (++osc_mode >= OSC_MODE_COUNT)
335 osc_mode = 0;
185 break; 336 break;
186 337
187 case OSCILLOSCOPE_PAUSE: 338 case OSCILLOSCOPE_PAUSE:
188 paused = !paused; 339 paused = !paused;
340 last_tick = 0;
341 break;
342
343 case OSCILLOSCOPE_SPEED_UP:
344 case OSCILLOSCOPE_SPEED_UP | BUTTON_REPEAT:
345 if (osc_delay > 1)
346 osc_delay--;
189 break; 347 break;
190 348
349 case OSCILLOSCOPE_SPEED_DOWN:
350 case OSCILLOSCOPE_SPEED_DOWN | BUTTON_REPEAT:
351 osc_delay++;
352 break;
353
191 case OSCILLOSCOPE_VOL_UP: 354 case OSCILLOSCOPE_VOL_UP:
192 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT: 355 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
193 vol = rb->global_settings->volume; 356 vol = rb->global_settings->volume;
@@ -216,12 +379,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
216 return PLUGIN_USB_CONNECTED; 379 return PLUGIN_USB_CONNECTED;
217 break; 380 break;
218 } 381 }
219 382 if (button != BUTTON_NONE)
383 lastbutton = button;
220 } 384 }
221
222 cleanup(NULL); 385 cleanup(NULL);
223 return PLUGIN_OK; 386 return PLUGIN_OK;
224} 387}
225#endif /* if using MAS */
226#endif /* if HAVE_LCD_BITMAP */ 388#endif /* if HAVE_LCD_BITMAP */
227#endif /* SIMULATOR */