Added MP3::Info.pm inside script to make it standalone.
[kugel-rb.git] / apps / plugins / oscilloscope.c
blobcfb833013431d7760e74c1e454673f8d1c1cf827
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Oscilloscope, with the thought-to-be impossible horizontal aspect!
12 * Copyright (C) 2004 Jens Arnold
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #ifndef SIMULATOR /* not for simulator by now */
23 #include "plugin.h"
25 #ifdef HAVE_LCD_BITMAP /* and also not for the Player */
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
33 #define MAX_PEAK 0x8000
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
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
52 #endif
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))))
58 /* global variables */
60 struct plugin_api* rb; /* global api struct pointer */
61 int x = 0;
62 int draw_mode = DRAW_MODE_FILLED;
63 bool scroll = true;
64 int left_val;
65 int right_val;
66 bool new_val = false;
68 /* prototypes */
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);
75 /* implementation */
77 void lcd_scroll_left(int count, bool black_border)
79 int by;
80 unsigned filler;
81 unsigned char *ptr;
83 if ((unsigned) count >= LCD_WIDTH)
84 return;
86 filler = black_border ? 0xFF : 0;
88 for (by = 0; by < (LCD_HEIGHT/8); by++)
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 */
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"
104 "bra .sl_end \n"
105 "nop \n"
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"
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"
125 rb->memset(ptr + LCD_WIDTH - count, filler, count);
129 void timer_isr(void)
131 static int last_left, last_right;
132 bool full_update = false;
134 if (new_val)
136 if ((unsigned)x >= LCD_WIDTH)
138 if (scroll)
140 lcd_scroll_left(1, false);
141 x = LCD_WIDTH-1;
142 full_update = true;
144 else
145 x = 0;
148 rb->lcd_clearline(x, 0, x, LCD_HEIGHT-1);
150 switch (draw_mode)
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;
159 case DRAW_MODE_OUTLINE:
160 if (x > 0)
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;
168 /* else fall through */
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;
176 if (full_update)
177 rb->lcd_update();
178 else
179 rb->lcd_update_rect(MAX(x - 1, 0), 0, 2, LCD_HEIGHT);
181 last_left = left_val;
182 last_right = right_val;
183 x++;
184 new_val = false;
188 void cleanup(void *parameter)
190 (void)parameter;
192 rb->plugin_unregister_timer();
195 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
197 int button, vol;
198 bool exit = false;
199 bool paused = false;
201 TEST_PLUGIN_API(api);
202 (void)parameter;
203 rb = api;
205 rb->plugin_register_timer(FREQ / 67, 1, timer_isr);
207 while (!exit)
209 if (!paused)
211 /* read the volume info from MAS */
212 left_val = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_HEIGHT/2-2));
213 right_val = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_HEIGHT/2-2));
214 new_val = true;
216 rb->yield();
218 button = rb->button_get(paused);
219 switch (button)
221 case OSCILLOSCOPE_QUIT:
222 exit = true;
223 break;
225 case OSCILLOSCOPE_SCROLL:
226 scroll = !scroll;
227 break;
229 case OSCILLOSCOPE_MODE:
230 draw_mode++;
231 draw_mode = draw_mode % DRAW_MODE_COUNT;
232 break;
234 case OSCILLOSCOPE_PAUSE:
235 paused = !paused;
236 break;
238 case OSCILLOSCOPE_VOL_UP:
239 case OSCILLOSCOPE_VOL_UP | BUTTON_REPEAT:
240 vol = rb->global_settings->volume;
241 if (vol < 100)
243 vol++;
244 rb->mpeg_sound_set(SOUND_VOLUME, vol);
245 rb->global_settings->volume = vol;
247 break;
249 case OSCILLOSCOPE_VOL_DOWN:
250 case OSCILLOSCOPE_VOL_DOWN | BUTTON_REPEAT:
251 vol = rb->global_settings->volume;
252 if (vol > 0)
254 vol--;
255 rb->mpeg_sound_set(SOUND_VOLUME, vol);
256 rb->global_settings->volume = vol;
258 break;
260 default:
261 if (rb->default_event_handler_ex(button, cleanup, NULL)
262 == SYS_USB_CONNECTED)
263 return PLUGIN_USB_CONNECTED;
264 break;
269 cleanup(NULL);
270 return PLUGIN_OK;
272 #endif
273 #endif