diff options
author | Jens Arnold <amiconn@rockbox.org> | 2004-11-07 10:31:39 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2004-11-07 10:31:39 +0000 |
commit | db14d8e50cbfcdc1e4c8dd15894d678a29df67aa (patch) | |
tree | 4082fa815948ccbc095a6f969f5f29b9985ec9ad /apps/plugins/oscilloscope.c | |
parent | 8ed50037e4c5b0e622045eb58c8ab54aad4477fc (diff) | |
download | rockbox-db14d8e50cbfcdc1e4c8dd15894d678a29df67aa.tar.gz rockbox-db14d8e50cbfcdc1e4c8dd15894d678a29df67aa.zip |
New plugin: Oscilloscope, with the thought-to-be impossible horizontal aspect
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5389 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/oscilloscope.c')
-rw-r--r-- | apps/plugins/oscilloscope.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c new file mode 100644 index 0000000000..b37f473491 --- /dev/null +++ b/apps/plugins/oscilloscope.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Oscilloscope, with the thought-to-be impossible horizontal aspect! | ||
11 | * | ||
12 | * Copyright (C) 2004 Jens Arnold | ||
13 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef SIMULATOR /* not for simulator by now */ | ||
23 | #include "plugin.h" | ||
24 | |||
25 | #ifdef HAVE_LCD_BITMAP /* and also not for the Player */ | ||
26 | |||
27 | /* The different drawing modes */ | ||
28 | #define DRAW_MODE_FILLED 0 | ||
29 | #define DRAW_MODE_OUTLINE 1 | ||
30 | #define DRAW_MODE_PIXEL 2 | ||
31 | #define DRAW_MODE_COUNT 3 | ||
32 | |||
33 | #define MAX_PEAK 0x8000 | ||
34 | |||
35 | /* variable button definitions */ | ||
36 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
37 | #define OSCILLOSCOPE_QUIT BUTTON_OFF | ||
38 | #define OSCILLOSCOPE_SCROLL BUTTON_F1 | ||
39 | #define OSCILLOSCOPE_MODE BUTTON_F2 | ||
40 | #define OSCILLOSCOPE_PAUSE BUTTON_PLAY | ||
41 | #define OSCILLOSCOPE_VOL_UP BUTTON_UP | ||
42 | #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN | ||
43 | |||
44 | #elif CONFIG_KEYPAD == ONDIO_PAD | ||
45 | #define OSCILLOSCOPE_QUIT BUTTON_OFF | ||
46 | #define OSCILLOSCOPE_SCROLL BUTTON_RIGHT | ||
47 | #define OSCILLOSCOPE_MODE BUTTON_MENU | ||
48 | #define OSCILLOSCOPE_PAUSE BUTTON_LEFT | ||
49 | #define OSCILLOSCOPE_VOL_UP BUTTON_UP | ||
50 | #define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN | ||
51 | |||
52 | #endif | ||
53 | |||
54 | /* unsigned 16 bit multiplication (a single instruction on the SH) */ | ||
55 | #define MULU16(a, b) ((unsigned long) \ | ||
56 | (((unsigned short) (a)) * ((unsigned short) (b)))) | ||
57 | |||
58 | /* global variables */ | ||
59 | |||
60 | struct plugin_api* rb; /* global api struct pointer */ | ||
61 | int x; | ||
62 | int draw_mode; | ||
63 | bool scroll; | ||
64 | int left_val; | ||
65 | int right_val; | ||
66 | bool new_val; | ||
67 | |||
68 | /* prototypes */ | ||
69 | |||
70 | void lcd_scroll_left(int count, bool black_border); | ||
71 | void timer_isr(void); | ||
72 | void cleanup(void *parameter); | ||
73 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter); | ||
74 | |||
75 | /* implementation */ | ||
76 | |||
77 | void lcd_scroll_left(int count, bool black_border) | ||
78 | { | ||
79 | int by; | ||
80 | unsigned filler; | ||
81 | unsigned char *ptr; | ||
82 | |||
83 | if ((unsigned) count >= LCD_WIDTH) | ||
84 | return; | ||
85 | |||
86 | filler = black_border ? 0xFF : 0; | ||
87 | |||
88 | for (by = 0; by < (LCD_HEIGHT/8); by++) | ||
89 | { | ||
90 | ptr = rb->lcd_framebuffer + MULU16(LCD_WIDTH, by); | ||
91 | asm volatile ( | ||
92 | "mov %0,r1 \n" /* check if both source... */ | ||
93 | "or %2,r1 \n" /* ...and offset are even */ | ||
94 | "shlr r1 \n" /* -> lsb = 0 */ | ||
95 | "bf .sl_start2 \n" /* -> copy word-wise */ | ||
96 | |||
97 | "add #-1,%2 \n" /* copy byte-wise */ | ||
98 | ".sl_loop1: \n" | ||
99 | "mov.b @%0+,r1 \n" | ||
100 | "mov.b r1,@(%2,%0) \n" | ||
101 | "cmp/hi %0,%1 \n" | ||
102 | "bt .sl_loop1 \n" | ||
103 | |||
104 | "bra .sl_end \n" | ||
105 | "nop \n" | ||
106 | |||
107 | ".sl_start2: \n" /* copy word-wise */ | ||
108 | "add #-2,%2 \n" | ||
109 | ".sl_loop2: \n" | ||
110 | "mov.w @%0+,r1 \n" | ||
111 | "mov.w r1,@(%2,%0) \n" | ||
112 | "cmp/hi %0,%1 \n" | ||
113 | "bt .sl_loop2 \n" | ||
114 | |||
115 | ".sl_end: \n" | ||
116 | : /* outputs */ | ||
117 | : /* inputs */ | ||
118 | /* %0 */ "r"(ptr + count), | ||
119 | /* %1 */ "r"(ptr + LCD_WIDTH), | ||
120 | /* %2 */ "z"(-count) | ||
121 | : /* clobbers */ | ||
122 | "r1" | ||
123 | ); | ||
124 | |||
125 | rb->memset(ptr + LCD_WIDTH - count, filler, count); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void timer_isr(void) | ||
130 | { | ||
131 | static int last_left, last_right; | ||
132 | bool full_update = false; | ||
133 | |||
134 | if (new_val) | ||
135 | { | ||
136 | if ((unsigned)x >= LCD_WIDTH) | ||
137 | { | ||
138 | if (scroll) | ||
139 | { | ||
140 | lcd_scroll_left(1, false); | ||
141 | x = LCD_WIDTH-1; | ||
142 | full_update = true; | ||
143 | } | ||
144 | else | ||
145 | x = 0; | ||
146 | } | ||
147 | |||
148 | rb->lcd_clearline(x, 0, x, LCD_HEIGHT-1); | ||
149 | |||
150 | switch (draw_mode) | ||
151 | { | ||
152 | case DRAW_MODE_FILLED: | ||
153 | rb->lcd_drawline(x, LCD_HEIGHT/2+1, | ||
154 | x, LCD_HEIGHT/2+1 + left_val); | ||
155 | rb->lcd_drawline(x, LCD_HEIGHT/2-1, | ||
156 | x, LCD_HEIGHT/2-1 - right_val); | ||
157 | break; | ||
158 | |||
159 | case DRAW_MODE_OUTLINE: | ||
160 | if (x > 0) | ||
161 | { | ||
162 | rb->lcd_drawline(x - 1, LCD_HEIGHT/2+1 + last_left, | ||
163 | x, LCD_HEIGHT/2+1 + left_val); | ||
164 | rb->lcd_drawline(x - 1, LCD_HEIGHT/2-1 - last_right, | ||
165 | x, LCD_HEIGHT/2-1 - right_val); | ||
166 | break; | ||
167 | } | ||
168 | /* else fall through */ | ||
169 | |||
170 | case DRAW_MODE_PIXEL: | ||
171 | rb->lcd_drawpixel(x, LCD_HEIGHT/2+1 + left_val); | ||
172 | rb->lcd_drawpixel(x, LCD_HEIGHT/2-1 - right_val); | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | if (full_update) | ||
177 | rb->lcd_update(); | ||
178 | else | ||
179 | rb->lcd_update_rect(MAX(x - 1, 0), 0, 2, LCD_HEIGHT); | ||
180 | |||
181 | last_left = left_val; | ||
182 | last_right = right_val; | ||
183 | x++; | ||
184 | new_val = false; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | void cleanup(void *parameter) | ||
189 | { | ||
190 | (void)parameter; | ||
191 | |||
192 | rb->plugin_unregister_timer(); | ||
193 | } | ||
194 | |||
195 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | ||
196 | { | ||
197 | int button, vol; | ||
198 | bool exit = false; | ||
199 | bool paused = false; | ||
200 | |||
201 | TEST_PLUGIN_API(api); | ||
202 | (void)parameter; | ||
203 | rb = api; | ||
204 | |||
205 | x = 0; | ||
206 | draw_mode = DRAW_MODE_FILLED; | ||
207 | scroll = true; | ||
208 | new_val = false; | ||
209 | |||
210 | rb->plugin_register_timer(FREQ / 67, 1, timer_isr); | ||
211 | |||
212 | while (!exit) | ||
213 | { | ||
214 | if (!paused) | ||
215 | { | ||
216 | /* read the volume info from MAS */ | ||
217 | left_val = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_HEIGHT/2-2)); | ||
218 | right_val = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_HEIGHT/2-2)); | ||
219 | new_val = true; | ||
220 | } | ||
221 | rb->yield(); | ||
222 | |||
223 | button = rb->button_get(false); | ||
224 | switch (button) | ||
225 | { | ||
226 | case OSCILLOSCOPE_QUIT: | ||
227 | exit = true; | ||
228 | break; | ||
229 | |||
230 | case OSCILLOSCOPE_SCROLL: | ||
231 | scroll = !scroll; | ||
232 | break; | ||
233 | |||
234 | case OSCILLOSCOPE_MODE: | ||
235 | draw_mode++; | ||
236 | draw_mode = draw_mode % DRAW_MODE_COUNT; | ||
237 | break; | ||
238 | |||
239 | case OSCILLOSCOPE_PAUSE: | ||
240 | paused = !paused; | ||
241 | break; | ||
242 | |||
243 | case OSCILLOSCOPE_VOL_UP: | ||
244 | case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT: | ||
245 | vol = rb->global_settings->volume; | ||
246 | if (vol < 100) | ||
247 | { | ||
248 | vol++; | ||
249 | rb->mpeg_sound_set(SOUND_VOLUME, vol); | ||
250 | rb->global_settings->volume = vol; | ||
251 | } | ||
252 | break; | ||
253 | |||
254 | case OSCILLOSCOPE_VOL_DOWN: | ||
255 | case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT: | ||
256 | vol = rb->global_settings->volume; | ||
257 | if (vol > 0) | ||
258 | { | ||
259 | vol--; | ||
260 | rb->mpeg_sound_set(SOUND_VOLUME, vol); | ||
261 | rb->global_settings->volume = vol; | ||
262 | } | ||
263 | break; | ||
264 | |||
265 | default: | ||
266 | if (rb->default_event_handler_ex(button, cleanup, NULL) | ||
267 | == SYS_USB_CONNECTED) | ||
268 | return PLUGIN_USB_CONNECTED; | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | } | ||
273 | |||
274 | cleanup(NULL); | ||
275 | return PLUGIN_OK; | ||
276 | } | ||
277 | #endif | ||
278 | #endif | ||