/* **********************************************************************
 * *                                                                    *
 * *   Common Structure & Memory Definitions for RVP8/Main Processes    *
 * *                                                                    *
 * **********************************************************************
 * File: include/rvp8main.h
 *
 *               COPYRIGHT (c) 2002, 2003, 2004, 2005 BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */
#ifndef SIGMET_RVP8MAIN_H
#define SIGMET_RVP8MAIN_H 1

/* *******************************
 * *                             *
 * * Message Catalog Definitions *
 * *                             *
 * *******************************
 */
#define      DIFMAGIC          1
#define RVP8_DIFMAGIC         (RVP8MAIN_FACILITY + DIFMAGIC)
#define      UNIMASKRES        2
#define RVP8_UNIMASKRES       (RVP8MAIN_FACILITY + UNIMASKRES)
#define      OCCUPROC          3
#define RVP8_OCCUPROC         (RVP8MAIN_FACILITY + OCCUPROC)
#define      NOSHOWPROC        4
#define RVP8_NOSHOWPROC       (RVP8MAIN_FACILITY + NOSHOWPROC)
#define      MISMATCHCODE      5
#define RVP8_MISMATCHCODE     (RVP8MAIN_FACILITY + MISMATCHCODE)
#define      MISMATCHIFD       6
#define RVP8_MISMATCHIFD      (RVP8MAIN_FACILITY + MISMATCHIFD)
#define      MISMATCHRX        7
#define RVP8_MISMATCHRX       (RVP8MAIN_FACILITY + MISMATCHRX)
#define      BADRTCBTIMER      8
#define RVP8_BADRTCBTIMER     (RVP8MAIN_FACILITY + BADRTCBTIMER)
#define      BADRTCBCLK        9
#define RVP8_BADRTCBCLK       (RVP8MAIN_FACILITY + BADRTCBCLK)
#define      EXITREQUEST      10
#define RVP8_EXITREQUEST      (RVP8MAIN_FACILITY + EXITREQUEST)
#define      EXITFORCE        11
#define RVP8_EXITFORCE        (RVP8MAIN_FACILITY + EXITFORCE)
#define      BADOPCODE        12
#define RVP8_BADOPCODE        (RVP8MAIN_FACILITY + BADOPCODE)
#define      TRIGALTERED      13
#define RVP8_TRIGALTERED      (RVP8MAIN_FACILITY + TRIGALTERED)
#define      NUMRXCARDS       14
#define RVP8_NUMRXCARDS       (RVP8MAIN_FACILITY + NUMRXCARDS)

#ifndef MESSAGE_ONLY                      

/* ***********************
 * *                     *
 * * Compilation Support *
 * *                     *
 * ***********************
 */
/* Include the small IPP header definitions (but not the huge list of
 * IPP prototypes) so that we can freely reference its structures and
 * typedefs in all of the RVP8 prototypes.
 */
#include "ippdefs.h"

/* Check compilation flags
 */
#ifndef STRUCTMAP  /* Skip during 'structmap' invocations */

#ifndef _REENTRANT
#error Missing _REENTRANT symbol required by pthreads
#endif

#ifdef SIGMET_DSP_LIB_H
#error RVP8/Main must not be compiled with dsp_lib.h
#endif

#if defined(SIGMET_RVP8PROC_H) || defined(RVP8PROC)
#error RVP8/Main must not be included in RVP8/Proc build
#endif

#endif /* #ifndef STRUCTMAP */

/* Special profiling support required by pthreads
 */
#ifdef __PROFILING		/* See rda/rdasubs/threads.c */
#define pthread_create gprof_pthread_create
#define LPROFILING TRUE
#else
#define LPROFILING FALSE
#endif

/* Various shorthands
 */
#define  ESC 0x1B		/* ESCAPE Character */
#define BELL 0x07		/* BELL Character */

/* ***********************************
 * *                                 *
 * *  Private RVP8/Main Definitions  *
 * *                                 *
 * ***********************************
 */
#define CONFIG_LIC_RPHASE  0	/* License required for Random Phase mode */

/* Debugging flags for use during program development.
 */
#define DEBUG_SIGNAL_HANDLER  0 /* Signal handler hits */
#define DEBUG_INITEXIT        0	/* Major mode and PROC section INIT/EXIT */
#define DEBUG_THREAD_RUNBLK   0	/* Debug thread Run/Block protocol */

/* Max starting range (in usec), and maximum number of direct IF data
 * samples (always at the full sysclock rate) that the trigger
 * generator will permit.
 */
#define MAXFIFDSTART (100.0 * 2E6 / FSPEED_OF_LIGHT) /* 100km Max Range */
#define MAXIIFDSYCNT 15000

/* Maximum Burst Pulse Tracking slew.  This is the amount on either
 * side of zero that we are willing to look, i.e., the burst pulse
 * must be found within ( -BPTMAXSLEW, +BPTMAXSLEW ).
 */
#define BPTMAXSLEW 15.0		/* Max slew (usec) */

/* The burst IF input is selected at the IFD with an extra margin on
 * both sides to make sure that it is cleanly captured.
 */
#define BURSTWIDENUSEC  0.400	/* Burst window safety margin (usec) */

/* Burst pulse simulator parameters
 */
#define SIMXMTDELAY   2.0	/* Simulated transmit delay (usec) */
#define SIMHALFWIDTH  0.5	/* Burst half width (usec) */
#define SIMNOISELEV   0.01	/* Additive noise amplitude (of fullscale) */
#define SIMENERGY     0.0	/* Energy in burst (dBm * usec) */

/* Timing parameters
 */
#define RVP8POLLMICROSEC     40000 /* Default polling rate (microseconds) */
#define FNCPIMAXMICROSEC   1000000 /* Max wait time for finding the next CPI */

#define ANGSAMP_SY_MICROSEC  20000 /* Sampling rate for live antenna angles */
#define ANGSAMP_IO_MICROSEC   3333 /*   for system/IO62 scheduling */

#define WATCHDOGMICROSEC     50000 /* Watchdog wakeup period */

/* ******************************************
 * *                                        *
 * * Common Memory Available to All Threads *
 * *                                        *
 * ******************************************
 */

/* ---------------------------- NOTE ----------------------------
 * All of the variables defined below are put here because they are
 * referenced by more than one thread.  Therefore, the 'volatile'
 * qualifier is the appropriate default in almost all cases.  The only
 * exceptions are variables that are known to be initialized only
 * once, and for which LIBC problems arise with the 'volatile' cast
 * (e.g. FILE*).
 */
#ifdef RVPCOMMON_ALLOCATE
#define XM
#define VM volatile
#else
#define XM extern
#define VM extern volatile
#endif

/* ------------------------------
 * Pointers to the various shared memory segments are put in common so
 * that they are available to all threads.  These areas are writable
 * by all RVP8/Main threads, but often will be mapped read-only by
 * other processes that share the data.  We omit the "_c" suffixes
 * because these symbols are used in zillions of places.
 */
VM struct rvp8Global * const GM ; /* RVP8/Main Global memory */
VM struct rvp8MMProc * const MM ; /* Main/Proc communication */

#ifdef SIGMET_RDASUBS_LIB_H
XM Rvp8TS *TS ;			/* Final output timeseries API */
XM Rvp8TS *RxTS[2] ;		/* Intermediate objects for dual receivers */
#endif /* #ifdef SIGMET_RDASUBS_LIB_H */

XM struct full_time_spec TimeBoot_c ; /* Full time and BTIME at which the RVP8 */
XM UINT4 iBtimeBoot_c ;		 /*   was booted. */
XM UINT4 iBtimeFork_c ;		/* BTIME when threads were forked. */

/* ------------------------------
 * File and Device pointers.  These may be NULL, indicating that
 * the device is either unused or unavailable.
 */
XM FILE *pProc_c ;		/* ==> Processor I/O (16-bit) interface */
XM FILE *pProcByteOut_c ; 	/* ==> Special byte-output interface */

XM SINT4 chatWrPipe_c ;		/* Write and read file descriptors of the */
XM SINT4 chatRdPipe_c ;		/*   pipe for incoming chat characters. */

XM FILE *wChat_c ;		/* ==> Current chat-mode output stream */

#ifdef SIGMET_PCICARDS_LIB_H
XM Rvp8Rx *Rx_c[2] ;		/* ==> RVP8/Rx primary & optional secondary */
XM Rvp8Tx *Tx_c ;		/* ==> Optional RVP8/Tx card */
XM  Io62 *Io_c ;		/* ==> Optional I/O-62 card */
XM UINT1 lHasPanel_c ;		/* Optional backpanel is present */

#define RXDUP( FUNC ) do {			\
 Rvp8Rx *Rx = Rx_c[0] ; FUNC ;			\
 if( NULL != (Rx = Rx_c[1]) ) FUNC ;		\
} while (0)

/* We generally get these from the driver, not from NV setups.  See
 * additional comments at iRvp8SetRxBoardParams().
 */
#define FSYCLK ( Rx_c[0] ? fRvp8RxSyClkMHz( Rx_c[0] ) : GM->nv.fSyClk )
#define FAQCLK ( Rx_c[0] ? fRvp8RxAqClkMHz( Rx_c[0] ) : GM->nv.fSyClk )
#define FTGCLK ( Rx_c[0] ? fRvp8RxTgClkMHz( Rx_c[0] ) : GM->nv.fSyClk )

XM SINT4 iRvp8RxCard_c ;	/* Unit numbers of the cards being */
XM SINT4 iRvp8TxCard_c ;	/*   used by the RVP8. */
XM SINT4 iIo62Card_c ;

XM UINT1 lRvp88dPanel_c ;	/* Provide ORDA panel support functions */

#define IO62_TIMER_ANGSAMP   0	/* IO62 timer fixed allocations */

#ifdef SIGMET_SOFTPLANE_LIB_H
XM SPL *SPL_c ;			/* ==> Softplane driver layer */
XM struct splLogicCnt splCntUsage_c ; /* Usage mask of output bits */
#endif /* #ifdef SIGMET_SOFTPLANE_LIB_H */

#ifdef SIGMET_RDA_H
XM struct rda_boardinfo RxInfo_c[2] ;
XM struct rda_boardinfo TxInfo_c ;
XM struct rda_boardinfo IoInfo_c ;
#endif /* #ifdef SIGMET_RDA_H */

XM struct synchro *syAZ_c ;	/* ==> Synchro conversion states */
XM struct synchro *syEL_c ;	/* ==>   for each axis. */

#endif /* #ifdef SIGMET_PCICARDS_LIB_H */

/* TTY/FIFO structure for optional serial line monitor
 */
#ifdef INCLUDE_TERMIOS_PROTOTYPES
XM struct ttydev sioMon_c ;
#endif /* #ifdef INCLUDE_TERMIOS_PROTOTYPES */

/* Some predicates related to optional RVP8/Rx I/O signals.
 */
#define USING_HVFLAG  ( GM->nv.iRxRS422Funcs[1] == RX_PIN2_HVFLAG  )
#define USING_GPS1PPS ( GM->nv.iRxRS422Funcs[2] == RX_PIN3_GPS1PPS )

/* ------------------------------
 * Process threads and control
 */
#define MAX_RVP8_THREADS 10
VM SINT4 nThreads_c ;		/* Number of running threads */
VM UINT1 lQuitFlag_c ;		/* Request to quit the RVP8 */
VM UINT1 lProcSectionRunning_c ; /* Active PROC section is running now */

XM UINT1 lHaveRootPrivs_c ;	/* We can get root privileges if needed */
VM UINT1 lMainRunning_c ;	/* RVP8 is running (all inits complete) */

#ifdef INCLUDE_PTHREAD_PROTOTYPES
struct oneThread {		/* Information about a thread */
  SINT4 iPID ;			/*   Actual process ID of this thread */
  pthread_t id ;		/*   Thread ID from pthread_create() */
  char sName[40] ;		/*   Name of this thread */
  pthread_mutex_t runlock ;	/*   Mutex to block running */
  UINT4 lReqReconfig ;		/*   Request global reconfiguration */
} ;
struct threadSet {		/* Entire collection of RVP8 threads */
  pthread_key_t pSelf ;		/*   ==> this thread in threads[] */
  pthread_mutex_t lock ;	/*   Lock for accessing the set */
  pthread_cond_t  cond ;	/*   Condition for wakeup initializations */
  struct oneThread threads[MAX_RVP8_THREADS] ;
} ;
XM struct threadSet threadSet_c ;

#endif /* #ifdef INCLUDE_PTHREAD_PROTOTYPES */

/* ------------------------------
 * Variables related to the chat/plotting commands and RTDisp.
 */
VM UINT1 lplotmonitor_c ;	/* Host computer is monitoring plot modes */
VM UINT1 lplotfullupd_c ;	/* Update all plot output records */
VM UINT1 lTTMonitor_c ;		/* TTY monitor is being used now */

/* ------------------------------
 * Processor I/O on RDAPROC interface
 */
VM UINT1 lhostalive_c ;		/* Indicates host computer has spoken */
VM SINT4 olost_c ;		/* # lost output words due to new commands */

VM UINT4 prochdr_c ;		/* PROC Header choices from DSP_HDR_xxx */

VM UINT1 liclockout_c ;		/* Flag that previous XOP_LICENSE cmd failed */
VM UINT4 licseed_c[2] ;		/* Seed value for XOP_LICENSE command */
VM UINT4 licflags_c[2] ;	/* Validated licensed features */
#define LIC_RPHASE 0x00000001	/*   Can run random phase algorithms */

VM SINT4 iTopOpCode_c ;		/* Possible bubbled up opcode */

VM UINT1 lSamplingNoise_c ;	/* Noise sample is happening now */

/* ------------------------------
 * Expose I/O Variables.
 */
#define EXIO_BUFSIZE  1024	/* Must be a power of two */
#define EXIO_OUTVAL      0	/* Code: "wout()" word is in low 16-bits */
#define EXIO_INVAL       1	/* Code: "getin()" word is in low 16-bits */
#define EXIO_OPNEXT      2	/* Code: The next INVAL is an opcode */

VM UINT4 iCodeExposeIO_c ;	/* Last code processed and printed */
VM SINT4 iWptrExposeIO_c ;	/* ==> Next slot to write */
VM SINT4 iRptrExposeIO_c ;	/* ==> Next slot to read */
VM UINT4 iQueueExposeIO_c[ EXIO_BUFSIZE ] ;

/* ------------------------------
 * The IRIS portion of the DSP setups that are stored here are from
 * the initial startup of the RVP8, and only a few of its elements
 * pertaining to toplevel config should ever be referenced.
 */
#ifdef SIGMET_SETUP_H
VM struct dsp_manual_setup irisdsp_c ;
VM struct    license_setup license_c ;
VM struct     rtdisp_setup rtdisp_c  ;
#endif

XM UINT4 iRdaLicenseFeats_c ;	/* Licensed RDA features bits */

VM UINT4 mtimeIRIS_c ;		/* Last modification times of IRIS and */
VM UINT4 mtimeRVP8_c ;		/*   RVP8 configuration files. */

#define RTDISP_ENABLED ( rtdisp_c.lEnabled == RTD_ENABLE_RVP )

/* ------------------------------
 * The following variables are used when direct samples of IF data are
 * required.  The requested values may not be achievable, hence actual
 * values also appear.
 */
VM FLT4  fifdstart_req_c ;	/* Requested start and width (usec) for IF */
VM FLT4  fifdwidth_req_c ;	/*  receiver data written to the IF FIFO. */

VM FLT4  fifdstart_c ;		/* Actual start (usec) */
VM SINT4 iifdSyCnt_c ;		/* Actual width measured in SysClock ticks */

/* ------------------------------
 * Burst Pulse Tracking/Hunting variables.
 */
VM FLT4 fBptSlew_c ;		/* Present slew value (usec) */
VM UINT1 lDisableBPT_c ;	/* Disable tracking feedback momentarily */

VM UINT1 lBphFailure_c ;	/* Hunt machine failed to find the burst */

VM UINT1 lBurstOkayToRun_c ;	/* Okay to perform burst pulse processing */
VM UINT1 lBurstRunning_c ;	/* Burst pulse processing is running now */

VM FLT4 fBurstMinPwrRaw_c ;	/* Minimum power for reliable measurement */
VM FLT4 fBurstMinPwrNorm_c ;	/*   (minimum power, normalized to 1.0 max) */
VM FLT4 fBurstMinAmpNorm_c ;	/*   (min amplitude, normalized to 1.0 max) */

/* ------------------------------
 * (I,Q) data logging variables
 */
VM UINT1 lIQDataOkayToRun_c ;	/* Okay to perform RVP8/Rx-->Memory */
VM UINT1 lIQDataRunning_c ;	/* Data transfers are running now */

/* Coordination of changes in TS writer status
 */
#ifdef INCLUDE_PTHREAD_PROTOTYPES
XM pthread_mutex_t TSWriter_mutex_c ; /* Lock for accessing variables */
VM UINT1 TSWriter_lockreq_c ;	/* Request that writer status not change */
VM UINT1 TSWriter_active_c ;	/* RVP8 is now the active writer */
#endif /* #ifdef INCLUDE_PTHREAD_PROTOTYPES */

/* The user specified IQ data stream bits are merged into all pulse
 * headers as they are created.  The current values of those bits are
 * also available here.
 */
VM struct uiqbits uiqBitsNow_c ;  /* Current user IQ header bits */
VM struct uiqbits uiqBitsThen_c ; /* Evolving history of user supplied bits */

struct uiqbits_ff {		/* Element of FIFO history of UIQ bits */
  UINT4 iSysTime ;		/*   IFD time that this element was created, */
  UINT4 iBtime ;		/*     and BTIME to prevent stale/overflow. */
  struct uiqbits bitsPerm ;	/*   Permanent user bits */
  struct uiqbits bitsOnce ;	/*   One-shot user bits */
} ;
#define UIQFFSIZE       40	/* FIFO queue size for user IQ bits */
#define UIQMAXAGEMS  20000	/* Maximum age (ms) of data in the queue */
VM SINT4 iUiqffWptr_c ;		/*   FIFO Write pointer via insertUIQ() */
VM SINT4 iUiqffRptr_c ;		/*   FIFO Read pointer (iqdata_main only) */
VM struct uiqbits_ff uiqff_c[ UIQFFSIZE ] ;

VM struct rvp8TaskID taskID_c ;	/* Task identification info */
VM UINT1 lNewTaskID_c ;		/* Flag that data have changed */

/* Table of unit vectors to unwind the phase versus range that is
 * introduced by the hardware FIR computation of (I,Q).
 */
XM Ipp32fc cPhaseUnwindRxBin_c[ MAXVIQPERBIN ][ RVP8MAXBINS ] ;

/* Parameters and variables related to combining two (I,Q) streams
 * into a single Wide Dynamic Range stream (RXM_WIDEDYN).
 */
XM FLT4    fWideChanSepDfltMag_c ; /* Fixed magnitude reference for TSAPI based */
XM Ipp32fc cWideChanSepDflt_c ;	   /*   on default complex channel separation. */
XM Ipp32fc cWideChanSepNow_c ;	   /* Present complex channel separation */
XM Ipp32fc cWideChanError_c ;      /* Present error ratio between channels */

#define WIDECHANRATIOMIN 1200	   /* Minimum size of ratio feedback list */
#define WIDECHANRATIODIM ( WIDECHANRATIOMIN + RVP8MAXBINS+1 )
XM Ipp32fc cWideChanRatios_c[ WIDECHANRATIODIM ] ;
VM SINT4   iWideChanRatios_c ;	   /* Number of feedback ratios in above array */
VM UINT4   iWideChanSamps_c ;	   /* Total number of feedback ratios so far */
VM FLT4    fWideChanArgFIR_c ;	   /* Phase correction built into FIR filters */

VM UINT1   lWideChanBadRatio_c ;   /* A power ratio was seen that exceeds */
#define FWIDECHANBADRATIO 6.31     /*   the largest ratio we'll ever accept. */

/* Auxiliary information about an FIR matched filter
 */
#ifdef SIGMET_PCICARDS_LIB_H
struct firinfo {
  FLT4 fMaxRawIQ ;		/* Saturation level of raw I&Q from FIR chips */
  FLT4 fMaxRawIQ_5db ;		/* Same, but at +5dB over saturation */

  FLT4 fActWidthMHz ;		/* Actual bandwidth in megaHertz */

  /* The following parameters control the extrapolation of additional
   * headroom for large signals that saturate the A/D converter.  The
   * first value is for total measured power, and the second is for
   * in-band power, i.e., the power at the fundamental frequency of
   * the clipped sine wave.
   */
  UINT4 lextrapolate ;		/* Okay to perform extrapolations */
  FLT4 fheadpower ;		/* Extrapolation limit actual power, */
  FLT4 fheadmval[2] ;		/*   measured comparison value,      */
  FLT4 fheadslope[2] ;		/*   and slope at endpoint.          */

  /* The actual headroom expansion is done via table lookup of a
   * multiplicative fix-factor based on the measured power above
   * saturation.
   */
  FLT4 fHeadTab[HEADTABSIZE] ;	/* The correction table itself */

  /* The integer version of the matched FIR filter taps for generating
   * I&Q.  These are the actual coefficients being used by the RVP8/Rx
   * hardware.
   */
  SINT4 iIQtaps[2][ DIMIMPLENGTH ] ; /* FIR filter taps for I&Q */
} ;
XM struct firinfo		         /* Filter info for each pulsewidth, */
  firinfos_c[RVP8NPWIDS][MAXVIQPERBIN] ; /*   and for all possible receivers. */
#endif /* #ifdef SIGMET_PCICARDS_LIB_H */

/* ------------------------------
 * Variables for the IRIS Antenna Driver, and for the live angle
 * sampling thread.
 */
#ifdef INCLUDE_PTHREAD_PROTOTYPES
XM pthread_mutex_t ant_mutex_c ; /* Lock for accessing the driver */
#endif /* #ifdef INCLUDE_PTHREAD_PROTOTYPES */

XM UINT1 lHasAntenna_c ;	/* This node has a real antenna */

VM UINT1 lAnglesOkayToRun_c ;	/* Okay to perform live angle sampling */
VM UINT1 lAnglesRunning_c ;	/* Live angle sampling is running now */

/* ------------------------------
 * Ray and CPI processing.  The ray history consists of an array of
 * previous CPIs that have been processed.
 */
#define RAYHISTS_RBACK 40	/* # of histories supplied by RBACK opcode */
#define RAYHISTS       45	/* Ray history size (at least one plus above) */
VM SINT4 rayHistPtr_c ;		/* Index of most recent history entry */
VM struct oneCPI rayHists_c[ RAYHISTS ] ;

/* ------------------------------
 * Background Watchdog thread variables
 */
VM UINT1 lWatchOkayToRun_c ;	/* Okay to perform background watchdog tasks */
VM UINT1 lWatchRunning_c ;	/* Background watchdog tasks are running now */

/* ------------------------------
 * Information that is exchanged across calls to the realtime callback
 * function (See rtCtrlCBF() below) during the PROC section of the
 * current major mode.
 */
struct rtCtrlCBTimer {
  /* Information that is passed into the callback function to describe
   * one of several event timers.  If this timer has a defined value
   * (iTVContents != RTCBTV_VOID), then the timer's current value,
   * mask of bits used, and number of ticks since the last time are
   * pased in.
   */
  UINT4 iTimerVal ;		/* Present value of timer/counter */
  UINT4 iTimerMask ;		/* Mask of bits used in iTimerVal */
  UINT4 iTimerDelta ;		/* Actual ticks since the last call */
  SINT4 iTimerError ;		/* Actual wait minus desired wait */
  UINT4 iTimerFireVal ;		/* Value at which timer would fire, or has fired */

  UINT1 lTimerFired ;		/* Timer actually hit its "fire" value */

  UINT1 iTVContents ;		/* What this timer value represents */
#define RTCBTV_VOID       0	/*   Unused entry (must be zero) */
#define RTCBTV_1MHZ       1	/*   Continuous 1MHz ticks (Timer #0 only) */
#define RTCBTV_1KHZ       2	/*   Continuous 1KHz ticks (Timers #1 and #2) */
#define RTCBTV_TRIG       3	/*   RVP8 trigger count (All Timers) */
#define RTCBTV_IOSHR0     4	/*   Shared IO62 status input #0 (Timer #0 only) */
#define RTCBTV_IOSHR1     5	/*   Shared IO62 status input #1 (Timer #1 only) */
#define RTCBTV_IOSHR2     6	/*   Shared IO62 status input #2 (Timer #2 only) */

  char pad22x1[1] ;
  /* Information returned from the callback function.  iTVWaitOnNext
   * should be set to one of the the RTCBTV_xxx parameters to decide
   * what type of event is to be counted.  The corresponding number of
   * events is passed back in iTimerWait.  Also, lTgBankAutoStart
   * indicates whether this timer should cause an instantaneous
   * trigger bank change if/when it fires.
   */
  UINT1 iTVWaitOnNext ;		/* What type of event to wait for */
  SINT4 iTimerWait ;		/* General how-long-to-wait Arg */

  UINT1 lTgBankAutoStart ;	/* Load new trig bank when this timer fires */
  char pad29x3[3] ;
} ;
/* The actual callback structure consists of several timers whose
 * events can be OR'd together, i.e., the callback will occur as soon
 * as the first of several possible conditions takes place.
 *
 * Callback routines can request that a new trigger bank be loaded at
 * the precise instant that the next timer event(s) fire.  This is
 * done by setting iTgBank to a TBANK_xxx trigger bank value, and
 * setting lTgBankAutoStart to TRUE in at least one of the active
 * timer requests.
 */
struct rtCtrlCBInfo {
  UINT4 lFirstCall ;		/* First call following initProcSection() */
#define NCBTIMERS      3	/* Max number of OR'd callback timers */
  struct rtCtrlCBTimer timers[ NCBTIMERS ] ;

  SINT4 iTgBank ; /* Trigger bank to run immediately after timer(s) fire. */
} ;

VM UINT1 lRTCtrlOkayToRun_c ;	/* Okay to run realtime callbacks */
VM UINT1 lRTCtrlRunning_c ;	/* Callback main thread is running now */

/* -----------------------------------------------------------------
 * ------------ RVP8/Main Callback Function Definitions ------------
 * -----------------------------------------------------------------
 *
 * Callback functions that are exclusively for RVP8/Main.  These
 * consist mostly of the custom routines that should be called to
 * handle different stages of processing in the current major mode.
 * See also the generic major mode info in GM->MMode.
 */

/* Each major mode can allocate a private data area for whatever
 * memory resources are required during the operation of that mode.
 * This private area is created and prepared by the INIT routine, as
 * part of its filling in this entire structure at the start of each
 * major mode.  The exitMajorMode() handler is responsible for
 * releasing all private memory resources.
 */
typedef void privateData_t ;	/* ==> Custom area for this mode */

/* EXIT routine to release all resources that were allocated during
 * the initialization and execution of the major mode.  The EXIT
 * routine is called whenever the major mode changes, or whenever we
 * are "between" modes, e.g., after a TTY Chat "q" command, or a
 * processor reset.  The RVP8 is guaranteed not to be within an
 * active PROC Section (See below) when exitMajorMode() is called;
 * i.e., if exitProcSection() needs to be invoked, that will always
 * happen first.
 */
typedef void ( exitMajorMode_f )( void ) ;

/* Pair of routines that will be called whenever the RVP8 enters and
 * exits active timeseries acquisition and processing.  The INIT
 * routine is called when a PROC opcode is executed that causes the
 * IQData thread to begin collecting data, and activates the RVP8
 * compute threads for the current major mode.  The EXIT routine is
 * called whenever anything interrupts those processes, e.g., the
 * execution of most other opcodes.  Note that the major mode itself
 * does not change at these transitions; rather, these functions
 * allow the current major mode to interact with the timeseries data
 * acquisition as needed.
 */
typedef void ( initProcSection_f )( void ) ;
typedef void ( exitProcSection_f )( void ) ;

/* Callback function for handling realtime control and sequencing
 * tasks for the current major mode.  This routine will be called
 * once following the invocation of initProcSection() that marks the
 * beginning of the data processing section.  It then performs
 * whatever work needs to be done, and requests that it be called
 * back at some later time.
 *
 * rtCtrlCBF() will run at a priority that is higher than any other
 * RVP8 thread.  As such, it should be as efficient as possible and
 * should not do anything terribly "dangerous".
 */
typedef void ( rtCtrlCBF_f )( struct rtCtrlCBInfo *cbi_a ) ;

/* The trigger timing sequence, polarization control, and Tx phase
 * sequence for the 'nominal' internal triggers are defined here,
 * i.e., the Normal, LowPRF, and BurstHunt triggers.  If this routine
 * is not supplied, then uniform trigger patterns will be produced by
 * defult.
 *
 *    pSequence : The complete trigger sequence specification
 *         fPRF : Nominal PRF to synthesize
 *        pwdef : Constants defining the current pulsewidth
 *       RETURN : Length of pSequence_a
 */
typedef SINT4 ( iNominalTrigSequence_f )
     ( struct rvp8TgPulse pSequence_a[RVP8MAXPULSES], FLT4 fPRF_a,
       volatile const struct rvp8Pwdef *pwdef_a
       ) ;

/* The trigger timing sequence, polarization control, and Tx phase
 * sequence for custom user triggers are defined here.  This routine
 * is called repeatedly from userTriggerOutputs() until returning an
 * empty pulse definition (length of zero).  The bank number is -1
 * on initial entry, and retains whatever exit value it had when the
 * next call is made.  An iteration call count (initially zero) is
 * also passed in to provide additional state for the routine.
 *
 *    pSequence : Timing sequence for a custom trigger pattern.
 *      tglines : Default trigger pattern supplied on entry. Fill in
 *                with altered pattern only if changes are necessary.
 *        pBank : Trigger bank to hold this pattern (-1 initially)
 *       iCalls : Count of calls that have been made so far
 *        pwdef : Constants defining the current pulsewidth
 *       RETURN : Number of pulses defined in pSequence_a
 */
typedef SINT4 ( iCustomTrigSequence_f )
     ( struct rvp8TgPulse pSequence_a[RVP8MAXPULSES],
       struct rvp8Tglines *tglines_a, SINT4 *pBank_a, SINT4 iCalls_a,
       volatile const struct rvp8Pwdef *pwdef_a
       ) ;

/* Custom user opcodes for this major mode.  This single mechanism
 * allows arbitrarily complex opcodes to be implemented to support
 * special features within each major mode.  The routine will be
 * invoked whenever the RVP8 receives a XOP_USRCONT or XOP_USRINTR
 * opcode.  If the opcode was preceeded by an XARG array of extended
 * arguments, then these will be passed in args[].  Likewise, if the
 * routine wishes to respond with output data, it places the UINT2
 * array in pResults[] and returns the count of output words.  A
 * return count of zero means that no output should be generated.
 *
 *        iOp : The opcode actually received
 *     args[] : Array of nArgs_a extended args (XARGS)
 *   pResults : Pointer to RETURN words to write back
 */
typedef SINT4 ( customUserOpcode_f )
     ( UINT2 iOp_a, const UINT2 args_a[], SINT4 nArgs_a,
       UINT2 **pResults_a
       ) ;

/* Design the matched filter to produce I&Q for transmitted pulses
 * that are simple gated CW waveforms.  Return as a set of floating
 * point coefficients.  "I" and "Q" data are computed via convolution
 * with each of the impulse response arrays.  If this routine is not
 * supplied, then the default RVP8 windowed-bandpass filters will be
 * used.
 *
 *     fICoefs[] : Returned "I" filter coefficients
 *     fQCoefs[] : Returned "Q" filter coefficients
 *     fActWidth : Returned actual 3dB width of the filter (radians)
 *     fReqWidth : Desired 3dB width of the filter (radians)
 *     implength : Impulse response length (number of filter taps)
 *   fCenterFreq : Center frequency of the filter (radians)
 *    fTapOffset : Fractional offset in taps, -0.5 to +0.5
 */
typedef void ( cwpulseMatchedFilter_f )
     ( FLT4 fICoefs_a[], FLT4 fQCoefs_a[], FLT4 *fActWidth_a,
       FLT4 fReqWidth_a, SINT4 implength_a, FLT4 fCenterFreq_a,
       FLT4 fTapOffset_a
       ) ;

/* This is the fundamental design routine for all Tx waveforms that
 * can be synthesized by the RVP8.  Given a specification of a
 * transmit waveform, generate an array of complex valued samples
 * taken at a given frequency across the full pulse duration.  The
 * output waveform is synthesized at baseband (zero center frequency),
 * and thus is independent of whatever intermediate frequency the
 * radar happens to use.
 *
 * If cRxFilt is non-Null the routine also returns the complex valued
 * matched filter coefficients that would be used to receive the
 * transmitted waveform.  Often this filter is simply the windowed
 * conjugate of the Tx waveform, but this additional hook is included
 * so that fancier filters can be explored.
 *
 * Both the transmit waveform and the matched receiver coefficients
 * are assumed to be normalized such that their maximum magnitude is
 * unity.
 *
 *         specs : ==> Tuning specifications for the waveform
 *      fSampMHz : Frequency (MHz) at which the waveform is sampled
 *    iMaxPoints : Size of cTxWave (maximum length of waveform)
 *       cTxWave : Output complex transmit waveform samples
 *       cRxFilt : Optional output matched filter coefficients
 *        RETURN : Number of sample points that were computed
 */
typedef SINT4 ( iTxWaveformDesign_f )
     ( volatile const struct rvp8TxWaveSpecs *specs_a,
       FLT4 fSampMHz_a, SINT4 iMaxPoints_a, Ipp32fc *cTxWave_a,
       Ipp32fc *cRxFilt_a ) ;

/* Routine to apply corrections to the raw (I,Q) data as they are
 * acquired within each pulse.  A brief history of recent pulse
 * headers is supplied as ancillary information.  The first pointer
 * slot (corresponding to the current pulse) will always be valid, but
 * the later pointers will likely be NULL at the very start of a new
 * acquisition sequence until the entire history list fills up.  Be
 * sure that this routine handles this variable length case properly.
 *
 * Note that this same function type is also used for the built-in
 * target simulator, since it is applied in the same manner and
 * following the raw pulse corrections.
 *
 *      pHdrs : ReadOnly history of recent pulse headers as well as
 *     fRefTS :   the (I,Q) data from those pulses, current == first.
 *        fTS : ==> complex (I,Q) to modify (starting w/burst sample)
 *    iRxReal : Data are from this real physical radar receiver,
 *    iRxSlot :   and reside in this slot of the pulse headers.
 */
#define RPCHISTORY 5
typedef void ( rawPulseCorrections_f )
     ( const struct rvp8PulseHdr *pHdrs_a[ RPCHISTORY ],
       const FLT4 *fRefTS_a[ RPCHISTORY ], FLT4 *fTS_a,
       SINT4 iRxReal_a, SINT4 iRxSlot_a
       ) ;

/* Check for errors in the current processing configuration. Returns
 * SS_NORMAL unless something is wrong with PROC setup itself, i.e.,
 * independent of possible problems that might occur later during
 * actual processing.  This check is applied early to catch obvious
 * errors in the execution of a PROC command.
 */
typedef MESSAGE ( iConfigError_f )( UINT1 iOp_a ) ;

/* Search for the next Coherent Processing Interval boundaries.  If
 * this routine is not supplied, then the standard fixed PRF locater
 * algorithm will be used.
 *
 *    prevCPIs : History of last CPIs that were actually used
 *     nextCPI : The next CPI that is ready to be processed
 * lLowLatency : Flag requesting "not too much" buffering delay
 *      RETURN : TRUE if nextCPI could be determined
 */
#define FNCPIHIST 10		/* Number of previous CPIs */
typedef UINT1 ( lFindNextCPI_f )
     ( volatile const struct oneCPI *prevCPIs_a[FNCPIHIST],
       volatile struct oneCPI *nextCPI_a, UINT1 lLowLatency_a
       ) ;
#if ( FNCPIHIST >= RAYHISTS )	/* Verify lFindNextCPI() is okay */
#error Inconsistent definitions of FNCPIHIST and RAYHISTS
#endif

/* Perform additional sanity checks on the CPI that we are about to
 * use.  These will generally be more exhaustive than the criteria
 * used by lFindNextCPI(), since we have the entire pulse header
 * sequence available for analysis.
 *
 *    nextCPI : The Coherent Processing Interval being tested
 *    pHdrs[] : Array of pulse headers from that CPI
 *     RETURN : TRUE if a problem was detected
 */
typedef UINT1 ( lCheckupCPI_f )
     ( volatile const struct oneCPI *nextCPI_a,
       const struct rvp8PulseHdr *pHdrs_a[]
       ) ;

/* Assign specific processing areas to the data contained within a
 * coherent processing interval.  The CPI's in a given major mode may
 * consist of multiple and/or batched PRTs, so the areas and PRFs that
 * we assign might refer to multiple sections within the entire CPI.
 * This routine is needed because PRF's are allowed to vary from CPI
 * to CPI, and because it allows rates to be assigned when an external
 * trigger is used.  If this routine is not supplied, the default
 * one-big-single-PRF-per-CPI analysis will be used.
 *
 *    nextCPI : The Coherent Processing Interval being modified.  The
 *              only element of this structure that should be changed
 *              is the procs[] array of individual CPI areas.
 *    pHdrs[] : Array of pulse headers from that CPI
 *     RETURN : TRUE if a problem was detected
 *
 * This routine also has the option of setting the GLS_PRFVARIED error
 * bit in the RVP8's global GPARM structure.  That bit indicates that
 * the PRT showed too much variation within a group of pulses that
 * should have been at a constant rate.  The setGparmPRTVariedFlag()
 * routine can be used to conveniently flag this error.
 */
typedef UINT1 ( lAssignProcsInCPI_f )
     ( volatile struct oneCPI *nextCPI_a,
       const struct rvp8PulseHdr *pHdrs_a[]
       ) ;

/* Assign the intervals of range bins from the current CPI that will
 * be handled by each of the available compute processors for all but
 * the BINMOMENTS phase (which instead uses a fixed distribution of
 * range bins to each processing thread based on how the (I,Q) data
 * can be efficiently extracted from the timeseries API).  If this
 * routine is not supplied, the default equal spread of bins across
 * the available processors will be used.
 *
 *    rngInfo : Filled in with range intervals for each processor
 *    nextCPI : The CPI for which we are assigning tasks
 *    pHdrs[] : Array of pulse headers that will be processed
 *      iPass : Which algorithm processing pass will use these ranges
 */
typedef void ( setupProcBins_f )
     ( volatile struct ctRngInfo *rngInfo_a,
       volatile const struct oneCPI *nextCPI_a,
       const struct rvp8PulseHdr *pHdrs_a[], SINT4 iPass_a
       ) ;

/* Analyze the sequence of transmit phases in order to deduce
 * properties that may be used later by the processing routines.
 * Returns NZ if a the measured phase sequence is not what is
 * needed/expected.
 *
 *     pPhseq : Results structure for burst phase analysis
 *    nextCPI : The Coherent Processing Interval being analyzed
 *    pHdrs[] : Array of pulse headers from that CPI
 *     RETURN : TRUE if a problem was detected
 */
typedef UINT1 ( lAnalyzeBurstPhseq_f )
     ( volatile struct burstPhseq *pPhseq_a,
       volatile const struct oneCPI *nextCPI_a,
       const struct rvp8PulseHdr *pHdrs_a[]
       ) ;

/* The mechanism for obtaining AZ and EL antenna angles as a
 * function of time can be different in each major mode, though
 * generally it will simply use the angles supplied by the IRIS
 * Antenna Driver.  The routine provided here must be capable of
 * supplying accurate angles for lookup times that are up to one
 * second old.  That's because the streaming (I,Q) pulses from the
 * RVP8/Rx card may be buffered several hundred miliseconds into the
 * past at the point that the RVP8 wants to associate angles with
 * them.
 *
 *   pAz, pEl : ==> Locations to write AZ/EL binary angles
 * pAuxPedINU : ==> Optional structure for all other Ped/INU data
 *     iBtime : Binary time for which the angle is desired.
 */
typedef void ( getAzElPosBtime_f )
     ( volatile BIN2 *pAz_a, volatile BIN2 *pEl_a,
       volatile struct rvp8AuxPedINU *pAuxPedINU_a, UINT4 iBtime_a
       ) ;

/* The RVP8 may be the actual source of live measured antenna angles
 * for whatever angle lookup mechanism is used by getAzElPosBtime().
 * The following two routines will be called periodically to sample
 * the live angles and insert them for later lookups.  The sampling
 * routine is allowed to return FALSE if, for some reason, it is not
 * able to supply a live angle measurement on a given invocation.
 */
typedef UINT1 ( sampleLiveAzElPos_f )
     ( volatile BIN2 *pAz_a, volatile BIN2 *pEl_a
       ) ;
typedef void ( insertLiveAzElPos_f )
     ( BIN2 iAz_a, BIN2 iEl_a, UINT4 iBtime_a
       ) ;

/* The RVP8's front panel display may contain custom information for
 * each major mode.  Format a MATORB_WIDTH character line of text to
 * be shown on the indicated line of the display (Top=0).  The line
 * can be either space padded or NULL terminated.
 */
#define FPDOVERSPILL   80	/* Sized to allow sloppy writers */
typedef void ( frontPanelDisplay_f )
     ( char sText_a[ FPDOVERSPILL ], UINT1 iLine_a
       ) ;

struct rvp8MainMajorMode {	/* Customized processing routines */
           privateData_t *privateData          ;
         exitMajorMode_f *exitMajorMode[ MAXEXITDEPTH ] ;
       initProcSection_f *initProcSection      ;
       exitProcSection_f *exitProcSection      ;
             rtCtrlCBF_f *rtCtrlCBF            ;
  iNominalTrigSequence_f *iNominalTrigSequence ;
   iCustomTrigSequence_f *iCustomTrigSequence  ;
      customUserOpcode_f *customUserOpcode     ;
  cwpulseMatchedFilter_f *cwpulseMatchedFilter ;
     iTxWaveformDesign_f *iTxWaveformDesign    ;
   rawPulseCorrections_f *rawPulseCorrections  ;
   rawPulseCorrections_f *targetSimulator      ;
          iConfigError_f *iConfigError         ;
          lFindNextCPI_f *lFindNextCPI         ;
           lCheckupCPI_f *lCheckupCPI          ;
     lAssignProcsInCPI_f *lAssignProcsInCPI    ;
         setupProcBins_f *setupProcBins        ;
    lAnalyzeBurstPhseq_f *lAnalyzeBurstPhseq   ;
       getAzElPosBtime_f *getAzElPosBtime      ;
     sampleLiveAzElPos_f *sampleLiveAzElPos    ;
     insertLiveAzElPos_f *insertLiveAzElPos    ;
     frontPanelDisplay_f *frontPanelDisplay    ;
} ;

VM struct rvp8MainMajorMode MMode_c ;

/* Handy macro to select a function entry from MMode_c, but to supply
 * the default routine when that entry is NULL.
 */
#define MMODEDFLT( FUNC ) \
  ( MMode_c.FUNC ? MMode_c.FUNC : FUNC##_dflt )

#undef VM /* End of shared variables */
#undef XM

/* ****************************************
 * *                                      *
 * *  RVP8/Main/Core Function Prototypes  *
 * *                                      *
 * ****************************************
 */

/* ------------------------------
 * Globally visible thread entry points, invoked only from the main
 * startup thread.
 */
int rvp8_main( int argc_a, char *argv_a[] ) ;

void     *chat_main( void *arg_a ) ;
void *setupTTY_main( void *arg_a ) ;
void     *cmds_main( void *arg_a ) ;
void    *burst_main( void *arg_a ) ;
void   *iqdata_main( void *arg_a ) ;
void   *rtctrl_main( void *arg_a ) ;
void   *angles_main( void *arg_a ) ;
void    *watch_main( void *arg_a ) ;

/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
 * Note that all of the following routines must either be reentrant,
 *      or must be locked by a mutex supplied by the caller.
 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
 */

/* ------------------- burst_api.c -------------------
 */
UINT1    lBurstOkay( void ) ;
UINT1 lBurstSettled( void ) ;
FLT4       fBurstDC( void ) ;
FLT4      fBurstMom( void ) ;
FLT4   fBurstMomVar( void ) ;
FLT4     fBurstFreq( void ) ;
UINT1      lAFCEnab( void ) ;
UINT1      lMFCEnab( void ) ;
SINT4     iAFCLevel( void ) ;

FLT4 fBurstPowerDBm( void ) ;

void enableAFCMFC( SINT4 iOp_a, SINT4 iAFCLevel_a ) ;
#define ENAFCMFC_OFF    0x01	/* Turn AFC and MFC both off */
#define ENAFCMFC_AFC    0x02	/* Run AFC mode */
#define ENAFCMFC_MFC    0x03	/* Run MFC mode */
#define ENAFCMFC_TOGGLE 0x04	/* Toggle between AFC&MFC modes */
#define ENAFCMFC_LOAD   0x10	/* Load new AFC level */

void afcTestKill( void ) ;
void afcTestWalk( UINT1 lPinNum_a ) ;
void afcTestData( UINT1 lPinNum_a, SINT4 iDWord_a ) ;

void killBurstFlags( void ) ;

UINT1 lAFCReady( void ) ;
SINT4 iafc_state( void ) ;

SINT4 iBurstCOMIndex( void ) ;

SINT4 fprint_burst_freq( FILE *stream_a ) ;
SINT4 fprint_burst_level( FILE *stream_a ) ;
SINT4 fprint_afc_info( FILE *stream_a ) ;
SINT4 fprint_ifd_info( FILE *stream_a, SINT4 iIFD_a ) ;

void setUplinkAFCData( void ) ;
SINT4 iAFCOutputPattern( void ) ;
SINT4 iPinMap( SINT4 iValue_a ) ;

/* -------------------- burst_track.c -------------------- */

#ifdef SIGMET_PCICARDS_LIB_H
UINT1 bpHuntMachine( Rvp8Rx *pDev_a, UINT1 lRun_a, UINT1 lStart_a ) ;
#endif /* #ifdef SIGMET_PCICARDS_LIB_H */

/* ------------------- subs_burst.c -------------------
 */
SINT4 iRxCoefficients_cwpulse
( SINT4 iICoefs_a[], SINT4 iQCoefs_a[], volatile FLT4 *fActWidthMHz_a,
  FLT4 fReqWidthMHz_a, SINT4 implength_a, SINT4 nBits_a, FLT4 fCenterFreqMHz_a,
  FLT4 fIFPhaseOffset_a ) ;

SINT4 iQuantizeRxCoefficients
( SINT4 iICoefs_a[], SINT4 iQCoefs_a[],
  const FLT4 fICoefs_a[], const FLT4 fQCoefs_a[],
  SINT4 implength_a, SINT4 nBits_a ) ;

void setup_fir_environment( void ) ;

SINT4 iFreqNyquistBand( volatile const struct rvp8Pwdef *pwdef_a ) ;
FLT4 fCalibrateBPFilt( FLT4 fcoefs_a[], SINT4 implength_a, FLT4 fifreq_a ) ;

#ifdef SIGMET_PCICARDS_LIB_H
FLT4 fheadpower
( FLT4 fpwr_a, UINT1 lfilt_a, const struct firinfo *firinfo_a ) ;
#endif /* #ifdef SIGMET_PCICARDS_LIB_H */

UINT1 lBpCanAdjustFreq( void ) ;
UINT1 lBpCanAdjustTime( void ) ;
UINT1 lBpCanHunt( void ) ;

void configUplink( UINT1 lSwapBurst_a, UINT1 lSwapIFs_a ) ;

void simulateBurst
( UINT2 *pIFBuf_a, volatile const struct rvp8Pwdef *pwdef_a, SINT4 iRepCount_a ) ;

UINT1 lHaveRecentCPI( SINT4 iMaxAgeMS_a ) ;

FLT4 fRvp8AvgMinMaxIF( FLT4 *fMinIF_a, FLT4 *fMaxIF_a ) ;

/* ------------------- subs_iqdata.c -------------------
 */
#ifdef SIGMET_PCICARDS_LIB_H
void insertUIQ
( Rvp8Rx *pDev_a,
  const struct uiqbits *pSet_a,
  const struct uiqbits *pClr_a,
  const struct uiqbits *pOnce_a ) ;
#endif /* #ifdef SIGMET_PCICARDS_LIB_H */

void unloadUIQ( struct rvp8PulseHdr *pHdr_a ) ;

MESSAGE iRvp8SetRxBoardParams( void ) ;

/* ------------------- subs_noise.c -------------------
 */
void noise_sample( void ) ;
void init_noise( volatile FLT4 *fnsedbdown_a ) ;

FLT4 flognoise( volatile const struct rvp8Noise *pNoise_a ) ;
FLT4 fnoise_maxrange( volatile const struct rvp8Pwdef *pwdef_a ) ;

/* ------------------- subs_nv.c -------------------
 */
void   factory_nv( volatile struct rvp8NV *pnv_a, UINT1 lUseIRIS_a ) ;
void   restore_nv( volatile struct rvp8NV *pnv_a ) ;
void      save_nv( volatile struct rvp8NV *pnv_a ) ;
void  quantize_nv( volatile struct rvp8NV *pnv_a ) ;
void nv_overrides( volatile struct rvp8NV *pnv_a ) ;

/* ------------------- subs_misc.c -------------------
 */
void  wout( UINT2 iWord_a ) ;
void  wout_flush( void ) ;
SINT4 wout_numFree( void ) ;
SINT4 wout_numUsed( void ) ;
void  wout_clear( void ) ;

void addOutExposeIO( UINT2 outval_a ) ;
void addInExposeIO( UINT2 inval_a ) ;
void addOpcodeExposeIO( void ) ;
void printExposeIO( void ) ;

void uniformRangeMask( FLT4 fStart_a, FLT4 fSpacing_a, SINT4 iCount_a ) ;
void    userRangeMask( volatile UINT2 iUserRangeMask[ USERMASKLEN ] ) ;

void clearAzElFilters( void ) ;
void limitsAzElFilters( void ) ;
SINT4 iLookupAzElFilters( BIN2 iAz_a, BIN2 iEl_a ) ;

void updateGparm( void ) ;
UINT2 iGparmPRTNow( void ) ;
UINT2 iGparmPRTFromSysTime( UINT4 iSysTimePRT_a ) ;

void setGparmPRTVariedFlag
( const struct rvp8PulseHdr *pHdrs_a[], SINT4 nPulses_a ) ;

void makeExParm( volatile struct dspExParmIO *pParm_a ) ;

void rvp8DispPrint
( SINT4 iLine_a, UINT1 lWait_a, const char *text_a ) ;

void      printBanner( FILE *stream_a ) ;
void    printLibDates( FILE *stream_a ) ;
void  printIppVersion( FILE *stream_a ) ;
SINT4 fprint_prf_info( FILE *stream_a ) ;

/* ------------------- subs_thread.c -------------------
 */
void createOneThread
( void *(*start_routine_a)( void * ), const char *sName_a,
  int iPolicy_a, int iPriority_a ) ;

void waitThreadInits( void ) ;
void requestReconfig( void ) ;
UINT1 lRequestingReconfig( void ) ;

void rvp8_run_as_root( void ) ;
void rvp8_run_as_operator( void ) ;

void printMainThreads( FILE *stream_a ) ;

MESSAGE forkComputeProc( SINT4 iSlot_a ) ;
void printComputeProcesses( FILE *stream_a ) ;

void procCmdSingle( SINT4 iCmd_a, SINT4 iProc_a ) ;
void procCmdBroadcast( SINT4 iCmd_a ) ;
void procCmdAllComplete( void ) ;

void mt_initMajorMode( SINT4 iMode_a ) ;
void mt_exitMajorMode( void ) ;

void mtPushExitMajorMode( void(* exitMajorMode_a )( void ) ) ;

void mt_initProcSection( void ) ;
void mt_exitProcSection( void ) ;

/* ------------------- subs_trigger.c -------------------
 */
void userTriggerOutputs( void ) ;

UINT4 iTgBankType( UINT1 iTgBank_a, FLT4 *pfPRF_a ) ;
#define TGBTYP_OPERATIONAL 0x0001 /* Valid trigger bank for data processing */
#define TGBTYP_LOWPRF      0x0002 /* Low-PRF version of trigger waveforms */

FLT4 fNominalGeneratedPRF( void ) ;

void Rvp8TrigRunbank   ( SINT4 iBank_a ) ;
void Rvp8TrigRunbankReq( SINT4 iBank_a, UINT4 iFlags_a ) ;

void Rvp8TriggerWait( SINT4 nTrigs_a ) ;

UINT1 lUsingExternalTrigger( void ) ;

UINT1 lBurstPulseMissing( void ) ;

UINT1 lSlewOnTrigs( void ) ;
float fSlewForTrig( SINT4 iRxTrig_a ) ;

SINT4   iMaxImplength( volatile const struct rvp8Pwdef *pwdef_a ) ;
SINT4  iMaxDecimation( volatile const struct rvp8Pwdef *pwdef_a ) ;
FLT4 fMinRangeMaskRes( volatile const struct rvp8Pwdef *pwdef_a ) ;

void    constrain_bfe( volatile       struct rvp8Pwdef *pwdef_a ) ;
UINT1   lbfe_fullsize( volatile const struct rvp8Pwdef *pwdef_a ) ;

UINT1 lValidateImplength   ( FILE *stream_a, volatile struct rvp8Pwdef *pwdef_a    ) ;
UINT1 lValidateRangeMaskRes( FILE *stream_a, volatile struct rvp8Pwdef *pwdef_a    ) ;
UINT1 lValidateAllPWs      ( FILE *stream_a, volatile struct rvp8Pwdef  pwdefs_a[] ) ;

char *sTrigAlteredText( UINT4 iTrigAltered_a, char *sText_a ) ;

UINT1 lValidateQuantizedPRT( FILE *stream_a ) ;

/* ------------------- watch_main.c -------------------
 */
void fpdNewsFlash( const char *pText_a, FLT4 fTimeSec_a ) ;

/* ****************************************
 * *                                      *
 * *  RVP8/Main/Open Function Prototypes  *
 * *                                      *
 * ****************************************
 */

/* ------------------------------
 * Initialization routines for OPEN major modes.  The only function
 * prototype that should appear here for each major mode is the INIT
 * routine for that mode.  It is inappropriate for one mode to call
 * another's processing routines directly, because the private and
 * shared data for each mode are different.
 */
void mtInitMajorMode_fft  ( void ) ;
void mtInitMajorMode_ppp  ( void ) ;
void mtInitMajorMode_rph  ( void ) ;
void mtInitMajorMode_dpt2 ( void ) ;
void mtInitMajorMode_batch( void ) ;

/* -------------------- angles.c --------------------
 */
getAzElPosBtime_f getAzElPosBtime_dflt ;

insertLiveAzElPos_f insertLiveAzElPos_dflt ;
sampleLiveAzElPos_f sampleLiveAzElPos_dflt ;

UINT1 lCheckSyncLimits( BIN2 iAngle_a, volatile SINT4 *pLastSyncIndex_a ) ;

SINT4 iSyncIndexTruncFromAngle( BIN2 angle_a ) ;
SINT4 iSyncIndexRoundFromAngle( BIN2 angle_a ) ;

/* -------------------- checkconfig.c --------------------
 */
iConfigError_f iConfigErrorCommon_dflt ;
iConfigError_f iConfigErrorDualPol_dflt ;
iConfigError_f iConfigErrorSinglePol_dflt ;

void setAllThreshFromOpprm
( volatile struct threshOneParam pprmThresh_a[ PPRMS_N_COUNT ],
  volatile struct opprm *opprm_a ) ;

void setOneThreshFromIOArgs
( volatile struct threshOneParam *oneThresh_a,
  SINT2 iLOGThr_a, SINT2 iCCRThr_a, SINT2 iWSPThr_a, SINT2 iSQIThr_a,
  UINT2 iTCF_a ) ;

/* ---------------------- cpi.c ----------------------
 */
lFindNextCPI_f lFindNextCPI_dflt ;

struct confIntFNCPI ;		/* To resolve forward references... */
typedef UINT1 ( lPossibleStartCPI_f )
     ( volatile const struct rvp8PulseHdr *pHdr_a
       ) ;
typedef UINT1 ( lRecentCPI_f )
     ( volatile const struct oneCPI *pCPI_a, UINT1 lLowLatency_a,
       const struct confIntFNCPI *pConf_a
       ) ;
typedef UINT1 ( lIntFindNextCPI_f )
     ( volatile const struct oneCPI *prevCPIs_a[FNCPIHIST],
       volatile struct oneCPI *nextCPI_a, UINT1 lContiguous_a,
       UINT4 iTrialSeqNum_a, const struct confIntFNCPI *pConf_a
       ) ;
struct confIntFNCPI {		/* Args for generic CPI locator */
  SINT4 nPulses ;		/*   Desired number of pulses in the CPI */
  SINT4 iBeginSearchFrom ;	/*   Where to begin the next CPI search */
#define CPIBSF_FROMEND      0	/*     From the last end pulse itself */
#define CPIBSF_AFTEREND     1	/*     From pulse following the end */
#define CPIBSF_AFTERSTART   2	/*     From pulse following the beginning */
  lRecentCPI_f        *lRecentCPI ;
  lPossibleStartCPI_f *lPossibleStartCPI ;  
  lIntFindNextCPI_f   *lIntFindNextCPI ;
  SINT4 iByStartOverlap ; /* Overlap parameter for lIntFindNextCPI_byStart() */
} ;
UINT1 lFindNextCPIHelper
( volatile const struct oneCPI *prevCPIs_a[FNCPIHIST],
  volatile struct oneCPI *nextCPI_a, UINT1 lLowLatency_a,
  const struct confIntFNCPI *pConf_a ) ;

lRecentCPI_f lRecentCPI_dflt ;

lIntFindNextCPI_f lIntFindNextCPI_dualPRF ;
lIntFindNextCPI_f lIntFindNextCPI_uniform ;
lIntFindNextCPI_f lIntFindNextCPI_byStart ;

void initOneCPI( volatile struct oneCPI *pCPI_a ) ;

lPossibleStartCPI_f lPossibleStartCPI_dflt ;
lPossibleStartCPI_f lPossibleStartCPI_waveZero ;

lCheckupCPI_f lCheckupCPI_dflt ;
lAssignProcsInCPI_f lAssignProcsInCPI_dflt ;
lAssignProcsInCPI_f lAssignProcsInCPI_dfltNoPRTV ;
setupProcBins_f setupProcBins_dflt ;

void setBinsForProcInCPI
( volatile struct procInCPI *proc_a, const struct rvp8PulseHdr *pHdrs_a[] ) ;

void printProcInCPI( volatile const struct procInCPI *proc_a ) ;
void printTopLevelCPI( volatile struct oneCPI *pCPI_a, UINT1 lVerbose_a ) ;

/* -------------------- fpdisplay.c ---------------------
 */
frontPanelDisplay_f frontPanelDisplay_dflt ;

/* -------------------- if_filter.c ---------------------
 */
cwpulseMatchedFilter_f cwpulseMatchedFilter_dflt ;

void applyBurstWindow( FLT4 fdata_a[], SINT4 ilength_a, FLT4 fTapOffset_a ) ;

void synchFunction
( FLT4 fcoefs_a[], SINT4 ilength_a, FLT4 fwc_a, FLT4 fTapOffset_a ) ;

void applySineShift
( FLT4 fdata_a[], SINT4 ilength_a, FLT4 fFreq_a, FLT4 fTapOffset_a, UINT1 lCosine_a ) ;

/* --------------------- rawpulse.c ---------------------
 */
rawPulseCorrections_f rawPulseCorrections_dflt ;
rawPulseCorrections_f targetSimulator_dflt ;

UINT1 lBpUpdateMagAvg
( volatile struct bpMagAvg *bpMagAvg_a, FLT4 fBurstMag_a ) ;

void iqInterferenceFilter
( FLT4 *fIQ_a, const FLT4 *fIQp1_a, const FLT4 *fIQp2_a,
  FLT4 fNoiseSQ_a, SINT4 iBins_a ) ;

UINT1 lTargetSimulatorNeeded( void ) ;
SINT4 iTargSysClkFreq( FLT4 fTargDoppler_a ) ;

void makePulseInfo( struct rvp8PulseInfo *pInfo_a ) ;

SINT4 iBinsWithinRadius( SINT4 iSyTicks_a ) ;
SINT4 iImpureDataBins( void ) ;

void wideChannelInit( void ) ;

SINT4 iWideChannelMerge
( const FLT4 *fLoGain_a, FLT4 *fHiGain_a, FLT4 fHiMaxMag_a,
  FLT4 fOverlapDB_a, SINT4 nVecs_a, SINT4 iSkipVecs_a, Ipp32fc *cRatios_a ) ;

UINT1 lWideChannelStaleFIR( void ) ;
void   wideChannelUpdate( FLT4 *pfWideChanArgFIR_a ) ;
UINT1 lWideChannelStats( FILE *stream_a ) ;

/* --------------------- rtctrl.c ---------------------
 */
struct rtCtrl_dflt {		/* Private data for default realtime callback */
  SINT4 iAlgorithm ;		/*   Which realtime callback services are needed */
#define RTDFALG_NONE     0	/*     No realtime support is required */
#define RTDFALG_ANGSYNC  1	/*     Recheck upon crossing every sync angle */
#define RTDFALG_EACHRAY  2	/*     Recheck after every ray's worth of pulses */
  UINT4 lLowPRF ;		/*   Low PRF is being generated now */
  SINT4 iLastSyncIndex ;	/*   Center angle of present sync interval */
  UINT4 lReloadSameBank ;	/*   Reload trigger bank, even when no change */
  SINT4 iDualPRFExtraPulses ;	/*   Number of extra waveform pulses to ignore */
  UINT4 iBtimeAccel ;		/*   Antenna still accelerating at this binary time */
  SINT4 iSyncHists ;		/*   Angle sync fit to this many prior points */
} ;

struct procSection_dflt {	/* Private data for default PROC section */
  struct rtCtrl_dflt rtCtrl ;
} ;
void initProcSection_dflt
( struct procSection_dflt *pd_a, UINT1 lReloadSameBank_a, SINT4 iDualPRFExtraPulses_a ) ;
void exitProcSection_dflt
( struct procSection_dflt *pd_a ) ;

void rtCtrlCBF_dflt( struct rtCtrl_dflt *pd_a, struct rtCtrlCBInfo *cbi_a ) ;
SINT4 iRtCtrlTrigBankToRun_dflt( UINT4 iBtime_a, UINT1 lLowPrf_a ) ;

/* --------------------- rtdisp.c ---------------------
 */
void rvp8RtdispInit( void ) ;
void rvp8RtdispExit( void ) ;

void rvp8RtdispNewRay
( const struct oneCPI *pCPI_a, SINT4 nBins_a,
  const UINT2 *pParams_a[ PPRMS_N_COUNT ], UINT1 lData16_a ) ;

/* The end of a volume scan has arrived.  
 * Called when we receive a FIFO reset command.
 */
void rvp8RtdispEndVolume(void);


/* --------------------- tdwr.c ---------------------
 */
UINT1 lTdwrPanelEnabled( void ) ;

void tdwrSTCSetMode( SINT4 iTdwrSTCMode_a, UINT1 lWaitForReady_a ) ;
#define TDWR_STC_NORMAL    0 	/* Normal pulse-to-pulse STC operation */
#define TDWR_STC_MINIMUM   1 	/* Set to minimum attenuation */
#define TDWR_STC_MAXIMUM   2 	/* Set to maximum attenuation */
#define TDWR_STC_LOAD      3 	/* Prepare to load a new STC curve */

void tdwrSTCLoadTable( UINT1 *pSTCTable_a, SINT4 iCount_a ) ;

/* --------------------- txsubs.c ---------------------
 */
iNominalTrigSequence_f iNominalTrigSequence_dflt ;

iCustomTrigSequence_f iCustomTrigSequence_dflt ;
iCustomTrigSequence_f iCustomTrigSequence_prfSect ;

SINT4 iCustomTrigSequenceIterator
( struct rvp8TgPulse pSequence_a[RVP8MAXPULSES],
  struct rvp8Tglines *tglines_a, SINT4 *pBank_a, SINT4 iCalls_a,
  volatile const struct rvp8Pwdef *pwdef_a,
  iCustomTrigSequence_f *pFuncs_a[], SINT4 nFuncs_a ) ;

SINT4 iTrigSeqFromPRTSeq
( struct rvp8TgPulse pTrig_a[RVP8MAXPULSES], const struct prtSequence *pSeq_a,
  SINT4 iSampleSize_a ) ;

SINT4 iGenPhaseSequence
( volatile BIN2 iPhases_a[RVP8MAXPULSES], SINT4 iPhSeq_a, BIN2 iDefaultPhase_a,
  SINT4 nBits_a, SINT4 iSuggestedLength_a ) ;

void genRandomPhaseSequence
( volatile BIN2 iPhases_a[RVP8MAXPULSES], SINT4 nBits_a, SINT4 iLength_a ) ;

lAnalyzeBurstPhseq_f lAnalyzeBurstPhseq_dflt ;

MESSAGE configTxCardWaveforms
( volatile const struct rvp8TxChanSetup *pTxChan_a, SINT4 iChan_a ) ;

void configTxCardFromNV( UINT1 lConfigClocks_a ) ;
void configTxCardClocks( void ) ;

/* ------------------- txwaves.c --------------------
 */
iTxWaveformDesign_f iTxWaveformDesign_dflt ;
iTxWaveformDesign_f iTxWaveformDesign_cwpulse ;
iTxWaveformDesign_f iTxWaveformDesign_linearFM ;
iTxWaveformDesign_f iTxWaveformDesign_nonlinFM ;

void txWaveRxFromTx_dflt
( Ipp32fc *cRxFilt_a, const Ipp32fc *cTxWave_a, SINT4 nPoints_a ) ;

SINT4 iTxWaveNumPoints
( volatile const struct rvp8TxWaveSpecs *specs_a,
  FLT4 fSampMHz_a, SINT4 iMaxPoints_a ) ;

void txWaveBandLimitEdge
( Ipp32fc *cTxWave_a, SINT4 nPoints_a, SINT4 nEdgePts_a ) ;

SINT4 iTxWaveEdgePoints
( SINT4 nPoints_a, FLT4 fBandWidthMHz_a, FLT4 fSampMHz_a ) ;

void txWaveUpDnConvert
( Ipp32fc *cWave_a, SINT4 nPoints_a, FLT4 fNormFreq_a, FLT4 fScale_a ) ;

void txWaveNormalizeMag( Ipp32fc *cWave_a, SINT4 nPoints_a ) ;

FLT4 fTxWaveOutputPower
( const Ipp32fc *cTxWave_a, const Ipp32fc *cRxFilt_a, SINT4 nPoints_a ) ;

void txWaveMagAmbiguity
( FLT4 *fMagAmbig_a, const Ipp32fc *cTxWave_a, const Ipp32fc *cRxFilt_a,
  SINT4 nPoints_a ) ;

void txWaveAmbigStats
( FLT4 *fMagAmbig_a, SINT4 nPoints_a,
  FLT4 *fPSL_a, FLT4 *fISL_a, FLT4 *fWidth_a ) ;

/* ------------------- rvp8main_open.c -------------------
 */
UINT1 lMainOpenProfiling( void ) ;
UINT4 iMainOpenUnique( void ) ;

/* ****************************************
 * *                                      *
 * *  RVP8/Main/Site Function Prototypes  *
 * *                                      *
 * ****************************************
 */

/* ------------------- mt_user.c -------------------
 */
void rvp8MainSiteInit( void ) ;
void rvp8MainSiteExit( void ) ;

void mtInitMajorMode_user1( void ) ;
void mtInitMajorMode_user2( void ) ;
void mtInitMajorMode_user3( void ) ;
void mtInitMajorMode_user4( void ) ;

UINT1 lMtInitMajorModeSwitch( SINT4 iMode_a ) ;

/* ------------------- rvp8main_site.c -------------------
 */
UINT1 lMainSiteProfiling( void ) ;
UINT4 iMainSiteUnique( void ) ;

#endif /* #ifndef MESSAGE_ONLY */
#endif /* #ifndef SIGMET_RVP8MAIN_H */
