         Name: LATNRM.ASM
         Type: Assembler Macro
      Version: 1.0
  Last Change:  1-Aug-86

 Description: Normalized Lattice IIR Filter Assembler Macro

 This implements a normalized lattice filter as described by
 A. Gray and J. Markel in "A Normalized Digital Filter Structure",
 IEEE ASSP June, 1975.





   | input
   V
   ------q2---->(+)-------->-----q1---->(+)-------->-----q0-->(+)---------
    |            ^          |            ^          |          ^         |
    |            |          |            |          |          |         |
    k2          -k2         k1          -k1         k0        -k0        V
    |            |          |            |          |          |         |
    V            |          V            |          V          |         |
  -(+)<--q2-------<--1/z---(+)<---q1------<--1/z---(+)<--q0-----<--1/z----
  |                s2    |                 s1    |               s0    |
  v3                     v2                      v1                    v0
  |                       \_______    __________/                      |
   \                              \  /                                /
     ------------------------------(+)--------------------------------
                                    L_________> output


 output sample is in A.  The filter is called by:

     latnrm      order          ;call normalized lattice filter

 where 'latnrm' is the filter macro name and 'order' is the order
 (number of different k parameters) of the filter (3 in this example).
 An example of how to use this macro is found in the DSPLIB in the
 file LATNRMT.ASM.

  The address registers are set as:

        r0                                  r4
        |                                   | 
        v                                   v
     X: q2 k2 q1 k1 q0 k0 v3 v2 v1 v0    Y: sx s2 s1 s0

        m0=3*N (=9, mod 10)                 m4=N  (=3, mod 4)


  The register R0  is  initialized  to  point  to  the  first  q
  coefficient  of  the  leftmost  section  of  the  filter.  The
  register R4 is initialized to point to the first  location  of
  modulo  storage for the filter states.  The modulo register M0
  is initialized to three times the order of  the  filter.   The
  modulo  register  M4 is initialized to the order of the filter
  (note that this results in a modulus of ORDER+1).

  The input sample is put in y0 (called w in the  comments)  and
  the output sample is in A.  The filter is called by:

       latnrm      order    ;call normalized lattice filter

  where 'latnrm' is the filter macro name and  'order'  is  the
  order  (number  of different k parameters) of the filter (3 in
  this example).

  FILTER OPERATION

  The operation of this filter can be described (refer to Figure
  7 and the macro 'latnrm'):

  1.  The input sample is initially in product register Y0.  The
      pointer  R0  is  initially  pointing  to  the first filter
      coefficient (Q2) and the state pointer R4 is  pointing  to
      the first location of the state variable storage.

  2.  The first MOVE instruction loads the first  Q  coefficient
      into  X1  for  the  leftmost  section  of the filter.  The
      pointer R0 is  then  incremented  to  point  to  the  next
      coefficient  (K).   Each  section  of  the filter has four
      multiplies with an additional multiply after the  loop  to
      compute the FIR taps.  Each section of this filter has the
      appearance of a "box".

  3.  The loop then makes ORDER passes.   This  loop  calculates
      the  state  variables.   These  state  variables are later
      multiplied by the V coefficient taps and  summed  to  form
      the output.

  4.  The first multiply in the loop multiplies the  input  (Y0)
      by  the first coefficient (Q2 in X1) and leaves the result
      in A.  This computes the top of the box.   Simultaneously,
      the  k  coefficient (k2) for this section of the filter is
      loaded and the coefficient pointer  is  incremented.   The
      state  variable  for  this  section  of the filter is also
      loaded (Y1) and the pointer to the state variables is  not
      incremented  so  that  later  in  the  loop, the new state
      variable can be written in its place.

  5.  The second instruction of the loop (MAC) multiplies the  k
      coefficient  (in  X0)  by  the  state  variable previously
      loaded (Y1) and subtracts this  result  from  the  summing
      junction  at  the top right of the box.  This value is the
      top left input to the next section  of  the  filter.   The
      value  in  B  is  saved  as the new state variable and the
      pointer R4 is incremented  to  point  to  the  next  state
      variable.   Note  that  on the first pass of the loop, the
      value in B is unknown and an unknown value is saved as the
      first   state   variable.    This   value   is  eventually
      overwritten after exiting the loop.

  6.  The next multiply will multiply the input  value  (Y0)  by
      the k coefficient (X0) to compute the left side of the box
      (B).  At this point, the top right value of the box (A) is
      moved into a product register (Y0) to be used as the input
      to the next filter section.

  7.  The state variable at the bottom left of the box  is  then
      computed  by  summing  the value from the left side of the
      box (B) with the product of the q value (Q2 in X1) and the
      state  variable  (Y1).   This  resulting state variable is
      saved on the next pass of the loop.  The next q value  for
      the  next section of the filter is then loaded into X1 and
      the pointer R0 is incremented.

  8.  Upon exiting from the loop, the loop  has  calculated  and
      saved  ORDER-1  state variables (the first value saved was
      an unknown value do to the order of the statements  always
      saving  the last state variable and upon entry to the loop
      the last  state  variable  is  a  unknown  value).   Since
      ORDER+1  state  variables  are  needed  to compute the FIR
      taps, the other two state variables need to be saved yet.

  9.  The value in the last state is then rounded and the second
      last  state  is  saved (B).  The pointer is incremented to
      point to the next  state  position.   At  this  point  the
      pointer  is  pointing  to the unknown value that was first
      written.

  10. The top rightmost value (in A) is then saved as  the  last
      state.   This value overwrites the unknown value initially
      saved.  The pointer R4 increments to point  to  the  state
      value to multiply the tap v3.

 11.  The state variable to multiply V3 by is then  loaded  into
      Y0  and  the  A  register is cleared to accumulate the FIR
      taps.

 12.  A repeat instruction is used to  multiply  and  accumulate
      ORDER  taps.   The  last  pass  of the DO loop had already
      loaded the first v coefficient (V3) into X1.

 13.  The last FIR tap is then multiplied, accumulated  and  the
      result  is  rounded.  Since R4 was incremented once before
      the repeat loop and ORDER times during the loop, R4 now is
      pointing  to  the same position again (the modulo on R4 is
      ORDER+1).  The register R4 is then incremented to point to
      the  next  state which is the first state to be loaded for
      the next sample time.

 Benchmarks for this filter are:
 13 instructions, 5N+9 instructions cycles, 2 stack locations.
