示例#1
0
文件: rockwell.c 项目: amigan/phoned
static void RV_pzPred(vgetty_s_int16 cx){
/*
   A little explanation is required here. Rockwell uses 16bit
   integers to represent numbers in [-1,1). They take 0x8000 to be -1
   and 0x7fff to be 0.999969482, i.e. the ints -32768 to 32767 are
   normalised over 32768 into the required interval.  The product of
   two such numbers is supposed to be, again, in the range [-1,1).
   I know that this is mathematically incorrect, but that's how they
   do it, just read on.

   The "adjustment" that is mentioned in D.ASM can be understood by
   the following example: Assume you want to multiply -1 with -0.5. In
   integers, that's imul 0x8000, 0xc000 (I know, it does actulally
   require a register), i.e. -32768*-16384. The result is 0x20000000.
   They only want to keep a 16 bit result, thus they need to round.
   First, however, an adjustment for the moved decimal point is
   required. The upper 16 bit of 0x20000000 are 0x2000 which
   corresponds only to 8192/32768=0.25 ! Thus, all the bits need to be
   left shifted by one place and the result will be 0x4000 which
   correctly corresponds to 0.5 now. This confusion is due to the fact
   that the original two numbers in total have two bits representing
   two different signs and the result, which is again represented by a
   total of 32 bits, needs only one sign bit.  Thus, the result in 32
   bits has effectively one more data bit available than the total of
   the two multiplicands. The nature of integer arithmetics feeds that
   bit in from the left behind the sign bit. A consequence of this is
   that the two leftmost bits of the resulting 32 bit integer are
   always equal, apart from one case, namely 0x8000*0x8000, or
   -32768*-32768, which results in 0x40000000. Arithmetically, we
   would expect this to be decimal-point-adjusted to the 16 bit
   representation 0x7fff. The Rockwell assembler code, however, just
   maps this to 0x8000, i.e. -1, by ignoring the special case of
   0x8000*0x8000. This explains the cryptic warnings like

     ; Determine sign of Q(n) * Y(n-1)
     ;
     ; Do not change the sign determination method!

   in D.ASM. Personally, this is the first time ever I have seen
   anyone using arithmetics like -1 * -1 = -1 whilst -1 * -0.99 = 0.99 ;-).

   So, after this type of decimal-point-adjustment they then round off
   the lower 16 bit and just take the upper 16 to be the result.

 */
  static vgetty_s_int32 x,y;        /* local accumulator(s) */
  static vgetty_s_int16 di;
  static int i;

  di = RV_QdataIndex;

  /*  Calculate coefficients a1 a2 b1 b2 b3 b4 b5 b6 . */

  for (i = 0; i < 8; i++)
    {

      x = RV_pzTable[i] * ((vgetty_s_int32) RV_PNT98);
      x <<= 1; /*
             Rockwell-adjust for decimal point shift, then round off
             lower 16 bits to obtain a 16 bit representation of the
             result.
           */
      x = RV_round_32_into_16 (x);
                         /* cx contains the NewQdata=Q(n) */
      y = ((vgetty_s_int32) cx) * ((vgetty_s_int32) RV_Qdata[di]);
      y <<= 1;           /* Rockwell-adjust for decimal point shift. */
      y = RV_round_32_into_16 (y);
      x += (y < 0 ? -1 : 1) * (i < 2 ? RV_PNT012 : RV_PNT006);
      /* i<2 ? The a's get RV_PNT012. All b's get RV_PNT006. */
      /*
         The result of a multiplication needs adjusting & rounding.
         The result of an addition/subtraction needs clipping.
       */
      RV_pzTable[i] = RV_clip_16 (x);
      di++;
      di %= 8;
    }
}
示例#2
0
static vgetty_s_int32 RV_ComOne(vgetty_s_int16 ax)
{
/*
   RVComOne

   Code a word into a bps bit codeword.  Local to this module.

   Inputs:
   AX = X(n)

 */
 int i;
 static vgetty_s_int16 adc16z1 = 0; /*         X(n-1)                 */
 static vgetty_s_int16 NewXpz = 0;  /*         Xp+z(n)                */
 static vgetty_s_int16 bx,cx,dx;
 static vgetty_s_int32 x, y;        /* local accumulator */
 static vgetty_s_int64 sum;

 sum = RV_XpzCalc ((vgetty_s_int16)0);   /*  Compute Xp+z(n)  */
 NewXpz = HIWORD(sum);
 x = ((vgetty_s_int32) adc16z1) * RV_PDEMPCF;
 x <<= 1;                  /* Rockwell-adjust for decimal point shift. */
 sum += x;
 sum = RV_clip_32 (sum);
 cx = HIWORD(sum);
               /* Optimise any of this at your own peril ! */
 x = cx;
 x -= ax;
 cx = RV_clip_16 (x);
 bx = cx;
 if (bx<0) bx = -bx;
 cx = -cx;
 adc16z1 = ax;
 y = RV_LastNu;          /*
                    Optimise any of this at your own peril !
                    Ideally, the important variables
                    here should all be declared volatile.
                    If you change any of this, your
                    optimiser might break it !
               */
 for (i=0;i<RV_cd_length;i++){
  x = ((vgetty_s_int32)RV_cd[i]) * y;
  x <<= 1;               /* Rockwell-adjust for decimal point shift. */
                                        /* Round and Multiply by 4 */
  x = (RV_round_32_into_16 (x) * ((vgetty_s_int32)4));
  dx = RV_clip_16 (x);
  if (bx<dx) break;
 }
 i++;
 if (cx<0){
  i -= RV_cd_length;
  i--;
  i = -i;
 } else i+= RV_cd_length;
 ax = i;
 x = ((vgetty_s_int32)RV_mul_p[i]) * y;
 x <<= 1;           /* Rockwell-adjust for decimal point shift. */
                                        /* Round and Multiply by 4 */
 x = (RV_round_32_into_16 (x) * ((vgetty_s_int32)4));
 RV_LastNu = RV_clip_16 (x);
 if (RV_LastNu < RV_QDLMN)
   RV_LastNu = RV_QDLMN;
 else if (RV_LastNu > RV_QDelayMX)
   RV_LastNu = RV_QDelayMX;
 /*            Make a new inverse quantizer value.          */
 x = ((vgetty_s_int32)RV_Zeta_p[i]) * y;
 x <<= 1;           /* Rockwell-adjust for decimal point shift. */
                                        /* Round and Multiply by 4 */
 x = (RV_round_32_into_16 (x) * ((vgetty_s_int32)4));
 cx = RV_clip_16 (x);
               /* Update predictor filter coefficients. */
 RV_pzPred (cx);
               /* Update delay line at the a1(n) table entry position. */
 RV_QdataIndex += 7;
 RV_QdataIndex %= 8;
 x = NewXpz;
 x += cx;
 RV_Qdata[RV_QdataIndex] = RV_clip_16 (x);   /* drop b6, now a1 Qdata. */
 RV_Qdata[(RV_QdataIndex+2)%8] = cx;         /* drop a2, now b1 Qdata. */
 return (vgetty_s_int32) ax;
}