summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorRobert Keevil <rkeevil+rockbox@gmail.com>2007-07-31 17:23:49 +0000
committerRobert Keevil <rkeevil+rockbox@gmail.com>2007-07-31 17:23:49 +0000
commit98e607390673a2e81eed132724d83f430a0ea66e (patch)
tree1a9ec519c852f7614e416d44161c755ee1fbc115 /apps/plugins
parentaea433c3e30a7ab2f836bd516b0104a236612bbf (diff)
downloadrockbox-98e607390673a2e81eed132724d83f430a0ea66e.zip
rockbox-98e607390673a2e81eed132724d83f430a0ea66e.tar.gz
rockbox-98e607390673a2e81eed132724d83f430a0ea66e.tar.bz2
rockbox-98e607390673a2e81eed132724d83f430a0ea66e.tar.xz
vu_meter: Use the fixedpoint lib (moving flog there)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14103 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/lib/fixedpoint.c30
-rw-r--r--apps/plugins/lib/fixedpoint.h1
-rw-r--r--apps/plugins/vu_meter.c89
3 files changed, 42 insertions, 78 deletions
diff --git a/apps/plugins/lib/fixedpoint.c b/apps/plugins/lib/fixedpoint.c
index cf69d9c..88c2f6e 100644
--- a/apps/plugins/lib/fixedpoint.c
+++ b/apps/plugins/lib/fixedpoint.c
@@ -202,3 +202,33 @@ long cos_int(int val)
}
return 0;
}
+
+/**
+ * Fixed-point natural log
+ * taken from http://www.quinapalus.com/efunc.html
+ * "The code assumes integers are at least 32 bits long. The (positive)
+ * argument and the result of the function are both expressed as fixed-point
+ * values with 16 fractional bits, although intermediates are kept with 28
+ * bits of precision to avoid loss of accuracy during shifts."
+ */
+
+long flog(int x) {
+ long t,y;
+
+ y=0xa65af;
+ if(x<0x00008000) x<<=16, y-=0xb1721;
+ if(x<0x00800000) x<<= 8, y-=0x58b91;
+ if(x<0x08000000) x<<= 4, y-=0x2c5c8;
+ if(x<0x20000000) x<<= 2, y-=0x162e4;
+ if(x<0x40000000) x<<= 1, y-=0x0b172;
+ t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
+ t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
+ t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
+ t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
+ t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
+ t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
+ t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
+ x=0x80000000-x;
+ y-=x>>15;
+ return y;
+}
diff --git a/apps/plugins/lib/fixedpoint.h b/apps/plugins/lib/fixedpoint.h
index c587989..7199157 100644
--- a/apps/plugins/lib/fixedpoint.h
+++ b/apps/plugins/lib/fixedpoint.h
@@ -23,3 +23,4 @@ long fsincos(unsigned long phase, long *cos);
long fsqrt(long a, unsigned int fracbits);
long cos_int(int val);
long sin_int(int val);
+long flog(int x);
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index ba64932..a03f38f 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -16,6 +16,7 @@
*
**************************************************************************/
#include "plugin.h"
+#include "fixedpoint.h"
#if defined(HAVE_LCD_BITMAP)
@@ -200,78 +201,20 @@ void reset_settings(void) {
vumeter_settings.digital_decay=0;
}
-/* taken from http://www.quinapalus.com/efunc.html */
-int fxlog(int x) {
- int t,y;
-
- y=0xa65af;
- if(x<0x00008000) x<<=16, y-=0xb1721;
- if(x<0x00800000) x<<= 8, y-=0x58b91;
- if(x<0x08000000) x<<= 4, y-=0x2c5c8;
- if(x<0x20000000) x<<= 2, y-=0x162e4;
- if(x<0x40000000) x<<= 1, y-=0x0b172;
- t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
- t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
- t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
- t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
- t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
- t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
- t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
- x=0x80000000-x;
- y-=x>>15;
- return y;
-}
-
-/*
- * Integer square root routine, good for up to 32-bit values.
- * Note that the largest square root (that of 0xffffffff) is
- * 0xffff, so the result fits in a regular unsigned and need
- * not be `long'.
- *
- * Original code from Tomas Rokicki (using a well known algorithm).
- * This version by Chris Torek, University of Maryland.
- *
- * This code is in the public domain.
- */
-unsigned int root(unsigned long v)
-{
- register unsigned long t = 1L << 30, r = 0, s; /* 30 = 15*2 */
-
-#define STEP(k) \
- s = t + r; \
- r >>= 1; \
- if (s <= v) { \
- v -= s; \
- r |= t; \
- }
- STEP(15); t >>= 2;
- STEP(14); t >>= 2;
- STEP(13); t >>= 2;
- STEP(12); t >>= 2;
- STEP(11); t >>= 2;
- STEP(10); t >>= 2;
- STEP(9); t >>= 2;
- STEP(8); t >>= 2;
- STEP(7); t >>= 2;
- STEP(6); t >>= 2;
- STEP(5); t >>= 2;
- STEP(4); t >>= 2;
- STEP(3); t >>= 2;
- STEP(2); t >>= 2;
- STEP(1); t >>= 2;
- STEP(0);
- return r;
-
-}
-
void calc_scales(void)
{
unsigned int fx_log_factor = E_POW_5/half_width;
unsigned int y,z;
+ long j;
+ long k;
+ int nh = LCD_HEIGHT - NEEDLE_TOP;
+ long nh2 = nh*nh;
+
for (i=1; i <= half_width; i++)
{
- y = (half_width/5)*fxlog(i*fx_log_factor);
+ /* analog scale */
+ y = (half_width/5)*flog(i*fx_log_factor);
/* better way of checking for negative values? */
z = y>>16;
@@ -281,25 +224,15 @@ void calc_scales(void)
analog_db_scale[i-1] = z;
/* play nice */
rb->yield();
- }
- long j;
- long k;
- unsigned int l;
- int nh = LCD_HEIGHT - NEEDLE_TOP;
- long nh2 = nh*nh;
- for (i=1; i<=half_width; i++)
- {
+ /* y values (analog needle co-ords) */
j = i - (int)(half_width/2);
k = nh2 - ( j * j );
- /* +1 seems to give a closer approximation */
- l = root(k) + 1;
- l = LCD_HEIGHT - l;
- y_values[i-1] = l;
+ /* fsqrt+1 seems to give a closer approximation */
+ y_values[i-1] = LCD_HEIGHT - (fsqrt(k, 16)>>8) - 1;
rb->yield();
}
-
}
void load_settings(void) {