Goeff Probert
Compute signal power with fixed-point calculators
Embedded Systems Programming
October, 2003

Listing 1: Fixed-point signal level calculator

#define MAX_TERM 27  
#define SCALE 131072 // 2^17


// LOG10_2NM1[n] = 131072 * 100 * 10 * log10((2^n)/(2^n-1))      n >= 1
int32_t const LOG10_2NM1[MAX_TERM] = 
{
  0, 39456604, 16375970, 7601120,
  3673781, 1807258, 896457, 446464,
  222794, 111288, 55617, 27802,
  13899, 6949, 3474, 1737,
  869, 434, 217, 109,
  54, 27, 14, 7,
  3, 2, 1  
};

// LOG10_2N[n] = -131072 * 100 * 10 * log10(2^n)          0 <= n < 32
int32_t const LOG10_2N[] = 
{
  0, -39456604, -78913207, -118369811,
  -157826414, -197283018, -236739622, -276196225,
  -315652829, -355109432, -394566036, -434022640,
  -473479243, -512935847, -552392450, -591849054,
  -631305657, -670762261, -710218865, -749675468,
  -789132072, -828588675, -868045279, -907501883,
  -946958486, -986415090, -1025871693, -1065328297,
  -1104784901, -1144241504, -1183698108, -1223154711
};

int32_t 
intLog10(uint32_t x)
{
  uint32_t	  z;
  int32_t	  y;
  int	          k;


  /*
   * log10(0) = -infiniti
   */
  if (x == 0) return (-2147483648);     // largest negative int32_t value

  /*
   * Left shift the argument until 1 <= x < 2.
   */
  for (k = 0; k < 32; k++)	
  {
    if (x & 0x80000000) break;
    x <<= 1;
  }

  /*
   * y is a function of the number of shifts just made.
   */
  y = LOG10_2N[k];

  /*
   * Begin Knuth's log algorithm.
   */
  z = x >> 1;
  for (k = 1; k < MAX_TERM; )
  {
    if (x == 0x80000000) break;

    if ((x - z) < 0x80000000)
    {
       z >>= 1;
       k++;
    }
    else
    {
       x -= z;
       z = x >> k;
       y += LOG10_2NM1[k];
    }
  }

  return (y);

}  /* intLog10() */
#define M0_ALAW -159540501 // log10(((1120**2 + 2624**2)/2) << 5)
#define M0_ULAW -81494089 // log10(((2207**2 + 5215**2)/2) << 5)

int32_t 
dBm0(uint32_t avesq, int32_t m0)
{
  return ((intLog10(avesq << 5) - m0) / SCALE);

}	/* dBm0() */