diff options
author | Robert Keevil <rkeevil+rockbox@gmail.com> | 2007-07-31 17:23:49 +0000 |
---|---|---|
committer | Robert Keevil <rkeevil+rockbox@gmail.com> | 2007-07-31 17:23:49 +0000 |
commit | 98e607390673a2e81eed132724d83f430a0ea66e (patch) | |
tree | 1a9ec519c852f7614e416d44161c755ee1fbc115 | |
parent | aea433c3e30a7ab2f836bd516b0104a236612bbf (diff) | |
download | rockbox-98e607390673a2e81eed132724d83f430a0ea66e.tar.gz rockbox-98e607390673a2e81eed132724d83f430a0ea66e.zip |
vu_meter: Use the fixedpoint lib (moving flog there)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14103 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/lib/fixedpoint.c | 30 | ||||
-rw-r--r-- | apps/plugins/lib/fixedpoint.h | 1 | ||||
-rw-r--r-- | apps/plugins/vu_meter.c | 89 |
3 files changed, 42 insertions, 78 deletions
diff --git a/apps/plugins/lib/fixedpoint.c b/apps/plugins/lib/fixedpoint.c index cf69d9c31b..88c2f6ea54 100644 --- a/apps/plugins/lib/fixedpoint.c +++ b/apps/plugins/lib/fixedpoint.c | |||
@@ -202,3 +202,33 @@ long cos_int(int val) | |||
202 | } | 202 | } |
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | |||
206 | /** | ||
207 | * Fixed-point natural log | ||
208 | * taken from http://www.quinapalus.com/efunc.html | ||
209 | * "The code assumes integers are at least 32 bits long. The (positive) | ||
210 | * argument and the result of the function are both expressed as fixed-point | ||
211 | * values with 16 fractional bits, although intermediates are kept with 28 | ||
212 | * bits of precision to avoid loss of accuracy during shifts." | ||
213 | */ | ||
214 | |||
215 | long flog(int x) { | ||
216 | long t,y; | ||
217 | |||
218 | y=0xa65af; | ||
219 | if(x<0x00008000) x<<=16, y-=0xb1721; | ||
220 | if(x<0x00800000) x<<= 8, y-=0x58b91; | ||
221 | if(x<0x08000000) x<<= 4, y-=0x2c5c8; | ||
222 | if(x<0x20000000) x<<= 2, y-=0x162e4; | ||
223 | if(x<0x40000000) x<<= 1, y-=0x0b172; | ||
224 | t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd; | ||
225 | t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920; | ||
226 | t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27; | ||
227 | t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85; | ||
228 | t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1; | ||
229 | t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8; | ||
230 | t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe; | ||
231 | x=0x80000000-x; | ||
232 | y-=x>>15; | ||
233 | return y; | ||
234 | } | ||
diff --git a/apps/plugins/lib/fixedpoint.h b/apps/plugins/lib/fixedpoint.h index c58798930a..719915709a 100644 --- a/apps/plugins/lib/fixedpoint.h +++ b/apps/plugins/lib/fixedpoint.h | |||
@@ -23,3 +23,4 @@ long fsincos(unsigned long phase, long *cos); | |||
23 | long fsqrt(long a, unsigned int fracbits); | 23 | long fsqrt(long a, unsigned int fracbits); |
24 | long cos_int(int val); | 24 | long cos_int(int val); |
25 | long sin_int(int val); | 25 | long sin_int(int val); |
26 | long flog(int x); | ||
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c index ba64932d84..a03f38fe54 100644 --- a/apps/plugins/vu_meter.c +++ b/apps/plugins/vu_meter.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * | 16 | * |
17 | **************************************************************************/ | 17 | **************************************************************************/ |
18 | #include "plugin.h" | 18 | #include "plugin.h" |
19 | #include "fixedpoint.h" | ||
19 | 20 | ||
20 | #if defined(HAVE_LCD_BITMAP) | 21 | #if defined(HAVE_LCD_BITMAP) |
21 | 22 | ||
@@ -200,78 +201,20 @@ void reset_settings(void) { | |||
200 | vumeter_settings.digital_decay=0; | 201 | vumeter_settings.digital_decay=0; |
201 | } | 202 | } |
202 | 203 | ||
203 | /* taken from http://www.quinapalus.com/efunc.html */ | ||
204 | int fxlog(int x) { | ||
205 | int t,y; | ||
206 | |||
207 | y=0xa65af; | ||
208 | if(x<0x00008000) x<<=16, y-=0xb1721; | ||
209 | if(x<0x00800000) x<<= 8, y-=0x58b91; | ||
210 | if(x<0x08000000) x<<= 4, y-=0x2c5c8; | ||
211 | if(x<0x20000000) x<<= 2, y-=0x162e4; | ||
212 | if(x<0x40000000) x<<= 1, y-=0x0b172; | ||
213 | t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd; | ||
214 | t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920; | ||
215 | t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27; | ||
216 | t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85; | ||
217 | t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1; | ||
218 | t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8; | ||
219 | t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe; | ||
220 | x=0x80000000-x; | ||
221 | y-=x>>15; | ||
222 | return y; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Integer square root routine, good for up to 32-bit values. | ||
227 | * Note that the largest square root (that of 0xffffffff) is | ||
228 | * 0xffff, so the result fits in a regular unsigned and need | ||
229 | * not be `long'. | ||
230 | * | ||
231 | * Original code from Tomas Rokicki (using a well known algorithm). | ||
232 | * This version by Chris Torek, University of Maryland. | ||
233 | * | ||
234 | * This code is in the public domain. | ||
235 | */ | ||
236 | unsigned int root(unsigned long v) | ||
237 | { | ||
238 | register unsigned long t = 1L << 30, r = 0, s; /* 30 = 15*2 */ | ||
239 | |||
240 | #define STEP(k) \ | ||
241 | s = t + r; \ | ||
242 | r >>= 1; \ | ||
243 | if (s <= v) { \ | ||
244 | v -= s; \ | ||
245 | r |= t; \ | ||
246 | } | ||
247 | STEP(15); t >>= 2; | ||
248 | STEP(14); t >>= 2; | ||
249 | STEP(13); t >>= 2; | ||
250 | STEP(12); t >>= 2; | ||
251 | STEP(11); t >>= 2; | ||
252 | STEP(10); t >>= 2; | ||
253 | STEP(9); t >>= 2; | ||
254 | STEP(8); t >>= 2; | ||
255 | STEP(7); t >>= 2; | ||
256 | STEP(6); t >>= 2; | ||
257 | STEP(5); t >>= 2; | ||
258 | STEP(4); t >>= 2; | ||
259 | STEP(3); t >>= 2; | ||
260 | STEP(2); t >>= 2; | ||
261 | STEP(1); t >>= 2; | ||
262 | STEP(0); | ||
263 | return r; | ||
264 | |||
265 | } | ||
266 | |||
267 | void calc_scales(void) | 204 | void calc_scales(void) |
268 | { | 205 | { |
269 | unsigned int fx_log_factor = E_POW_5/half_width; | 206 | unsigned int fx_log_factor = E_POW_5/half_width; |
270 | unsigned int y,z; | 207 | unsigned int y,z; |
271 | 208 | ||
209 | long j; | ||
210 | long k; | ||
211 | int nh = LCD_HEIGHT - NEEDLE_TOP; | ||
212 | long nh2 = nh*nh; | ||
213 | |||
272 | for (i=1; i <= half_width; i++) | 214 | for (i=1; i <= half_width; i++) |
273 | { | 215 | { |
274 | y = (half_width/5)*fxlog(i*fx_log_factor); | 216 | /* analog scale */ |
217 | y = (half_width/5)*flog(i*fx_log_factor); | ||
275 | 218 | ||
276 | /* better way of checking for negative values? */ | 219 | /* better way of checking for negative values? */ |
277 | z = y>>16; | 220 | z = y>>16; |
@@ -281,25 +224,15 @@ void calc_scales(void) | |||
281 | analog_db_scale[i-1] = z; | 224 | analog_db_scale[i-1] = z; |
282 | /* play nice */ | 225 | /* play nice */ |
283 | rb->yield(); | 226 | rb->yield(); |
284 | } | ||
285 | 227 | ||
286 | long j; | 228 | /* y values (analog needle co-ords) */ |
287 | long k; | ||
288 | unsigned int l; | ||
289 | int nh = LCD_HEIGHT - NEEDLE_TOP; | ||
290 | long nh2 = nh*nh; | ||
291 | for (i=1; i<=half_width; i++) | ||
292 | { | ||
293 | j = i - (int)(half_width/2); | 229 | j = i - (int)(half_width/2); |
294 | k = nh2 - ( j * j ); | 230 | k = nh2 - ( j * j ); |
295 | /* +1 seems to give a closer approximation */ | ||
296 | l = root(k) + 1; | ||
297 | l = LCD_HEIGHT - l; | ||
298 | 231 | ||
299 | y_values[i-1] = l; | 232 | /* fsqrt+1 seems to give a closer approximation */ |
233 | y_values[i-1] = LCD_HEIGHT - (fsqrt(k, 16)>>8) - 1; | ||
300 | rb->yield(); | 234 | rb->yield(); |
301 | } | 235 | } |
302 | |||
303 | } | 236 | } |
304 | 237 | ||
305 | void load_settings(void) { | 238 | void load_settings(void) { |