/**C*
 *
 * Vaisala software source code file
 *
 * Copyright (c) Vaisala Oyj 1989, 1990, 1992, 1995, 1996, 1997, 1998, 1999,
 * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2010, 2011, 2012, 2013.
 * All rights reserved.
 *
 **C*/

/** @file
 *
 * Vaisala Weather Radar - Digital Signal Processor Library
 *
 * $URL: https://subversion.vaisala.com/svn/repos/sigmet/wr_iris_rda/branches/release8.13.5/base/dsp_lib/dsp_lib.h $
 *
 * $Id: dsp_lib.h 30289 2014-10-24 20:42:55Z rke $
 *
 */

/*
 * This collection of library routines provides a uniform interface to a
 * Vaisala Radar Signal Processor (RVP7/8/9, etc).  All library source
 * files are located in the libs/dsp directory.  The libraries
 * themselves are libs/lib/libdspi.a (the "information" routines), and
 * libs/lib/libdsp.a (the "I/O" routines).
 */
#ifndef SIGMET_DSP_LIB_H
#define SIGMET_DSP_LIB_H 1

#ifdef __cplusplus
extern "C" {
#endif

#define DSP_BADROM           (DSP_FACILITY + 2)
#define DSP_BYTEORDER_ERR    (DSP_FACILITY + 3)
#define DSP_BYTEORDER_UNK    (DSP_FACILITY + 4)
#define DSP_CANT_PROC        (DSP_FACILITY + 5)
#define DSP_CANT_TSEQ        (DSP_FACILITY + 10)
#define DSP_CASE_IFACE       (DSP_FACILITY + 11)
#define DSP_CLOCK_MASK       (DSP_FACILITY + 12)
#define DSP_DEV_ENOENT       (DSP_FACILITY + 13)
#define DSP_FEATURE_MISSING  (DSP_FACILITY + 14)
#define DSP_INIT_FIRST       (DSP_FACILITY + 15)
#define DSP_NO_DSP           (DSP_FACILITY + 16)
#define DSP_MAJOR_MODE       (DSP_FACILITY + 20)
#define DSP_NEWCODE          (DSP_FACILITY + 21)
#define DSP_NOBOOT           (DSP_FACILITY + 22)
#define DSP_NSE_INTERFERE    (DSP_FACILITY + 23)
#define DSP_NSE_TRIG         (DSP_FACILITY + 24)
#define DSP_NSE_RANGE        (DSP_FACILITY + 25)
#define DSP_NSE_LINEAR       (DSP_FACILITY + 26)
#define DSP_RADIATE_WRONG    (DSP_FACILITY + 29)
#define DSP_POLAR_BAD        (DSP_FACILITY + 30)
#define DSP_POLAR_WRONG      (DSP_FACILITY + 31)
#define DSP_PROC_BADMIX      (DSP_FACILITY + 32)
#define DSP_SCSI_00001       (DSP_FACILITY + 33)
#define DSP_SCSI_00010       (DSP_FACILITY + 34)
#define DSP_SCSI_00100       (DSP_FACILITY + 35)
#define DSP_SCSI_01000       (DSP_FACILITY + 40)
#define DSP_SCSI_01010       (DSP_FACILITY + 41)
#define DSP_SCSI_01100       (DSP_FACILITY + 42)
#define DSP_SCSI_10001       (DSP_FACILITY + 43)
#define DSP_SCSI_10100       (DSP_FACILITY + 44)
#define DSP_SCSI_XXXXX       (DSP_FACILITY + 45)
#define DSP_TCF_STRING       (DSP_FACILITY + 50)
#define DSP_TYPE_MISMATCH    (DSP_FACILITY + 51)
#define DSP_UNALIGN_RD       (DSP_FACILITY + 52)
#define DSP_UNALIGN_WR       (DSP_FACILITY + 53)
#define DSP_UNK_IFACE        (DSP_FACILITY + 54)
#define DSP_UNK_TYPE         (DSP_FACILITY + 55)
#define DSP_VERSION_MISMATCH (DSP_FACILITY + 56)
#define DSP_WRONG_PW         (DSP_FACILITY + 60)
#define DSP_RANGE_MASK_ERR   (DSP_FACILITY + 61)
#define DSP_MAX_PRF_ERR      (DSP_FACILITY + 62)
#define DSP_PW_CONT_ERR      (DSP_FACILITY + 63)
#define DSP_OPEN_ERROR       (DSP_FACILITY + 64)
#define DSP_EXPORT_BUSY      (DSP_FACILITY + 65)
#define DSP_WRONG_MMODE      (DSP_FACILITY + 66)
#define DSP_READ_PACKET_SIZE (DSP_FACILITY + 67)
#define DSP_NOT_OPEN_IO      (DSP_FACILITY + 68)
#define DSP_BIGSYNCTABLE     (DSP_FACILITY + 69)


/* ***********************************
 * *                                 *
 * *  Basic DSP Library Definitions  *
 * *                                 *
 * ***********************************
 */

/* The type of processor we have here.  WARNING: Code depends on
 * increasing the type number with newer processors!
 */
/* #define TYPE_RVP5      (1) */     /* RVP-5 125-m resolution */
/* #define TYPE_PPP       (2) */     /* PPP 18.75-m resolution */
/* #define TYPE_FFT       (4) */     /* EEC FFT Processor (c1984) */
#define SIGMET_DSP_TYPE_DEFINED 1
#define DSP_TYPE_MIN    (7)
enum sigmet_dsp_type
{
    DSP_TYPE_RVP6    =  5,   /* RVP6 Processor */
    DSP_TYPE_RVP6_2  =  6,   /* RVP6 Dual board Processor */
    DSP_TYPE_RVP7    =  7,   /* RVP7 Processor */
    DSP_TYPE_RVP8    =  8,   /* RVP8 Processor */
    DSP_TYPE_RVP9    =  9    /* RVP900 Processor */
};
#define DSP_TYPE_MAX    (9)

/* The interface to the processor
 */
#define DSPIFACE_MIN     (2)
  /* #define DSPIFACE_GPIO    (1) */	/* HP GPIO parallel connection */
#define DSPIFACE_SCSI    (2)	/* Small-Systems-Computer-Interface */
#define DSPIFACE_NATIVE  (3)	/* DSP is implemented on native machine itself */
#define DSPIFACE_SOCKET  (4)	/* DSP is implemented on native machine itself */
#define DSPIFACE_MAX     (4)

/* The DSP information structure's actual contents are hidden from the
 * outside world at this point.  Only access should be through the
 * library.
 */
struct dsp_info ;
typedef struct dsp_info Dsp ;

/* ********************************************
 * *                                          *
 * * Function Prototypes for Library Routines *
 * *                                          *
 * ********************************************
 */

/* --------------------------------------------------------------
 * ------------- Fundamental Communication Routines -------------
 * --------------------------------------------------------------
 */
/* DspOpenForIo() must be called before any I/O to the signal
 * processor can be performed.  If there is an error, it will return
 * NULL, and set the message value in istatus_a.  Likewise DSP_OPEN()
 * must be called to get the DSP pointer before any dsp library info
 * calls can be made.  You only call one routine or the other, never
 * both.
 */
Dsp *DspOpenForIo
( MESSAGE *istatus_a ) ;	/* MESSAGE return */

Dsp *DspOpen
( MESSAGE *istatus_a ) ;	/* Exit status */

/* ============================================================
 * Raise authorization from info to I/O mode.  Called with an
 * already opened Dsp.  Returns error if it cannot authorize I/O,
 * but the library remains open.  DspOpenForIo essentially just
 * calls DspOpen(), then DspAuthorizeIo().
 */
MESSAGE DspAuthorizeIo
( Dsp *pDsp_a );

/* DspClose() should be called after all I/O to the signal processor
 * has been performed.  It releases the interface so that other
 * programs can use it.
 */
MESSAGE DspClose
( Dsp *dsp_a ) ;

/* Routine to alter the timeout duration of an open DSP interface, if
 * that is still possible to do.
 */
MESSAGE DspSetTimeoutMS( Dsp *pDsp_a, SINT4 iTimeoutMS_a ) ;

/* Routine to reliably reset the output FIFO of any RVP-style signal
 * processor.
 */
MESSAGE DspResetFifo
( Dsp *dsp_a ) ;

/* Reset the kernel FIFOs, if such an operation makes sense on the
 * current interface.
 */
MESSAGE DspResetKernelFifos
( Dsp *dsp_a,
  UINT4 iOper_a ) ;
#define RESKFF_TODSP      0x0001 /* Reset kernel FIFO going to the DSP */
#define RESKFF_FROMDSP    0x0002 /* Reset kernel FIFO coming from the DSP */

/* This routine is called to read the time from a remote RVP8/9.
 */
MESSAGE DspGetTimeFull
( Dsp *pDsp_a,
  struct full_time_spec *pTime_a,
  int iFlags_a );

/* Routine to check whether the byte order of the signal processor is
 * correct for this workstation.  Returns:
 *
 *            SS_NORMAL : All is well
 *    DSP_BYTEORDER_UNK : Byte order can not be determined
 *    DSP_BYTEORDER_ERR : Byte order is swapped
 *
 * Note that this will skip the byte order checking if this is turned
 * off in setup.
 */
MESSAGE DspCheckByteOrder
( Dsp *dsp_a ) ;

/* IDSP_INTERFACE() returns the type of interface used to connect
 * between the DSP and computer.  IDSP_TYPE() returns the processor
 * type, and IDSP_STRUCT_SIZE() returns the size in bytes of the
 * opaque (Dsp*) structure.
 */
UINT4 idsp_interface		/* Returns one of DSPIFACE_xxx */
( Dsp* dsp ) ;

UINT4 idsp_type			/* Returns one of DSP_TYPE_xxx */
( Dsp* dsp ) ;

/* Returns flag indicating if we are open for I/O
 */
UINT1 lDspOpenForIo
( Dsp *pDsp_a ) ;

SINT4 idsp_struct_size
( void ) ;

/* Returns a pointer to the setup structure.  This may be derived from
 * a remote machine in the case of a socket interface.
 */
#ifdef SIGMET_SETUP_H
const struct dsp_manual_setup *DspGetSetupPointer
( Dsp *pDsp_a );            /* Dsp structure */
#endif  /* #ifdef SIGMET_SETUP_H */

/* Return a pointer to the Z calibration information in the library.
 */
const struct dsp_refl_cal *DspGetZcalPointer
(Dsp *pDsp_a );            /* Dsp structure */

/* Save the Z calibration information in the library and on disk.
 */
MESSAGE DspSetZcal
(Dsp *pDsp_a,            /* Dsp structure */
 const struct dsp_refl_cal *pzCalibration_a );

/* Send the supplied ZCAL structure in ASCII format over a socket. */
MESSAGE DspSendZcalSocket
( Dsp *pDsp_a,
  const char* sPrefix_a,              /* Prefix string */
  const struct dsp_refl_cal *pData_a, /* Data to send */
  const char* sWho_a,                 /* Who I am */
  int iSocket_a );                    /* Socket to write on */

SINT4 idsp_maxSampleSize( Dsp* dsp_a ) ;
SINT4 idsp_maxSpectrumSize( Dsp* dsp_a ) ;

/* Fundamental read/write routines to the signal processor.  All DSP
 * I/O is handled by DSP_READ() and DSP_WRITE(); both from within the
 * library, and from external calls.  I/O operations are fundamentally
 * 16-bits wide.
 */

  /* dsp_read() reads in one DMA operation.  It will always return the
   * full number of bytes desired, or return an error and no data.
   */
MESSAGE dsp_read
( Dsp *dsp_a,
  volatile void *irbuf_a,	/* Buffer to receive data */
  SINT4 ircnt_a,		/* Number of 16-bit words to read */
  volatile SINT4 *iactwcnt_a ) ; /* Actual number of words read */

  /* DspReadAvail() is an optimization of the dsp_read() function.  It is
   * used when you are not sure the number of words which will be output.
   * It checks the data available bit, and as long as there is data
   * available, and there maximum size is not reached, it issues
   * another dsp_read() of the DMA size.  It will always return a read
   * size which is a nonnegative integer times the DMA size.  In a network
   * interface, this operation is done on the remote system which greatly
   * increases the performance.
   */
MESSAGE DspReadAvail
( Dsp *pDsp_a,
  volatile void *irbuf_a,      /* Data goes here */
  SINT4 ircnt_a,               /* Maximum size of the transfer */
  SINT4 iDmaSize_a,            /* Size of individual reads */
  volatile SINT4 *iactwcnt_a );/* Actual size of the transfer */

MESSAGE dsp_write
( Dsp *dsp_a,
  volatile const void *iwbuf_a,	/* Buffer of data to be written */
  SINT4 iwcnt_a ) ;		/* Number of 16-bit words to write */

/* DSPR_STATUS() provides the 3-bit processor I/O status from the
 * external DSP.  The LSB represents "data available", i.e., at least
 * one 16-bit word of data could be read from the signal processor
 * right now.
 */
MESSAGE dspr_status
( Dsp *dsp_a,
  UINT2 *istatus_a ) ;		/* 3-bit DSP status lines */

#define DSPSTS_OUTAVAIL    0x1	/* Output words are available from the DSP */
#define DSPSTS_INQUEUED    0x2	/* Input words to the DSP are still queued */

/* DSPSTART() is a high-level version of DSP_OPEN_FOR_IO() that also
 * initializes the DSP in several ways.  It performs the read/write
 * test, checks for code upgrades, and puts the processor into a known
 * idle state.
 */
Dsp *DspStart
( MESSAGE *pStatus_a ) ;

/* DSPR_WALK() reads a walking ones pattern (1,2,4,...) from the DSP,
 * and is intended to test the I/O output data path.  DSPW_PAT()
 * writes a 16-word pattern which is then echoed back and can be
 * picked up with DSP_READ().
 */
MESSAGE dspr_walk
( Dsp *dsp_a,
  UINT2 iwalk_a[16] ) ;		/* Walking ones read from DSP */

MESSAGE dspw_pat
( Dsp *dsp_a,
  const UINT2 idiag_a[16] ) ;	/* Test pattern to write */

/* DSPW_RESET() performs various types of processor resets
 */
MESSAGE dspw_reset
( Dsp *dsp_a,
  UINT2 lzoff_a,		/* Zero log, I, Q offsets */
  UINT2 lfifo_a,		/* Clear processor output FIFO */
  UINT2 lpwrp_a ) ;		/* Complete powerup reset */

/* DSPW_ROMLOAD() loads a new ROM code image into the RVP7.
 */
MESSAGE dspw_romload
( Dsp *dsp_a, const char *sPathName_a,
  UINT1 lOnlyIfDifferent_a, UINT1 lFailOkay_a ) ;

MESSAGE dspw_led		/* Turn On/Off Red LED */
( Dsp *dsp_a,
  UINT2 lon_a ) ;

void dsp_lib_nls_init(void);  /* File: dsp_lib_message_init.c */
#define DSP_LIB_INIT dsp_lib_nls_init()

/* ---------------------------------------------------------------
 * ------------------ Data Type Parameter Masks ------------------
 * ---------------------------------------------------------------
 */
/* Return a mask showing all the 1-byte and 2-byte data that are
 * available from the DSP.
 */
void Dsp1ByteMask
( struct dsp_data_mask *pDataMask_a ) ;

void Dsp2ByteMask
( struct dsp_data_mask *pDataMask_a ) ;

/* Various logical operations on data masks.
 */
void DspMaskAnd			/* AND into a mask */
( volatile struct dsp_data_mask *pMainMask_a,
  const struct dsp_data_mask *pAndMask_a ) ;

void DspMaskAndNot		/* AND complemented into a mask */
( volatile struct dsp_data_mask *pMainMask_a,
  const struct dsp_data_mask *pAndMask_a ) ;

void DspMaskOr			/* OR into a mask */
( struct dsp_data_mask *pMainMask_a,
  const struct dsp_data_mask *pOrMask_a ) ;

/** Clear all data types in the mask */
void DspMaskClearAll(struct dsp_data_mask *pDataMask_a);

void DspMaskClear		/* Clear one datatype bit */
( struct dsp_data_mask *pDataMask_a,
  UINT1 iDataType_a ) ;

void DspMaskSet			/* Set one datatype bit */
( struct dsp_data_mask *pDataMask_a,
  UINT1 iDataType_a ) ;

UINT1 lDspMaskTest		/* Check for one datatype bit */
( volatile const struct dsp_data_mask *pDataMask,
  UINT1 iDataType_a ) ;

UINT1 lDspMaskEmpty		/* Test for no bits set */
( const struct dsp_data_mask *pDataMask_a ) ;

UINT1 lDspMaskEqual		/* Test for two masks equal */
( volatile const struct dsp_data_mask *pDataMask1_a,
  const struct dsp_data_mask *pDataMask2_a ) ;

/* This function returns a mask including bits set for all the data
 * types possible with the given major mode and polarization.
 */
void DspDataMaskFromMode
( Dsp* dsp_a,
  struct dsp_data_mask *pMask_a,
  UINT1 iMajorMode_a,
  UINT1 iPolarization_a ) ;

/* This function returns a mask including bits set for all the data
 * types that the specified processor can produce.
 */
void dsp_data_set
( Dsp* dsp, struct dsp_data_mask *pMask_a ) ;

/* Returns a bit mask of all the data windows (WIN_xxx values) that
 * this DSP supports internally.
 */
UINT4 idsp_windowTypeMask( Dsp* dsp_a ) ;

/* Return TRUE if the spectral output from this DSP represent the true
 * power levels of the original data, rather than hacked so that the
 * peak power is preserved regardless of window selection.
 */
UINT1 ldsp_trueSpectralLevels( Dsp* dsp_a ) ;

/* -----------------------------------------------------------------
 * --------------- Data Processing and Configuration ---------------
 * -----------------------------------------------------------------
 */
/* DSPW_PROC() invokes the actual processing and output of radar data.
 */
enum sigmet_dsp_proc_mode
{
    DSP_PROC_SYNCHRONOUS  = 1,
    DSP_PROC_FREE_RUNNING = 2,
    DSP_PROC_TIME_SERIES  = 3
};


/* Legacy PROC command */
MESSAGE dspw_proc
( Dsp *dsp_a,
  uint16_t larch_a,      /* Choose "archive" format output */
  const struct dsp_data_mask *pDataMask_a, 
                         /* Which set of data to output. For the Doppler output 
		          * this is some combination of the DB_xxx  parameter 
		          * constants; Unused for time series.
		          */
  uint16_t iSpectraType_a, /* Only used time series mode */
  enum sigmet_dsp_proc_mode imode_a );

#ifdef ENUM_DSP_TSOUT_FORMAT_DEFINED
/* New call with detailed time series and spectrum support */
MESSAGE dspw_proc_ts_details
(Dsp *dsp_a,
 const struct dsp_data_mask *pDataMask_a, 
                        /* Which set of data to output. For the Doppler output 
                         * this is some combination of the DB_...  parameter 
                         * constants; Unused for time series.
                         */
 enum sigmet_dsp_spec_type SpecType_a,
 enum sigmet_dsp_ts_type   TsType_a,
 enum sigmet_dsp_tsout_format TsFormat_a,
 enum sigmet_dsp_proc_mode Mode_a);
#endif  /* #ifdef ENUM_DSP_TSOUT_FORMAT_DEFINED */

/* DSPW_THRESH() configures the data thresholding levels for all of
 * the processed parameters that are computed in the DSP.  You may
 * also set the thresholding criteria for a collection of individual
 * data types using DSPW_THRESH_TYPES().
 */
MESSAGE dspw_thresh
( Dsp *dsp_a,
  FLT4 fnoithre_a,	 	/* Log receiver noise threshold dB */
  FLT4 rcorthre_a,		/* Clutter Correction in dB */
  FLT4 rsqithre_a,		/* SQI threshold */
  FLT4 rpowthre_a,		/* Log power threshold */
  UINT2 iczflag_a,		/* Corrected Z threshold flag */
  UINT2 iuzflag_a,		/* Uncorrected Z threshold flag */
  UINT2 ivelflag_a,		/* Velocity threshold flag */
  UINT2 iwidflag_a,		/* Width threshold flag */
  UINT2 izdrflag_a ) ;		/* ZDR threshold flag */

#ifdef SIGMET_DSP_H
MESSAGE dspw_thresh_types
( Dsp *dsp_a,
  const struct dsp_data_mask *pDataMask_a, 
  const struct dspThreshOneParam *pThr_a ) ;
#endif /* #ifdef SIGMET_DSP_H */

/* Given an 8-nybble threshold control mask and 16-bit flag word, test
 * whether a given combination of bits passes those specified criteria.
 */
UINT1 lDspThreshTest( UINT2 iTCF_a, UINT2 iTCFMask_a, UINT2 iTCFBits_a ) ;

/* Given a threshold mask and flags, remove any terms that can not be
 * computed using the legacy WSP/SQI/CSR/LOG scheme.  The modified TCF
 * is returned based on a TCFMASK_LEGACY set of threshold terms.
 */
UINT2 iDspThreshForceLegacy( UINT2 iTCF_a, UINT2 iTCFMask_a ) ;

/* Factor a TCF logical equation into sum of products, i.e., the OR of
 * several AND'd terms.  The low four bits of each iProd[] output term
 * represent the combination of TCF_Q<n> AND'd together.  Returns the
 * number of product terms written to iProds[].
 */
#define DSPTCF_IOR_TERMS 4      /* Max # of OR'ed terms */

SINT4 iDspThreshMakeSumOfProds  /* TCF --> SumOfProds */
( UINT2 iTCF_a, SINT4 iProds_a[ DSPTCF_IOR_TERMS ] ) ;

/* Given a sum of products representation, convert to a TCF word that
 * expresses the overall equation.
 */
UINT2 iDspThreshEvalSumOfProds  /* SumOfProds --> TCF */
( SINT4 iNumOR_a, const SINT4 iProds_a[ DSPTCF_IOR_TERMS ] ) ;

/* Given a string describing a Boolean relation among threshold
 * qualifiers, DSP_TCF_FROM_STRING() converts to a 16-bit threshold
 * control field.  For example, the string "SQI & LOG" would result in
 * the value 0xA0A0.
 *
 * Likewise, given a threshold control value, DSP_STRING_FROM_TCF()
 * converts to the simplest algebraic Boolean representation for that
 * value.
 */
MESSAGE dsp_tcf_from_string
( const char expr_a[], UINT2 *tcf_a, UINT2 *iTCFMask_a ) ;

char * dsp_string_from_tcf( UINT2 tcf_a, UINT2 iTCFMask_a ) ;

/* Setup the breakpoint and slope that will modify the LOG threshold
 * according to the Clutter-To-Noise ratio of the target.  This makes
 * the LOG threshold behave properly even as the noise floor becomes
 * elevated due to very strong clutter targets.  The default signal
 * processor settings will be restored if pMod_a is NULL.
 */
struct logModifiers {
  FLT4  fSlope[2] ;	 /* Residual clutter LOG noise rejection margin */
  FLT4  fBegDB[2] ;	 /*   slope (dB/dB) and beginning Clut/Nse (dB). */
} ;
MESSAGE dspw_LOGModifiers( Dsp *dsp_a, struct logModifiers *pMod_a ) ;

/* Write parameters related to meteorological conditions around the
 * radar.  Note: the special value SOPRM_NOMELTHG means "unknown".
 */
MESSAGE dspw_meteorParams
( Dsp *dsp_a,
  SINT2 iMeltHgtMeters_a ) ;	/* Melting height, meters relative to radar */

/* The DSPW_OPTIONS() routine sets up many of the user selected
 * options.  Special processing and output options for power spectra
 * are selected by DSPW_SPECOPTS(), and special control of timeseries
 * data is via DSPW_TSOPTS().
 */
MESSAGE dspw_options
( Dsp *dsp_a,
  UINT2 ipmode_a,           /* Major Mode (See PMODE_xxx constants) */
  SINT2 ismpsize_a,         /* Sample size */
  UINT2 ioptions_a,         /* Processing flags (See OPF_xxx constants) */
                            /* Passes all bits except OPF_ANYSPEC and OPF_POL */
  UINT2 iagcfil_a,          /* AGC filter code  */
  UINT2 idelay_a,           /* Dual PRF stabilization delay */
  UINT2 iunfold_a,          /* Choices: One of PRF_XXX */
  UINT2 iwindow_a,          /* Window choice (See WIN_xxx constants) */
  SINT2 iRangeSmooth_a );   /* Optional range smoothing (0:None, 1:Pairs, etc) */

MESSAGE dspw_specOpts
( Dsp *dsp_a,
  UINT1 lWantAnySize_a,		/* Request for any output spectrum size */
  UINT1 *plGetAnySize_a ) ;	/* Flag indicating whether we got it */


MESSAGE dspw_tsOpts
( Dsp *dsp_a,
  UINT2 iFlagsTS_a ) ;		/* Timeseries flags (See OPTS_xxx constants) */

  /* Does this DSP have the TsOpts?  dsp_info library */
UINT1 lDspHasTsOpts
( Dsp* dsp_a );

/* Set options that pertain to timeseries playback.  The signal
 * processor generally will not attempt to produce output rays when
 * certain critical processing parameters do not match those of the
 * playback data in the timeseries API.  This routine gives finer
 * control over how those decisions are made by allowing a mask of
 * MMTS_xxx bits specifying which mismatch criteria to ignore.
 */
MESSAGE dspw_playbackTSOpts
( Dsp *dsp_a,
  UINT2 iMismatchTSIgnore_a ) ;

/* Configure the interference filter.
 */
MESSAGE DspWriteIntFilter
( Dsp *dsp_a, 
  UINT2 iType_a,     /* Which type of interference filter to run */
  FLT4  fC1_a,       /* Parameter C1 in dB */
  FLT4  fC2_a );     /* Parameter C2 in dB */

/* Routines to configure point clutter detection and point clutter
 * censoring.
 */
MESSAGE dspw_pointClutter
( Dsp *dsp_a, UINT4 iFlags_a, FLT4 fThreshDB_a, SINT4 iSideSkip_a ) ;

#define PTCLT_DETECT  0x0001 	/* Detect point clutter and set flags */
#define PTCLT_CENSOR  0x0002 	/* Censor detected point clutter bins */
#define PTCLT_FLAGALL 0x0004 	/* Flag all bins that were modified */

/* Routines to configure BATCH mode processing
 */
#ifdef SIGMET_DSP_H

MESSAGE dspw_batchSetup
( Dsp *dsp_a, volatile const struct dspBatchSetup *pUser_a ) ;

MESSAGE dspr_batchSetup
( Dsp *dsp_a, volatile struct dspBatchSetup *pUser_a ) ;

#endif /* #ifdef SIGMET_DSP_H */

/* Return bits set for each of various options and formats that this
 * DSP supports.
 *
 * Bits set in itsformats_a: Selections from DSP_TSOUT_xxx
 *    Bits set in ipmodes_a: Selections from PMODE_xxx
 */
MESSAGE dspr_formats
  (Dsp *dsp_a,			/* Dsp structure */
   UINT4 *itsformats_a,		/* Time series formats returned here */
   UINT4 *ipmodes_a );		/* Processing mode options returned here */

/* Similar to dspr_formats, except available in dspi library, so it does
 * need I/O, and is not as accurate.
 */
void DspiFormats
( Dsp *pDsp_a,            /* Dsp structure */
  UINT4 *ipmodes_a);      /* Processing mode options returned here */

#ifdef SIGMET_SETUP_H
const char *DspStringFromPMode  /* Returns string to name the specified PMode */
( char sString_a[16],           /* Storage to place string in */
  UINT2 pmode_a,
  const char sUserPModeNames_a[NUMPMODENAMES][16]   /* Optional user names */
  );
#endif  /* #ifdef SIGMET_SETUP_H */

/* Given a numerical transmit polarization, convert to text string.
 */
const char *DspStringFromPol
( char sString_a[4],            /* Storage to place string in */
  UINT1 iPolarization_a );

/* Given a numerical phase modulation, convert to text string. */
const char *DspStringFromPhaseMod
( char sString_a[8],            /* Storage to place string in */
  UINT1 iPhaseMod_a );

const char *DspStringFromTypeEnum
( char sString_a[8],    /* Storage to place string in */
  enum sigmet_dsp_type iType_a );

UINT2 ldsp_has_log_filter	/* Processor has LOG filter capabilities */
( Dsp* dsp ) ;

UINT2 ldsp_has_log_rcv		/* LOG receiver used, requires slope calibration */
( Dsp* dsp ) ;

/* DSPR_VIEWSPECS() returns a bitmask of spectra types that can be
 * viewed from this DSP.
 */
MESSAGE dspr_viewspecs
( Dsp *dsp_a,
  UINT4 *iViewspecMask_a ) ;

/* DSPW_HEADER_CFG() sets the options for the headers.  This feature
 * is not available on the RVP6, or the RVP7 before release 7.  Will
 * signal when a bit is supplied which is not available for that
 * processor.
 */
MESSAGE dspw_header_cfg
( Dsp *dsp_a,
  UINT4 imask_a ) ;		/* Mask of DSP_HDR_xxx values */

/* This function returns TRUE if the signal processor supports control
 * of header words specified.
 */
UINT1 lDspHasHeaderCfg
( Dsp* dsp_a,
  UINT4 imask_a );	/* Mask of DSP_HDR_xxx values */

/* Returns the number of bytes in the optional ray headers read from 
 * the DSP based on the supplied mask.
 */
UINT4 iDspHeaderCfgSize
( UINT4 iCfgHdrMask_a );

/* Returns the byte offset in the header to the specified
 * field.  Returns the total size if called with 0 arg.
 */
UINT4 iDspHeaderCfgLoc
(UINT4 iCfgHdrBit_a,
 UINT4 iCfgHdrMask_a );

/* IDSP_FILL_CNT() returns the number of trigger pulses that must be
 * transmitted by the signal processor before data will be valid in
 * dual PRF modes.
 */
SINT4 idsp_fill_cnt
( Dsp* dsp ) ;

/* Return information about how many CPI reads are required to
 * get to valid data rays.  This peeps at information from recent
 * configuration commands.
 */
  SINT4 iDspPipelineDepth( Dsp *dsp_a );

/* Setup for using simulated time series, and load one pulse of data
 * into the processor.
 */
struct dspSimPointIO_1 {	/* Legacy LSIMUL data format */
  UINT2 logsamp ; SINT2 isamp, qsamp ; UINT2 iagc ;
} ;
struct dspSimPointIO_2 {	/* Improved LSIMUL data format */
  UINT2 iIPackSamp, iQPackSamp ;
} ;
struct dspSimPoint {		/* What the user sees */
  FLT4 fISamp, fQSamp ;
} ;
MESSAGE dspw_sim_init( Dsp *dsp_a, UINT2 lsimulate_a ) ;

MESSAGE dspw_sim_pulse
( Dsp *dsp_a,
  SINT4 ibincount_a,
  BIN2 iphase_a,
  SINT2 imagnitude_a,
  struct dspSimPoint *simpts_a,
  UINT2 *ldone_a ) ;

/* Get some useful simulation numbers.  The return value is the
 * present sample size that is loaded into the DSP.  Remaining
 * simulation pulse count is optinally stored.
 */
SINT4 iDspGetSimInfo( SINT4 *piSimPulseCount ) ;

/* The RVP8/9 contains a built-in target simulator tool that can test
 * and debug processing algorithms that work with multiple trip returns.
 * Several real physical targets can be simulated, each having a range
 * span measured in kilometers, a Doppler shift in Hertz, and an echo
 * power relative to the saturation level of the receiver.  The echos
 * are correctly placed in range exactly according to how they have been
 * illuminated by whatever sequence of pulses have been transmitted so
 * far.
 */
#ifdef SIGMET_DSP_H

UINT1 lDspHasTargSim( Dsp *dsp_a ) ;

MESSAGE dspw_targSimEnable( Dsp *dsp_a, UINT1 lEnable_a ) ;

MESSAGE dspw_targSimDefine
( Dsp *dsp_a, SINT4 iSlot_a, struct dspPhysTargSim *pTarg_a ) ;

#endif /* #ifdef SIGMET_DSP_H */

/* -----------------------------------------------------------------
 * ------------------- Time Series Data Tagging --------------------
 * -----------------------------------------------------------------
 */
/* Set/Clr optional user bits that are included in the pulse headers
 * of the signal processor's (I,Q) data stream.  The separate CLEAR
 * and SET args allows the library to fiddle with subsets of the bits
 * without affecting others.  Args may be NULL if unneeded.
 *
 * The permanent Set/Clr bits are updated in the signal processor and
 * retain their value from the last time they were defined.  The bits
 * are repeated into all pulse headers.  The ONCE bits, however, are
 * transitory and will appear in only one pulse header each time they
 * are set.
 *
 * The user bits from separate calls will never be collapsed into a
 * single pulse header, even if the header and bit times indicate that
 * they could.  This means that each XOP_UIQBITS opcode will always
 * result in at least one pulse header being tagged with exactly those
 * data.  This is generally what you want, since no other exact
 * outcome could be guaranteed based on time-of-arrival alone.
 */
#ifdef SIGMET_DSP_H
MESSAGE dspw_uiqBits
( Dsp *dsp_a, struct uiqbits *set_a, struct uiqbits *clr_a,
  struct uiqbits *once_a ) ;

MESSAGE dspr_uiqBits
( Dsp *dsp_a, struct uiqbits *uiqbits_a ) ;
#endif /* #ifdef SIGMET_DSP_H */

#ifdef SIGMET_DSP_H
uint8_t is_dsp_using_hybrid_pulse
(Dsp* dsp_a,
 const struct gparm *pGparm_a);
#endif /* #ifdef SIGMET_DSP_H */

/* This routine informs the DSP about the current progress of the
 * application's task.  This information is then included with the time
 * series data, which will help with eventual interpretation.  Command
 * only available on the RVP8 and later.  There is no error returned for
 * older processors, because this is only a hint, and not critical for
 * proper operation of older processors.
 *
 * Issuing this call increments the iAqMode field of the rvptsPulseHdr.
 * The continuous flow of data is not otherwise interrupted.  SIGMET
 * strongly encourages all control programs and time series recording
 * programs to use this mechanism.  This will allow customers to mix
 * and match their programs.
 */
MESSAGE DspWriteTaskId
( Dsp *dsp_a,
  const char *sTaskName_a,   /* Name of task, only first 16 chars used */
  UINT2 iSweepNumber_a,      /* Sweep number within the task, origin 1, 0=N/A */
  UINT2 iAuxNumber_a,        /* Aux number within the task */
  UINT1 iScanType_a ) ;	     /* One of SCAN_xxx */

/* -----------------------------------------------------------------
 * --------------- Reflectivity Calibration Support ----------------
 * -----------------------------------------------------------------
 */
/* DSPW_CAL() configures the calibration numbers for the DSP.
 */
MESSAGE dspw_cal
( Dsp *dsp_a,
  FLT4 flogslope_a,		/* Log slope  */
  FLT4 fcaliref_a,		/* Calibration Reflectivity */
  FLT4 fzdroffset_a,		/* ZDR Calibration offset */
  FLT4 fldroffset_a,		/* LDR Calibration offset */
  FLT4 fgas_atten_a,		/* Gaseous attenuation constant (dB/km) */
  FLT4 fburst_power_a) ;        /* Calibration burst power */

  /* FDSPGETZCAL() returns the correct Z calibration value for the
   * requested polarization.
   */
#ifdef SIGMET_SETUP_H
  FLT4 fDspGetZCal
  ( Dsp* pDsp_a,
    const struct dsp_cal *pStoredCal_a,  /* Calibration file to use */
    UINT2 iPW_a,                         /* Pulse width index */
    UINT2 iDspPolarization_a ) ;          /* Polarization to use */
#endif  /* #ifdef SIGMET_SETUP_H */
  
  /* Returns the radar constant calculated from the setup information.
   * Part of info library, but not callable from a process which did not
   * do the DspOpen().
   */
  FLT4 fDspRadarConstant
  ( Dsp *pDsp_a,
    const SINT4 iwidth_a,
    UINT1 lHorizontalPolarization_a  /* Which constant to return */
    ) ;

/* Convert gas attenuation constant to/from the 16-bit interface
 * format code used by the RVP7.  Codes from 0-10000 have a slope of
 * 1E-5; subsequent codes have a slope of 1E-4.  The overall span is
 * from 0.0 to approx 5.6535.
 */
FLT4 fGasAttenFromCode16
( UINT2 icode16_a  ) ;

UINT2 iCode16FromFGasAtten
( FLT4 fGasAtten_a ) ;

/* -----------------------------------------------------------------
 * -------------- Readback of Processor Configuration --------------
 * -----------------------------------------------------------------
 */
#ifdef SIGMET_DSP_H

/* Get the GPARM parameters from the signal processor.  Optional bits
 * control whether the latched status bits are cleared or kept after
 * the data are fetched.
 */
#define GPARM_LSTATUS_CLEAR  (0x0001)
#define GPARM_LSTATUS_KEEP   (0x0002)
MESSAGE dspr_gparm
( Dsp *dsp_a,
  struct gparm *pGparm_a,
  UINT4 iOptions_a ) ;

MESSAGE dspr_exParm		/* Read additional 'extended' processor parameters. */
( Dsp *dsp_a,			/* The legacy call point (returns obsolete state unless prior OP_PROC). */
  struct dspExParm *pParm_a ) ;

MESSAGE dspr_exParm_now         /* Read the current extended processor parameters. */
( Dsp *dsp_a,                   /* This call point returns current status. Activates OP_PROC */
  uint8_t iNoProc_a,   
  const struct gparm *pGparm_a,
  struct dspExParm *pParm_a ) ;

#ifdef SIGMET_ENUM_CONVERT_DEFINED
MESSAGE dspr_Classifiers
( Dsp *pDsp_a,                  /* Echo classifiers' info */
  const struct dsp_data_mask * const pMask_a,
  uint16_t uiLenName_a,
  struct enum_convert Enums_a[NR_CLASSIFIERS],
  char * const psConfigName_a) ;                
#endif  /* #ifdef SIGMET_ENUM_CONVERT_DEFINED */

/* Return (-1,0,+1) according to whether the version of code implied
 * by a GPARM structure is (<,=,>) a given level.
 */
int dsp_cmp_version
( const struct gparm *gparm_a,
  int iMajor_a,
  int iMinor_a ) ;

/* Return (-1,0,+1) according to whether first version is (<,=,>) to
 * the second version.
 */
int dsp_cmp_versions
( int iMajor1_a,
  int iMinor1_a,
  int iMajor2_a,
  int iMinor2_a);

/* Parse the version string into major and minor numbers.  Returns
 * zero in a number field, if that field is not parsable.
 */
void dsp_parse_version
(const char *sVersion_a,
 int *iMajor_a,
 int *iMinor_a );

/* Return the saturation A/D input power for an RVP7/8.  This can be
 * deduced from a 4-bit code in the GPARM structure.
 */
FLT8  frvp7_power_max
( const struct gparm *pGparm_a ) ;

/* Return the measured DC offset in either the "I" or "Q" channel.
 * This routine deals with the two possible formats that might have
 * been used to encode the DC levels.  Return value is in the range
 * -1.0 to +1.0.
 */
FLT4 fGetNoiseLevelDC
( const struct gparm *pGparm_a,
  UINT1 lGetQ_a ) ;

#endif /* #ifdef SIGMET_DSP_H */

/* DSPR_RBACK() gets Read-Back data from the DSP.  It reads ICOUNT_A
 * words containing data selected by IOP_A into the PDATA_A output
 * array.
 */
MESSAGE dspr_rback
( Dsp *dsp_a,
  UINT2 iop_a,			/* One of RBACK_xxx */
  void *pData_a,		/* Buffer for readback data */
  UINT2 icount_a ) ;		/* Number of 16-bit words */

/* ----------------------------------------------------------------
 * --------------- Trigger Waveform and PRF Control ---------------
 * ----------------------------------------------------------------
 */
/* This subroutine sets the PRF and pulse width of the DSP.  It should
 * be used throughout IRIS.  It uses both the DSP library, and antenna
 * library if required.  If the pulsewidth is being changed, it will
 * set the PRF to the lower of the two PRFs for the wait time.
 */
MESSAGE dsp_set_prf
( Dsp *dsp_a,
  FLT4  fPrf_a,
  UINT2 ipulsewidth_a,
  UINT1 lUseDsp_a ) ;		/* Use the DSP (otherwise just the RCP) */

/* Returns the default PRF from setup.
 * Part of info library, but not callable from a process which did not
 * do the DspOpen().
 */
FLT4 fDspDefaultPrf
( Dsp *pDsp_a );

/* Define an alternate trigger rate that will take effect when the
 * antenna is within a prescribed solid sector.  This command must be
 * issued after dsp_set_prf(), as that routine clears all of the
 * information that we supply here.
 */
MESSAGE dspw_prfSect
( Dsp *dsp_a,
  FLT4 fPrf_a,			/* Alternate PRF to use */
  SINT4 iSector_a,		/* Sector being defined (0 to PRTSECT_MAXSECTS-1) */
  BIN2 iAzLo_a, BIN2 iAzHi_a,	/* AZ/EL sector boundaries */
  BIN2 iElLo_a, BIN2 iElHi_a ) ;

/* DSPR_PRF() reads the current pulse width and PRF.
 */
MESSAGE dspr_prf
( Dsp *dsp_a,
  FLT4 *fPrf_a,			/* PRF in Hertz */
  UINT2 *ipwcode_a ) ;		/* Select one of the four pulse codes */

/* dspr_txchannels() reads the current selected TX channel's parameters.
 */
MESSAGE dspr_txchannels
( Dsp *dsp_a,
  int iChansel_a,     /* which channel parameters to return */
  int *iMode_a,
  int *lPhaseMod_a,
  int *lAbruptPH_a,
  int *lPeakPower_a,
  float *fFreqMHz_a,
  float *fPhaseDeg_a,
  float *fPowerdBm_a) ;

/* dspr_getADC reads ADC volts from IFDR.
 */
MESSAGE dspr_getADC
( Dsp *dsp_a,
  float *fVolts,
  int iLen ) ;

/* DspWritePwInfo() defines the pulse width control bits and PRT
 * limits.  This is normally ignored on RVP7 and later processors.
 * Values written are from internal setup.
 */
MESSAGE DspWritePwInfo
( Dsp *dsp_a );

/* Old routine.  Allows values not from setup!
 */
MESSAGE dspw_pwinfo
( Dsp *dsp_a,
  volatile const UINT2 iplscode_a[4],
  const UINT2 imaxprf_a[4] ) ;

/* FDSP_TRIG_IN_RES() returns the resolution of the trigger PRT
 * setting command in microseconds.  This resolution is also used by
 * the define minimum trigger period command.
 */
FLT4  fdsp_trig_in_res
( Dsp* dsp ) ;

  FLT4 fDspPrfFromPrtIn( Dsp *dsp_a, UINT2 iPrt_a );
  UINT2 iDspPrtInFromPrf( Dsp *dsp_a, FLT4 fPrf_a );

/* FDSP_TRIG_OUT_RES() returns the resolution of the measured trigger
 * read from the signal processor.  Note that this is different from
 * the resolution specified for input.  This value is in microseconds,
 * so multiplying the DSP output by this value and dividing by 10^6
 * gives a PRT in seconds, and inverting the result gives PRF in
 * Hertz.
 */
FLT4  fdsp_trig_out_res
( Dsp* dsp ) ;

/* The following set of routines are used to load trigger waveforms
 * into the RVP6 (and older) signal processors.  They should never be
 * used with the RVP7 (and later), since those processors support
 * internal trigger definitions.
 */
FLT4  fdsp_trig_wave_res	/* Obsolete */
( Dsp* dsp ) ;

MESSAGE load_dsp_trig		/* Obsolete */
( Dsp *dsp_a, FLT4 fstart_a[4][6],
  volatile const FLT4 fwidth_a[4][6],
  volatile const FLT4 fpol_time_a[4],
  volatile const UINT2 *ilevel_a,
  UINT2 buffer_a[2049] ) ;

void trig_wform_gen		/* Obsolete */
( Dsp *dsp_a,
  volatile UINT2 iwave_a[2049],
  volatile const FLT4 fbegin_a[6],
  volatile const FLT4 fwidth_a[6],
  FLT4 fpol_time_a,
  UINT2 ihold_a ) ;

/* ----------------------------------------------------------------
 * -------- Pulsewidth, Polarization and Phase Modulation ---------
 * ----------------------------------------------------------------
 */

/* Returns the number of pulsewidths available. 
 */
SINT4 iDspPwCount
( Dsp *pDsp_a );

/* Convert a pulsewidth (in 1/100 microseconds) to the nearest table index. 
 * Old routine.
 */
SINT4 iDspPwIndexFromPwidth
( Dsp *pDsp_a, SINT4 ipwidth_a );

/* Convert a pulsewidth (in microseconds) to the nearest table index.  
 */
SINT4 iDspPwIndexFromfPwidth
( Dsp *pDsp_a, FLT4 fPwidth_a );

/* Return the pulsewidth (in microseconds) for the specified index.
 */
FLT4 fDspPwidthFromIndex
( Dsp *pDsp_a, SINT4 iPwIndex_a );

/* DSPW_PHASESEQ() sets up the phase modulation hardware in the signal
 * processor.  The phase control output lines will be configured for
 * the requested type of sequence.  In addition, knowing that this
 * sequence is being transmitted, the DSP algorithms will then handle
 * the received data properly.  IDSPXMTPHASECHOICES() returns what
 * type of phase control choices are available for your radar.
 */
MESSAGE dspw_phaseSeq
( Dsp * dsp_a,
  UINT2 iPhaseSeq_a,
  SINT4 iAngleListLength_a,
  const BIN2 iAngleList_a[] ) ;

UINT1 iDspXmtPhaseChoices
( Dsp* dsp_a ) ;
#define DSP_PHASE_FIXED      (0)
#define DSP_PHASE_RANDOM     (1)
#define DSP_PHASE_CONTROLLED (2)

/* This subroutine sets the XMT Polarization.  It should be used
 * throughout IRIS.  It uses both the DSP library, and antenna library
 * if required.
 */
MESSAGE dsp_set_polarization
( Dsp *dsp_a,			/* Dsp structure */
  UINT2 iPolar_a,		/* Polarization to set */
  UINT1 lUseDsp_a ) ;		/* Use the DSP (otherwise just the RCP) */

/* DSPW_FILT() loads into the signal processor an array of clutter
 * filter codes that will be applied at each of the selected range
 * bins.  The legacy entry point works with all versions of signal
 * processors, but does not allow filters that vary according to
 * antenna angle.
 */
MESSAGE dspw_filt( Dsp *dsp_a, const UINT2 ifcode_a[] ) ;

/* The enhanced version of LFILT allows 2D and 3D filter selections as
 * a function of Range, AZ, and EL.  Each invocation of this command
 * fills in another slot in the signal processor's Range/AZ/EL clutter
 * filter array.  If pFilt_a is NULL, or if pFilt_a->nBins is not in
 * the valid range of [1,RVPX_MAXBINS], then the indicated slot will be
 * invalidated.  Moreover, if iSlot_a is not in the valid range of
 * [0,RVPXASTABSIZE-1], then the entire filter array will be cleared.
 */
#ifdef SIGMET_DSP_H
MESSAGE dspw_filt3D
( Dsp *dsp_a, SINT4 iSlot_a, const struct rvpxSectorFilters *pFilt_a ) ;

/* Load a new clutter filter definition into the signal processor,
 * overwriting one of the existing filter slots.  Valid filter slots are
 * in the range [ 1, DSP_NFILTS-1 ], i.e., you can not overwrite the all
 * pass filter #0.
 *
 * Return the complete array of clutter filter definition structures
 * that are currently being used by the DSP.  The all-pass filter in
 * slot #0 is always returned as all zeros.
 */
MESSAGE dspw_filterSpecs
( Dsp *dsp_a, SINT4 iSlot_a, const struct dspSpecFilt *pFilt_a ) ;

MESSAGE dspr_filterSpecs
( Dsp *dsp_a, struct dspSpecFilt pFilt_a[ DSP_NFILTS ] ) ;

MESSAGE dspw_ML
( Dsp *dsp_a, 
  const void *pProduct_a,
  const char *pPathName_a,
  const void *pPtrFnct_a, 
  const void *pXargs_a,
  const struct rvpxMLinfo *pMLinfo_a,
  const BIN2 *piSweepAngles_a,
  const BIN2 *piRayAngles_a ) ;
#endif /* #ifdef SIGMET_DSP_H */

/* This function returns the maximum filter number that is allowed for
 * the signal processor specified.  Note that this routine does not do
 * any I/O to the DSP, and as a result does not require that
 * dsp_open_for_io() has been run.
 */
SINT4 idsp_filter_max( Dsp* dsp ) ;

/* --------------------------------------------------------------
 * -------------------- Range Mask Selection --------------------
 * --------------------------------------------------------------
 */
/* Check the starting range, resolution, and bin count to verify that
 * a valid range mask could be created from those parameters.  Return
 * mask of any values that were changed along with those new values.
 */
UINT4 range_mask_check
( Dsp *dsp_a,
  FLT4  *fbegin_a,		/* The range at which the sampling starts.  */
  SINT4 *icount_a,		/* The number of range bins required  */
  FLT4  *fres_a,		/* Range between bins in kilometers */
  SINT4 iPwIndex_a ) ;

#define RMC_ALTER_BEGIN  0x0001	/* Beginning range was altered */
#define RMC_ALTER_RESOL  0x0002	/* Range resolution was altered */
#define RMC_ALTER_COUNT  0x0004	/* Range bin count was altered */

/* RANGE_MASK_GEN() creates a range mask having a given starting point
 * and bin spacing; DSPW_RANGE_MASK() can then be used to write that
 * mask to the signal processor.  Return value is a mask of input
 * parameters that were changed from their requested values.  The
 * routine attempts to preserve the bin count at all costs, but even
 * this sometimes can not be done.
 */
UINT4 range_mask_gen
( Dsp *dsp_a,
  UINT2 imask_a[],		/* Array to hold the range mask.  */
  FLT4  fbegin_a,		/* The range at which the sampling starts.  */
  SINT4 icount_a,		/* The number of range bins required  */
  FLT4  fres_a,			/* Range between bins in kilometers */
  SINT4 iPwIndex_a ) ;

MESSAGE dspw_range_mask
( Dsp *dsp_a,
  const UINT2 imask_a[],
  UINT2 ipram_a ) ;

/* DSPCHECKMASKSPACING() checks that the range mask spacing of the
 * signal processor matches the IRIS setup values.
 */
MESSAGE DspCheckMaskSpacing
( Dsp *dsp_a ) ;

  /* DspCheckPrfLimits checks that the maximum PRFs and pulse width
   * control codes for each defined pulsewidth in the signal processor
   * match the setup values.
   */
MESSAGE DspCheckPrfLimits
( Dsp *dsp_a );

/* FDSP_MASK_RES() returns the resolution of the range mask (in Km)
 * for the signal processor type specified.  Note that this routine
 * does not do any I/O to the DSP, and as a result does not require
 * that dsp_open_for_io() has been run.
 */
FLT4  fdsp_mask_res
( Dsp* dsp,
  SINT4 iPwIndex_a ) ;     /* The desired pulse width index */

/* IDSP_BIN_MAX() returns the maximum number of bins that are allowed
 * for the signal processor type specified.  IDSP_MASK_SIZE() returns
 * the number of bits in the range mask for the signal processor type
 * specified.
 */
SINT4 idsp_bin_max
( Dsp* dsp ) ;

SINT4 idsp_mask_size
( Dsp* dsp ) ;

/* --------------------------------------------------------------
 * ------------------ Noise Sampling Routines -------------------
 * --------------------------------------------------------------
 */
/* This routine estimates the current noise level from the log
 * receiver.
 *
 */
MESSAGE dspw_noise_sample
( Dsp *dsp_a,
  SINT2 istartrng_a,  /* Start range in km.  Negative means use previous value. */
  UINT2 iprf_a ) ;    /* Trigger rate in hz.  Zero means use previous value. */

/* This routine sets the current noise level of the receiver.  It will
 * not actually take a noise sample.  It does not bother to check and
 * report all the possible errors.  The assumption here is that the
 * program checked these errors on the initial noise sample.  Command
 * only available on the RVP8 and later.
 */
MESSAGE DspWriteNoiseValues
( Dsp *dsp_a,
  SINT2 istartrng_a,     /* Start range in km.  Negative means previous value remains. */
  UINT2 iprf_a,          /* Trigger rate in hz.  Zero means previous value remains. */
  UINT2 iNoiseLevel_a,   /* Noise level, to be placed in gparm word 6 */
  SINT2 iStandardDev_a,  /* Noise STD, to be place in gparm word 49 */
  SINT2 iHVRatio_a,      /* Horiz/Vert noise ratio, to be placed in gparm work 50 */
  UINT2 iLStatus_a );    /* Latched status bits, to be placed in gparm word 9 */

/* Similar function, supports multiple pulses */
MESSAGE DspWriteNoiseHybrid
( Dsp *dsp_a,
  int16_t  istartrng_a,     /* Start range in km.  <0 means previous value */
  uint16_t iprf_a,          /* Trigger rate in hz.  Zero means previous value */
  int    iPulseCount_a,     /* Number of pulses supplied */
  const uint16_t *iNoiseLevel_a,   /* Noise levels for each pulse */
  const int16_t  *iStandardDev_a,  /* Noise STD, for each pulse */
  const int16_t  *iHVRatio_a,      /* Horiz/Vert noise ratios, for each pulse */
  uint16_t iLStatus_a);     /* Latched status bits */

/* This routine restores the original powerup default noise levels.
 * Command only available on the RVP8 and later.
 */
MESSAGE DspSetDefaultNoise
( Dsp *dsp_a ) ;

/* FDSP_NOISE_POWER() computes the noise power based on the results of
 * a GPARM command.  FDSP_NOISE_RANGE() computes the appropriate range
 * to take a noise sample at, given the PRF it will be taken at.
 */
#ifdef SIGMET_DSP_H
FLT8  fdsp_noise_power
( Dsp* dsp_a,
  UINT1 lHorizontalPolarization_a,  /* Which noise level to return */
  const struct gparm *pGparm_a ) ;
#endif /* #ifdef SIGMET_DSP_H */

#ifdef SIGMET_DSP_H
FLT8  fdsptype_noise_power
( UINT2 iDspType_a,
  UINT1 lHorizontalPolarization_a,  /* Which noise level to return */
  const struct gparm *pGparm_a );
#endif /* #ifdef SIGMET_DSP_H */

#ifdef SIGMET_DSP_H
FLT4  fDspNoiseStd
( Dsp* dsp_a,
  UINT1 lHorizontalPolarization_c,  /* Which noise level to return */
  const struct gparm *pGparm_a );
#endif /* #ifdef SIGMET_DSP_H */

FLT4  fdsp_noise_range
( Dsp* dsp, FLT4 fprf ) ;

/* ----------------------------------------------------------------
 * ------------------ Scanning Antenna Support --------------------
 * ----------------------------------------------------------------
 */
/* DSPW_SYN_MODE() sets the options for antenna synchronization on
 * Azimuth.  DSPW_SYN_TABLE() writes a table of binary angles that
 * will be used to synchronize data rays.
 */
MESSAGE dspw_syn_mode
( Dsp *dsp_a,
  SINT2 isyn_mode_a,		/* One of ANGSYN_xxx */
  UINT2 iFlags_a ) ;		/* Modifier flags ANGSYNFLG_xxx */
#define ANGSYN_NONE    (0)
#define ANGSYN_STATIC  (1)
#define ANGSYN_DYNAMIC (2)

#define ANGSYNFLG_BCD   0x0001	/* Binary-Coded-Decimal angles, else binary */
#define ANGSYNFLG_SHORT 0x0002	/* Allow short sync'd rays to be output */

MESSAGE dspw_syn_table_
( Dsp *dsp_a,
  const UINT2 isync_a[],	/* Table of binary angles */
  SINT2 iwcnt_a,		/* Number of elements in table */
  UINT2 ifuzz_a ) ;		/* Fuzz (binang) for static sync'ing */

/* ---------------------------------------------------------------
 * ---------------- Frequency Control (AFC / MFC) ----------------
 * ---------------------------------------------------------------
 */
/* DSPW_BPHUNT() hunts for burst pulse.  Initiate the hunting process
 * if we do not see a burst pulse now, or if we are being forced to do
 * so.
 */
MESSAGE dspw_bphunt		/* Hunt for burst pulse */
( Dsp *dsp_a,			/*   DSP to use */
  UINT1 lForce_a ) ;		/*   Force a hunt, even if burst is present */

/* Return information about what AFC tracking and hunting features are
 * available in this DSP.
 */
UINT1 lDspCanAdjustBPFreq( Dsp *dsp_a ) ;
UINT1 lDspCanAdjustBPTime( Dsp *dsp_a ) ;
UINT1 lDspCanHuntBP( Dsp *dsp_a ) ;

UINT1 lDspHasAFC( Dsp* dsp_a ) ;

/* Write AFC level (frequency slew) and trigger slew, both of which
 * may be affected during burst pulse tracking/hunting.
 */
MESSAGE dspw_afclevel		/* Set AFC level */
( Dsp *dsp_a,			/*   DSP to use */
  SINT2 iLevel_a ) ;		/*   Signed 16-bit level (-100% to +100%) */

MESSAGE dspw_afcmfclevel        /* Set AFC/MFC mode and level */
( Dsp *dsp_a,                   /*   DSP to use */
  UINT1 lMFC_a,                 /*   1: set MFC mode; 0: set AFC mode */
  SINT2 iLevel_a ) ;            /*   Signed 16-bit level (-100% to +100%) */

MESSAGE dspw_trigslew		/* Set trigger slew */
( Dsp *dsp_a,			/*   DSP to use */
  FLT4 fSlew_a ) ;		/*   Trigger slew in microseconds */

/* Control whether the signal processor is phase locking its (I,Q)
 * data to the measured burst phase, whether pulse-to-pulse amplitude
 * correction is being applied, etc.  The argument should be some
 * OR-combination of the BPL_xxx parameters.
 */
MESSAGE dspw_burstPulseOpts( Dsp *dsp_a, UINT2 iBPLOpts_a ) ;


/* ---------------------------------------------------------------
 * ---------------- Set transmit channel control  ----------------
 * ---------------------------------------------------------------
 */

/* Set TX Channel mode.
 * iCh_a:   TX-IF Channel, either 0 or 1.
 * iMode_a: Channel mode. TX_MODE_UNUSED, TX_MODE_FIXEDFREQ or TX_MODE_TXWAVEFORM. Definitions in dsp.h
 */
MESSAGE dspw_setTXChannelMode( Dsp *dsp_a, int iCh_a, uint8_t iMode ) ;

/* Set TX power.
 * iCh_a:       TX-IF Channel, either 0 or 1.
 * fPowerdBm_a: TX-IF output power level [-20.00, 14.80] dBm.
 */
MESSAGE dspw_setTXChannelPower( Dsp *dsp_a,  int iCh_a, float fPowerdBm_a) ;

/* Set TX Frequency.
 * iCh_a:      TX-IF Channel, either 0 or 1.
 * fFreqMHz_a: Frequency of TX-IF CW signal [0.00000, 84.00000] MHz.
 */
MESSAGE dspw_setTXChannelFreq( Dsp *dsp_a,  int iCh_a, float fFreqMHz_a) ;

/* Set All TX Channel parameters.
 * iApply_a:     Bit-field mask to select what changes to apply and what to ignore. Definitions in dsp.h
 * iChanSel_a:   TX-IF Channel selection where to apply the changes. Either 0 or 1.
 * iMode_a:      Channel mode. TX_MODE_UNUSED, TX_MODE_FIXEDFREQ or TX_MODE_TXWAVEFORM. Definitions in dsp.h
 * lPhaseMod_a:  Turn on or off pulse-to-pulse phase modulation. TRUE or FALSE.
 * lAbruptPH_a:  Turn on or off abrupt phase changes. TRUE or FALSE.
 * lPeakPower_a: Turn on or off peak power for TX waveform. TRUE or FALSE.
 * fFreqMHz_a:   Frequency of TX-IF CW signal [0.00000, 84.00000] MHz.
 * fPhaseDeg_a:  Set fixed relative phase offset, degrees. [-360.0, 360.0].
 * fPowerdBm_a:  TX-IF output power level [-20.00, 14.80] dBm.
 */
MESSAGE dspw_setTXChannelAll( Dsp *dsp_a,
			      uint8_t iApply_a,
                              uint8_t iChanSel_a,
			      uint8_t iMode_a,
			      uint8_t lPhaseMod_a,
			      uint8_t lAbruptPH_a,
			      uint8_t lPeakPower_a,
			      float   fFreqMHz_a,
			      float   fPhaseDeg_a,
			      float   fPowerdBm_a);


/* ---------------------------------------------------------------
 * ---------------- ChatMode Interface to the DSP ----------------
 * ---------------------------------------------------------------
 */
#ifdef SIGMET_DSP_H

struct scope_line_params {	/* One stroke of a plot */
  UINT2 lvisible ;		/* NZ if this line is being plotted */
  UINT2 intensity ;		/* 2-Bit intensity */
} ;

struct scope_config_params {	/* All possible strokes of a plot */
  struct scope_line_params scope_line[ MAXPLOTS ] ;
} ;

struct scope_data {		/* The plotted data itself */
  UINT2 iplotnum ;		/* Which plot is being drawn (0 - MAXPLOTS-1) */
  char ipad2x2[2] ;
  UINT2 idata[ PLOTLEN ] ;	/* Data points in range 0-4095 */
} ;

#define TTYOP_ERROR        (-1)	/* TTY data were unrecognizable */
#define TTYOP_NONE         ( 0)	/* Nothing in the structure */
#define TTYOP_TTYCHAR      ( 1)	/* A TTY output character */
#define TTYOP_SCOPE_ACTIVE ( 2)	/* Scope plot active/off */
#define TTYOP_SCOPE_DATA   ( 3)	/* Scope plot data */
#define TTYOP_SCOPE_CONFIG ( 4)	/* Scope plot configuration */

union ttyop_readback_u {
  char ittychar ;
  UINT2 lscope_active ;
  struct scope_data scope_data ;
  struct scope_config_params scope_config ;
} ;
struct ttyop_readback {
  SINT4 itype ;			/* Discriminant */
  union ttyop_readback_u u ;
} ;

/* The DSPW_TTYCHAR() routine writes a virtual terminal character to
 * the DSP.  DSPW_PLOTMONITOR() controls whether plotting data will be
 * output on the host computer interface.
 */
MESSAGE dspw_ttychar
( Dsp * dsp_a,
  const char char_a ) ;

MESSAGE dspw_plotmonitor
( Dsp * dsp_a,
  UINT2 lenable_a ) ;

/* Read the next word or group of words from the DSP on the assumption
 * that it is in chat mode.  Return a structure indicating the type of
 * data that was found.
 */
MESSAGE dspr_ttyop
( Dsp *dsp_a,
  struct ttyop_readback *ttyop_a ) ;

#endif /* #ifdef SIGMET_DSP_H */


/* ---------------------------------------------------------------
 * ---------------- Support for Intel HEX Records ----------------
 * ---------------------------------------------------------------
 */
/* This describes the format of an Intel hex file produced by a suitable
 * assembler. This code is often downloaded from a PC to a development
 * system and run from RAM. Alternatively, the hex file can be converted
 * to a binary file and programmed into an EPROM.
 *
 * Here is an example hex file:
 *
 * :10008000AF5F67F0602703E0322CFA92007780C361
 * :1000900089001C6B7EA7CA9200FE10D2AA00477D81
 * :0B00A00080FA92006F3600C3A00076CB
 * :00000001FF
 * 
 * Now look at the top line...
 *
 *   The first character (:) indicates the start of a record.
 *   The next two characters indicate the record length (10h in this case).
 *   The next four characters give the load address (0080h in this case).
 *   The next two characters indicate the record type (see below).
 *   Then we have the actual data.
 *   The last two characters are a checksum (sum of all bytes + checksum = 00).
 *
 * The EOF record on the last line of the file is special (Length=0,
 * Addr=0, Type=1), and will always look like that above.
 */
#define IHEX_MAXDATA (32)	/* Maximum data length */
#define IHEX_MAXRECL ( 1 + 2 + 4 + 2 + (2 * IHEX_MAXDATA) + 2 + 1 )

#define IHEX_NORMAL    0	/* Normal return */
#define IHEX_EOF       1	/* EOF record encountered */
#define IHEX_BADREC    2	/* Bad record format */
#define IHEX_CHECKSUM  3	/* Checksum error */

#ifdef INCLUDE_STDIO_PROTOTYPES
void intelHexEncode
( UINT1 iData_a[],		/* Byte data to be encoded */
  SINT4 iLength_a,		/* Length of the data array */
  UINT4 iAddress_a,		/* Address of the first byte of data */
  UINT4 *iOffset_a,		/* Address offset (retained state) */
  FILE *file_a ) ;		/* File descriptor for output */
#endif  /* #ifdef INCLUDE_STDIO_PROTOTYPES */

SINT4 intelHexDecode
( const char sRecord_a[],	/* ASCII Hex record */
  UINT1 iData_a[],		/* Decoded data */
  SINT4 *iLength_a,		/* Length of the data array */
  UINT4 *iAddress_a,		/* Address of the first byte of data */
  UINT4 *iOffset_a ) ;		/* Address offset (retained state) */

/* Generate the 32-bit checksum term contributed by a given byte
 * appearing at a given address.
 */
UINT4 intelHexCS
( UINT4 iAddress_a, UINT1 iByte_a ) ;


MESSAGE ReadTrigLoad		/* File: ireadtrigload.c */
( Dsp* pDsp_a, 
  UINT2 buffer[2049]
  );

/* ---------------------------------------------------------------
 * ---------------- Custom Major Mode Interfaces -----------------
 * ---------------------------------------------------------------
 */

#ifdef __cplusplus
}
#endif

#endif /* #ifndef SIGMET_DSP_LIB_H */
