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:
parent
aea433c3e3
commit
98e6073906
3 changed files with 42 additions and 78 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue