diff options
Diffstat (limited to 'apps/plugins/vu_meter.c')
-rw-r--r-- | apps/plugins/vu_meter.c | 336 |
1 files changed, 163 insertions, 173 deletions
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c index 677d41886d..685d2f65d8 100644 --- a/apps/plugins/vu_meter.c +++ b/apps/plugins/vu_meter.c | |||
@@ -1,232 +1,222 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | |||
3 | * __________ __ ___. | 2 | * __________ __ ___. |
4 | |||
5 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
6 | |||
7 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
8 | |||
9 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
10 | |||
11 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
12 | |||
13 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
14 | |||
15 | * | 8 | * |
16 | |||
17 | * Copyright (C) 2003 Lee Pilgrim | 9 | * Copyright (C) 2003 Lee Pilgrim |
18 | |||
19 | * | 10 | * |
20 | |||
21 | * All files in this archive are subject to the GNU General Public License. | 11 | * All files in this archive are subject to the GNU General Public License. |
22 | |||
23 | * See the file COPYING in the source tree root for full license agreement. | 12 | * See the file COPYING in the source tree root for full license agreement. |
24 | |||
25 | * | 13 | * |
26 | |||
27 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 14 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
28 | |||
29 | * KIND, either express or implied. | 15 | * KIND, either express or implied. |
30 | |||
31 | * | 16 | * |
32 | |||
33 | **************************************************************************/ | 17 | **************************************************************************/ |
34 | |||
35 | #ifndef SIMULATOR /* The simulator dosen't have a MAS */ | ||
36 | |||
37 | #include "plugin.h" | 18 | #include "plugin.h" |
38 | 19 | ||
20 | #ifndef SIMULATOR | ||
21 | #ifdef HAVE_LCD_BITMAP | ||
39 | 22 | ||
23 | static struct plugin_api* rb; | ||
40 | 24 | ||
41 | #ifdef HAVE_LCD_BITMAP | 25 | /* This table is used to define x positions on a logarithmic (dBfs) scale. |
26 | The formula I used to figure these out was log(x+1)*31.89293, | ||
27 | where x was the original x position. */ | ||
28 | static unsigned char db_scale[] = {0,9.6,15.2,19.2,22.3,24.8,27,28.8,30.4,31.9,33.2,34.4,35.5,36.6,37.5,38.4, | ||
29 | 39.2,40,40.8,41.5,52.2,42.8,43.4,44,44.6,45.1,45.7,46.2,46.6,47.1,47.6,48, | ||
30 | 48.4,48.8,49.2,49.6,50,50.4,50.7,51.1,51.4,51.8,52.1,52.4,52.7,53,53.3,53.6, | ||
31 | 53.9,54.2,54.5,54.7,55,55.3,55.5,55.8,56}; | ||
32 | |||
33 | /* Define's y positions, and makes it look like an arch, like a real needle would. */ | ||
34 | static unsigned char y_values[] = {32,31,30,29,28,27,26,25,24,24,23,22,22,21,21,20,19,19,18,18,18,18,18,17,17,17,17,17, | ||
35 | 17,17,17,17,17,18,18,18,18,18,19,19,20,21,21,22,22,23,24,24,25,26,27,28,29,30,31,32, | ||
36 | 32,31,30,29,28,27,26,25,24,24,23,22,22,21,21,20,19,19,18,18,18,18,18,17,17,17,17,17, | ||
37 | 17,17,17,17,17,18,18,18,18,18,19,19,20,21,21,22,22,23,24,24,25,26,27,28,29,30,31,32}; | ||
38 | |||
39 | /* Linear mode bitmap icon. */ | ||
40 | static unsigned char mode_linear[] = {0xDF,0x10,0xD0,0x00,0xDF,0x00,0xDF,0x02,0xC4,0x08,0xDF, | ||
41 | 0x00,0xDF,0x15,0xD1,0x00,0xDE,0x05,0xDE,0x00,0xDF,0x05, | ||
42 | 0xDA}; | ||
43 | |||
44 | /* Logarithmic (dBfs) mode bitmap icon. */ | ||
45 | static unsigned char mode_dbfs[] = {0xC8,0x14,0x14,0x1F,0x00,0xDF,0x15,0x15,0x0A,0xC0,0x1E, | ||
46 | 0x05,0x05,0xC0,0x16,0x15,0xD5,0x09,0xC0,0x00,0xF0,0x00, | ||
47 | 0xFE}; | ||
48 | |||
49 | |||
50 | #define MAX_PEAK 0x7FFF | ||
51 | #define NEEDLE_BOTTOM_Y 54 | ||
52 | |||
53 | #define LEFT_NEEDLE_BOTTOM_X 28 | ||
54 | int left_needle_top_y; | ||
55 | int left_needle_top_x; | ||
56 | int old_left_needle_top_x = 0; | ||
57 | int left_needle_top_x_no_log; | ||
58 | |||
59 | #define RIGHT_NEEDLE_BOTTOM_X 84 | ||
60 | int right_needle_top_y; | ||
61 | int right_needle_top_x; | ||
62 | int old_right_needle_top_x = 56; | ||
63 | int right_needle_top_x_no_log; | ||
64 | |||
65 | bool show_arch = true; | ||
66 | bool use_log_scale = true; | ||
67 | int needle_cover_mode = 1; | ||
68 | |||
69 | /* This draws everthing but the needles, needle covers, and the visible arch. */ | ||
70 | void draw_status_bar(void) | ||
71 | { | ||
72 | rb->lcd_setfont(FONT_SYSFIXED); | ||
73 | rb->lcd_clear_display(); | ||
42 | 74 | ||
75 | rb->lcd_drawline(0, 10, 111, 10); | ||
76 | rb->lcd_putsxy(1, 1, "VU Meter"); | ||
43 | 77 | ||
78 | if(use_log_scale) | ||
79 | rb->lcd_bitmap(mode_dbfs, 88, 1, 23, 8, true); | ||
80 | else | ||
81 | rb->lcd_bitmap(mode_linear, 88, 1, 23, 8, true); | ||
44 | 82 | ||
45 | static struct plugin_api* rb; | 83 | rb->lcd_putsxy(25, 56, "L"); |
84 | rb->lcd_putsxy(81, 56, "R"); | ||
46 | 85 | ||
86 | /* The last line under the needle covers. */ | ||
87 | rb->lcd_drawline(0, 54, 111, 54); | ||
47 | 88 | ||
89 | rb->lcd_update(); | ||
90 | } | ||
48 | 91 | ||
49 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | 92 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) |
50 | |||
51 | { | 93 | { |
52 | |||
53 | TEST_PLUGIN_API(api); | 94 | TEST_PLUGIN_API(api); |
54 | |||
55 | (void) parameter; | 95 | (void) parameter; |
56 | |||
57 | rb = api; | 96 | rb = api; |
58 | 97 | ||
59 | 98 | draw_status_bar(); | |
60 | |||
61 | /* | ||
62 | |||
63 | I hope to make (left/right)_needle_top_y change some day (because it looks | ||
64 | |||
65 | like it is stretching) so that is why it is a int and not a #define. | ||
66 | |||
67 | */ | ||
68 | |||
69 | #define LEFT_NEEDLE_BOTTOM_X 28 | ||
70 | |||
71 | #define LEFT_NEEDLE_BOTTOM_Y 53 | ||
72 | |||
73 | int left_needle_top_x; | ||
74 | |||
75 | int left_needle_top_y = 18; | ||
76 | |||
77 | |||
78 | |||
79 | #define RIGHT_NEEDLE_BOTTOM_X 84 | ||
80 | |||
81 | #define RIGHT_NEEDLE_BOTTOM_Y 53 | ||
82 | |||
83 | int right_needle_top_x; | ||
84 | |||
85 | int right_needle_top_y = 18; | ||
86 | |||
87 | |||
88 | 99 | ||
89 | while (!PLUGIN_OK) | 100 | while (!PLUGIN_OK) |
90 | |||
91 | { | 101 | { |
102 | left_needle_top_x_no_log = | ||
103 | (rb->mas_codec_readreg(0xC) * 56 / MAX_PEAK); | ||
92 | 104 | ||
93 | /* These are to define how far the tip of the needles can go to the | 105 | right_needle_top_x_no_log = |
94 | 106 | (rb->mas_codec_readreg(0xD) * 56 / MAX_PEAK) + 56; | |
95 | left and right. The names are a bit confusing. The LEFT/RIGHT tells | ||
96 | |||
97 | which needle it is for, and the L/R at the end tells which side | ||
98 | |||
99 | of the needle. */ | ||
100 | |||
101 | #define MAX_LEFT_L 2 | ||
102 | |||
103 | #define MAX_LEFT_R 55 | ||
104 | |||
105 | #define MAX_RIGHT_L 57 | ||
106 | |||
107 | #define MAX_RIGHT_R 111 | ||
108 | |||
109 | |||
110 | |||
111 | #define MAX_PEAK 0x7FFF | ||
112 | |||
113 | |||
114 | |||
115 | left_needle_top_x = | ||
116 | |||
117 | (rb->mas_codec_readreg(0xC) * | ||
118 | |||
119 | (MAX_LEFT_R - MAX_LEFT_L) / MAX_PEAK) + MAX_LEFT_L; | ||
120 | |||
121 | |||
122 | |||
123 | right_needle_top_x = | ||
124 | |||
125 | (rb->mas_codec_readreg(0xD) * | ||
126 | |||
127 | (MAX_RIGHT_R - MAX_RIGHT_L) / MAX_PEAK) + MAX_RIGHT_L; | ||
128 | |||
129 | |||
130 | |||
131 | /* Time to draw all of the display stuff! | ||
132 | |||
133 | Could I move some of these out of the loop so they don't have to | ||
134 | |||
135 | be re-drawn everytime, but still be displayed, or would that | ||
136 | |||
137 | improve performance any at all? */ | ||
138 | 107 | ||
139 | rb->lcd_clear_display(); | 108 | rb->lcd_clear_display(); |
140 | 109 | ||
110 | if (use_log_scale) | ||
111 | { | ||
112 | left_needle_top_x = db_scale[left_needle_top_x_no_log]; | ||
113 | right_needle_top_x = db_scale[right_needle_top_x_no_log-56]+56; | ||
114 | } | ||
141 | 115 | ||
116 | else | ||
117 | { | ||
118 | left_needle_top_x = left_needle_top_x_no_log; | ||
119 | right_needle_top_x = right_needle_top_x_no_log; | ||
120 | } | ||
142 | 121 | ||
143 | rb->lcd_drawline(LEFT_NEEDLE_BOTTOM_X, LEFT_NEEDLE_BOTTOM_Y, | 122 | /* Makes a decay on the needle. Todo: Make a user custom decay. */ |
144 | 123 | left_needle_top_x = (left_needle_top_x+old_left_needle_top_x*2)/3; | |
145 | left_needle_top_x, left_needle_top_y); | 124 | right_needle_top_x = (right_needle_top_x+old_right_needle_top_x*2)/3; |
146 | |||
147 | rb->lcd_drawline(RIGHT_NEEDLE_BOTTOM_X, RIGHT_NEEDLE_BOTTOM_Y, | ||
148 | |||
149 | right_needle_top_x, right_needle_top_y); | ||
150 | |||
151 | |||
152 | |||
153 | rb->lcd_setfont(FONT_SYSFIXED); | ||
154 | |||
155 | rb->lcd_putsxy(30, 1, "VU Meter"); | ||
156 | |||
157 | |||
158 | |||
159 | /* The first is the line under "VU Meter" and the second is under | ||
160 | |||
161 | the needles. */ | ||
162 | |||
163 | rb->lcd_drawline(30, 9, 77, 9); | ||
164 | |||
165 | rb->lcd_drawline(0, 53, 111, 53); | ||
166 | |||
167 | |||
168 | |||
169 | /* These are the needle "covers" - we're going for that | ||
170 | |||
171 | "old fashioned" look */ | ||
172 | |||
173 | |||
174 | |||
175 | /* The left needle cover - organized from the top line to the bottom */ | ||
176 | |||
177 | rb->lcd_drawline(27, 48, 29, 48); | ||
178 | |||
179 | rb->lcd_drawline(25, 49, 31, 49); | ||
180 | |||
181 | rb->lcd_drawline(23, 50, 33, 50); | ||
182 | |||
183 | rb->lcd_drawline(22, 51, 34, 51); | ||
184 | |||
185 | rb->lcd_drawline(22, 52, 34, 52); | ||
186 | |||
187 | |||
188 | |||
189 | /* The right needle cover - organized from the top line to | ||
190 | |||
191 | the bottom */ | ||
192 | |||
193 | rb->lcd_drawline(83, 48, 85, 48); | ||
194 | |||
195 | rb->lcd_drawline(81, 49, 87, 49); | ||
196 | |||
197 | rb->lcd_drawline(79, 50, 89, 50); | ||
198 | |||
199 | rb->lcd_drawline(78, 51, 90, 51); | ||
200 | |||
201 | rb->lcd_drawline(78, 52, 90, 52); | ||
202 | 125 | ||
126 | old_left_needle_top_x = left_needle_top_x; | ||
127 | old_right_needle_top_x = right_needle_top_x; | ||
203 | 128 | ||
129 | left_needle_top_y = y_values[left_needle_top_x]; | ||
130 | right_needle_top_y = y_values[right_needle_top_x]; | ||
204 | 131 | ||
205 | rb->lcd_update(); | 132 | /* Draws the needles */ |
133 | rb->lcd_drawline(LEFT_NEEDLE_BOTTOM_X, NEEDLE_BOTTOM_Y, | ||
134 | left_needle_top_x, left_needle_top_y); | ||
206 | 135 | ||
136 | rb->lcd_drawline(RIGHT_NEEDLE_BOTTOM_X, NEEDLE_BOTTOM_Y, | ||
137 | right_needle_top_x, right_needle_top_y); | ||
207 | 138 | ||
139 | if(needle_cover_mode == 1) /* Rounded needle cover. */ | ||
140 | { | ||
141 | /* Left needle cover, top to bottom */ | ||
142 | rb->lcd_drawline(27, 49, 29, 49); | ||
143 | rb->lcd_drawline(25, 50, 31, 50); | ||
144 | rb->lcd_drawline(23, 51, 33, 51); | ||
145 | rb->lcd_drawline(22, 52, 34, 52); | ||
146 | rb->lcd_drawline(22, 53, 34, 53); | ||
147 | |||
148 | /* Right needle cover, top to bottom */ | ||
149 | rb->lcd_drawline(83, 49, 85, 49); | ||
150 | rb->lcd_drawline(81, 50, 87, 50); | ||
151 | rb->lcd_drawline(79, 51, 89, 51); | ||
152 | rb->lcd_drawline(78, 52, 90, 52); | ||
153 | rb->lcd_drawline(78, 53, 90, 53); | ||
154 | } | ||
208 | 155 | ||
209 | /* We must yield once in a while to make sure that the MPEG thread | 156 | else /* Pyramid needle cover. */ |
157 | { | ||
158 | /* Left needle cover, top to bottom */ | ||
159 | rb->lcd_drawpixel(28, 49); | ||
160 | rb->lcd_drawline(27, 50, 29, 50); | ||
161 | rb->lcd_drawline(26, 51, 30, 51); | ||
162 | rb->lcd_drawline(25, 52, 31, 52); | ||
163 | rb->lcd_drawline(24, 53, 32, 53); | ||
164 | |||
165 | /* Right needle cover, top to bottom */ | ||
166 | rb->lcd_drawpixel(84, 49); | ||
167 | rb->lcd_drawline(83, 50, 85, 50); | ||
168 | rb->lcd_drawline(82, 51, 86, 51); | ||
169 | rb->lcd_drawline(81, 52, 87, 52); | ||
170 | rb->lcd_drawline(80, 53, 88, 53); | ||
171 | } | ||
210 | 172 | ||
211 | isn't starved, but we use the shortest possible timeout for best | 173 | if(show_arch) |
174 | { | ||
175 | int i; | ||
176 | for(i=0;i<=112;i++) | ||
177 | rb->lcd_drawpixel(i, (y_values[i])-2 ); | ||
178 | } | ||
212 | 179 | ||
213 | performance */ | 180 | rb->lcd_update_rect(0,15,112,39); |
214 | 181 | ||
215 | switch (rb->button_get_w_tmo(1)) | 182 | switch (rb->button_get_w_tmo(1)) |
216 | |||
217 | { | 183 | { |
218 | |||
219 | case BUTTON_OFF: | 184 | case BUTTON_OFF: |
220 | |||
221 | return PLUGIN_OK; | 185 | return PLUGIN_OK; |
222 | 186 | break; | |
187 | |||
188 | case BUTTON_ON: | ||
189 | rb->lcd_clear_display(); | ||
190 | rb->lcd_putsxy(1, 1, "Information:"); | ||
191 | rb->lcd_putsxy(2, 15, "OFF: Exit"); | ||
192 | rb->lcd_putsxy(2, 25, "ON: This Info"); | ||
193 | rb->lcd_putsxy(2, 35, "PLAY: Change Scale"); | ||
194 | rb->lcd_putsxy(2, 45, "F1: Needle Covers"); | ||
195 | rb->lcd_putsxy(2, 55, "F2: Visible Arch"); | ||
196 | rb->lcd_update(); | ||
197 | rb->sleep(HZ*3); | ||
198 | draw_status_bar(); | ||
199 | break; | ||
200 | |||
201 | case BUTTON_PLAY: | ||
202 | use_log_scale = !use_log_scale; | ||
203 | draw_status_bar(); | ||
204 | break; | ||
205 | |||
206 | case BUTTON_F1: | ||
207 | needle_cover_mode==2 ? needle_cover_mode=1 : needle_cover_mode++; | ||
208 | break; | ||
209 | |||
210 | case BUTTON_F2: | ||
211 | show_arch = !show_arch; | ||
212 | break; | ||
213 | |||
214 | case SYS_USB_CONNECTED: | ||
215 | rb->usb_screen(); | ||
216 | return PLUGIN_USB_CONNECTED; | ||
217 | break; | ||
223 | } | 218 | } |
224 | |||
225 | } | 219 | } |
226 | |||
227 | } | 220 | } |
228 | 221 | #endif /* #ifdef HAVE_LCD_BITMAP */ | |
229 | #endif /* HAVE_LCD_BITMAP */ | ||
230 | |||
231 | #endif /* #ifndef SIMULATOR */ | 222 | #endif /* #ifndef SIMULATOR */ |
232 | |||