*------------- Telecommunications & Signal Processing Lab --------------
*                          McGill University
*
*
* Module:
*     PROGRAM PLTFILTER
*
*
* Purpose:
*     Calculate and plot a filter response
*
*
* Description:
*     This routine plots the response of a filter specified by its
*     coefficients.
*
*     *** FIR or WIN:
*     For an FIR filter, the coefficients are the direct-form
*     coefficients, h(i)
*
*              N-1       -i
*       H(z) = SUM h(i) z    .
*              i=0
*
*     *** ALL:
*     For an all-pole IIR filter, the response is specified by the
*     direct-form feedback coefficients, h(i),
*
*               1                    N-1       -i
*       H(z) = ----  ,  where C(z) = SUM h(i) z    .
*              C(z)                  i=0
*
*     Normally, the first coefficient is unity, i.e. h(0)=1.  A
*     non-unity value will result in a gain scaling of the response.
*
*     *** IIR:
*     For a general IIR filter, the response is specified in terms of
*     the coefficients of cascaded second order sections,
*
*              NSECT
*       H(z) = PROD H(k,z) .
*              k=1
*
*     Each second order section has a response defined by five
*     coefficients,
*
*               h(1,k)*z**2 + h(2,k)*z + h(3,k)
*      H(k,z) = -------------------------------  .
*                  z**2 + h(4,k)*z + h(k,5)
*
*     *** CAS:
*     For a cascade analog filter, the response is specified in terms
*     of the coefficients of cascaded second order sections,
*
*              NSECT
*       H(s) = PROD H(k,s) .
*              k=1
*
*     Each second order section has a response defined by five
*     coefficients,
*
*               h(1,k)*s**2 + h(2,k)*s + h(3,k)
*      H(k,s) = -------------------------------  .
*                  s**2 + h(4,k)*s + h(k,5)
*
*
* Parameters:
*     This routine reads the parameters for a filter response plot.
*
*     % pltfilter Filename PlotDevice OptionString1 OptionString2 ...
*
*     If any of the arguments is missing, the program prompts for the
*     arguments.
*
*     File_name - This program reads filter coefficients from the named
*        input file.  The file may specify an FIR response, an all-
*        pole IIR response, a general IIR response, or a cascade analog
*        filter.  The first 4 characters in the first record in the
*        file specify the type of filter.
*        Valid filter types are:
*          !ALL - all-pole IIR filter
*          !CAS - cascade analog filter
*          !FIR - FIR digital filter
*          !IIR - IIR cascade digital filter
*          !WIN - window response (treated the same as !FIR)
*        The file can also contain comment records with an exclamation
*        mark in the first position.
*     PlotDevice - Plot device as recognized by the plot initialization
*        routine PLINIT.
*     Options - These are options to select the type of plot and
*        control scaling. If supplied on the command line, the options
*        can be broken into separate option strings separated by white
*        space or commas.  If options are not specified on the command
*        line, the program prompts for options.  Prompting continues
*        until a null line is entered.
*
*        Option strings on the command line should be surrounded
*        by single marks to prevent special characters such as
*        parentheses and double quotes from being interpreted before
*        being passed to this program, for example,
*          'X=(-80,20)' and 'TITLE="Title string"'
*
*        The following table shows the option keywords.  The keywords
*        can be specified in either uppercase or lowercase.  In the
*        table, * indicates the position corresponding to the minimum
*        length short form for the keyword.
*
*     Response options:
*        AMP*LITUDE_RESPONSE - Linear amplitude
*        DB*_AMPLITUDE_RESPONSE - Amplitude in dB (default)
*        LOG*_AMPLITUDE_RESPONSE - Logarithmic amplitude
*        DELAY*_RESPONSE - Group delay
*        PHASE*_RESPONSE - Phase response (degrees)
*        RADIAN_PHASE*_RESPONSE - Phase response (units of pi radians)
*        IMP*ULSE_RESPONSE - Impulse response (not available for analog
*          filters)
*     Scaling options:
*        SAMP*LING_FREQUENCY=SFreq - Sets the sampling frequency.  The
*          default is a normalized sampling frequency equal to 1 for
*          digital filters.
*        X*-LIMITS=(Xmin,Xmax) - Minimum and maximum abscissa values.
*          For frequency response plots, these are in units of Hz or pi
*          radians (for RADIAN_FREQUENCY).  For impulse response plots,
*          these are in seconds.
*          default values:
*          - frequency response of a digital filter: 0 to half the
*            sampling frequency.
*          - frequency response of a cascade analog filter: 0 to 5 Hz
*          - impulse response of an FIR digital filter: 0 to the extent
*            of the impulse response
*          - impulse response of an IIR digital filter or the sampled
*            impulse response of a cascade analog filter: 0 to the
*            extent of the impulse response as determined by the point
*            at which the impulse response falls below 1/1000 of the
*            largest value.
*        Y*-LIMITS=(Ymin,Ymax) - Minimum and maximum ordinate values.
*          The units depend on the type of plot.  For linear or
*          logarithmic amplitude responses these are amplitude units.
*          For dB amplitude plots these are in dB units.  For phase
*          response plots, the units are in degrees or pi radians
*          (RADIAN_PHASE_REPONSE).  For delay response plots, the units
*          are seconds.  For impulse responses these are in amplitude
*          units.
*          default values:
*            The default values vary with the type of plot, the type of
*            filter, and the actual response values.  For dB amplitude
*            plots, the default is to plot the amplitude with a range
*            which spans at most 100 dB.
*        LOG_FREQ*UENCY or LOG_FREQ*UENCY=ON or OFF
*          Specifies whether the frequency responses use a log
*          frequency scale or a linear frequency scale.
*          (default ON)
*        RADIAN_FREQ*UENCY or RADIAN_FREQ*UENCY=ON or OFF
*          Specifies whether the frequency responses use a frequency
*          scale in units of pi radians or Hz.
*          (default ON)
*     Other options:
*        LAB*ELS or LAB*ELS=ON or OFF
*          Controls the printing of the axis labels for the plot.
*          (default ON)
*        T*ITLE="title_string" or OFF
*          Controls the printing of a title across the top of the plot.
*          The default title string is the filename of the coefficient
*          file. This default string is used if the TITLE option is not
*          specified or if the title string is null. The keyword OFF is
*          used to suppress the printing of titles.  The default is to
*          print titles.
*        DEVICE_OPT*IONS="device options string"
*          The option string is passed to the plot initialization
*          routine PLINIT.
*        PLOT_OPT*IONS="plot options string"
*          The option string is passed to the plotting routine PLOTYX.
*
*
* Author / revision:
*     P. Kabal
*     $Revision: 1.7 $  $Date: 1995/03/08 15:46:39 $
*
*
*-----------------------------------------------------------------------

      PROGRAM PLTFILTER


      INTEGER LINAR,DBAR,LOGAR,DELYR,PHASD,PHASR,IMPLR
      PARAMETER (LINAR=1,DBAR=2,LOGAR=3,DELYR=4,PHASD=5,PHASR=6,
     -           IMPLR=7)
      INTEGER LINS,LOGS
      PARAMETER (LINS=0,LOGS=1)
      INTEGER MXNPT,MAXCOF
      PARAMETER (MXNPT=2001,MAXCOF=1000)
      REAL EPS
      PARAMETER (EPS=1E-3)

      INTEGER IPLOT,IFAXIS,NCOF,NPT,NCXL,NCXU,NCYL,NCYU,ILOG,NCT
      INTEGER LENNUL,LENSTR

      LOGICAL NFREQ

      CHARACTER*3 FLTTYP*3
      CHARACTER*255 FNAME,PLTDEV,TSTR
      CHARACTER*512 DEVOPT
      CHARACTER*1024 PLTOPT
      CHARACTER*40 XLABEL,XUNITS,YLABEL,YUNITS

      REAL SFREQ,XMIN,XMAX,YMIN,YMAX
      REAL H(MAXCOF),X(0:MXNPT-1),Y(0:MXNPT-1)

      LOGICAL XSPEC,YSPEC,LABELS,TITLES


*==========
* Get the parameters
      CALL PFGETP(FNAME,PLTOPT,PLTDEV,DEVOPT,IPLOT,IFAXIS,
     -            SFREQ,XMIN,XMAX,XSPEC,YMIN,YMAX,YSPEC,
     -            LABELS,TITLES,TSTR)

*==========
* Read the filter coefficients
      CALL READCF(FNAME,MAXCOF,H,NCOF,FLTTYP)
      IF (NCOF.LE.0)
     -  CALL HALT('PLTFILTER - No filter coefficients in file')
      IF (FLTTYP.EQ.' ') THEN
        FLTTYP='FIR'
        CALL WARN('PLTFILTER - FIR filter assumed')
      END IF

*==========
* Set the default sampling frequency
      NFREQ=.FALSE.
      IF (SFREQ.LT.0.0) THEN
        SFREQ=1.0
        IF (FLTTYP.NE.'CAS') NFREQ=.TRUE.
      END IF

*==========
* Fill in the time or frequency array
      CALL PFSETX(IPLOT,IFAXIS,FLTTYP,NCOF,SFREQ,X,MXNPT,NPT,
     -            XMIN,XMAX,XSPEC)

* Fill in the ordinate values
      CALL PFSETY(IPLOT,FLTTYP,H,NCOF,SFREQ,X,Y,NPT)

* Find the extent of an impulse response
* PFILIM modifies NPT and XMAX
      IF (.NOT.XSPEC .AND. IPLOT.EQ.IMPLR .AND.
     -    (FLTTYP.EQ.'ALL' .OR. FLTTYP.EQ.'IIR'))
     -    CALL PFILIM(SFREQ,Y,NPT,EPS,XMAX)

*==========
* Frequency or time scale labels
      CALL ABSCAL(X,NPT,XMIN,XMAX,NFREQ,IPLOT,IFAXIS,
     -            XLABEL,NCXL,XUNITS,NCXU)

*==========
* Find the minimum and maximum ordinate values
      IF (.NOT.YSPEC) CALL PFYLIM(Y,NPT,YMIN,YMAX,NCOF,SFREQ,
     -                            IPLOT,FLTTYP)

* Ordinate scale labels
      CALL ORSCAL(Y,NPT,YMIN,YMAX,SFREQ,IPLOT,
     -            YLABEL,NCYL,YUNITS,NCYU)

*==========
* Plot the frequency response
      CALL PLINIT(PLTDEV,DEVOPT)

* Plot the response
      ILOG=MOD(IFAXIS,2)
      IF (ILOG.EQ.LOGS) CALL CONSTR('X-AXIS=LOG',',',PLTOPT,PLTOPT)
      IF (IPLOT.EQ.LOGAR) CALL CONSTR('Y-AXIS=LOG',',',PLTOPT,PLTOPT)
      IF (IPLOT.EQ.DBAR) CALL CONSTR('X-AXIS=(ORIGIN=OFF)',',',
     -                               PLTOPT,PLTOPT)
      CALL PLOTYX(X,Y,NPT,NPT,1,XMIN,XMAX,YMIN,YMAX,PLTOPT)

* Axis titles and filename
      IF (LABELS)
     -  CALL PLTITL(XLABEL(1:NCXL),XUNITS(1:NCXU),
     -              YLABEL(1:NCYL),YUNITS(1:NCYU))
      IF (TITLES) THEN
        NCT=LENNUL(TSTR)
        IF (NCT.EQ.0) THEN
          CALL FFNAME(FNAME,TSTR)
          NCT=LENSTR(TSTR)
        END IF
        IF (NCT.GT.0) CALL PLTLEG(TSTR(1:NCT))
      END IF

      CALL PLEND


      END
