/**---------------------------------------------------------------------------
 ** 
 ** scan_nbr.h -- 
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/07/30 11:54:37
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/07/30 14:42:56
 ** Update Count    : 9
 ** Directory       : /pcdata1/jaccard/codas3c/gfi/src/apps/nbr/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    Undocumented.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **------------------------------------------------------------------------**/

#include "geninc.h"
#include "ioserv.h"
#include "dbsource.h"
#include "use_db.h"
#include "vstat.h"
#include "gfimisc.h"
#include "gfinbr.h"
#include "gfimath.h"

/* ##################################################################
	 -Control File:
	 ################################################################## */

/* ------------------------------------------------------------------
	 --Parameters:
	 ------------------------------------------------------------------ */

static FILE_NAME_TYPE file_list;
static FILE_NAME_TYPE out_file;
static int year_base;

static PARAMETER_LIST_ENTRY_TYPE scan_nbr_params[] =
{
	{" file_list:", "%79s",  (char *) file_list,  TYPE_STRING},
	{" out_file:",  "%79s",  (char *) out_file,   TYPE_STRING},
	{" year_base:", "%d",    (char *) &year_base, TYPE_INT},
	{ NULL, NULL, (char *) NULL, 0}
};
	
/* ------------------------------------------------------------------
	 --Options:

	 The different options allow to select different checks, and to generate
	 different statistical results on the data. All options correspond to a bit
	 in an [[ULONG]] variable. There is one [[ULONG]] to store options relative
	 to error checks, and another one for saving data statistic checks and flag
	 status. 

	 ---Error Bit Codes:

	 ERROR CHECKS:

	   Transducer Error:

	     BIT0  : check BIT status
			 BIT7  : all_error_bits

		 Configuration Changes:

	     BIT8  : output buffer size
	     BIT9  : velocity_buffer_size
	     BIT10 : spectral_width_buffer_size
	     BIT11 : echo_intensity_buffer_size 
	     BIT12 : percent_good_buffer_size
	     BIT13 : status_buffer_size
			 BIT14 : time_between_pings
			 BIT15 : pings_per_ensemble
			 BIT16 : number_of_bins
			 BIT17 : bin_length
			 BIT18 : transmit_pulse_length
			 BIT19 : blank_after_transmit
			 BIT20 : delay_after_blank
			 BIT21 : adcp_config
			 BIT22 : signal_noise_threshold
			 BIT23 : percent_good_threshold
			 BIT31 : all_config_bits

	 ---Statistics and Flags Bit Codes:

	 DATA STATISTICS:

	   Data Statistics:
	 
			 BIT0  : time_between_ensemble
			 BIT1  : heading			 
			 BIT2  : pitch
			 BIT3  : roll
			 BIT4  : heading_std_dev
			 BIT5  : pitch_std_dev
			 BIT6  : roll_std_dev
			 BIT7  : adcp_temperature
			 BIT23 : all_stat_bits

		 Flag Status:

			 BIT24 : bottom_tracking
			 BIT31 : all_flag_bits

	---Bottom Tracking Flag:

	Bottom tracking is a flag which may be ON or OFF. Bad bottom tracking is
	defined as: 

	    +The number of beams, whose bottom track percent good is less than the
			 percent good threshold, is less than [[NB_BT_PCG_MIN]].
	
		or

 	    +The number of beams, whose bottom track velocity that are bad, is less
			than [[NB_BT_VEL_MIN]].

	At startup, bottom tracking is set to -1, which means undefined.

	---Tilt Offsets:

	Tilts offsets are entered as if they would be a transducer misalignment,
	although heading pitch and roll may be completely independent of transducer
	disposition. By default, these are zero. 

  ---SCAN_BITS:

	These bits are used to control scanning of data. The following bits have
	been implemented:

	   BIT0 : Also output ascii log data in log file.

	------------------------------------------------------------------ */

static TRANSDUCER_MISALIGNMENT_TYPE tr_mis={0.0, 0.0, 0.0};
static ULONG error_check_bits=0;
static ULONG data_stat_bits=0 ;
static ULONG scan_bits=0;

static OPTION_TYPE error_check_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{"BIT_Status",        0, set_long_bit, (char *) &error_check_bits},
	{"ALL",                7, set_long_bit, (char *) &error_check_bits},
	{NULL, 0, NULL, (char *) NULL}
};

#define ASCII_LOG_BIT           ((ULONG) BIT0)

#define ALL_CONFIG_CHECK_BIT   ((ULONG) \
																BIT8  | BIT9  | BIT10 | BIT11 | \
																BIT12 | BIT13 | BIT14 | BIT15 | \
																BIT16 | BIT17 | BIT18 | BIT19 | \
																BIT20 | BIT21 | BIT22 | BIT23 )

static OPTION_TYPE config_check_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{"output_buffer_size"				 ,  8, set_long_bit, (char *) &error_check_bits},
	{"velocity_buffer_size"			 ,  9, set_long_bit, (char *) &error_check_bits},
	{"spectral_width_buffer_size", 10, set_long_bit, (char *) &error_check_bits},
	{"echo_intensity_buffer_size", 11, set_long_bit, (char *) &error_check_bits},
	{"percent_good_buffer_size"	 , 12, set_long_bit, (char *) &error_check_bits},
	{"status_buffer_size"				 , 13, set_long_bit, (char *) &error_check_bits},
	{"time_between_pings"				 , 14, set_long_bit, (char *) &error_check_bits},
	{"pings_per_ensemble"				 , 15, set_long_bit, (char *) &error_check_bits},
	{"number_of_bins"						 , 16, set_long_bit, (char *) &error_check_bits},
	{"bin_length"								 , 17, set_long_bit, (char *) &error_check_bits},
	{"transmit_pulse_length"		 , 18, set_long_bit, (char *) &error_check_bits},
	{"blank_after_transmit"			 , 19, set_long_bit, (char *) &error_check_bits},
	{"delay_after_blank"				 , 20, set_long_bit, (char *) &error_check_bits},
	{"adcp_config"							 , 21, set_long_bit, (char *) &error_check_bits},
	{"signal_noise_threshold"		 , 22, set_long_bit, (char *) &error_check_bits},
	{"percent_good_threshold"		 , 23, set_long_bit, (char *) &error_check_bits},
	/* ---------------------------------
		 To unselect specific bits
		 --------------------------------- */
	{"!output_buffer_size"				 ,108, set_long_bit, 
	 (char *) &error_check_bits},
	{"!velocity_buffer_size"			 ,109, set_long_bit, 
	 (char *) &error_check_bits},
	{"!spectral_width_buffer_size", 110, set_long_bit, 
	 (char *) &error_check_bits},
	{"!echo_intensity_buffer_size", 111, set_long_bit, 
	 (char *) &error_check_bits},
	{"!percent_good_buffer_size"	 ,112, set_long_bit, 
	 (char *) &error_check_bits},
	{"!status_buffer_size"				 ,113, set_long_bit, 
	 (char *) &error_check_bits},
	{"!time_between_pings"				 ,114, set_long_bit, 
	 (char *) &error_check_bits},
	{"!pings_per_ensemble"				 ,115, set_long_bit, 
	 (char *) &error_check_bits},
	{"!number_of_bins"						 ,116, set_long_bit, 
	 (char *) &error_check_bits},
	{"!bin_length"								 ,117, set_long_bit, 
	 (char *) &error_check_bits},
	{"!transmit_pulse_length"		   ,118, set_long_bit, 
	 (char *) &error_check_bits},
	{"!blank_after_transmit"			 ,119, set_long_bit, 
	 (char *) &error_check_bits},
	{"!delay_after_blank"				   ,120, set_long_bit, 
	 (char *) &error_check_bits},
	{"!adcp_config"							   ,121, set_long_bit, 
	 (char *) &error_check_bits},
	{"!signal_noise_threshold"		 ,122, set_long_bit, 
	 (char *) &error_check_bits},
	{"!percent_good_threshold"		 ,123, set_long_bit, 
	 (char *) &error_check_bits},
	/* ---------------------------------
		 To select all
		 --------------------------------- */
	{"ALL", (int) ALL_CONFIG_CHECK_BIT , logical_or, (char *) &error_check_bits},
	{NULL, 0, NULL, (char *) NULL}
};

#define ALL_DATA_STAT_BIT   ((ULONG) \
														 BIT0  | BIT1  | BIT2  | BIT3  | \
														 BIT4  | BIT5  | BIT6  | BIT7  )
														 
static OPTION_TYPE data_stat_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{"time_between_ensemble",	     0, set_long_bit, (char *) &data_stat_bits},	
	{"heading",							 1, set_long_bit, (char *) &data_stat_bits},	
	{"pitch",									     2, set_long_bit, (char *) &data_stat_bits},	
	{"roll",										   3, set_long_bit, (char *) &data_stat_bits},	
	{"heading_std_dev",				     4, set_long_bit, (char *) &data_stat_bits},	
	{"pitch_std_dev",					     5, set_long_bit, (char *) &data_stat_bits},	
	{"roll_std_dev",						   6, set_long_bit, (char *) &data_stat_bits},	
	{"adcp_temperature",				   7, set_long_bit, (char *) &data_stat_bits},	
	/* ---------------------------------
		 To unselect specific bits
		 --------------------------------- */
	{"!time_between_ensemble",	 100, set_long_bit, (char *) &data_stat_bits},
	{"!heading",								 101, set_long_bit, (char *) &data_stat_bits},
	{"!pitch",									 102, set_long_bit, (char *) &data_stat_bits},	
	{"!roll",										 103, set_long_bit, (char *) &data_stat_bits},	
	{"!heading_std_dev",				 104, set_long_bit, (char *) &data_stat_bits},	
	{"!pitch_std_dev",					 105, set_long_bit, (char *) &data_stat_bits},	
	{"!roll_std_dev",						 106, set_long_bit, (char *) &data_stat_bits},	
	{"!adcp_temperature",				 107, set_long_bit, (char *) &data_stat_bits},	
	/* ---------------------------------
		 To select all
		 --------------------------------- */
	{"ALL", (int) ALL_DATA_STAT_BIT, logical_or, (char *) &data_stat_bits},	
	{NULL, 0, NULL, (char *) NULL}
};

#define ALL_FLAGS_BIT   ((ULONG) BIT24)

static OPTION_TYPE data_flag_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{"bottom_tracking",			 24, set_long_bit, (char *) &data_stat_bits},	
	/* ---------------------------------
		 To unselect specific bits
		 --------------------------------- */
	{"!bottom_tracking",		124, set_long_bit, (char *) &data_stat_bits},	
	/* ---------------------------------
		 To select all
		 --------------------------------- */
	{"ALL", ALL_FLAGS_BIT, logical_or, (char *) &data_stat_bits},	
	{NULL, 0, NULL, (char *) NULL}
};

static OPTION_TYPE transducer_misalignment_options[]=
{
	{"end", 0, NULL, (char *) NULL},
	{"heading=", TYPE_DOUBLE, op_get_param, (char *) &(tr_mis.heading)},
	{"pitch=", TYPE_DOUBLE, op_get_param, (char *) &(tr_mis.pitch)},
	{"roll=", TYPE_DOUBLE, op_get_param, (char *) &(tr_mis.roll)},
	{NULL, 0, NULL, (char *) NULL}
};

static OPTION_TYPE scan_options[] =
{
	{"end", 0, NULL, (char *) NULL},
	{"OPTIONS:", 0, NULL, (char *) NULL},
	{"error_check_options:",     1, execute_sub_options, 
	 (char *) error_check_options},
	{"config_check_options:",    1, execute_sub_options, 
	 (char *) config_check_options},
	{"data_stat_options:",       1, execute_sub_options,
	 (char *) data_stat_options},
	{"data_flag_options:",       1, execute_sub_options,
	 (char *) data_flag_options},
	{"tilt_offset:", 1, execute_sub_options, 
	 (char *) transducer_misalignment_options},
	{"ascii_log", 0, set_long_bit, (char *) &scan_bits },
	{NULL, 0, NULL, (char *) NULL}
};

/* ##################################################################
	 -Checking:
	 ################################################################## */

/* ------------------------------------------------------------------
	 --Configuration Checks:

	 The next structure is used to access the different variables to check
	 during configuration checking. The code value must be the same as the one
	 used in the [[config_check_options]] list. These data are required to
	 perform configuration checks.
	 ------------------------------------------------------------------ */

#define SIZE_OF_USHORT 2
#define SIZE_OF_UBYTE  1
#define SIZE_OF_TBP    3

static NBR_ENSEMBLE_TYPE tmp_ens;

typedef struct
{
	int  code;   /* Value to identify the variable     */
	int  size;   /* Size in bytes occupied by variable */
	char *ptr;   /* pointer to variable                */
} SCAN_NBR_CONFIG_CHECK_TYPE;

static SCAN_NBR_CONFIG_CHECK_TYPE config_check_list[]=
{
	{ 8, SIZE_OF_USHORT, (char *) &(tmp_ens.header.output_buffer_size)},
	{ 9, SIZE_OF_USHORT, (char *) &(tmp_ens.header.velocity_buffer_size)},
	{10, SIZE_OF_USHORT, (char *) &(tmp_ens.header.spectral_width_buffer_size)},
	{11, SIZE_OF_USHORT, (char *) &(tmp_ens.header.echo_intensity_buffer_size)},
	{12, SIZE_OF_USHORT, (char *) &(tmp_ens.header.percent_good_buffer_size)},
	{13, SIZE_OF_USHORT, (char *) &(tmp_ens.header.status_buffer_size)},
	{14, SIZE_OF_TBP,    (char *) &(tmp_ens.leader.time_between_pings)},
	{15, SIZE_OF_USHORT, (char *) &(tmp_ens.leader.pings_per_ensemble)},
	{16, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.number_of_bins)},
	{17, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.raw_bin_length)},
	{18, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.xmt_pulse_length)},
	{19, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.blank_after_xmt)},
	{20, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.delay_after_blank)},
	{21, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.adcp_config)},
	{22, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.signal_noise_threshold)},
	{23, SIZE_OF_UBYTE,  (char *) &(tmp_ens.leader.percent_good_threshold)},
	{-1, 0, (char *) NULL}
};

/* ------------------------------------------------------------------
	--Data Statistics:

	Some data require to be converted before one can use them to calculate mean
	values. The same applies after the mean has been calculated. This must be
	done in specific functions.

	The code in the unistat information list below corresponds to the data_check
	bit value of the variable.

	Special codes in variable names:

     [HDG]: this variable is of heading type, and special conversions
            have to be applied during summations (due to {360 = 0}).
						This is required by the matlab scripts used to process
						log files infromation.
	------------------------------------------------------------------ */

static UNISTAT_LIST_TYPE unistat_list[]=
{
	{"time_between_ensemble", "%8.2lf", 1, U_ALL, 0, NULL, NULL},
	{"heading [HDG]",         "%8.2lf", 1, U_ALL, 1, NULL, NULL},
	{"pitch",                 "%8.2lf", 1, U_ALL, 2, NULL, NULL},
	{"roll",                  "%8.2lf", 1, U_ALL, 3, NULL, NULL},
	{"heading_std_dev",       "%8.2lf", 1, U_ALL, 4, NULL, NULL},
	{"pitch_std_dev",         "%8.2lf", 1, U_ALL, 5, NULL, NULL},
	{"roll_std_dev",          "%8.2lf", 1, U_ALL, 6, NULL, NULL},
	{"adcp_temperature",      "%8.3lf", 1, U_ALL, 7, NULL, NULL},
	{(char *) NULL, (char *) NULL, 0, 0, 0, NULL, NULL}
};

/* ------------------------------------------------------------------
	 The same remark applies for flag data. [[BADBYTE]] values mean
	 [[undefined_flag]], while a value of zero mean [[bad_flag]].
	 ------------------------------------------------------------------ */

static FLAG_LIST_TYPE flag_list[]=
{
	{"successful_scan", 1, NULL, -1},
	{"good_heading",    1, NULL, -2},
	{"bottom_tracking", 1, NULL, 24},
	{NULL, 0, 0, 0}
};

/* ##################################################################
	 -SCAN Data Type:

	 In order to facilitate argument passing, use the following structure.
	 ################################################################## */

typedef struct
{
	DOUBLE              yd;           /* decimal day of current ensemble   */
	DATA_FILE_INFO_TYPE fi;           /* file information                  */
	NBR_ENSEMBLE_TYPE   ping;         /* ping data of current ensemble     */
	UNISTAT_LIST_TYPE   *stat_list;   /* pointer to unistat variables list */ 
	FLAG_LIST_TYPE      *flag_list;   /* pointer to flag variable list     */
} SCAN_NBR_PING_TYPE;

typedef struct
{
	FILE *lst;
	FILE *log;
	FILE *bin;
	FILE *sta;
} SCAN_NBR_FILE_TYPE;

/* ##################################################################
	 -ADCP BIT Results Codes:

	 The following array defines the bit result codes, according to RDI's
	 technical manual. The first ones (MS nibble '0') are entered as is. Beam
	 related codes can be retrieved as follows:

	    +An MS nibble of 1, 2, 3 or 4 defines a beam 1, 2, 3 or 4 related
			 problem, respectively.

			+The corresponding problem is an additive combination of the bits set in
			 the LS nibble. The signification of each of these 4 bits may be
			 retrieved from the array below under the codes with MS nibble set to
			 'F'. 
	################################################################## */

typedef struct {
	UBYTE code;
	char *name;
} NBR_ERROR_BIT_CODE_TYPE;

static NBR_ERROR_BIT_CODE_TYPE error_bit_codes[]=
{
	{ 0, "NONE"},
	{ 1, "LO1 FREQUENCY ERROR"}, 
	{ 2, "CPU CLOCK FREQUENCY ERROR"},
	{ 3, "BAUD RATE FREQUENCY ERROR"},
	{ 4, "MM 810-2 ONE-SHOT ERROR"},
	{ 5, "REAL TIME CLOCK FREQ"},
	{ 6, "D/A - A/D CONVERSION"},
	{ 7, "MULTIPLIER RESULTS"},
	{ 8, "DIVIDER RESULTS"},
	{ 9, "ROM CHECKSUM ERROR"},
	{10, "RAM READ/WRITE ERROR"},
	{11, "RAM ADDRESSING ERROR"},
	{12, "FLUX GATE TIMEOUT"},
	{13, "BAD TRANSDUCER PROM"},
	{81, "VERY LOW TRANSMITTER CURRENT"},
	{82, "LOW TRANSMITTER CURRENT"},
	{83, "HIGH TRANSMITTER CURRENT"},
	{0xF1, "DoppFreq"},
	{0xF2, "SpectWidth"},
	{0xF4, "Signal"},
	{0xF8, "AGC"},
	{0, (char *) NULL}
};
	






