1
0
Fork 0
forked from len0rd/rockbox

vu_meter: Use the fixedpoint lib (moving flog there)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14103 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Robert Keevil 2007-07-31 17:23:49 +00:00
parent aea433c3e3
commit 98e6073906
3 changed files with 42 additions and 78 deletions

View file

@ -202,3 +202,33 @@ long cos_int(int val)
} }
return 0; 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;
}

View file

@ -23,3 +23,4 @@ long fsincos(unsigned long phase, long *cos);
long fsqrt(long a, unsigned int fracbits); long fsqrt(long a, unsigned int fracbits);
long cos_int(int val); long cos_int(int val);
long sin_int(int val); long sin_int(int val);
long flog(int x);

View file

@ -16,6 +16,7 @@
* *
**************************************************************************/ **************************************************************************/
#include "plugin.h" #include "plugin.h"
#include "fixedpoint.h"
#if defined(HAVE_LCD_BITMAP) #if defined(HAVE_LCD_BITMAP)
@ -200,78 +201,20 @@ void reset_settings(void) {
vumeter_settings.digital_decay=0; 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) void calc_scales(void)
{ {
unsigned int fx_log_factor = E_POW_5/half_width; unsigned int fx_log_factor = E_POW_5/half_width;
unsigned int y,z; 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++) 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? */ /* better way of checking for negative values? */
z = y>>16; z = y>>16;
@ -281,25 +224,15 @@ void calc_scales(void)
analog_db_scale[i-1] = z; analog_db_scale[i-1] = z;
/* play nice */ /* play nice */
rb->yield(); rb->yield();
}
long j; /* y values (analog needle co-ords) */
long k;
unsigned int l;
int nh = LCD_HEIGHT - NEEDLE_TOP;
long nh2 = nh*nh;
for (i=1; i<=half_width; i++)
{
j = i - (int)(half_width/2); j = i - (int)(half_width/2);
k = nh2 - ( j * j ); 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(); rb->yield();
} }
} }
void load_settings(void) { void load_settings(void) {