summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/oscilloscope.c278
2 files changed, 279 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index a42b919a8d..775e20e9ee 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -24,6 +24,7 @@ mandelbrot.c
24minesweeper.c 24minesweeper.c
25mosaique.c 25mosaique.c
26oscillograph.c 26oscillograph.c
27oscilloscope.c
27pong.c 28pong.c
28rockblox.c 29rockblox.c
29sliding_puzzle.c 30sliding_puzzle.c
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
60struct plugin_api* rb; /* global api struct pointer */
61int x;
62int draw_mode;
63bool scroll;
64int left_val;
65int right_val;
66bool new_val;
67
68/* prototypes */
69
70void lcd_scroll_left(int count, bool black_border);
71void timer_isr(void);
72void cleanup(void *parameter);
73enum plugin_status plugin_start(struct plugin_api* api, void* parameter);
74
75/* implementation */
76
77void 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
129void 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
188void cleanup(void *parameter)
189{
190 (void)parameter;
191
192 rb->plugin_unregister_timer();
193}
194
195enum 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