// flash_hex0901.c
// 25apr09 
// reads in the flash card hex file, created by flash2hex
// i.e., 'D_hex.txt' for data, 'V_hex.txt' for Doppler
// and creates an ascii-readable output
// 18Dec09...updating to use coeff in .cfg to convert cnts to eng. units


//command line input is:
// flash_hex0901 YYM SN M_ID C
// where YYM is Year-Month code
// SN = Spray s/n
// M_ID = mission ID for YYM (typ 1)
// C = First character of file name : 'D' = data, 'V' = doppler files.

//---03May10, updated for 0902 CF_DIVE format

//   oct11, updated for polyplus packet, DOX sensor

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "base_fnx.h"
#include "cf_tags.h"

// definitions -------------------------------------------
                     
#define DIAG 0 // if=1, will print out ea packet info to screen
#define DBG 0  // can use for debugging

#define NLINE 512  // max # char per each line
//--- structures --------------------------------------------------
struct scan_prm
{   // global structure for the scan info
  int   type;       // scan type
  int   surf;       // = surfacing # (#times done surface comms)
  int   ncyc;       // May10, cycle # for this surface#
  int   pro;        // profile # (May10, total #profiles so far)
  long  ti0;        // start of surf ux time
  long  tip;        // start of profile ux time
  int   nb;         // # of byte in dat[]
  int   dat[NLINE]; // data array of bytes
};
//---------------------------------------------------------------
	//--global definitions---------------------------
	struct scan_prm scan;  // first time this is called
	int NCell=0; 
	int PSurf=0;
	int Npro=1;  
	int MajVer=-1; 
	FILE  *fp_in, *fp_out, *fp_cfg;
	int H_c2i = 60;  // Hydraulics count-to-amps conversion; default
	int Wc2v14= 66;  // GPIO/Watchdog counts to 14V conversion; default
	int Wc2v07= 40;  // GPIO/Watchdog counts to 7V conversion; default
	int C2alt = 100; // altimeter counts to meters/100; default = ADP


char predat[] = "c:\\d_spray\\data\\"; // location of the data directories
int sn, m_id;   // Spray s/n plus mission id = m_id
char datdir[4]; // YYM of the data directory

//---for cfg file -------------------------------------------------------------

#define NL1 7    // #of char in the first, eeprom, label
#define NL2 30   // #of char in the 2nd, more descriptive, label
#define NDATE 9  // 9 char for date string
#define NTIME 4  // 4 char for time string
#define NCONFIG 300 // max # of variables

struct cfg_param {  // = all the params for each line entry
  int  min;        // minimum value (inclusive)
  int  max;        // maximum value (inclusive)
  int  jarg;       // index position in argument list for this variable
  int  value;      // value of the argument
  int  ee_addr;    // eeprom value, if applies

  char remote;      // ='S' = Set(fixed) value, 'R'=can change by Remote command
  char group;      // group function character identifier
  char eelabel[NL1+1]; // Spray's eeprom label
  char  label2[NL2+1]; // longer label for the variable
  char shore;      // shore command char
  char sub;        // sub command
  char type;       // param type (i=int, f=float, s=string)

  char cdate[NL2+1]; // date-string
  char ctime[6];     // time-string
  int  idive;        // dive #
};  // global structure for the config file.
struct cfg_param cfg[NCONFIG];  // list of all parameters
char miss_d[NLINE]; // global mission descriptor line

//-----------------------------------------------------------------------------


// cfg prototypes -----------------------------------------
void  init_cfg    ( void    );
int   read_config ( int *max);
int   find_label_1( char str[], int num );
int   find_label_2( char str[] );

//*** prototypes *****************************************************
int    read_scan     ( void   );
int    rdhex         ( char *ch,     int  num    ); 
int    rd_ushort     ( int dat[],    int i       );
int    rd_short      ( int dat[],    int i       );
unsigned long rd_ulong (int dat[],int i);
float  rd_float      ( int dat[],    int i       );

void   rd_dive       ( void  );
void   rd_gps        ( void  );
void   rd_surf       ( void  );
void   rd_pdat       ( void  );
void   rd_phdat      ( void  );
void   rd_edat       ( void  );
void   rd_ppdat      ( void  );
void   rd_eng        ( void  );
void   rd_hyd        ( void  );
void   rd_pwr        ( void  );
void   rd_sbd        ( void  );
void   rd_end        ( void  );
void   rd_abort      ( void  );
void   rd_drift      ( void  );
void   rd_motor      ( void  );
void   rd_aca        ( void  );
void   rd_adp        ( void  );
void   rd_adp_h      ( void  );


//*****************************************************************************
int main(int argc, char *argv[])   //******************************************
{
	int nb; // nb = #bytes in each record
	int cf_type; // compact-flash scan type
	// int dat[NLINE]; // data (byte per byte) for one scan
	int nscan=0; //#of scans processed
	int dive_max=0, num;
	
	char infile[80], outfile[80], cfgfile[80];
	char cf = 'D'; // default value

   // read in the arguments ----------------------------------------
   switch (argc) //-------------------------------------------------
   { // read in the variables
   		case 5 : sscanf(argv[4],"%c",&cf);
   		case 4 : sscanf(argv[3],"%d",&m_id);
   		case 3 : sscanf(argv[2],"%d",&sn);
   		case 2 : sscanf(argv[1],"%s",datdir);
   } // end switch
   			// now query the rest of the variables
   switch (argc)
   { // query for the rest
   		case 1 :	printf ("Give 3-char date YYM to process\n");
   					scanf("%s",datdir); 
   		case 2 :	printf("Give s/n to process for date %s\n",datdir);
   					scanf("%d",&sn);
   		case 3 :	printf("Give the mission id \n");
   					scanf("%d",&m_id);
   		case 4 :	printf("Give the file-letter type (A,D, or V) \n");
   					scanf("%c",&cf);
   } // end switch ------------------------------------------------
   // -------------------------------------------------------------

	printf("Program will convert hex to ascii format\n",cf);

	// read in the config file, and update the structure -----------
   	sprintf(cfgfile,"%s%s\\Spray%03d_%1d\\%04d.cfg",
   	       predat,datdir,sn,m_id,sn); 
	printf("cfg file is %s\n",cfgfile);
	fp_cfg = fopen(cfgfile,"r"); 
	if (fp_cfg ==NULL)
	{  
	   printf("Open file failed: %s\n",cfgfile);
	   return 0;
	}
	init_cfg();    // initialize the array to set values
	num = read_config(&dive_max ); // Read in the cfg list 
	if (num<0 || MajVer<0 )
	{ //failure
	  printf("Failed reading cfg file %s\n", cfgfile);
	  return 0;
	}
	printf("Spray Version = %04d\n",MajVer);

    //open the input file ------------------------------------------
   	sprintf(infile,"%s%s\\Spray%03d_%1d\\%c_hex.txt",
   	       predat,datdir,sn,m_id, cf); 
	printf("input file is %s\n",infile);
	fp_in = fopen(infile,"r"); 
	if (fp_in==NULL)
	{  
	   printf("Open file failed: %s\n",infile);
	   return 0;
	}
	//--------------------------------------------------------------

    //open the output file ----------------------------------------
   	sprintf(outfile,"%s%s\\%s%03d%02d.raw2",
   	       predat,datdir,datdir,sn,m_id ); 
	printf("output will go to %s\n",outfile);
	fp_out = fopen(outfile,"w"); 
	if (fp_out==NULL)
	{  
	   printf("Open outfile failed: %s\n",outfile);
	   return 0;
	}
	//--------------------------------------------------------------
	
	
	//step thru each input record -----------------------------------------
	//---------------------------------------------------------------------
	//---------------------------------------------------------------------
	scan.surf = 1; // assume the first surfacing is #1!
	do
	{

		nb = read_scan(); // read in the next scan
		// data is saved in struct scan
    	
    	if (nb>0) // then process the scan
    	{ //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
    	  cf_type = scan.type; //= scan type id
		  //printf("dive = %02x, scan type = %02x\n", scan.pro, scan.type);
    	  
    	  switch(cf_type) //ssssssssssssssssssssssssssssssssssssssss
    	  { // dependent upon scan type, write different things
    	    case CF_DIVE: 
    	         rd_dive();
    	         break;
    	    
    	    case CF_GPS0 : case CF_GPS1 : case CF_GPS2 : case CF_GPS3 :
    	         rd_gps();
    	         break;

    	    case CF_SURF : 
    	         rd_surf();
    	         break; 

    	    case CF_PDAT : 
    	         rd_pdat();
    	         break; 

    	    case CF_EDAT : 
    	         rd_edat();
    	         break; 

    	    case CF_PPDAT : //oct11 add polyplus processing
    	         rd_ppdat();
    	         break; 

    	    case CF_ENG : 
    	         rd_eng();
    	         break; 

    	    case CF_HYD : 
    	         rd_hyd();
    	         break; 

    	    case CF_MOTOR : 
    	         rd_motor();
    	         break; 

    	    case CF_DRIFT : 
    	         rd_drift();
    	         break; 

    	    case CF_PWR : 
    	         rd_pwr();
    	         break; 

    	    case CF_SBD : 
    	         rd_sbd();
    	         break; 
    	              
    	    case CF_ADP_H : 
    	         rd_adp_h();
    	         break; 
    	              
    	    case CF_ADP  : case CF_ADPS :
    	         rd_adp();
    	         break; 
    	         
    	    case CF_ABORT : 
    	         rd_abort();
    	         break; 
    	    case CF_PH : 
    	         rd_phdat();
    	         break;
    	         
    	    case CF_END : 
    	         rd_end();
    	         break; 
    	    case CF_ACA : 
    	         rd_aca();
    	         break;
    	  } //ssssssssssssssssssssssssssssssssssssssssssssssssssssss
    	  
    	  nscan++;
    	} //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
	} while (nb>-1); //----------------------------------------------------
	//---------------------------------------------------------------------
	//---------------------------------------------------------------------

	printf("%5d scans processed\n", nscan);
	fclose(fp_in);
	fclose(fp_out);


	return 0;
} //***************************************************************************
//*****************************************************************************

//****cfg functions ***********************************************************
// ****************************************************************************
void init_cfg( void )
{ // initialize the cfg structure
  int i;
  char tmp1[NL1+1], tmp2[NL2+1], tmp3[NDATE+1], tmp4[NTIME+1];
  tmp1[0] = 0;
  tmp2[0] = 0;
  blankfill(tmp1,NL1);
  blankfill(tmp2,NL2);
  blankfill(tmp3,NDATE);
  blankfill(tmp4,NTIME);
  
  for (i=0;i<NLINE;i++) miss_d[i] = 0; //zero out mission descriptor array
  
  for (i=0;i<NCONFIG;i++)
  { 
	 strcpy(cfg[i].eelabel, tmp1);
	 strcpy(cfg[i].label2 , tmp2);
     strcpy(cfg[i].cdate  , tmp3);
     strcpy(cfg[i].ctime  , tmp4);
     cfg[i].remote  = '*'; // use '*' as flag that it is not valid
     cfg[i].group   = ' ';
     cfg[i].shore   = '*';
     cfg[i].sub     = '_'; // no sub-command defined
     cfg[i].jarg    =  0;
     cfg[i].value   =  0;
     cfg[i].ee_addr = -1;
     cfg[i].idive   =  0;
  }
  
     
  return;
} // end init_cfg ******************************************************

// *********************************************************************
int read_config(int *dive_max  )
{ // read the configuration file, fp_cfg
  char line[NLINE];
  char c1, c2;
  char label1[NL1+1], label2[NL2+1], cdate[NDATE+1], ctime[NTIME+1];
  int n, j, i=0, n1, n2, k, idive;
  
    *dive_max =0; // set to 0
	do // do until no more lines
	{ 
		
		for (j=0;j<NLINE;j++) line[j] = 0;  // NULL out entire array
		// fgets(line,NLINE,fp_cfg); // reads up to a Newline = '\n' = LF = 0x0a
		// n = strlen(line);
		n = fget_line(fp_cfg,line,NLINE);
		if  (n>0)
		{  // then it is a valid line: parse accordingly
		   if ( line[0]=='S' || line[0]=='R' ) 
		   { // then it is a line with configuration info
			  sscanf(line,"%c%c %d %d:%s %s %s %s %d",
			          &c1,&c2, &n1, &n2, &label1,&label2, &cdate, &ctime, &idive );

			  if (idive> *dive_max) *dive_max = idive;
			  
			  blankfill(label1, (int) NL1  );
			  blankfill(label2, (int) NL2  );
			  blankfill(cdate , (int) NDATE);
			  blankfill(ctime , (int) NTIME);
			  		  	
			  // k = find_label_1(label1, i); // check to see if it already exists
			  k = find_label_2(label2 ); // check to see if it already exists
			  if (k == -1)
			  {  // then wasn't found, store the values
			    cfg[i].value   = n1;
			    cfg[i].ee_addr = n2;
			    cfg[i].remote  = c1;
			    cfg[i].group   = c2;
			    strcpy(cfg[i].eelabel, label1);
			    strcpy(cfg[i].label2 , label2);
			    strcpy(cfg[i].cdate, cdate);
			    strcpy(cfg[i].ctime, ctime);

			    i++;
			  } // end if new label
			} // end if 'S' or 'R'
			/*
			if ( line[0] == 'W' )
			{  // then a waypoint line
			  read_waypt(line); // read in the waypoint info
			} */
			if ( line[0] == 'M' && line[1] == 'D' )
			{ // then the mission descriptor
			  strcpy(miss_d, line);
			}
		} // end if line is the correct type

	} while (  n>-1 ); // end do..while
	
	printf("%d parameters found in the cfg file\n",i);
	
	//---get the eeprom verions	
	j = find_label_1("MajVer ",i);
	if (j>=0)
	{  MajVer = cfg[j].value; }
	else { printf("NO MajVer found\n"); i=-1;  }
	
	//find and store the gain coefficients for the a/d
	j = find_label_1("Wc2v14 ",i);
	if (j >=0)
	{  Wc2v14 = cfg[j].value; }
	else { printf("NO H_2ci found\n"); i=-1; }
	
	j = find_label_1("Wc2v07 ",i);
	if (j>=0)
	{  Wc2v07 = cfg[j].value; }
	else { printf("NO H_2ci found\n"); i=-1; }
	
	j = find_label_1("H_c2i  ",i);
	if (j>=0)
	{  H_c2i = cfg[j].value; }
	else { printf("NO H_2ci found\n"); i=-1; }
	
	j = find_label_1("ADP_k1 ",i);
	if (j>=0)
	{  if (cfg[j].value >=0) C2alt=100;
	   else { C2alt=100; printf("CHECK Altimeter gain!!!\n"); i=-1; }
	}
	else { printf("NO H_2ci found\n"); i=-1; }
	
	if (i>-1) printf("C2alt=%d, H_c2i=%d, Wc2v07=%d, Wc2v14=%d\n",
	                  C2alt, H_c2i, Wc2v07, Wc2v14 );
	
 return(i);
} // end read_config **************************************************

//*********************************************************************
int find_label_1( char label[], int num )
{ // look for label in the param list
  // if found, return the index.  Else return -1
  int i=-1, k=0,  match;
  char tmp[NL1+1];
  
  do
  { // do until at the end of the list
      strncpy(tmp, cfg[k].eelabel, NL1);
      tmp[NL1] = 0;
      // printf("%s %s\n",tmp, label);
      match = strncmp(tmp, label, NL1);
  } while (k++<num  && match !=0 );
  
    if (match==0) i = k-1;
  return(i);
} // end find_label_1 **************************************************

//**********************************************************************
int find_label_2( char label[]  )
{ // look for label in the master param list
  // if found, return the index.  Else return -1
  int i=-1, k=0,  match;
  char tmp[NL2+1];
  
  do
  { // do until at the end of the list
      strncpy(tmp, cfg[k].label2, NL2);
      tmp[NL2] = 0;
      match = strncmp(tmp, label, NL2);
      //if (DBG) fprintf(fp_dbg,"%s %s %d\n",tmp, label, match);
  } while (k++<NCONFIG  && match !=0 );
  
    if (match==0) i = k-1;
  return(i);
} // end find_label_2 *************************************************

//common base functions for writeing the .raw2 file
int rd_ushort(int dat[],int i) //**********************************************
{ // read two bytes and return unsigned value
  int val=0;
  
  val = dat[i]*256 + dat[i+1]; // msb+lsb
  //printf("%4d %4d %4d\n",val, dat[i], dat[i+1]);
  
  return(val);
} //***************************************************************************

int rd_short(int dat[],int i) //***********************************************
{ // read two bytes and return unsigned value
  int val=0;
  
  val = rd_ushort(dat,i); // unsigned value
  if (val>32767) val -= 65536; // make signed
  
  return(val);
} //***************************************************************************

unsigned long rd_ulong (int dat[],int i) //************************************
{ // read 4 bytes and return unsigned value
  int j;
  unsigned long val;
  
  val = 0;
  for (j=0;j<4;j++)
    val = val*256 + dat[i++]; // shift & add
  
  return (val);
} //***************************************************************************

 float rd_float (int dat[], int i) //******************************************
 { // read in Motorola real # and convert to intel
    unsigned char byte[4];
    float *x;
    
    x = (float*) &byte[0]; // address of x =start of byte array
     	
 	byte[3] = dat[i++]; 
 	byte[2] = dat[i++];
 	byte[1] = dat[i++];
 	byte[0] = dat[i++]; 


 	return(*x);
} //***************************************************************************




int read_scan( void) //********************************************************
// reads the next line in fp_in, and parses out:
// updates the global structure 'scan'

// cf_type = scan id type (see description at top of program)
// dat = integer array of the data
// returns nb = #bytes in the scan
{
   char line[NLINE], ds[NLINE];
   int i, j, m, n, nb=-1, diff, ns, cf_type;
   
   n = fget_line(fp_in, line, NLINE); // n=# of char in line
   
   if (n==0) return(0);  // blank line...skip
   if (n<0)  return(-1); // EOF
   // else n>0
   
   m = sscanf(line,"%x %d %s",&cf_type, &nb, ds);
   // m=#arg actually read in, should =3
   // ds = data string
   ns = strlen(ds);
   diff = nb*2 - ns; // should = 0
   
   if (m<2 || cf_type<0 ||   diff !=0 )
   { // then something doesn't make sense
      printf("BAD scan MARK: %s\n",line);
      return(0);
   }
   
   // else have a valid data type, and #bytes makes sense
   for (i=0, j=0; i<nb; i++)
   {
      scan.dat[i] = rdhex( &ds[j],2); j +=2;
      // if (*cf_type==0x0f) printf("%4d\n",dat[i] );
   }
   scan.nb   = nb;      // save #bytes
   scan.type = cf_type; // and scan id type
     
   return(nb);
}  //**************************************************************************


int  rdhex ( char *ch, int  num)  //*****************************************
 {//convert num HEX characters in *ch to  integer
  // returns the value
  int val,i;
  char c;
  
  c = *ch++; val=0; i=0;
  while ( (c != '\0') && (i<num) ) 
   {
    val = val * 16; //shift value over
    c = tolower(c);
    switch (c)
     {
      case '0' : break;
      case '1' : val = val+1; break;
      case '2' : val = val+2; break;
      case '3' : val = val+3; break;
      case '4' : val = val+4; break;
      case '5' : val = val+5; break;
      case '6' : val = val+6; break;
      case '7' : val = val+7; break;
      case '8' : val = val+8; break;
      case '9' : val = val+9; break;
      case 'a' : val = val+10; break;
      case 'b' : val = val+11; break;
      case 'c' : val = val+12; break;
      case 'd' : val = val+13; break;
      case 'e' : val = val+14; break;
      case 'f' : val = val+15; break;
      default  : val = 0; i = 5;  //set to bad values
     } //end switch
    c = *ch++; //point to next character
    i++;
   } //end while
  return(val);
 }  //end rdhex ***************************************************************
 
//***specific raw2 packet reads ***********************************************


void   rd_dive (  void ) //****************************************************
{ // parse a dive marker and write out ****************************************
  int surf, pro, ncyc;
  long ti0, tipro;
  char *s;
    
  char line[200];
  
  int i=0;
  //parse the  structure --------------------------------------------------
  surf = rd_ushort( scan.dat,i); i+=2; //dive #
  ncyc = rd_ushort( scan.dat,i); i+=2; //cycle # added May10
  if (MajVer >901) //then the profile # is stored as well
    {  pro  = rd_ushort( scan.dat,i); i+=2;  } //profile #
  else { pro = Npro; } //0901 didn't have the profile #, keep track here
  ti0  = rd_ulong ( scan.dat,i); i+=4; //ux time @ start of dive
  tipro= rd_ulong ( scan.dat,i); i+=4; //ux time @ start of profile
  //-----------------------------------------------------------------------
  
  //---save surf # and profile # in global ------------
  scan.surf = surf;
  scan.pro  = pro; 
  scan.ncyc = ncyc; // May10, save the cycle #
  scan.ti0  = ti0;
  scan.tip  = tipro;
  //---------------------------------------------------
  
  // now write out ------------------------------------
  s = ctime( &tipro);
  s[ strlen(s) -1] = 0;
  sprintf(line,
  "%02x %4d %2d %6d %11lu %11lu %s",
    CF_DIVE, surf, ncyc, pro,ti0, tipro, s ); //May10, old printed out Npro instead of ncyc
  
  Npro++; // increment total profile counter. 
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************


void  rd_gps( void  ) //*******************************************************
{ // cft = compact-flash scan type
  // dat = byte array of the data
  // n = #of bytes in dat[]
  
  // following are as defined in the GPS structure
  int  gsurf, valid, t_acq;
  int ysign, ydeg;
  float ymin;
  int xsign,xdeg;
  float xmin;
  int utc_hr, utc_mn, utc_sec;
  int gps_wk, gps_day;
  int nsat, smin, savg, smax, hdop;
  float ylat, xlon, yylat, xxlon;
  float olat, olon;
  int ovalid, wing;
  
  int i=0; // pointer into the data array
  float utc, yrday; // julian day output
  int surf = scan.surf; // surfacing #
  int health, yr, jd, stat;
  char line[200];
  
  //parse the GPS structure -----------------------------------------------
  gsurf  = rd_ushort( scan.dat,i); i+=2; //surfacing #
  valid  = rd_ushort( scan.dat,i); i+=2; //valid flag=1 if good
  t_acq  = rd_ushort( scan.dat,i); i+=2; //time to acquire [sec/10]
  ysign  = rd_short ( scan.dat,i); i+=2; //sign of latitude
  ydeg   = rd_ushort( scan.dat,i); i+=2; //abs(latitude) degrees
  ymin   = rd_float ( scan.dat,i); i+=4; //latitude minutes (+fraction)
  xsign  = rd_short ( scan.dat,i); i+=2; //sign of longitude
  xdeg   = rd_ushort( scan.dat,i); i+=2; //abs(longitude) degrees
  xmin   = rd_float ( scan.dat,i); i+=4; //long. minutes(+fraction)
  
  utc_hr = rd_ushort( scan.dat,i); i+=2; //utc hours, 0..24
  utc_mn = rd_ushort( scan.dat,i); i+=2; //utc minutes
  utc_sec= rd_ushort( scan.dat,i); i+=2; //utc seconds
  gps_wk = rd_ushort( scan.dat,i); i+=2; //GPS week number
  gps_day= rd_ushort( scan.dat,i); i+=2; //GPS day-of-week
  
  nsat   = rd_ushort( scan.dat,i); i+=2; // # of satellites-in-view
  smin   = rd_ushort( scan.dat,i); i+=2; // minimum SNR
  savg   = rd_ushort( scan.dat,i); i+=2; // average SNR
  smax   = rd_ushort( scan.dat,i); i+=2; // maximum SNR
  hdop   = rd_ushort( scan.dat,i); i+=2; // HDOP*10
  
  yylat  = rd_float ( scan.dat,i); i+=4; //present latitude, decimal degrees
  xxlon  = rd_float ( scan.dat,i); i+=4; //present long., decimal degrees
  olat   = rd_float ( scan.dat,i); i+=4; //last valid lat.
  olon   = rd_float ( scan.dat,i); i+=4; //last valid long.
  ovalid = rd_ushort( scan.dat,i); i+=2; //flag=TRUE if last fix was valid
  wing   = rd_ushort( scan.dat,i); i+=2; //wing used for fix
  //-----------------------------------------------------------------------
  // done reading in the GPS structure
         // printf("%4d, read %4d\n",scan.nb, i);
  
  if (gsurf != surf ) printf("GPS surf mismatch %d != %d\n", gsurf, surf);
  //convert to correct units to write out
  utc =  utc_hr + (utc_mn + utc_sec/60.0)/60.0; // hh.hhhh
  health = ( nsat & 0xf0) >> 4;  // health of GPS
  nsat = nsat &0x0f; // lower-nibble is # of satellites
  

   stat = gps_wkday_2_yd(gps_wk, gps_day, &yr, &jd); //convert to yr, julian-day

   if (stat==0) // -----------------------------
   { // then no error
      yrday = jd + utc/24.0; // decimal year-day
   } else
   {
      yrday = 0;
   } //-----------------------------------------
   
   if (valid==0) yrday=-98.0; // FLAG that it is not a valid number
   
   //compute xlat, xlon from decimal minutes..should be better resolution
   xlon = xsign*(xdeg+xmin/60.0);
   ylat = ysign*(ydeg+ymin/60.0);

   /*write out the GPS line
   sprintf(line,
   " -99 %4d %9.4f %11.5f %11.5f %6d %4d %4d %4d %4d %4.1f %4d %4d %2x\0",
   surf, yrday, xlon, ylat, t_acq, nsat, smin, savg, smax,
   hdop*0.01, yr, surf, health); /**/
   
   sprintf(line,"%02x %4d %1d %4d %9.4f %11.5f %11.5f %6.2f %3d %2d %4d %4d %4d %02d:%02d:%02d",
   scan.type,surf,valid,yr,yrday,ylat,xlon,hdop*0.01,t_acq*10,nsat,smin,savg,smax,utc_hr,utc_mn,utc_sec );
   // printf("%s\n",line);
   fprintf(fp_out,"%s\n",line );
  
  
  return;
} //***************************************************************************


void   rd_pdat  (  void ) //***************************************************
{ // parse a profile data scan and write out **********************************
  int ti, pr, te, sa, op, sbe; //time,pressure, temp, sal, opt, sbe flag
  int ds, dp, dc, ty;  //dive, profile #, cycle#,type
  int i, dox,doT,doU,is_dox,is_do6;
  char line[200];
  
  ds = scan.surf;
  dp = scan.pro;
  dc = scan.ncyc;
  ty = scan.type;
  
  //printf("scan.nb = %d\n",scan.nb);
  
  //---DOX oct2011, kluge to read in: this should be set by reading in the
  // header lines in the .sat file, or .cfg, or elsewhere
  // but here, just relying on the # of bytes in the message
  is_dox =  ( scan.nb == 14 ); // TRUE if includes DOX
  is_do6 =  ( scan.nb == 18 ); // TRUE if includes DO6
  
  i=0;
  //parse the data structure ----------------------------------------------
  ti   = rd_ushort( scan.dat,i); i+=2; //time [s] since start of dive
  pr   = rd_ushort( scan.dat,i); i+=2; //dBar = pr*0.04 - 10;
  te   = rd_ushort( scan.dat,i); i+=2; //degC = te*0.001 - 5;
  sa   = rd_ushort( scan.dat,i); i+=2; //PSU  = sa*0.001 -1.0;
  op   = rd_short ( scan.dat,i); i+=2; //optical counts, can be negative
  
  if (is_dox)
  { dox= rd_ushort( scan.dat,i); i+=2; //Dissolved oxygen counts
  }
  if (is_do6)
  { dox= rd_short( scan.dat,i); i+=2; //Dissolved oxygen counts
  }
  sbe  = rd_ushort( scan.dat,i); i+=2; //sbe flag=1 if sbe ctd is being taken
  if (is_do6)
  {
    doT= rd_short( scan.dat,i); i+=2; //Dissolved oxygen counts
    doU= rd_short( scan.dat,i); i+=2; //Dissolved oxygen counts
  }  
  

  //-----------------------------------------------------------------------
    
  // now write out
  if (is_dox) //---------------------------------------------------
  { //create output line with DOX tacked onto the end
    sprintf(line,
    "%02x %4d %2d %6d %5d %5d %5d %5d %5d %1d %5d",
      ty,  ds, dc, dp, ti, pr, te, sa, op,sbe,dox);
  } else if (is_do6)
  { sprintf(line,
    "%02x %4d %2d %6d %5d %5d %5d %5d %5d %1d %5d %5d %5d",
      ty,  ds, dc, dp, ti, pr, te, sa, op,sbe,dox,doT,doU);  
  } else 
  { // no DOX
    sprintf(line,
    "%02x %4d %2d %6d %5d %5d %5d %5d %5d %1d",
      ty,  ds, dc, dp, ti, pr, te, sa, op, sbe);
  } //-------------------------------------------------------------
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************
void   rd_phdat  (  void ) //***************************************************
{ // parse a profile data scan and write out **********************************
  int ti, v1,v2,v3,v4,v5,v6, hum; //voltages
  int ds, dp, dc, ty,i;  //dive, profile #, cycle#,type
  unsigned long s_no;
  char line[200];
  
  ds = scan.surf;
  dp = scan.pro;
  dc = scan.ncyc;
  ty = scan.type;
  i=0;
  //printf("scan.nb = %d\n",scan.nb);
  
  //parse the data structure ----------------------------------------------
  ti   = rd_ushort( scan.dat,i); i+=2; //time [s] since start of dive
  s_no = rd_ulong(scan.dat, i); i += 4; //scan number
  hum  = rd_ushort( scan.dat,i); i+=2; // 
  v1   = rd_ushort( scan.dat,i); i+=2; //
  v2   = rd_ushort( scan.dat,i); i+=2; //
  v3   = rd_ushort( scan.dat,i); i+=2; //
  v4   = rd_ushort( scan.dat,i); i+=2; //
  v5   = rd_ushort( scan.dat,i); i+=2; //
  v6   = rd_ushort( scan.dat,i); i+=2; //  
  //-----------------------------------------------------------------------
    
  // now write out
  sprintf(line, "%02x %4d %2d %6d %5d %6d %5d %5d %5d %5d %5d %5d %5d",
      ty,  ds, dc, dp, ti, s_no, hum,v1, v2, v3, v4, v5, v6);
  //-------------------------------------------------------------
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************

void   rd_edat  (  void ) //***************************************************
{ // parse an engineering data scan and write out *****************************
  int he, pi, ro; // heading, pitch, roll
  int pp, rr; // pitch pot, roll pot
  int b14, amp, oil,b07, alt, err;
  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dp = scan.pro;
  dc = scan.ncyc;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  he   = rd_short ( scan.dat,i); i+=2; //Heading = he*0.1;
  pi   = rd_short ( scan.dat,i); i+=2; //Pitch degrees = pi*0.1;
  ro   = rd_short ( scan.dat,i); i+=2; //Roll degrees = ro*0.1;
  
  pp   = rd_short( scan.dat,i); i+=2; //pitch pot counts
  rr   = rd_short( scan.dat,i); i+=2; //roll pot counts
  
  b14  = rd_short( scan.dat,i); i+=2; //14V pack volts, cnts: needs .cfg for coeff;
  amp  = rd_short( scan.dat,i); i+=2; //current, ALREADY IN units amps = cnts*0.01
  oil  = rd_short( scan.dat,i); i+=2; //oil cnts;
  b07  = rd_short( scan.dat,i); i+=2; //7V pack volts, cnts: needs .cfg for coeff;
  alt  = rd_short( scan.dat,i); i+=2; //altimeter
  err  = rd_ushort( scan.dat,i); i+=2; //error flags
  //-----------------------------------------------------------------------
  
  if (alt>9999) alt=9999; //if not initialized, keep to <4 digits
  else
  {  alt = alt*C2alt/100; } // convert to m
  
  b14 = b14*Wc2v14 /100; // 0.01V per count
  b07 = b07*Wc2v07 /100; // 0.01V per count
  //0901 code stores hyd->amps, already converted to 0.01amps per cnt
  //amp = amp*H_c2i  /100; // 0.01amp per count
  if (oil==0) amp=0;   // if oil==0, then motor isn't on.
  
  // now write out
  sprintf(line,
  "%02x %4d %2d %6d %5d %4d %4d %4d %4d %4d %4d %4d %4d %4d %04x",
    ty,  ds, dc, dp, he, pi, ro, pp, rr,b14,amp,oil,b07,alt, err );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************

void   rd_ppdat  (  void ) //**************************************************
{ //*** oct11: parse a polyplus data scan and write out ***********************
  int r1, r2, x1, x2;
  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dp = scan.pro;
  dc = scan.ncyc;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  // load is 1 byte, msn = load 2, lsn = load 1
  // bit 0=1 = r1, bit1=1 = r2, bit2=1 = r3, bit3=1 = r4
  r1   = rd_ushort( scan.dat,i); i+=2; //r1 and r2
  r2   = r1 & 0x00f0; // msn
  r1   = r1 & 0x000f; // lsn
  r2   = r2 >> 4;

  x1   = rd_ushort( scan.dat,i); i+=2; //first a/d value
  x2   = rd_ushort( scan.dat,i); i+=2; //2nd a/d value
  //-----------------------------------------------------------------------
  //---switch load from bit-set to value = 0..4
  switch (r1)
  { //--- r1 ----------------
  	case 8 : r1 = 4; break;
  	case 4 : r1 = 3; break;
  	case 2 : r1 = 2; break;
  	case 1 : r1 = 1; break;
  	default : break;
  } //-----------------------
  switch (r2)
  { //--- r1 ----------------
  	case 8 : r2 = 4; break;
  	case 4 : r2 = 3; break;
  	case 2 : r2 = 2; break;
  	case 1 : r2 = 1; break;
  	default : break;
  } //-----------------------
  
  // now write out
  sprintf(line,
  "%02x %4d %2d %6d %4d %4d %5d %5d",
    ty,  ds, dc, dp, r1, r2, x1, x2 );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************


void   rd_eng   (  void ) //***************************************************
{ // parse an engineering packet and write out ********************************
  int ver, nb,zmax, adb, alt, b14, amp, p0;
  int pi,he, drx, dry, yd, yx, xd, xx;
  int nbad, navg, tp1, tp2 , vac, icyc, ipr , tI, mI;
  int er, ts, nt, ns, si, ss;
  int ex, st1, st2, za, vt, vs;
  int adp_alt, w;

  int ds, dp, ty, dc;  //dive, profile #, type
  int i;
  //char line[200];
  
  ds = scan.surf; // surfacing #
  dp = scan.pro;  // accum profile #
  dc = scan.ncyc; // surfacing cycle #
  ty = scan.type;
  
  //parse the data structure ----------------------------------------------
  ver  = scan.dat[0]; // first byte = version #
  i=1;
  nb   = rd_short ( scan.dat,i); i+=2; //#bytes;
  zmax = rd_short ( scan.dat,i); i+=2; //max depth [m];
  adb  = (unsigned char) scan.dat[i++]; //if ADP, return strength[dB] of bottom
  alt  = (unsigned char) scan.dat[i++]; //altimeter: 1 cnt=1 m
  b14  = rd_short( scan.dat,i); i+=2; //14V battery during deep pump
  amp  = rd_short( scan.dat,i); i+=2; //current during deep pump
  p0   = rd_short( scan.dat,i); i+=2; //surface pressure, counts
  
  pi   = rd_short( scan.dat,i); i+=2; //pitch angle [degrees];
  he   = rd_short( scan.dat,i); i+=2; //heading steered [degrees];
  drx  = rd_short( scan.dat,i); i+=2; //dead-reckon dx [m];
  dry  = rd_short( scan.dat,i); i+=2; //dead-reckon dy [m];
  yd   = rd_short( scan.dat,i); i+=2; //waypoint Latitude degrees
  yx   = rd_short( scan.dat,i); i+=2; //waypoint Latitude dec. degrees*1000
  xd   = rd_short( scan.dat,i); i+=2; //waypoint Long. degrees
  xx   = rd_short( scan.dat,i); i+=2; //waypoint Long. dec. degrees*1000
  
  nbad = scan.dat[i++];  //#times high current was detected
  navg = scan.dat[i++];  //#8s scans avg'd per one output satellite datum
  tp1  = scan.dat[i++];  //pmp time to neutral buoy: 1 cnt=10s
  tp2  = scan.dat[i++];  //remaining pmp time: 1 cnt=10s:  tp1+tp2=total pmp time
  
  vac  = rd_short( scan.dat,i); i+=2; //vac cnts: 1 cnt=0.01 in-Hg
  ipr  = rd_short( scan.dat,i); i+=2; //accum profile #
  icyc = rd_short( scan.dat,i); i+=2; //cycle #
  tI   = (unsigned char) scan.dat[i++];  // time of max pump current: 1 cnt=10s
  mI   = (unsigned char) scan.dat[i++];  // max current: 1 cnt = 0.02 amps
  
  er   = scan.dat[i++]; //accum. roll error@bottom turn: 1 cnt=0.1 deg.
  ts   = (unsigned char) scan.dat[i++]; // time trying to send SBD messages 1cnt=1s
  nt   = scan.dat[i++]; //#SBD connect tries
  ns   = scan.dat[i++]; //#SBD packets sent last surfacing
  si   = scan.dat[i++]; //sbdi =out-bound sbd status: wing id in upper nibble.
  ss   = scan.dat[i++]; //status of parsing a shore command
  
  ex   = rd_ushort( scan.dat,i); i+=2; //exception status word
  st2  = (unsigned char) scan.dat[i++];  // ti@surface doing final pumping 1cnt=10s
  st1  = (unsigned char) scan.dat[i++];  // ti to leave surface @start-dive 1cnt=10s
  za   = rd_ushort( scan.dat,i); i+=2; //depth at time of alt reading
  vt   = scan.dat[i++]; //time that the vent ran, 1 cnt = 0.1s
  vs   = scan.dat[i++]; //vent status: bit0=1 if air@start, bit1=1 if air@end   
  //-----------------------------------------------------------------------
  
   //---catch dive, profile discrepancies -------------------------
   //if ( idv != dd) printf("Eng dive mismatch: %d != %d \n",idv,dd);
   if ( ipr != dp) printf("Profile# mismatch: %d != %d \n",ipr,dp);
  
   //do additional parsing
   adp_alt = ( ex  & 0x4000 ); // flag = TRUE if ADP altimeter
   if (alt>99) { alt=99;  adb=0; } // keep bounded
   w = ( si & 0xf0 )>>4; //wing-id: 0=stbd, 1=port
   si = si &0x0f; //only keep lower id
   if (er>127) er -= 256; // make signed.
   
   
  //--- write out
  fprintf(fp_out,
  "%02x %4d %2d %6d %4d %3d %3d %4d %4d %4d",
    ty,  ds, dc, dp,zmax,adb,alt,b14,amp,p0  );
    
  fprintf(fp_out," %2d %3d %5d %5d %3d.%03d %4d.%03d",
                    pi, he,drx, dry,yd, yx, xd, xx  );

  fprintf(fp_out," %2d %2d %4d %4d %5d %3d %3d ",
                 nbad,navg,tp1,tp2,vac, tI, mI );

  fprintf(fp_out," %5d %4d %3d %3d %1d %3d %3d  ",
                    er, ts, nt, ns,  w, si, ss  );

  fprintf(fp_out," %4d %4d %4d %3d %2d %04x \n",
                   st2,st1, za, vt, vs, ex  );

  //>>>> could also/otherwise write out the EC,EF,EN,EP lines as well,
  //>>>> see hex2tmp for their formats 
    
  return;
} //***************************************************************************


void   rd_motor (  void ) //***************************************************
{ // parse motor-status packet and write out **********************************
  int cs, st, p1, p2, amp, v14, ti, lim;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  cs   = rd_short ( scan.dat,i); i+=2; // chip-select ( 0x05= pitch, 0x09= roll )
  st   = rd_short ( scan.dat,i); i+=2; // status of operation
  p1   = rd_short ( scan.dat,i); i+=2; // pot cnts @ start
  p2   = rd_short( scan.dat,i); i+=2;  // pot cnts @ end
  amp  = rd_short( scan.dat,i); i+=2;  // motor current: 1 cnt=1mA
  v14  = rd_short( scan.dat,i); i+=2;  // volts: 1 cnt = 0.01V
  ti   = rd_short( scan.dat,i); i+=2;  // time(1cnt=0.1s) that motor ran;
  lim  = rd_short( scan.dat,i); i+=2;  // limit sw status (1=open,0=closed)
  //-----------------------------------------------------------------------
  
  
  // now write out
  sprintf(line,
  "%02x %4d %2d %6d %2d %2d %4d %4d %4d %4d %4d %02d",
    ty,  ds, dc, dp, cs, st, p1, p2,amp,v14, ti,lim );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************


void   rd_sbd (  void ) //*****************************************************
{ // parse sbd information  **********************************
  int ns, nt, tx, dt;
  unsigned long t0, t1;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  ns   = rd_short ( scan.dat,i); i+=2; // #messages sent
  nt   = rd_short ( scan.dat,i); i+=2; // #of tries
  tx   = rd_short ( scan.dat,i); i+=2; // total transmit time [s]
  t0   = rd_ulong ( scan.dat,i); i+=4;  // start ux time
  t1   = rd_ulong ( scan.dat,i); i+=4;  // end   ux time
  //-----------------------------------------------------------------------
  dt = (short) ( t1 - t0 ); // total time in sbd_surface fnx call
  
  //  write out
  sprintf(line,
  "%02x %4d %2d %6d %3d %3d %3d %4d %4lu %4lu",
    ty,  ds, dc, dp, ns, nt, tx, dt,  t0,  t1 );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************

void   rd_aca(void) //*****************************************************
{ // parse debug information  **********************************
	//int ns, nt, tx, dt;
	//unsigned long t0, t1;

	int ds, dp, dc, ty, nb;  //dive, profile #, type
	int i;
	char line[256];
	char outstr[256 + 32];

	ds = scan.surf;
	dc = scan.ncyc;
	dp = scan.pro;
	ty = scan.type;
	nb = scan.nb;

	//printf("Found CF_ACA tag, type = %02x, nb=%d\n", ty, nb);
	//i = 0;
	//parse the data structure ----------------------------------------------
	//for (i = 0; i < nb; i++)
	//{
	//	line[i] = rd_ushort(scan.dat, i); i += 2; // #messages sent
	//}
	//-----------------------------------------------------------------------


	//  write out
	fprintf(fp_out, "%02x %4d %2d %6d ", ty, ds, dc, dp);
	for (i = 0; i < nb; i++)
	{
		fprintf(fp_out, "%c", scan.dat[i]);
	}
	fprintf(fp_out, "\n");
    
  return;
} //***************************************************************************



/* status of go_pump function, as from Spray2008 pump.c code
variable st below is equal to this value
#define PUMP_WAIT     0  // pump is running...not done yet
#define PUMP_OK       1  // ran normally, stopped due to time
#define PUMP_OIL_END  2  // pump stopped, due to oil sensor
#define PUMP_AMPS     3  // pump stopped, due to high current
#define PUMP_STOP     4  // pump stopped, due to master request
#define PUMP_TMAX     5  // pump at tmax...can't run any more
#define PUMP_OFF      6  // pump is off, just handling an a/d request
*/

void   rd_hyd  (  void ) //****************************************************
{ // parse hyd-status packet and write out  ***********************************
  // this packet is written to flash at:
  // end of bottom-turn
  // end of ascent
  // after final pumping at the surface
  int st, ti, to, amp, v14, oil;
  int ma, mt, wa, vac, bad, nbad;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  st   = rd_ushort( scan.dat,i); i+=2; // status of operation (see above)
  ti   = rd_ushort( scan.dat,i); i+=2; // time[s] pump ran in last op.
  to   = rd_ushort( scan.dat,i); i+=2; // accum. pmp time [s]
  amp  = rd_ushort( scan.dat,i); i+=2; // pump current: 1 cnt=0.01A
  v14  = rd_ushort( scan.dat,i); i+=2; // volts: 1 cnt = 0.01V
  oil  = rd_ushort( scan.dat,i); i+=2; // last oil cnts;
  
  ma   = rd_ushort( scan.dat,i); i+=2; // max amps seen 1cnt=0.01A
  mt   = rd_ushort( scan.dat,i); i+=2; // time[s] of max amps
  wa   = rd_ushort( scan.dat,i); i+=2; // avg watts 1cnt=0.01watts
  vac  = rd_short ( scan.dat,i); i+=2; // vacuum reading@end  1cnt=0.01 in-hg;
  bad  = rd_ushort( scan.dat,i); i+=2; // flag=TRUE if amps>max allowed;
  nbad = rd_ushort( scan.dat,i); i+=2; // counter of #bad amps;
  
  //-----------------------------------------------------------------------
  
  
  // now write out
  sprintf(line,
  "%02x %4d %2d %6d %2d %3d %4d %4d %4d %4d %4d %3d %5d %4d %1d %3d",
    ty,  ds, dc, dp, st, ti, to,amp,v14,oil, ma, mt, wa,vac,bad,nbad );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************


void   rd_pwr  (  void ) //****************************************************
{ // parse pwr-status packet and write out  ***********************************
  // this packet is written to flash after the final surface pump,
  // and represents dive-accumulated power requirements for pitch, roll, hyd

  int w[4], t[4], e[5];
  int v7, v14;
  int j;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  for (j=0;j<4;j++)
  {  w[j]   = rd_ushort( scan.dat,i); i+=2;} // watts for hyd,pitch,roll,(unused)
  for (j=0;j<4;j++)
  {  t[j]   = rd_ushort( scan.dat,i); i+=2;}// time[s] for hyd,pitch,roll,(unused)
  v7   = rd_ushort( scan.dat,i); i+=2; // volts: 1 cnt = 0.01V
  v14  = rd_ushort( scan.dat,i); i+=2; // volts: 1 cnt = 0.01V
  for (j=0;j<5;j++)
  {  e[j]   = (unsigned char) scan.dat[i++]; } // spi err count
  
  //-----------------------------------------------------------------------
  w[3]=0; t[3]=0; // not used-blank out
  
  // now write out
  fprintf(fp_out,"%02x %4d %2d %6d ", ty,  ds, dc, dp  );
  for (j=0;j<4;j++)
    fprintf(fp_out,"%6d ", w[j]);  
  for (j=0;j<4;j++)
    fprintf(fp_out,"%4d ", t[j]);  
  fprintf(fp_out,"%5d %4d ", v7, v14  );
  for (j=0;j<5;j++)
    fprintf(fp_out,"%3d ", e[j]);  
  fprintf(fp_out,"\n");
    
  return;
} //***************************************************************************


void   rd_drift (  void ) //***************************************************
{ // parse drift packet and write out  ****************************************
  // this packet is only written if the Spray entered drift mode
  // this is a copy of what is sent back via satellite as well

  int tm, ns, p0, pa, pe, ptm;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  tm   = rd_ushort( scan.dat,i); i+=2; // drift time [minutes]
  ns   = rd_ushort( scan.dat,i); i+=2; // #of P samples taken
  p0   = rd_ushort( scan.dat,i); i+=2; // start-drift P [dBar]
  pa   = rd_ushort( scan.dat,i); i+=2; // average P [dBar]
  pe   = rd_ushort( scan.dat,i); i+=2; // end-drift P [dBar]
  ptm  = rd_ushort( scan.dat,i); i+=2; // time pumped [s] during drift
  
  //-----------------------------------------------------------------------
  
  
  // now write out
  sprintf(line,
  "%02x %4d %2d %6d %5d %4d %5d %5d %5d %4d",
    ty,  ds, dc, dp, tm, ns, p0, pa, pe, ptm );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************


void   rd_surf  (  void ) //***************************************************
{ // parse surface drift packet and write out  ********************************

  int valid[2];
  long lat[2];
  long lon[2];
  long  ti[2];
  int      ii;
  int      dx;
  int      dy;
  int      dt;
  double xx, yy;
  
  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  valid[0]   = rd_ushort( scan.dat,i); i+=2; // =1 if start-surface GPS is OK
  valid[1]   = rd_ushort( scan.dat,i); i+=2; // =1 if   end-surface GPS is OK
    lat[0]   = rd_ulong ( scan.dat,i); i+=4; // lat, 1cnt = 1e-7 deg
    lat[1]   = rd_ulong ( scan.dat,i); i+=4; // lat, 1cnt = 1e-7 deg
    lon[0]   = rd_ulong ( scan.dat,i); i+=4; // lon, 1cnt = 1e-7 deg
    lon[1]   = rd_ulong ( scan.dat,i); i+=4; // lon, 1cnt = 1e-7 deg
     ti[0]   = rd_ulong ( scan.dat,i); i+=4; // unix time start-surface
     ti[1]   = rd_ulong ( scan.dat,i); i+=4; // unix time, end-surface
    
  ii   = rd_short ( scan.dat,i); i+=2; // tmp index...ignore
  dx   = rd_short ( scan.dat,i); i+=2; // lon. drift =1m/cos(lat)
  dy   = rd_short ( scan.dat,i); i+=2; // lat. drift = 1m
  dt   = rd_short ( scan.dat,i); i+=2; // time between fixes
  
  //-----------------------------------------------------------------------
  
  
 
 
  
  // now write out
  fprintf(fp_out, "%02x %4d %2d %6d ", ty, ds, dc, dp );
  for ( i=0; i<2; i++)
  { // compute lat, lon & write out
    yy = lat[i]*1e-7;
    xx = lon[i]*1e-7;
     //printf("lon[%d] = %ul, lat[%d] = %ul\n",i,i,lon[i],lat[i]);
     //printf("xx = %ld, yy = %ld\n");
    ii = valid[i];
    fprintf(fp_out," %1d %10ld %12.6f %12.6f  ",ii,ti[i], yy,xx);
  }
  
  fprintf(fp_out," %5d %5d %4d\n", dx, dy, dt );
    
  return;
} //***************************************************************************


void   rd_abort (  void ) //***************************************************
{ // parse abort packet and write out  ****************************************
  // this packet is written in abort mode,
  // and is used to see if the Spray is on the surface.

  int pr;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[80];
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  
  pr   = rd_ushort( scan.dat,i); i+=2; // Press counts
  //-----------------------------------------------------------------------
  
  
  //  write out
  sprintf(line,
  "%02x %4d %2d %6d %5d",
    ty,  ds, dc, dp, pr );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************


void   rd_end  (  void ) //****************************************************
{ // parse the end-file packet  ***********************************************
  // this packet is written to flash just before a file is closed

  char s[4];
  int ds, dp, dc, ty;  //dive, profile #, type
  int i, j;
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  i=0;
  for (j=0;j<3;j++)
    s[j] = scan.dat[i++];  
  s[3]=0; // null char
  
  //  write out
  fprintf(fp_out,"%02x %4d %2d %6d %s\n", ty,  ds, dc, dp, s  );
    
    
  return;
} //***************************************************************************



//***Doppler functions ********************************************************
//*****************************************************************************


void   rd_adp_h (  void ) //***************************************************
{ // parse adp header packet  *************************************************

  int bd, aa, ic, nc, ce, pl, snr, ps;

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  char line[200];
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro; 
  ty = scan.type;
  
  i=0;
  //parse the data structure ----------------------------------------------
  bd   = scan.dat[i++];  // blanking distance: 1 cnt = 0.1m
  aa   = scan.dat[i++];  // alpha = attenuation coeff 1 cnt =.01 dB/m
  ic   = scan.dat[i++];  // cycle # [0..n] cycles for this surfacing
  nc   = scan.dat[i++];  // Ncell = #cells (bins)
  ce   = scan.dat[i++];  // cell size [m]
  pl   = scan.dat[i++];  // pulse length [m]
  snr  = scan.dat[i++];  // minimum snr used in processing (-1=255=not used)
  ps   = rd_ushort( scan.dat,i); i+=2; // Psurf= press cnts @last surfacing
  
  //-----------------------------------------------------------------------
  NCell = nc; // save as global...used in rd_adp
  PSurf = ps; // save as global...used in rd_adp
  if (snr>127) snr -=256; //it's a signed value
  
  //---flag potential confusion
  if ( ic != dc ) printf("ADP profile # conflict %d != %d\n",ic,dc);
  
  //  write out
  sprintf(line,
  "%02x %4d %2d %6d %5d %4d %5d %5d %5d %4d %6d %5d",
    ty,  ds, dc, dp, bd, aa, ic, nc, ce, pl,snr, ps );
    
  fprintf(fp_out,"%s\n",line );
    
  return;
} //***************************************************************************

void   rd_adp   (  void ) //***************************************************
{ // parse adp data packet    *************************************************

  int pr, he, pi, ro; 
  int num, n, v0, a0, n0;
  int jb, k, i1, i2, i3;
  int vel[3][5]; //3=3 beams, 5=max cells
  int amp[3][5]; //amplitude return : 1cnt=0.43db
  int  no[3];    //noise estimate for ea beam: 1 cnt=0.43db

  int ds, dp, dc, ty;  //dive, profile #, type
  int i;
  
  ds = scan.surf;
  dc = scan.ncyc;
  dp = scan.pro;
  ty = scan.type;
  
  num= scan.nb; //# of bytes
  n = 6 + 12*NCell;  // NCell is set in rd_adp_h...should be set
  if ( n!=num)
    printf("ADP pkt size=%d, expected %d: NCell=%d\n",num,n,NCell);
  v0 = 6; // index to 1st velocity value
  a0 = v0 + 6*NCell + 3*NCell; // index to 1st amplitude value
  n0 = a0 - 4; // index to 1st noise value
  
  i=0;
  //parse the header info -------------------------------------------------
  pr   = rd_short( scan.dat,i); i+=2;  // pressure counts
  he   = rd_short( scan.dat,i); i+=2;  // heading: 1 cnt=0.1 degree
  pi   = scan.dat[i++];  // pitch angle: 1 cnt=0.4 deg
  ro   = scan.dat[i++];  // roll  angle: 1 cnt=0.4 deg
  // dec09, make sure #'s are signed
  if (pi>127) pi = pi - 256;
  if (ro>127) ro = ro - 256;
  //-----------------------------------------------------------------------
  
  //--- parse velocity STORED AS LITTLE-ENDIAN !!!!!-----------------------
  i = v0; // point to velocity data
  for (jb=0;jb<3; jb++) //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  { // step through for each beam
    for (k=0; k<NCell; k++) //kkkkkkkkkkkkkkkkkkkkkkk
    { // read in each cell
      i1 = scan.dat[i++];  // first byte = lsb
      i2 = scan.dat[i++];  // second byte= msb
      i3 = i2*256 + i1; // total value
      if (i3>32767) i3 -= 65536; // signed value
      vel[jb][k] = i3; // store the value
    } //kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
  } //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  
  //--- parse amplitude ---------------------------------------------------
  i = a0; // point to amplitude
  for (jb=0;jb<3; jb++) //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  { // step through for each beam
    for (k=0; k<NCell; k++) //kkkkkkkkkkkkkkkkkkkkkkk
    { // read in each cell
      amp[jb][k] = scan.dat[i++]; 
    } //kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
  } //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  
  //--- parse noise  ------------------------------------------------------
  i = n0; // point to noise
  for (jb=0;jb<3; jb++) //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  { // step through for each beam
      no[jb] = scan.dat[i++]; 
  } //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  

  //--- write out ---------------------------------------------------------
  fprintf(fp_out, "%02x %4d %2d %6d %5d %5d %4d %4d", ty,  ds, dc, dp, pr, he, pi, ro );
  for (jb=0; jb<3; jb++) //===noise ===============
     fprintf(fp_out,"%3d ", no[jb]);
     
  for (jb=0; jb<3; jb++) //===amp =================
  {   for (k=0; k<NCell; k++)
        fprintf(fp_out, "%3d ",amp[jb][k] );
  }
  
  for (jb=0; jb<3; jb++) //===vel =================
  {   for (k=0; k<NCell; k++)
        fprintf(fp_out, "%5d ",vel[jb][k] );
  }
  fprintf(fp_out,"\n");
    
  return;
} //***************************************************************************



//**** END  *******************************************************************

