summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-03-01 09:52:24 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-03-01 09:52:24 +0000
commite392a1b6e65fb93393488806ca405bf251069a1e (patch)
tree7d20d286dae1ba9fbd7c82c1eeb65e399edbe90f
parent50c2261756123f4c334c57ba72650b208754ec1d (diff)
downloadrockbox-e392a1b6e65fb93393488806ca405bf251069a1e.tar.gz
rockbox-e392a1b6e65fb93393488806ca405bf251069a1e.zip
Log scale for the VU meter, patch #897248 by Lee Pilgrim
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4323 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/vu_meter.c336
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
23static 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. */
28static 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. */
34static 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. */
40static 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. */
45static 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
54int left_needle_top_y;
55int left_needle_top_x;
56int old_left_needle_top_x = 0;
57int left_needle_top_x_no_log;
58
59#define RIGHT_NEEDLE_BOTTOM_X 84
60int right_needle_top_y;
61int right_needle_top_x;
62int old_right_needle_top_x = 56;
63int right_needle_top_x_no_log;
64
65bool show_arch = true;
66bool use_log_scale = true;
67int needle_cover_mode = 1;
68
69/* This draws everthing but the needles, needle covers, and the visible arch. */
70void 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
45static 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
49enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 92enum 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