/* **********************************************************************
 * *                                                                    *
 * *          Structures related to the Real-Time Display               *
 * *                                                                    *
 * ********************************************************************** 
 * File: include/sig_rtdisp.h
 *
 *                  COPYRIGHT (c) 2003, 2004 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. 
 *
 * Include Requirements: sigtypes.h
 */
#ifndef SIGMET_SIG_RTDISP_H
#define SIGMET_SIG_RTDISP_H 1

#ifdef __cplusplus
extern "C" {
#endif


/* ====================================================================== */
/* RTQ structures defined here.
 */

#define RTQ_QUEUE_SIZE  25
#define RTQ_MAX_MOMENTS 10  /* Must be a multiple of 2 */
#define RTQ_MAX_BINS    3072
/* ================ Superformat going to the RTD transmitter ============= */
struct rtq_volume_header
{
  UINT2 iFlags ;	 
#define RTQ_FLAG_VOLUME_START  (0x0001)  /*First ray of volume, volume header may change */
#define RTQ_FLAG_SWEEP_START   (0x0002)  /*First ray of sweep, time may change */
#define RTQ_FLAG_VOLUME_END    (0x0004)  /*Done, no ray included */
  UINT2 ipolar ;                   /* Type of polarization, see dsp_lib.h */
  char  sSiteName16[20];           /* 16-char site name, null terminated */
  char  sSiteName3[4];             /* 3-char site name, null terminated */
  BIN4  ilat;                      /* Latitude of radar */
  BIN4  ilon;                      /* Longitude of radar */
  UINT4 iAntStatus;                /* Bits indicating antenna status */
  UINT4 iAntStatusMask;            /* Bits indicating which antenna bits are available */
  struct ymds_time ing_time;       /* Time of start of sweep */
  SINT4 ibin_first;                /* Range of first range bin in cm, can be negative */
  UINT4 ibin_step;                 /* Step between bins in cm */
  SINT4 iNominalBinCount;          /* Number of range bins in the task */
  UINT1 iScanType;                 /* See SCAN_* in iris_task.h */
  char  ipad_69x1;
  SINT2 iMomentCount;              /* Number of data moments sent */
  UINT2 iDTypes[RTQ_MAX_MOMENTS];  /* Data type of each moment */
  SINT4 iprf;                      /* PRF */
  UINT4 itrig;                     /* Dual PRF scheme */
  SINT4 ilambda;                   /* Radar wavelength in 1/100 of a cm */
  char  stname[16];                /* Task name, null terminated */
};

/* Real time ray header, contents change with each ray */
struct rtq_ray_header
{
  SINT4 itime;           /* Time offset in milliseconds */
  BIN2  azimuth_start;   /* Starting azimuth */
  BIN2  azimuth;         /* Ending azimuth */
  BIN2  elevation_start; /* Starting elevation */
  BIN2  elevation;       /* Ending elevation */
  UINT2 iBinCount;       /* Number of range bins, can change with each ray */
};

struct RtqQueueElement
{
  UINT4 iSequenceNum;       /* Element Sequence number */
  struct rtq_volume_header VHeader;
  struct rtq_ray_header    RHeader;
  UINT1  iData[RTQ_MAX_MOMENTS][2*RTQ_MAX_BINS];
};

#ifdef SIGMET_SETUP_H
struct rtdisp_control
{
  struct rtdisp_setup RSetup;
  /*
   * The real time display process is driven by the following queue that is
   * written by INGEST (or some alternate program).  As rays become available
   * to be displayed they are added to the queue.  This queue is opened read-only
   * by any readers.  If a reader is falling behind, is should skip forward.  
   * This gives a uniformly degraded display rather than "spokes".  RTD_XMT 
   * will sleep and poll whenever it realizes that there is nothing more to do.
   */
  UINT2 iQueueIn;              /* Pointer to the last inserted ray */
  UINT1 lWriterAlive;          /* TRUE if the write is still alive */
  char ipad3x5[5];             /* pad to make whole structure multiple of 8 bytes */
  struct RtqQueueElement disqueue[ RTQ_QUEUE_SIZE ];    /* Display queue */
};
#endif  /* #ifdef SIGMET_SETUP_H */


#ifndef UDP_DATA_SIZE
#define UDP_DATA_SIZE 1472  /*Maximum size of data in a UDP packet */
#else

#if ( UDP_DATA_SIZE != 1472 )
#error Inconsistent definitions of UDP_DATA_SIZE
#endif

#endif

/* =====================  Legacy V1 RTD format  ======================== */
/* Real time display volume header.  This is sent at the beginning of a volume
 * scan, and periodically thereafter.
 */
struct rtd_v1_vol_header
{
  UINT2 iCode;
  UINT2 ipolar ;		/* Type of polarization, see dsp_lib.h */
  char  sSiteName16[20];        /* 16-char site name, null terminated */
  char  sSiteName3[4];          /* 3-char site name, null terminated */
  BIN4  ilat;                   /* Latitude of radar */
  BIN4  ilon;                   /* Longitude of radar */
  struct ymds_time ing_time;    /* Time of start of sweep */
  UINT4 ibin_first;             /* Range of first range bin in cm */
  UINT4 ibin_step;              /* Step between bins in cm */
  SINT4 iNominalBinCount;       /* Number of range bins in the task */
  UINT2 idata[RTQ_MAX_MOMENTS]; /* Data type of each moment */
  SINT4 iprf;                   /* PRF */
  UINT4 itrig;                  /* Dual PRF scheme */
  SINT4 ilambda;                /* Radar wavelength in 1/100 of a cm */
  char  stname[16];             /* Task name, null terminated */
  SINT2 iMomentCount;           /* Number of data moments which will be sent */
  UINT1 iScanType;              /* See SCAN_* in iris_task.h */
  char  ipad_end[1] ;
};

/* Real time ray header */
struct rtd_v1_ray_header
{
  UINT2 iCode;
  char  sSiteName3[4];   /* 3-char site name, null terminated */
  BIN2  azimuth_start;   /* Starting azimuth */
  BIN2  azimuth;         /* Ending azimuth */
  BIN2  elevation_start; /* Starting elevation */
  BIN2  elevation;       /* Ending Elevation */
  UINT2 itime;           /* Time offset in seconds */
  UINT2 iBinCount;       /* Number of range bins in this ray */
  UINT1 iData[1];        /* Data starts here */
};

/* =====================  V2 RTD format  ======================== */
/* Real time display volume header.  This is sent at the beginning of a volume
 * scan, and periodically thereafter.
 */
struct rtd_v2_vol_header
{
  UINT2 iCode;
  UINT2 ipolar ;		/* Type of polarization, see dsp_lib.h */
  char  sSiteName3[4];          /* 3-char site name, null terminated */
  char  sSiteName16[20];        /* 16-char site name, null terminated */
  BIN4  ilat;                   /* Latitude of radar */
  BIN4  ilon;                   /* Longitude of radar */
  struct ymds_time ing_time;    /* Time of start of sweep */
  SINT4 ibin_first;             /* Range of first range bin in cm, can be negative */
  UINT4 ibin_step;              /* Step between bins in cm */
  SINT4 iNominalBinCount;       /* Total number of range bins */
  UINT2 iBinsPerPacket;         /* Number of bins sent in each packet */
  SINT2 iMomentCount;           /* Number of data moments which will be sent */
  UINT2 idata[RTQ_MAX_MOMENTS]; /* Data type of each moment */
  UINT4 itrig;                  /* Dual PRF scheme */
  SINT4 iprf;                   /* PRF */
  SINT4 ilambda;                /* Radar wavelength in 1/100 of a cm */
  char  stname[16];             /* Task name, null terminated */
  UINT1 iId;                    /* Rtdisp Id byte */
  char  ipad_end[3] ;
};

/* Real time V2 format supports much larger rays than will fit into 
 * a single UDP packet.  Each ray will be split into several UDP packets.
 * To help sort this out, we include a sequence number which only changes
 * for each new ray.  It is simply the low bits from the RTQ packet 
 * sequence number.  It may increment by more than one for out of band
 * packets in the RTQ, and if the transmitter falls behind. 
 */
/* Each ray will be broken into a separate packet for each data type.
 * Within each data type, the ray will be broken in range if it cannot
 * fit in the buffer.  The DataIndex and RangeIndex indicate which
 * subset of the data is sent.  Both of these start at zero, and the
 * range will increment first.  Note that data can be 1-byte or 2-byte
 * per bin.
 */
struct rtd_v2_ray_header
{
  UINT2 iCode;
  UINT2 iSequenceNum;  /* Sequence number */
  char  sSiteName3[4]; /* 3-char site name, null terminated */
  BIN2  azimuth_start; /* Starting azimuth */
  BIN2  azimuth;       /* Ending azimuth */
  BIN2  elevation;     /* Ending Elevation */
  UINT2 itime;         /* Time offset in seconds */
  UINT1 iDataIndex;    /* Origin 0 index into moment list */
  UINT1 iRangeIndex;   /* Origin 0 index into section in range */
  UINT2 iDataSize;     /* Size of data array in bytes */
  UINT2 iBinCount;     /* Number of range bins in this ray */
  UINT1 iId;           /* Real Time ID byte (zero) */
  UINT1 iData[1];      /* Data starts here */
};

#define RTD_PACKET_SIZE_MASK (0x07ff)
#define RTD_PACKET_TYPE_MASK (~RTD_PACKET_SIZE_MASK)

/* Note that header only has first two bytes of the rtray_header */
#define RTD_PACKET_TYPE_HEADER  (0x0000)
#define RTD_PACKET_TYPE_RAY     (0x0800)
#define RTD_PACKET_TYPE_END     (0x1000)  /* Sweep has completed */

/*
 * --------------- Real Time Display Version 1 Transmission Format ---------------
 * Structure used for each packet transmitted.
 */
union rtd_v1_packet  /* Was DisQueueElement */
{
  UINT2  iCode;
  struct rtd_v1_vol_header VHeader;
  struct rtd_v1_ray_header RHeader;
  UINT1  iBodyPad[UDP_DATA_SIZE];
};

/*
 * --------------- Real Time Display Version 2 Transmission Format ---------------
 * Structure used for each packet transmitted.
 */
union rtd_v2_packet 
{
  UINT2  iCode;
  struct rtd_v2_vol_header VHeader;
  struct rtd_v2_ray_header RHeader;
  UINT1  iBodyPad[UDP_DATA_SIZE];
};


/* Real time Modified NIDS/3 format for Radtec.
 */
struct rtd_nids3_ray_header
{
  UINT2 iStartCode;    /* Always 0xaf1f */
  UINT2 iRadarStatus;   /* Active low flags, the following are true if bit cleared */
#define RTD_NIDS3_STATUS_SERVO      (0x0001)  /* Servo power is on */
#define RTD_NIDS3_STATUS_POWER      (0x0002)  /* T/R power is on */

#define RTD_NIDS3_STATUS_AFCALARM   (0x0020)  /* AFC Alarm */
#define RTD_NIDS3_STATUS_COHOALARM  (0x0040)  /* COHO Alarm */
#define RTD_NIDS3_STATUS_STALOALARM (0x0080)  /* STALO Alarm */
#define RTD_NIDS3_STATUS_XMTFAULT   (0x0100)  /* Transmitter fault */
#define RTD_NIDS3_STATUS_XMTPOWER   (0x0200) 
#define RTD_NIDS3_STATUS_SIMULATED  (0x0400)  /* Simulated data */

#define RTD_NIDS3_STATUS_RADIATE    (0x2000)  /* Radar is radiating */
#define RTD_NIDS3_STATUS_STANDBY    (0x4000)  /* Radar is in standby (ready to radiate) */
#define RTD_NIDS3_STATUS_WARMING    (0x8000)  /* Radar is warming up (not ready to radiate) */
  UINT2 iBinCount;
#define RTD_NIDS3_DATA_T    (0x0001)
#define RTD_NIDS3_DATA_Z    (0x0002)
#define RTD_NIDS3_DATA_V    (0x0004)
#define RTD_NIDS3_DATA_W    (0x0008)
#define RTD_NIDS3_DATA_MASK (0x000f)
#define RTD_NIDS3_CHANGE_PROD  (0x0010)
#define RTD_NIDS3_CHANGE_RANGE (0x0020)
#define RTD_NIDS3_CHANGE_ELEV  (0x0040)
#define RTD_NIDS3_CHANGE_OTHER (0x0080)
#define RTD_NIDS3_CHANGE_MASK  (0x00F0)
#define RTD_NIDS3_MODE_PRECIP  (0x0100)
#define RTD_NIDS3_MODE_8BIT    (0x0200)
  UINT2 iModes;        /* Modes packed in nibbles: Unused | Product | Config| Select */
  UINT2 iScales;       /* Scales packed in bytes: Threshold | Increment */
  UINT2 iBinSpacing;   /* Bin spacing in 1/10 of meters */
  UINT2 iNyquists;     /* Unsigned Nyquist vel in low byte, Nyquist with in high, 1/3 m/s */
  UINT2 ipad14x2;
  UINT2 iAzimuth;      /* Azimuth in 1/100 of degrees */
  SINT2 iElevation;    /* Elevation in 1/100 of degrees */
  UINT2 iData[1];      /* Data starts here */
};

union rtd_nids3_packet
{
  struct rtd_nids3_ray_header RHeader;
  UINT1  iBodyPad[UDP_DATA_SIZE];
};
#define RTD_NIDS3_MAX_BINS (2+UDP_DATA_SIZE-sizeof(struct rtd_nids3_ray_header))


#ifdef __cplusplus
}
#endif
#endif /* #ifndef SIGMET_SIG_RTDISP_H */
