/* **********************************************************************
 * *                                                                    *
 * *                     IRIS Scan library                              *
 * *                                                                    *
 * **********************************************************************
 * File: base/irisscan_lib/irisscan_lib.h
 *
 *                 COPYRIGHT (c) 2008, 2009, 2010, 2011 BY
 *              VAISALA, INC., 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.
 */
/** \file */

#define SIGMET_IRISSCAN_LIB_H 1

#define ISCAN_ANT_LOCAL      (IRISSCAN_FACILITY + 1)
#define ISCAN_ANT_MORBID_AZ  (IRISSCAN_FACILITY + 2)
#define ISCAN_ANT_MORBID_EL  (IRISSCAN_FACILITY + 3)
#define ISCAN_ANT_MORBID_NO  (IRISSCAN_FACILITY + 4)
#define ISCAN_BAD_SCAN       (IRISSCAN_FACILITY + 5)
#define ISCAN_NOT_RADIATING  (IRISSCAN_FACILITY + 6)
#define ISCAN_DSP_WBOUT      (IRISSCAN_FACILITY + 7)
#define ISCAN_MFCMODE        (IRISSCAN_FACILITY + 8)
#define ISCAN_MISSES         (IRISSCAN_FACILITY + 9)
#define ISCAN_RVP_DIAGERR    (IRISSCAN_FACILITY + 10)
#define ISCAN_RVP_DSPCOUNT   (IRISSCAN_FACILITY + 11)
#define ISCAN_RVP_DNLINK     (IRISSCAN_FACILITY + 12)
#define ISCAN_RVP_PLLCLK     (IRISSCAN_FACILITY + 13)
#define ISCAN_RVP_SWITCH     (IRISSCAN_FACILITY + 14)
#define ISCAN_RVP_SYLDERR    (IRISSCAN_FACILITY + 15)
#define ISCAN_RVP_BPHFAIL    (IRISSCAN_FACILITY + 16)
#define ISCAN_RVP_PHSEQGEN   (IRISSCAN_FACILITY + 17)
#define ISCAN_RVP_UPLINK     (IRISSCAN_FACILITY + 18)
#define ISCAN_RVP_NOBURST    (IRISSCAN_FACILITY + 19)
#define ISCAN_RVP_SLIPBURST  (IRISSCAN_FACILITY + 20)
#define ISCAN_SPAN_AZ        (IRISSCAN_FACILITY + 21)
#define ISCAN_SPAN_EL        (IRISSCAN_FACILITY + 22)
#define ISCAN_SWP_STOP       (IRISSCAN_FACILITY + 23)
#define ISCAN_TASK_ALT       (IRISSCAN_FACILITY + 24)
#define ISCAN_TASK_DATACOUNT (IRISSCAN_FACILITY + 25)
#define ISCAN_TASK_DSP_CANT  (IRISSCAN_FACILITY + 26)
#define ISCAN_TASK_MIXED     (IRISSCAN_FACILITY + 27)
#define ISCAN_TASK_MODE_CANT (IRISSCAN_FACILITY + 28)
#define ISCAN_TR_LOCAL       (IRISSCAN_FACILITY + 29)
#define ISCAN_TASK_NO_BITS   (IRISSCAN_FACILITY + 30)
#define ISCAN_RNG_INCONS     (IRISSCAN_FACILITY + 31)
#define ISCAN_RVP_NTGPROC    (IRISSCAN_FACILITY + 32)
#define ISCAN_RVP_PRFVARIED  (IRISSCAN_FACILITY + 33)
#define ISCAN_RVP_FIFOERROR  (IRISSCAN_FACILITY + 34)
#define ISCAN_RVP_RMASK      (IRISSCAN_FACILITY + 35)
#define ISCAN_RVP_PHSEQMES   (IRISSCAN_FACILITY + 36)
#define ISCAN_RVP_PMODERR    (IRISSCAN_FACILITY + 37)
#define ISCAN_RVP_TXCLK      (IRISSCAN_FACILITY + 38)
#define ISCAN_RVP_MMTS       (IRISSCAN_FACILITY + 39)
#define ISCAN_RVP_POLERROR   (IRISSCAN_FACILITY + 40)
#define ISCAN_RVP_NOLICENSE  (IRISSCAN_FACILITY + 41)
#define ISCAN_TASK_ERROR     (IRISSCAN_FACILITY + 42)


#define ISCAN_MAX_MOMENTS   6

/* IRIS scans will not work in passive mode.  It will not work
 * in TS playback mode.
 */

#ifdef SIGMET_DSP_H
#ifdef SIGMET_ANTENNA_LIB_H
/**
 * This structure holds information some or all of which will be
 * used to assemble a ray header with the archived data.
 */
struct ray_header_info
{
  BIN2 iaz[2];			/* Azimuth at begining and end of ray */
  BIN2 iel[2]; 
  BIN2 iAzMid;                  /* Average az/el */
  BIN2 iElMid;
  SINT4 iTagPrf;                /* Tag Measured PRF */
  SINT4 iTagPulses;             /* Tag number of pulses in the ray */
  SINT2 iTagPlaybackVersion;    /* Tag playback version */
  UINT2 iTagMismatchTS;         /* Tag Missmatched time series */
  struct dspTaskID TagTaskId;   /* Tag Task ID */
  struct ymds_time Ymds;        /* Time of ray */
  struct gparm Gparm;           /* Tag Gparm from the ray */

  /* All data below is derived from the serial line antenna
   * driver.  The information is read from the driver after the
   * ray is read from the signal processor.  This is to partly
   * compensate for the serial line delay.  Because of uncertain
   * buffering there is still a lot of uncertainty.
   */
  FLT4 fazv;
  FLT4 felv;
  FLT4 fpitchv;
  FLT4 frollv;
  FLT4 fheadingv;
  FLT4 finu_pos[3];
  FLT4 finu_vel[3];		/* Velocity of the inu */
    double fped_vel[3];
  SINT4 iage;                   /* Age in ms since last update */
  BIN2 iant_az;
  BIN2 iant_el;
  BIN2 itrain;
  BIN2 ielor;
  BIN2 ipitch;
  BIN2 iroll;
  BIN2 iheading;
  UINT2 inav_flag;
  SINT2 iPlatformVelCor1;      /* Platform motion correction 1-byte format */
  SINT2 iPlatformVelCor2;      /* Platform motion correction 2-byte format */
    enum ant_scan_geometry iScanGeometry;     /* How the antenna scans */
    uint8_t ipad_end[3];
};
#endif  /* #ifdef SIGMET_ANTENNA_LIB_H */
#endif  /* #ifdef SIGMET_DSP_H */


#define ANGLE_HISTORY_SIZE (40)   /**< history size (steps) */
#define HISTORY_TIME_SPAN  (300)  /**< history time span (ms) */
/** Subclass of PositionHistory. */
struct angle_history
{
  BIN2  iEl;     /**< Elevation angle, from tags */
  BIN2  iAz;     /**< Azimuth angle, from tags */
  UINT4 iBTime;  /**< Time ray was taken.  This time may be from another computer */
};


/** Suncal sweep angle position history. */
class PositionHistory
{
 private:
  struct angle_history History[ANGLE_HISTORY_SIZE] ;
  UINT2 iHistoryCount ;	      /**< Number of entries in the history buffer */
  UINT2 iHistoryPointer ;     /**< Slot to fill in next in history buffer */
  
 public:
  PositionHistory();  /**< Constructor */
  UINT1 lAdaquateHistory(void)const;  /**< flag for adequate history */
  UINT4 GetLastBtime( void )const;     /**< get time of last position */
  FLT4  ComputeDeviation( UINT1 lAzAxis_a )const;  /**< compute deviation */
  FLT4  ComputeVelocity( UINT1 lAzAxis_a )const;
  void  FillPosition( BIN2 iAz_a, BIN2 iEl_a, UINT4 iBtimeNow_a );  /**< fill position */
};


#ifdef SIGMET_DSP_H
#ifdef SIGMET_ANTENNA_LIB_H
/** Last ray header */
class LastRayHeader
{
 private:
  struct ray_header_info LastHeader;

 public:
  /** Get the last ray header pointer */
  const struct ray_header_info *GetPointer( void )const;

  /** Get the last ray header writeable pointer */
  struct ray_header_info *GetWritePointer( void );

  /** Clear the last ray header */
  void Clear( void );
};
#endif  /* #ifdef SIGMET_ANTENNA_LIB_H */
#endif  /* #ifdef SIGMET_DSP_H */


#ifdef SIGMET_HEADERS_H
#ifdef SIGMET_INGEST_H
#ifdef SIGMET_ANTENNA_LIB_H
#define IRIS_SCAN_STATE_DEFINED 1
/** State structure can change */
struct iris_scan_state
{
  FLT8  fSumElErrors;     /**< Accumulate for average elevation errors */
  int   iSumElCount;      /**< Accumulate for average elevation counts */
  int   imem_req;         /**< Memory requirement for one sweep */
  int   lsweep_just_started; /**< .*/

  BIN2  iNomElFile;       /**< Nominal elevation in file */
  BIN2  iNomElAntenna;    /**< Nominal elevation for antenna */
  BIN2  iNomAz;           /**< Nominal azimuth to start this volume */
  SINT4 iel_misses;
  SINT4 icalls;
  SINT4 imisses;
  UINT4 ibtime_misses;
  SINT4 iSectorDir;       /**< Direction of the Sector scans current sweep */
  SINT4 iwritn;
  bool  bFullClockwise;   /**< Direction of the Full scans */
  UINT1 *pSweepBuffer;  /**< Pointer to the array of sweep buffers */
  int32_t iMomentCount;  /**< values from 1 to ISCAN_MAX_MOMENTS are valid */
  struct ingest_moment_info Moments[ISCAN_MAX_MOMENTS];

  /* The following parameter sets the size of the statically allocated
   * DSP intermediate buffer.  This buffer must be large enough to hold
   * one complete ray cycle of DSP output.  It is sized for 2-byte data.
   */
#define DSPB_SIZE  (DSP_HEADER_MAX_SIZE + (2 * MAX_BINS * MAX_MOMENTS) )
  union {
    UINT1 u1[ DSPB_SIZE     ] ;
    UINT2 u2[ DSPB_SIZE / 2 ] ;
  } dspBuf ;
  
  PositionHistory history;
  LastRayHeader   lastRayHeader;
};
#endif  /* #ifdef SIGMET_ANTENNA_LIB_H */
#endif  /* #ifdef SIGMET_INGEST_H */
#endif  /* #ifdef SIGMET_HEADERS_H */


#ifdef SIGMET_DSP_H
#ifdef SIGMET_DSP_TYPE_DEFINED
bool bIngestScanCheckGparm
( const struct gparm *pGparm_a,
  enum sigmet_dsp_type dsp_type_a,
  const char *sTask_a );
#endif  /* #ifdef SIGMET_DSP_TYPE_DEFINED */
#endif  /* #ifdef SIGMET_DSP_H */

#ifdef SIGMET_DSP_LIB_H
typedef void (*IrisScanStartMessageProc)( const struct ingest_header *pIHdr_a, Dsp *pdsp_a );

typedef void (*IrisScanOverrideElevationsProc)( BIN2 *pNomElFile_a, BIN2 *pNomElAntenna_a, \
						int32_t iSweep_a );

typedef void (*IrisScanOverrideAzimuthProc)(BIN2 *pAzimuth_a );

typedef void (*IrisScanOverrideDataProc)( struct data_ray *ray_a, \
					  const struct ingest_moment_info *pMoment_a, \
					  const struct task_configuration *pTask_a );

#ifdef IRIS_SCAN_STATE_DEFINED 
class IrisScan
{
 private:
  Dsp *pdsp_g;
  struct iris_scan_state State_g;
  IrisScanStartMessageProc OptionalStartMessageProc_g;
  IrisScanOverrideElevationsProc OptionalOverrideElevationsProc_g;
  IrisScanOverrideAzimuthProc OptionalOverrideAzimuthProc_g;
  IrisScanOverrideDataProc OptionalOverrideDataProc_g;

  void ingestProcessGparm( struct ingest_header *pIHdr_a, Dsp *pdsp_a );
  void PpiSectorScan(struct ingest_header *pIHdr_a,  struct iris_scan_state *pState_a );
  void PpiFullScan(struct ingest_header *pIHdr_a, struct iris_scan_state *pState_a );

  bool bContinuePpiSectorSweep( const struct iris_scan_state *pState_a,   
				const struct task_configuration *pTcf_a );
  bool bContinuePpiFullSweep
    ( const struct ingest_header *pIHdr_a,   /* Ingest header structure */
      UINT1 *lWrapStarted_a,        /* Store wrap started flag in here */
      UINT1 *lWrapAlmostStarted_a,  /* One short of starting wrap */
      SINT4  iCumAngle_a,           /* Cumulative angle travelled */
      UINT1  lstop_wrap_a );         /* Stop the wrap */
  void data_loop( UINT1 *sb_a, const struct ingest_header *pIHdr_a,
		  struct iris_scan_state *pState_a, Dsp *pdsp_a, MESSAGE *pStatus_a );
  SINT4 iIngestPointerFromAngle( BIN2 iAngleMid_a, const struct iris_scan_state *pState_a,
				 const struct ingest_configuration *pIcf_a );
  SINT4 iIngestErrorFromAngle( BIN2 iAngleMid_a, const struct iris_scan_state *pState_a,
			       const struct ingest_configuration *pIcf_a );
  void data_loop_param(struct data_ray *ray_a, const struct task_configuration *pTask_a,
		       const struct ingest_data_header *pIDH_a,
		       struct iris_scan_state *pState_a,
		       const struct ingest_moment_info *pMoment_a,
		       SINT4 *iadded_a );

 public:
  IrisScan( );
  MESSAGE Init( void );      /* File: IrisScan.C */

  void SetStartMessageProc( IrisScanStartMessageProc Proc_a );
  void SetOverrideElevationsProc( IrisScanOverrideElevationsProc Proc_a );
  void SetOverrideAzimuthProc( IrisScanOverrideAzimuthProc Proc_a );
  void SetOverrideDataProc( IrisScanOverrideDataProc Proc_a );
  
  void RunTask                  /* File: IrisScan.C */
    (struct ingest_header *pIHdr_a,             /* Pointer to ingest header, task defined */
     const struct full_time_spec *pStartTime_a, /* Time on task started*/
     const struct license_setup *pLSetup_a );

  void RunTask_ext              /* File: IrisScan.C */
    (struct ingest_header *pIHdr_a,             /* Pointer to ingest header, task defined */
     const struct full_time_spec *pStartTime_a, /* Time on task started*/
     const struct license_setup *pLSetup_a,     /* IRIS site information (license) */
     const struct iris_setup    *pISetup_a );   /* IRIS setup configuration */

  Dsp *GetDspPointer(void);
  const struct iris_scan_state *GetStatePointer(void);
  
  void Shutdown( void );    /* Stop the scanning, free hardware, Dsp invalid after this */

  void FreeAllResources( void );  /* State invalid after this */
  
};
#endif  /* #ifdef IRIS_SCAN_STATE_DEFINED */

void idle_loop                /* File: IrisScan.C */
( MESSAGE *pStatus_a,         /* Optionally filled in */
  const struct ingest_header *pIHdr_a,
  struct iris_scan_state *pState_a,  /* State of the calibration */
  Dsp *pdsp_a );                     /* Dsp lib pointer */

void irisscan_lib_nls_init(void);
#define IRISSCAN_LIB_INIT irisscan_lib_nls_init()
#endif  /* #ifdef SIGMET_DSP_LIB_H */
