/* **********************************************************************
 * *                                                                    *
 * *             Sun calibration utility header file                    *
 * *                                                                    *
 * **********************************************************************
 * File: utils/suncal/suncal_h.h
 *
 *                      COPYRIGHT (c) 2005, 2006 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.
 */

#ifdef SUNCAL_ALLOCATE
#define EXTERN
#else
#define EXTERN extern
#endif

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

struct sun_axis_setup
{
  FLT4  fSpacing;       /* Spacing in degrees */
  FLT4  fSpan;          /* Span in degrees */
  FLT4  fSweepStartErr; /* Max position error for starting (degrees)*/
  FLT4  fSweepStartVel; /* Max velocity before starting (degrees/second) */
  FLT4  fMinimumVel;    /* The minimum speed we expect to go (degrees/sec) */
  FLT4  fMinimumWait;   /* Additional wait time (seconds) */
};

/* This structure comes from a configuration file, and does
 * not change while we are running.
 */
struct sun_cal_setup
{
  char  sVersion[8];
  UINT1 lLogToFile;       /* Enable logging to terminal or file or both */
  UINT1 lLogToTerm;
  UINT1 iAngleSource;     /* Set to either ANG_SRC_TAG_BIN16 or ANG_SRC_RCP */
  UINT1 lSimulateSun;     /* Simulate the sun half a degree off */
  FLT4  fPrf;             /* PRF in Hz to record at */
  FLT4  fRangeStart;      /* Starting range to record, in km */
  FLT4  fRangeStep;       /* Range step, in km */
  FLT4  fMinimumSunEl;    /* Minimum elevation allowed for the sun */
  SINT4 iBinCount;        /* Number of bins to record */
  SINT4 iSampleSize;      /* Sample size */
  struct sun_axis_setup Az;
  struct sun_axis_setup El;
  char  sBeamDirectory[DIRECTORY_SIZE];
  FLT4  fBeamRangeStart;    /* Starting range of BEAM, in km */
  FLT4  fBeamPower;         /* Only consider power above this threshold */
  FLT4  fBeamArea;          /* Reject if thresholded area < this, in square degrees */
  FLT4  fBeamPowerThresh;   /* Alert if power below this threshold */
  FLT4  fBeamPosThresh;     /* Alert if position error above this threshold, degrees */
  char  sResultsDirectory[DIRECTORY_SIZE];
};

struct sun_cal_results 
{
  char sVersion[8];               /* Version of the suncal program */
  char sSitename16[20];           /* Data sitename, null terminated */
  char sSitename3[8];             /* Data sitecode, null terminated */
  struct ymds_time VolumeYmds;    /* Time of data recording */
  struct ymds_time BeamYmds;      /* Time of BEAM product generation */
  struct ymds_time FileYmds;      /* Time of sun_cal_results calculation and file write */
  FLT8 fRadarLon, fRadarLat;      /* Location of the radar */
  FLT8 fSunAzPos, fSunElPos;      /* Calculated location of the sun at start time */
  FLT8 fTargetAzPos, fTargetElPos;/* Measured location of the target in beam product */
  FLT8 fAzError, fElError;        /* Error to the expected position */
  FLT8 fTargetArea;               /* Area of the sun > threshold */
  FLT8 fTargetPowerSnr;           /* Peak signal power of the sun, in SNR */
  FLT8 fTargetPowerTotal;         /* Peak total power of the sun, in dBm */
  FLT8 fTargetPowerSun;           /* Peak signal power of the sun, in dBm */
  FLT8 fTargetWidthAzRaw;         /* Azimuth beamwidth of target in BEAM */
  FLT8 fTargetWidthAz;            /* Azimuth beamwidth of target corrected */
  FLT8 fTargetWidthEl;            /* Elevation beamwidth of target */
  FLT8 fFitError;                 /* Error in the polynomial fit */

  /* Store some setup information.  Not currently posible */
  //  FLT8 fBeamPower;              /* Only consider power above this threshold */

  /* Helpful calibration values */
  FLT8 fI0Horiz;                /* I0 cal number in dBm */
  FLT8 fCalNoiseHoriz;          /* Noise at calibration time in dBm */
  FLT8 fRadarConstantHoriz;     /* Radar Constant in dB */
  FLT8 fActNoiseHoriz;          /* Current noise level in dBm */
  FLT8 fReceiverBandwidth;      /* Receiver bandwidth in MHz */
};

/* ------------------------------
 * This structure holds information some or all of which will be
 * used to assemble a ray header with the archived data.
 */
#ifdef SIGMET_DSP_H
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 */
  struct ymds_time Ymds;        /* Time of ray */
  struct gparm Gparm;           /* Tag Gparm from the ray */

};
#endif  /* #ifdef SIGMET_DSP_H */


#define ANGLE_HISTORY_SIZE (40)
#define HISTORY_TIME_SPAN  (300)
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 */
};

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;
  UINT4 GetLastBtime( void )const;
  FLT4  ComputeDeviation( UINT1 lAzAxis_a )const;
  void  FillPosition( BIN2 iAz_a, BIN2 iEl_a, UINT4 iBtimeNow_a );
};


#ifdef SIGMET_DSP_H
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_DSP_H */


#ifdef SIGMET_HEADERS_H
#ifdef SIGMET_INGEST_H
/* State structure can change */
struct sun_cal_state
{
  FLT8  fSunAzStartTask;  /* Sun's position at the start of the task, degrees*/
  FLT8  fSunElStartTask;
  FLT8  fSunAzStartSweep; /* Sun's position at the start of the sweep, degrees*/
  FLT8  fSunElStartSweep;
  FLT8  fSigma;           /* Expected Standard deviation of antenna beam */
  FLT8  fSumElErrors;     /* Accumulate for average elevation errors */
  int   iSumElCount;
  int   imem_req;         /* Memory requirement for one sweep */
  int   lsweep_just_started;

  BIN2  iNomEl;           /* Nominal elevation and azimuth to start this volume */
  BIN2  iNomAz;
  BIN2  iSunAzMotion;     /* Bearing sun has moved since the start of the task */
  BIN2  iSunElMotion;
  SINT4 iel_misses;
  SINT4 icalls;
  SINT4 imisses;
  UINT4 ibtime_misses;
  SINT4 idir;           /* Direction of the current sweep */
  SINT4 iwritn;
  UINT1 *pSweepBuffer;  /* Pointer to the array of sweep buffers */
  char  sSiteCode[8];   /* 3 char site code for file names */
  char  sBeamPathName[PATHNAME_SIZE];
  struct ingest_header IHdr;
  struct ingest_moment_info Moment;

  /* 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) )

  UINT1 idspbyt[ DSPB_SIZE ];
  
  PositionHistory history;
  LastRayHeader   lastRayHeader;
};
#endif  /* #ifdef SIGMET_INGEST_H */
#endif  /* #ifdef SIGMET_HEADERS_H */



/* Function to load the configuration file */
MESSAGE LoadSunCalSetup       /* File: LoadSetup.C */
( struct sun_cal_setup *pSSetup );

MESSAGE SaveSunCalSetup       /* File: LoadSetup.C */
( const struct sun_cal_setup *pSSetup_a );

void SunScanSector(void);     /* File: SunScan.C */

void data_loop                /* File: SunDataLoop.C */
( UINT1 *sb_a,
  const struct ingest_header *pIHdr_a,
  struct sun_cal_state *pState_a,
  MESSAGE *pStatus_a );

void idle_loop                /* File: SunScan.C */
( MESSAGE *pStatus_a,         /* Optionally filled in */
  const struct ingest_header *pIHdr_a,
  struct sun_cal_state *pState_a );  /* State of the calibration */

/* Print to log file and/or screen */
void Lprintf(const char *log_str);   /* File: suncal.C */
void LprintfError(const char *log_str);

void SunMakeBeam              /* File: SunMakeBeam.C */
( struct sun_cal_state *pState_a );

void SunProcessBeam           /* File: SunProcessProduct.C */
( const char *sPath_a );  /* Path name of the BEAM product */
  

MESSAGE LoadSunCalResults     /* File: SaveResults.C */
( const char *sName_a,
  const char *sDirectory_a,
  struct sun_cal_results *pSResults_a );

MESSAGE SaveSunCalResults     /* File: SaveResults.C */
( const char *sDirectory_a,                    /* Directory to put it in */
  const struct sun_cal_results *pResults_a );

/* Shared storage between files */
EXTERN struct sun_cal_setup SSetup_c;


#undef EXTERN

