summaryrefslogtreecommitdiff
path: root/apps/plugins/oscillograph.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/oscillograph.c')
-rw-r--r--apps/plugins/oscillograph.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/apps/plugins/oscillograph.c b/apps/plugins/oscillograph.c
new file mode 100644
index 0000000000..a34aa8bfa9
--- /dev/null
+++ b/apps/plugins/oscillograph.c
@@ -0,0 +1,207 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Philipp Pertermann
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21#ifdef HAVE_LCD_BITMAP
22#ifndef SIMULATOR /* don't want this code in the simulator */
23
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
29
30#define MAX_PEAK 0x8000
31
32/* number of ticks between two volume samples */
33static int speed = 1;
34/* roll == true -> lcd rolls */
35static bool roll = true;
36/* see DRAW_MODE_XXX constants for valid values */
37static int drawMode = DRAW_MODE_FILLED;
38
39/**
40 * Displays a vertically scrolling oscillosgraph using
41 * hardware scrolling of the display. The user can change
42 * speed
43 */
44enum plugin_status plugin_start(struct plugin_api* rb, void* parameter)
45{
46 /* stores current volume value left */
47 int left;
48 /* stores current volume value right */
49 int right;
50 /* specifies the current position on the lcd */
51 int y = LCD_WIDTH - 1;
52
53 /* only needed when drawing lines */
54 int lastLeft = 0;
55 int lastRight = 0;
56 int lasty = 0;
57
58 bool exit = false;
59
60 TEST_PLUGIN_API(rb);
61 (void)parameter;
62
63 /* the main loop */
64 while (!exit) {
65
66 /* read the volume info from MAS */
67 left = rb->mas_codec_readreg(0xC) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
68 right = rb->mas_codec_readreg(0xD) / (MAX_PEAK / (LCD_WIDTH / 2 - 2));
69
70 /* delete current line */
71 rb->lcd_clearline(0, y, LCD_WIDTH-1, y);
72
73 switch (drawMode) {
74 case DRAW_MODE_FILLED:
75 rb->lcd_drawline(LCD_WIDTH / 2 + 1 , y,
76 LCD_WIDTH / 2 + 1 + right, y);
77 rb->lcd_drawline(LCD_WIDTH / 2 - 1 , y,
78 LCD_WIDTH / 2 - 1 -left , y);
79 break;
80
81 case DRAW_MODE_OUTLINE:
82 /* last position needed for lines */
83 lasty = MAX(y-1, 0);
84
85 /* Here real lines were neccessary because
86 anything else was ugly. */
87 rb->lcd_drawline(LCD_WIDTH / 2 + right , y,
88 LCD_WIDTH / 2 + lastRight , lasty);
89 rb->lcd_drawline(LCD_WIDTH / 2 - left , y,
90 LCD_WIDTH / 2 - lastLeft, lasty);
91
92 /* have to store the old values for drawing lines
93 the next time */
94 lastRight = right;
95 lastLeft = left;
96 break;
97
98 case DRAW_MODE_PIXEL:
99 /* straight and simple */
100 rb->lcd_drawpixel(LCD_WIDTH / 2 + right, y);
101 rb->lcd_drawpixel(LCD_WIDTH / 2 - left, y);
102 break;
103 }
104
105
106 /* increment and adjust the drawing position */
107 y++;
108 if (y >= LCD_HEIGHT)
109 y = 0;
110
111 /* I roll before update because otherwise the new
112 line would appear at the wrong end of the display */
113 if (roll)
114 rb->lcd_roll(y);
115
116 /* now finally make the new sample visible */
117 rb->lcd_update_rect(0, MAX(y-1, 0), LCD_WIDTH, 2);
118
119 /* There are two mechanisms to alter speed:
120 1.) slowing down is achieved by increasing
121 the time waiting for user input. This
122 mechanism uses positive values.
123 2.) speeding up is achieved by leaving out
124 the user input check for (-speed) volume
125 samples. For this mechanism negative values
126 are used.
127 */
128
129 if (speed >= 0 || ((speed < 0) && (y % (-speed) == 0))) {
130 bool draw = false;
131
132 /* speed values > 0 slow the oszi down. By user input
133 speed might become < 1. If a value < 1 was
134 passed user input would be disabled. Thus
135 it must be ensured that at least 1 is passed. */
136
137 /* react to user input */
138 switch (rb->button_get_w_tmo(MAX(speed, 1))) {
139 case BUTTON_UP:
140 speed++;
141 draw = true;
142 break;
143
144 case BUTTON_DOWN:
145 speed--;
146 draw = true;
147 break;
148
149 case BUTTON_PLAY:
150 /* pause the demo */
151 rb->button_get(true);
152 break;
153
154 case BUTTON_F1:
155 /* toggle rolling */
156 roll = !roll;
157 break;
158
159 case BUTTON_F2:
160 /* step through the display modes */
161 drawMode ++;
162 drawMode = drawMode % DRAW_MODE_COUNT;
163
164 /* lcd buffer might be rolled so that
165 the transition from LCD_HEIGHT to 0
166 takes place in the middle of the screen.
167 That produces ugly results in DRAW_MODE_OUTLINE
168 mode. If rolling is enabled this change will
169 be reverted before the next update anyway.*/
170 rb->lcd_roll(0);
171 break;
172
173 case BUTTON_F3:
174 speed = 1;
175 draw = true;
176 break;
177
178 case BUTTON_OFF:
179 exit = true;
180 break;
181
182 case SYS_USB_CONNECTED:
183 rb->usb_screen();
184 return PLUGIN_USB_CONNECTED;
185 }
186
187 if (draw) {
188 char buf[16];
189 rb->snprintf(buf, sizeof buf, "Speed: %d", -speed);
190 rb->lcd_putsxy(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT, buf);
191 rb->lcd_update_rect(0, (y + LCD_HEIGHT - 8) % LCD_HEIGHT,
192 LCD_WIDTH, 8);
193 }
194 }
195 }
196
197 /* restore to default roll position.
198 Looks funny if you forget to do this... */
199 rb->lcd_roll(0);
200 rb->lcd_update();
201
202 /* standard return */
203 return PLUGIN_OK;
204}
205
206#endif /* #ifndef SIMULATOR */
207#endif