Added MP3::Info.pm inside script to make it standalone.
[kugel-rb.git] / apps / plugins / oscillograph.c
blob5beeb8891b3cd49adccaf72dfaf5e95c0932bdb8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Philipp Pertermann
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "plugin.h"
21 #ifdef HAVE_LCD_BITMAP
22 #ifndef SIMULATOR /* don't want this code in the simulator */
24 /* The different drawing modes */
25 #define DRAW_MODE_FILLED 0
26 #define DRAW_MODE_OUTLINE 1
27 #define DRAW_MODE_PIXEL 2
28 #define DRAW_MODE_COUNT 3
30 #define MAX_PEAK 0x8000
32 /* variable button definitions */
33 #if CONFIG_KEYPAD == RECORDER_PAD
34 #define OSCILLOGRAPH_QUIT BUTTON_OFF
35 #define OSCILLOGRAPH_SPEED_UP BUTTON_UP
36 #define OSCILLOGRAPH_SPEED_DOWN BUTTON_DOWN
37 #define OSCILLOGRAPH_ROLL BUTTON_F1
38 #define OSCILLOGRAPH_MODE BUTTON_F2
39 #define OSCILLOGRAPH_SPEED_RESET BUTTON_F3
40 #define OSCILLOGRAPH_PAUSE BUTTON_PLAY
42 #elif CONFIG_KEYPAD == ONDIO_PAD
43 #define OSCILLOGRAPH_QUIT BUTTON_OFF
44 #define OSCILLOGRAPH_SPEED_UP BUTTON_UP
45 #define OSCILLOGRAPH_SPEED_DOWN BUTTON_DOWN
46 #define OSCILLOGRAPH_ROLL BUTTON_RIGHT
47 #define OSCILLOGRAPH_MODE BUTTON_MENU
48 #define OSCILLOGRAPH_SPEED_RESET BUTTON_LEFT
50 #endif
52 /* global api struct pointer */
53 static struct plugin_api* rb;
54 /* number of ticks between two volume samples */
55 static int speed = 1;
56 /* roll == true -> lcd rolls */
57 static bool roll = true;
58 /* see DRAW_MODE_XXX constants for valid values */
59 static int drawMode = DRAW_MODE_FILLED;
61 /**
62 * cleanup on return / usb
64 void cleanup(void *parameter)
66 (void)parameter;
68 /* restore to default roll position.
69 Looks funny if you forget to do this... */
70 rb->lcd_roll(0);
71 rb->lcd_update();
74 /**
75 * Displays a vertically scrolling oscillosgraph using
76 * hardware scrolling of the display. The user can change
77 * speed
79 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
81 int button;
82 /* stores current volume value left */
83 int left;
84 /* stores current volume value right */
85 int right;
86 /* specifies the current position on the lcd */
87 int y = LCD_WIDTH - 1;
89 /* only needed when drawing lines */
90 int lastLeft = 0;
91 int lastRight = 0;
92 int lasty = 0;
94 bool exit = false;
96 TEST_PLUGIN_API(api);
97 (void)parameter;
98 rb = api;
100 /* the main loop */
101 while (!exit) {
103 /* read the volume info from MAS */
104 left = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
105 right = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
107 /* delete current line */
108 rb->lcd_clearline(0, y, LCD_WIDTH-1, y);
110 switch (drawMode) {
111 case DRAW_MODE_FILLED:
112 rb->lcd_drawline(LCD_WIDTH / 2 + 1 , y,
113 LCD_WIDTH / 2 + 1 + right, y);
114 rb->lcd_drawline(LCD_WIDTH / 2 - 1 , y,
115 LCD_WIDTH / 2 - 1 -left , y);
116 break;
118 case DRAW_MODE_OUTLINE:
119 /* last position needed for lines */
120 lasty = MAX(y-1, 0);
122 /* Here real lines were neccessary because
123 anything else was ugly. */
124 rb->lcd_drawline(LCD_WIDTH / 2 + right , y,
125 LCD_WIDTH / 2 + lastRight , lasty);
126 rb->lcd_drawline(LCD_WIDTH / 2 - left , y,
127 LCD_WIDTH / 2 - lastLeft, lasty);
129 /* have to store the old values for drawing lines
130 the next time */
131 lastRight = right;
132 lastLeft = left;
133 break;
135 case DRAW_MODE_PIXEL:
136 /* straight and simple */
137 rb->lcd_drawpixel(LCD_WIDTH / 2 + right, y);
138 rb->lcd_drawpixel(LCD_WIDTH / 2 - left, y);
139 break;
143 /* increment and adjust the drawing position */
144 y++;
145 if (y >= LCD_HEIGHT)
146 y = 0;
148 /* I roll before update because otherwise the new
149 line would appear at the wrong end of the display */
150 if (roll)
151 rb->lcd_roll(y);
153 /* now finally make the new sample visible */
154 rb->lcd_update_rect(0, MAX(y-1, 0), LCD_WIDTH, 2);
156 /* There are two mechanisms to alter speed:
157 1.) slowing down is achieved by increasing
158 the time waiting for user input. This
159 mechanism uses positive values.
160 2.) speeding up is achieved by leaving out
161 the user input check for (-speed) volume
162 samples. For this mechanism negative values
163 are used.
166 if (speed >= 0 || ((speed < 0) && (y % (-speed) == 0))) {
167 bool draw = false;
169 /* speed values > 0 slow the oszi down. By user input
170 speed might become < 1. If a value < 1 was
171 passed user input would be disabled. Thus
172 it must be ensured that at least 1 is passed. */
174 /* react to user input */
175 button = rb->button_get_w_tmo(MAX(speed, 1));
176 switch (button) {
177 case OSCILLOGRAPH_SPEED_UP:
178 speed++;
179 draw = true;
180 break;
182 case OSCILLOGRAPH_SPEED_DOWN:
183 speed--;
184 draw = true;
185 break;
187 #ifdef OSCILLOGRAPH_PAUSE
188 case OSCILLOGRAPH_PAUSE:
189 /* pause the demo */
190 rb->button_get(true);
191 break;
192 #endif
194 case OSCILLOGRAPH_ROLL:
195 /* toggle rolling */
196 roll = !roll;
197 break;
199 case OSCILLOGRAPH_MODE:
200 /* step through the display modes */
201 drawMode ++;
202 drawMode = drawMode % DRAW_MODE_COUNT;
204 /* lcd buffer might be rolled so that
205 the transition from LCD_HEIGHT to 0
206 takes place in the middle of the screen.
207 That produces ugly results in DRAW_MODE_OUTLINE
208 mode. If rolling is enabled this change will
209 be reverted before the next update anyway.*/
210 rb->lcd_roll(0);
211 break;
213 case OSCILLOGRAPH_SPEED_RESET:
214 speed = 1;
215 draw = true;
216 break;
218 case OSCILLOGRAPH_QUIT:
219 exit = true;
220 break;
222 default:
223 if (rb->default_event_handler_ex(button, cleanup, NULL)
224 == SYS_USB_CONNECTED)
225 return PLUGIN_USB_CONNECTED;
226 break;
229 if (draw) {
230 char buf[16];
231 rb->snprintf(buf, sizeof buf, "Speed: %d", -speed);
232 rb->lcd_putsxy(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT, buf);
233 rb->lcd_update_rect(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT,
234 LCD_WIDTH, 8);
239 cleanup(NULL);
240 /* standard return */
241 return PLUGIN_OK;
244 #endif /* #ifndef SIMULATOR */
245 #endif