//*** Nortek AD2CP code for Spray controller
//*** bdj JAN 2014: initial port to CF2
// aug15: added fake nortek profile code, for debugging pitch/nortek interaction.
// oct16: added control of LED to always leave it off.
//-----------------------------------------------------------------------------

#include	<cfxbios.h>		// Persistor BIOS and I/O Definitions
#include	<cfxpico.h>		// Persistor PicoDOS Definitions

#include	<assert.h>
#include	<ctype.h>
#include	<errno.h>
#include	<float.h>
#include	<limits.h>
#include	<locale.h>
#include	<math.h>
#include	<setjmp.h>
#include	<signal.h>
#include	<stdarg.h>
#include	<stddef.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<time.h>

#include    "cf2_qsm332.h"
#include    "spi_cmd.h"
#include    "dat_fnx.h"
#include    "tcm2.h"
#include    "lifo.h"
#include    "sbe.h"
#include    "adp.h"
#include    "gpio_mux.h"
#include    "setup.h"
#include    "ntk.h"


// globals
extern char   Verbose;  // switch for displaying more info
extern char   IRQ_Flag; // interrupt flag: says what caused the interrupt
extern short  iparam [ MAX_PARAM ]; // global parameter settings
extern struct all_param all;
//=========================================================================
uchar ntk_exc; // exception status, see definitions below
//=== apr13 error exception definitions : BIT FLAGS ======================
#define   NTK_EXC_START      0x01 // means ntk_start_pro was successful
#define   NTK_EXC_STOP       0x02 // means ntk_stop_pro  was successful
#define   NTK_EXC_SW_MODE    0x04 // required a power cycle in ntk_sw_mode



//#define NTK_TO   GPS_TO
//#define NTK_FROM GPS_FROM
//-------------------------------------------------
#define N_NTK_PKT_DATA ( 16 * NTK_NCELL )        // MAX #bytes in data packet = 16*ncells = 320
#define N_NTK_PKT_BYTES ( N_NTK_PKT_DATA + 51 )  //51 bytes in header = 371
#define N_NTK_PROFILE ( 12 * ADP_NCELL )         //data bytes stored for sat = 12*5 = 60
#define N_NTK_OUT ( N_NTK_PROFILE + 6 )          // MAX #bytes for output in one scan = 65
//#define NTK_MAX_NUM (N_NTK_PKT_BYTES*2 )         //2 packets if needed = 742; round up to 1024
#define NTK_MAX_NUM 1024         // 1024 = mar13 enough for two data packets

//=== internal prototypes ===============================================
void   menu_ntk         ( void );
short  ntk_partial_wait ( void );
void   fake_ntk_pro     ( void );
//======================================================================


/*
void ntk_rs232_init(void) // ** set up serial i/o port using TPU **************
{  short ierr;      //*** open up the TPU channels as serial ports 

   // make sure that they are properly closed (ok to call if already closed)
   ierr =  TSerClose(NTK_FROM);
   ierr  = TSerClose(NTK_TO);
   
   // before opening up at the right baud rate
   ierr = TSerOpen(NTK_FROM, MiddlePrior, INP, adpInBuf,
	           NTK_MAX_NUM,9600, 'N', 8, 1); 
   if (ierr) cprintf("\n err on Nortek input chan = %d \n", ierr);
   
   ierr = TSerOpen(NTK_TO, MiddlePrior, OUTP, adpOutBuf,
	           NTK_MAX_NUM,9600, 'N', 8, 1); 
   if (ierr) cprintf("\n err on Nortek output chan = %d \n", ierr);
   

   return;
} //***************************************************************************
*/

short ntk_on(void) // turn on ntk *********************************************
{  //
  adp_on();
  
  return(1);  //value=1 means ntk is now on
} //***************************************************************************

short ntk_off(void) // turn off ntk *******************************************
{  
   adp_off();

   return(0); //value=0 means ntk is now off
} //***************************************************************************


//*****************************************************************************
void ntk_alloc(struct adp_param *adp) 
// ** allocate memory for ADP serial in/out & data
// ** may12; expanded to include post processing arrays.
{  unsigned char *buf;
   short i, n=0;
   long nbytes;
   //long nout = N_NTK_OUT; // =max #bytes per ensemble for buffer array = 65
   

   adp->pmin = 1000; // 0702 keeps track of most-shallow adp sample

   for (i=0;i<3;i++)  // amin = noise floor for each beam
     adp->amin[i] = 0; // initialize to zero

   
   adp->nscans = ADP_NSCANS; // max #scans expected
   cprintf("NTK max scans  = %d\n",adp->nscans);
   adp->iscan = 0;  // pointer to first data record
   // mar13 each stored scan = N_NTK_OUT + 16 + 4 + 10 = 65 + 30 = 95 bytes
   // if ADP_NSCANS = 140, = 13.3k
   nbytes = ADP_NSCANS * N_NTK_OUT;  // # of bytes to allocate
   //---may12 ---- add more for data processing
   // longs = tmp, uavg, vavg, wavg
   nbytes += ADP_NSCANS*16; // add space for longs
   //--unsigned shorts = pr, aavg
   nbytes += ADP_NSCANS*4; // add space for ushorts
   //-- shorts = *phi, *rol, *head, *navg, *nbsavg;
   nbytes += ADP_NSCANS*10; // add space for shorts
   
   //**allocate data buffer area
   buf = (unsigned char *) malloc(nbytes);
   if (buf == NULL)
   { cprintf("ERROR ntk_alloc\n");
   }
   adp->buf = buf; // otherwise OK, store buffer pointer
   cprintf("  NTK dat ptr = %p  nbytes = %ld End addr=%p\n", 
            buf , nbytes, buf+nbytes  );
   
   return;
}  // ** end ntk_alloc ********************************************************

short ntk_cmd_rqst(char *s) //*************************************************
{ // give command s and echo the returned info (w/o CR/LF on the end)
  //--RETURNS:
  //  0 = no reply
  //  1 = got some sort of reply
  
  short nget, i, found;
  char r[81]; // returned string
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  TURxFlush  ( tup );   // flush the tpu portr
  tputs(tup, s); // send the string
  nget = tgets(tup,r,79,1,'\n',&found); //=1st echo
     if (nget>2) {for (i=0;i<nget-2;i++) SCITxPutChar(r[i]); }  //display 1st echo
  SCITxPutChar(':');
  nget = tgets(tup,r,79,1,'\n',&found); //2nd=response
     if (nget>2) {for (i=0;i<nget-2;i++) SCITxPutChar(r[i]); } 
  cprintf("\n");
  
  return(nget>0);
} //***************************************************************************

void   ntk_set_beam(void) //map beams so can mount NTK in either dir
{ //aug14
  struct ntk_param *ntk;
  
  ntk = all.ntk; //point to the ntk structure

  if(iparam [ IA_ntk_fwd] ) //beam 1 facing fwd (DO6)
   {
    ntk->FWD = 1 - 1;
    ntk->PORT= 2 - 1;
    ntk->AFT = 3 - 1;
    ntk->STBD= 4 - 1;
    }
   else
   {
    ntk->AFT = 1 - 1;
    ntk->STBD= 2 - 1;
    ntk->FWD = 3 - 1;
    ntk->PORT= 4 - 1;
    }    
  return;
}//*****************************************************************************

short  ntk_partial_wait ( void ) //********************************************
{ // apr13: flush the serial buffer and wait to make sure that
  // no partial packet is spewing.
  // This makes sure that we're not trying to do anything 
  // during a data packet, which can give unreliable results.
  //----
  // returns n = #bytes received while waiting, max=400
 
  short n=0; // byte counter
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  TURxFlush  ( tup );   // flush the tpu port
  
  DelayMilliSecs(50);  // wait for a byte to arrive,
  
   // get bytes until xmit is finished ------------------------------
   while ( TURxQueuedCount(tup) && (n<399) )  
   {
	 n++;  	//* increment n
	 TURxGetByte(tup,FALSE);  	//* read in character
   	 if ( !TURxQueuedCount(tup) ) 	//*wait if nothing there
		DelayMilliSecs(50);
   }
  //----------------------------------------------------------------

  return(n);
} //***************************************************************************

short ntk_inq(void) //*********************************************************
{ //return which mode ntk is in
  //--RETURNS:
  //    0 = BAD,
  //   >0 actual mode
  short mode = 0;  //should never be in zero mode
  short nget, k=0,found;
  char r[81]; // returned string
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  k = ntk_partial_wait(); 
 
  DelayMilliSecs(50);
  TURxFlush  ( tup );   // flush the tpu port
  DelayMilliSecs(50);
  tputs(tup, "INQ"); // send the string
  nget = tgets(tup,r,20,1,'\n',&found); //=1st response is mode
  //   the INQ reply is a fixed format = '000x' where x=mode
  //   The following does tighter QC on the returned string:
     if (nget>4 && nget<8 ) 
     { // should be 6...
       k =sscanf(r,"000%d",&mode);    //store
       if ( k != 1) mode = 0; // if bad sscanf, make sure it is set as BAD
     }
     else
     { 
       k = ( nget>2 && nget<5 ); // aug15; either 3 or 4 ok
       // newer firmware looks like returns 3char instead of 4
       if ( k && r[0] == 'O' && r[1] == 'K' )
       { // then OK response to START cmd in SW mode
         // pass up on printing an error
         // but still returns an error
       }
       else // print what we did get
       { cprintf("BAD INQ %d:%s",nget,r); }
     }
     
    
  return(mode);    
} //***************************************************************************


//   from the 'break' doc., need to send a string w/o '/r/n' at the end
//   use tput() below instead of tputs (tput defined in sbd.c)

short ntk_brk(void) //*********************************************************
{ //send break to ntk AND goes to the command mode
  //IMPORTANT, this can hang the NTK if it is spewing data over the ser port.
  //--RETURNS the present mode,
  //  expected returned value=2= NTK_CMD_MODE
  //  any other mode means the 'MC' command failed.
  
  short mode = 0;  //should never be in zero mode
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  ntk_partial_wait(); // apr13, don't try if NTK is spewing,
  
    TURxFlush  ( tup ); // flush input buffer
    tput(tup, "@@@@@@"); // send the beginning
    DelayMilliSecs(100); // wait for a response
    tput(tup, "K1W%!Q"); // send the mid
    DelayMilliSecs(300); // wait for a response 
    tput(tup, "K1W%!Q"); // send again (dont think this is needed)
    DelayMilliSecs(300); // wait for a response
    
    //  the above 'break' gets us from measurement to the confirmation-mode
    //  however, if was in the command-mode, it stays in the command-mode.
    
    //  the following 'MC' gets us from confirm to the command mode
    //  (and is ignored if already in the command mode)
    tputs(tup, "MC"); // go to the command mode
    DelayMilliSecs(300); // wait for a response
    TURxFlush  ( tup ); // flush input buffer
    mode = ntk_inq();
    if( mode == NTK_CONFIRM_MODE ) 
     { // still in confirm-mode, try again
      tputs(tup, "MC"); // go to the command mode
      DelayMilliSecs(300); // wait for a response
      mode = ntk_inq();
     } 
  return(mode);    
} //***************************************************************************


//---mode definitions returned from ntk_inq() request-------------
//---these are defined in ntk.h
//#define NTK_UPDATE_MODE   0  // firmware-update (should never happen)
//#define NTK_MEASURE_MODE  1  // measurement 
//#define NTK_CMD_MODE      2  // command 
//#define NTK_GETDATA_MODE  4  // data-retrieval 
//#define NTK_CONFIRM_MODE  5  // confirmation 

short ntk_sw_mode(short newmode) //********************************************
{ //switch op modes.  1=measurement, 2=command, 4=data retrieval, 5=confirmation
  // presently only supports going to the command or measurement mode.
  //--RETURNS:
  //  -2 = could not get to the command mode.
  //  -1 = not legal mode
  //  else returns the present mode
  
  short mode = 0;  //should never be in zero mode
  short i=0;
  char s[24] = "Power Cycle NTK"; //string to tag cf files with
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  
  //-- first check for a legal request ----------------
  if (   (newmode == NTK_MEASURE_MODE ) 
      || (newmode == NTK_CMD_MODE     )    ) 
  {} // then mode we allow, fall through to the below code
  else { return(-1); } // illegal mode, return -1
        
  //if(newmode<1 || newmode==3 || newmode>5)return(-1); //bad mode request
  
  //-- next check to see if we are already in that mode
  mode = ntk_inq(); // get the present mode
  //cprintf("sw_1:");
  
  #if DEBUG==1
    cprintf("SW_MODE: initial mode=%d\n",mode);
  #endif
  
  
  if ( mode == newmode ) return(mode);  //already there

  //-- at this point we want to switch modes.  
  //   For simplicity, go to command mode first
  if ( mode != NTK_CMD_MODE ) //+++++++++++++++++++++++++++++++++++++++++++
   {  // then we'll need to try to switch to the cmd_mode
    
    while( mode!=NTK_CMD_MODE && i<3) //try 3x
     {
      if( mode == NTK_MEASURE_MODE || mode == 0 ) 
        // need to handle a break from sample mode differently,
        // can't send the break sequence while data is spewing.
        // also treat a bad mode the same way
        {     
          //ntk_wait_xmit(UeeGetWord(ee_ntk_sr));
          ntk_partial_wait(); //JUL13 change to this since we will have a very
                              //long time between BURST samples
        } 
         
        //cprintf("sw_2:"); // debug
        mode=ntk_brk();//send break: also goes to the command mode
        #if DEBUG==1
           cprintf("SW_MODE: send first break, mode=%d\n",mode);
        #endif
      
      DelayMilliSecs(100);    
      i++;
     }
   }//end if mode!= NTK_CMD_MODE +++++++++++++++++++++++++++++++++++++++++ 
   
   
   // apr13 add the power-cycle attempt =====================================
   if (mode != NTK_CMD_MODE ) //not in command mode, try 1x to power cycle
    {
     cprintf("pwr %s!\n",s);
     flash_store(strlen(s),(uchar*)s,CF_ACA); //tag the cf1 for later diagnosis
     ntk_exc |= NTK_EXC_SW_MODE; //set status bit = needed power cycle
     ntk_off();
     DelayMilliSecs(1000);
     ntk_on();//turn on ntk
     DelayMilliSecs(3000); //this is longer than in start_pro.
                           //trying to vary the timing
     
     mode = ntk_inq(); // get the present mode
     i=0;
     while( mode!=NTK_CMD_MODE && i<3) //try 3x
       {
         if( mode == NTK_MEASURE_MODE || mode == 0 ) 
         // need to handle a break from sample mode differently,
         // can't send the break sequence while data is spewing.
         // also treat a bad mode the same way
         {     
          //ntk_wait_xmit(UeeGetWord(ee_ntk_sr));
          ntk_partial_wait(); //JUL13 change to this since we will have a very
                              //long time between BURST samples
         }    
         mode=ntk_brk();//send break: also goes to the command mode
         DelayMilliSecs(100);    
         i++;
       } // end trying to get to CMD_MODE
       
     }  // end if mode != NTK_CMD_MODE
   //=====================================================================
   
   if (mode != NTK_CMD_MODE ) return(-2); //still cant get to command mode, 
                                          //we have problems
   
   //if we are here, then we are in command mode.
   //cprintf("sw_3:"); // debug
   if (newmode== NTK_MEASURE_MODE ) //we want to switch to measure mode
    {
     tputs(tup, "START"); // send the confirm
     
     //DelayMilliSecs(1000); // wait for a response. 750ms wait will give
                          // wrong answer at below inq request (NTK hasnt
                          // finished sending the OK
                          
     i=0;

     while( mode!=NTK_MEASURE_MODE && i<10) //try a few times
      { // FIRST TIME fails due to getting the OK response to START
       //cprintf("swi%d",i);
       mode = ntk_inq(); //see if successful
       DelayMilliSecs(50);
       i++;
      }
      #if DEBUG==1
        cprintf("tried %d cycles to get right answer from inq\n",i);
      #endif 
    }//end go to NTK_MEASURE_MODE
    
  #if DEBUG==1
    cprintf("SW_MODE: final mode=%d\n",mode);
  #endif   
  return(mode);    
} //***************************************************************************

short ntk_pwrdwn(void) //******************************************************
{ //put into lowpower mode.  This has to be issued from cmd mode
  //--RETURN
  //  2 = successful
  //  0 = failed getting to the command mode
  
  short stat;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  
  stat = ntk_sw_mode( NTK_CMD_MODE );

  if (stat== NTK_CMD_MODE ) tputs(tup, "POWERDOWN"); // send the string
  else return(0);
  
  return(stat);
} //***************************************************************************


void Transparent( void )  
{ //A Transparent path between Spray's serial COMM port and the
  //NTK.  Quits when both ends are idle for COM_to seconds.
  //Assumes the LOCAL modem is powered up and leaves it on when done.
  short COM_to, ifecho;
  char c;
  unsigned long now,tl_com;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // tpu uart port pointer for ACM/ADP
  
  /*acm_off();
  cprintf("Power Up ");fflush(stdout);
  err=acm_Power_Up(); //make sure LOC is powered up
  if (err>=0)
    cprintf("OK\n");
  else 
  { cprintf("Err=%d\n",err);
    return;
  }*/
 
  SerInFlush();  //flush Spray COMM input buffer
  cprintf("Idle channel timeout (seconds)? ");fflush(stdout);
  scanf("%d",&COM_to);
  cprintf("Local echo of Spray output (y/n)? ");fflush(stdout);
  ifecho=YesNo();

 
  TURxFlush  ( tup );   // flush the tpu port input buffer
  SerInFlush();  //flush Spray COMM input buffer
  
  //transfer bytes in both directions until neither end has transmitted
  //for tl_com seconds
  now=tl_com=RTCGetTime(0,0);
  while( (short)(now-tl_com) <= COM_to )
  { if( SCIRxQueuedCount() )
    { //xfer byte waiting at Spray COMM port to AC modem
      c = (char)SCIRxGetChar();
      TUTxPutByte ( tup, c, 0);   
      if(ifecho)SCITxPutChar(c);  //provide local echo
      tl_com=RTCGetTime(0,0);  //secs of last char from COMM
    }
   
    if( TURxQueuedCount(tup) )
    { //xferbyte waiting at AC modem to Spray COMM port
	    c = (char)TURxGetByte(tup,FALSE);  	//read in character
	    SCITxPutChar(c);
      tl_com=RTCGetTime(0,0);  //secs of last char from modem
    }
    
    now=RTCGetTime(0,0); 
  }
  cprintf("Channel has been Idle for %d seconds\n",COM_to);
  
  return;
}  //end Transparent

short   ntk_led (  short on  )  // ********************************************
{ // enable the LED (on=1), or disable (on=0), oct16
  //--RETURN
  //   0 = failed
  //  >0 = OK

  short stat=0; //default to bad return value
  short nget, found;
  char s[81]; // output string
  char r[81]; // returned string
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // tpu uart port pointer for ACM/ADP
  
  if (on) sprintf(s,"SETINST,LED=\"ON\"");
  else    sprintf(s,"SETINST,LED=\"OFF\"");

     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, s); // send the string
     nget = stat = tgets(tup,r,40,2,'\n',&found); //1ST response = OK 
     if (stat>0 && r[0]!='O') stat=0; //failed
     if (stat)
     { if (on) cprintf("LED is now ON\n");
       else    cprintf("LED is now OFF\n");
     }


     if (stat && on==0 ) //---------------------------------
     { // save if OK and it is off
       
       TURxFlush  ( tup ); // flush input buffer
       sprintf(s,"SAVE,INST");
       tputs(tup, s ); // save 
     
       nget = stat = tgets(tup,r,40,2,'\n',&found); //response = OK
       if (stat>0 && r[0]!='O') // then failed
       { stat=0; } 
       
       if (stat==0) cprintf("ERROR sent %s\n got %d:%s;\n",s, nget,r);
     } 
     //----------------------------------------------------
     
  return(stat);
} // **************************************************************************



//  need to decide at some point what we want to set and how it gets set,
//  i.e. eeprom parameters - adopt some from present ADP?
//  --I think all of these can be hard-wired ------------
short ntk_plan(short set)  //****************************
{ //get or set the plan.  set=0 get plan, set=1 set plan
  //--RETURN
  //   0 = failed
  //  >0 = OK

  short stat=0; //default to bad return value
  short nget, miburst,found;
  char s[81]; // output string
  char r[81]; // returned string
  //struct ntk_param *ntk;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // tpu uart port pointer for ACM/ADP

  //ntk = all->ntk; //point to the ntk structure
  miburst=iparam [ IA_ntk_sr ]; // =seconds per wakeup and burst sample.
  //>>> add future bounds checking after ad2cp usage settles down.
  
  if(set) //setting the plan ++++++++++++++++++++++++++++++++++++++++++
   {
    //should check bounds on plan variables here (or somewhere)
    
    //SETPLAN,CP=1,MICP=1,DICP=0,MV=15,FN="DATA.BRT"
    sprintf(s,"SETPLAN,MIBURST=%d,CP=0,BURST=1,SO=1",
                       miburst    //MIBURST = Measurement Interval, BURST mode
                       //ntk->cp,      //CP = 1/0 = Current Profile enabled/disabled
                       //ntk->burst,   //BURST = 1/0 = Burst Mode enabled/disabled (DISABLED)
                       //ntk->miburst, //MIBURST = Measurement Interval Burst Mode
                       //ntk->fn,      //FN = FileName; none specified: 'Data'=default
                       //ntk->so       //SO = Serial Output = 0/1 = disabeld/enabled
                       );
     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, s); // send the string
     nget = stat = tgets(tup,r,40,2,'\n',&found); //1ST response = OK 
     if (stat>0 && r[0]!='O') stat=0; //failed

     if (stat ) //-----------------------------------------
     { // sep13, save if  SETPLAN is OK
       tputs(tup, "SAVE,PLAN"); // save 
     
       nget = stat = tgets(tup,r,40,2,'\n',&found); //response = OK
       if (stat>0 && r[0]!='O') stat=0; //failed
       if (stat==0) cprintf("save PLAN sent %s\n got %d:%s;\n",s, nget,r);
     } else // not OK SET command
     { cprintf("setPLAN err; sent %s\n got %d:%s;\n",s,nget,r); } // print error
     //----------------------------------------------------
     
   }//end setting the values ++++++++++++++++++++++++++++++++++++++++++
  
  else //reading the plan
   {
     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, "GETPLAN"); // send the string
     nget = tgets(tup,r,79,1,'\n',&found); //1ST response = info
     //600,0,0,0,10,35,1,0,0,1500,DATA.BRT,0,0
     //MICP,CP,DICP,VD,MV,SA,BURST,MIBURST,DIBURST,SV,FN,SO,TMP
     cprintf("r=%s\n",r);

   }//end else reading the plan
  
  return(stat);
} //***************************************************************************

/*
//  mar13: ntk_cp is called at ntk_start_pro: OK
//  need to decide at some point what we want to set and how it gets set,
//  i.e. eeprom parameters - adopt some from present ADP?
//  --NC, CS = good values to control; use ee_adp_ncell, ee_adp_cellsize
//  could use more robust checking; i.e.
//   SET, Read back, and SAVE if good.

short ntk_cp(struct all_param *all,short set)  //****************************
{ //get or set the cp parameters.  set=0 get, set=1 set
  //--RETURN
  //   0 = failed
  //  >0 = OK

  short stat=0; //default to bad return value
  short nget=0, nc, pl;
  char r[81]; // returned string
  float cs;
  struct ntk_param *ntk;
  

  ntk = all->ntk; //point to the ntk structure
  nc  = UeeGetWord(ee_ntk_nc); // # of cells
  cs  = 0.1* (float) UeeGetWord(ee_ntk_cs); // cell size, [m]
  ntk->cscp = cs; //mar13 type-casting above makes sure cscp is set OK
  pl=0;  //+++ hardwire since it cant change.  May want to eventually put in eeprom
  
  if(set) //setting the values ++++++++++++++++++++++++++++++++++++++++
   {
    //should check bounds on cp variables here (or somewhere)
    
    sprintf(r,"SETCP,NC=%d,CS=%2.1f,PL=%f",
                       nc       ,      //NC = #of cells
                       ntk->cscp,      //CS = cell size
                       pl              //PL - power level: not changing even when talking
                                       //directly to NTK
                       );
     TSerInFlush(NTK_FROM); // flush input buffer
     tputs(NTK_TO, r); // send the string
     stat = tgets(NTK_FROM,r,79,1,'\n'); //1ST response = OK 
     if (stat>0 && r[0]!='O') stat=0; //failed

     if (stat ) //-----------------------------------------
     { // sep13, save if  SETCP is OK
       tputs(NTK_TO, "SAVE,CP"); // save 
     
       stat = tgets(NTK_FROM,r,79,1,'\n'); //response = OK
       if (stat>0 && r[0]!='O') stat=0; //failed
       if (stat==0) cprintf("save CP err = %s\n",r);
     } else // not OK SET command
     { cprintf("setCP err = %s\n",r); } // print error
     //----------------------------------------------------
     
   }//end setting the values ++++++++++++++++++++++++++++++++++++++++++

 else //reading the cp
   {
     TSerInFlush(NTK_FROM); // flush input buffer
     tputs(NTK_TO, "GETCP"); // send the string
     nget = tgets(NTK_FROM,r,79,1,'\n'); //1ST response = info
     cprintf("%s\n",r);
   }//end else reading the cp
   
  return(stat);
} //***************************************************************************

*/
#define NTK_NS 8 // sep13, #samples per burst, hardwired with what works best.
#define NTK_SR 8 // sep13, sample rate = rate per sample.
// the fastest we can ping is 8 Hz, so (NTK_NS*NPING)<=8

//each sample is the average of NPING pings, also hardwired here to 1,
//this way, every ping taken is recorded to allow better post-processing
short ntk_burst(short set)  //****************************
{ //get or set the burst parameters.  set=0 get, set=1 set
  //--RETURN
  //   0 = failed
  //  >0 = OK

  short stat=0; //default to bad return value
  short nget=0, nc, pl;
  short ntk_ns, ntk_sr, found;
  char s[81]; // string to send
  char r[81]; // returned string
  float cs;
  struct ntk_param *ntk;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  ntk = all.ntk; //point to the ntk structure
  nc  = iparam [ IA_ntk_nc ]; // # of cells
  cs  = 0.1* (float) iparam [ IA_ntk_cs ]; // cell size, [m]
  ntk->cscp = cs; //mar13 type-casting above makes sure cscp is set OK
  pl=0;  //+++ hardwire since it cant change.  May want to eventually put in eeprom
  ntk_ns = NTK_NS; // #samples per burst
  ntk_sr = NTK_SR; // #sample rate for ns samples
  // ntk_sr * NPING = 8 max = hardware limit
  // cprintf("ns = %d, sr = %d\n", ntk_ns, ntk_sr );
  
  if(set) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   { // set the values
    //should check bounds on cp variables here (or somewhere)
    //sep13, change resetting NPING to changing NS = #samples
    
    sprintf(s,"SETBURST,NC=%d,CS=%2.1f,PL=%d,NS=%d,NPING=1,SR=%d",
                       nc       ,      //NC = #of cells
                       ntk->cscp,      //CS = cell size
                       pl,             //PL = power level
                       ntk_ns,         //NTK_NS = #samples per burst
                       ntk_sr          //sampling rate (Hz)
                       );
     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, s); // send the string
     nget = stat = tgets(tup,r,40,2,'\n',&found); //1ST response = OK 
     if (stat>0 && r[0]!='O')stat=0; //failed

     if (stat ) //-----------------------------------------
     { // sep13, save if  SETBURST is OK
       tputs(tup, "SAVE,BURST"); // save 
     
       nget = stat = tgets(tup,r,40,2,'\n',&found); //response = OK
       if (stat>0 && r[0]!='O') stat=0; //failed
       if (stat==0) cprintf("save burst err: sent %s\n got %d:%s;\n",s,nget,r);
     } else // not OK
     { cprintf("setburst err; sent %s\n, got %d:%s;\n",s,nget,r); } // print error
     //----------------------------------------------------
     
   }//end setting the values ++++++++++++++++++++++++++++++++++++++++++
 else 
   { // reading the values
     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, "GETBURST"); // send the string
     nget = tgets(tup,r,79,1,'\n',&found); //1ST response = info
     cprintf("%s\n",r);
   } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   
  return(stat);
} //***************************************************************************

/*
// mar13; TM is not used;
// mar13 update: version that sets values to TURN OFF
// should be initialized from the menu before deployment
short ntk_tm(struct all_param *all,short set)  //****************************
{ //get or set the tm=telemetry parameters.  set=0 get, set=1 set
  short stat=0; //default to bad return value
  short nget;
  char r[81]; // returned string
  struct ntk_param *ntk;
  //float ftmp;

  ntk = all->ntk; //point to the ntk structure
  // mar13 NEXT TWO are NOT USED for NTK TM setup
  // but rather sub-sampling, averaging by spray 
  // ntk->cd=UeeGetWord(ee_ntk_tmCD);
  // ntk->pd=UeeGetWord(ee_ntk_tmDZ);
  ntk->sd = 0; //+++ hardwired off
  ntk->sa = 0; //+++ hardwired off
  ntk->cd = 0; //+++ hardwired off
  ntk->pd = 0; //+++ hardwired off
  
  if(set) //setting the cp
   {
    //should check bounds on tm variables here (or somewhere)
    
    sprintf(r,"SETTM,SD=%d,SA=%d,CD=%d, PD=%d",
                       ntk->sd,      //SD
                       ntk->sa,      //SA
                       ntk->cd,      //CD
                       ntk->pd       //PD
                       );
     TSerInFlush(NTK_FROM); // flush input buffer
     tputs(NTK_TO, r); // send the string
     stat = tgets(NTK_FROM,r,79,1,'\n'); //1ST response = OK 
     tputs(NTK_TO, "SAVE,TM"); // send the string
     stat = tgets(NTK_FROM,r,79,1,'\n'); //1ST response = OK
     if (stat>0 && r[0]!='O')stat=0; //failed
   }//end setting the cp
 // else //reading the cp
 //  {
     TSerInFlush(NTK_FROM); // flush input buffer
     tputs(NTK_TO, "GETTM"); // send the string
     nget = tgets(NTK_FROM,r,79,1,'\n'); //1ST response = info
     //
     //cprintf("%s\n",r);

     if (nget>2) //then store
      {
       stat = sscanf(r,"%d,%d,%d,%d",
                       &ntk->sd,    //SD
                       &ntk->sa,    //SA
                       &ntk->cd,    //CD
                       &ntk->pd     //PD
                       );
        }
     //cprintf("stat=%d\n",stat);DelayMilliSecs(750);               
     nget = tgets(NTK_FROM,r,79,1,'\n'); //=2nd response is OK 
  // }//end else reading the cp
  
  return(stat);
} //***************************************************************************


//   feb13 presently only read/set through menu:
//   need to decide if we want to update at all during the mission.
*/

short  ntk_clk( void )  //*****************************************************
{ // get the clk parameters: stores in ntk struct. 
  // returns the sscanf status (should be 6).
  short stat=0; //default to bad return value
  short nget,found;
  char r[81]; // returned string
  struct ntk_param *ntk;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  ntk = all.ntk; //point to the ntk structure
  

     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, "GETCLOCK"); // send the string
     nget = tgets(tup,r,79,1,'\n',&found); //1ST response = info

     if (nget>2) //then store
     {
       stat = sscanf(r,"%d,%d,%d,%d,%d,%d",
                       &ntk->yy,    //yy
                       &ntk->mm,    //mm
                       &ntk->dd,    //dd
                       &ntk->hr,    //hr
                       &ntk->mn,    //mn
                       &ntk->ss     //ss
                       );
     }
     nget = tgets(tup,r,79,1,'\n',&found); //=2nd response is OK 
  
  return(stat);
} //***************************************************************************

//   feb13 ntk_erase only called from the menu

short ntk_erase(short fid) //*************************************************
{ //erase files stored in NTK.  0=fp in PLAN, 1 = telemetry file
  short nget,found;
  char r[81]; // returned string
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  
  if(fid==0) //erasing file in PLAN
   {
    TURxFlush  ( tup ); // flush input buffer
    tputs(tup, "ERASE,CODE=9999"); // send the string
    nget = tgets(tup,r,79,1,'\n',&found); //1ST response = info    
   }//end erasing file in PLAN
  else //erase telemetry file
   {
    TURxFlush  ( tup ); // flush input buffer
    tputs(tup, "ERASETM,CODE=9999"); // send the string
    nget = tgets(tup,r,79,1,'\n',&found); //1ST response = info
   } //end erase telemetry file
   
  return(1); //should return status.  Is there a way to check filesize?
} //***************************************************************************


//   feb13, only called at start_pro for synch tag
short ntk_fwrite(char *s, short fid)//*****************************************
{ //write to files stored in NTK.  0=fp in PLAN, 1 = telemetry file
  //--RETURNS
  //  0 = failed,
  //  1 = OK.
  //  >>>may need to make sure we're back into the original mode?
  
  char r[81]; //string
  short mode;
  short status=0;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  
  //--changed from r to s in next line
  //--and changed length of r = 200 + header ~30 
  if (strlen(s)>199)return(status); //max string length is 200 bytes
  
  if(fid==0) //write tag to file in PLAN
   {
    sprintf(r,"FWRITE,FNUM=0,ID=0,STR=\"%s\"", s);
     cprintf(  "%s\n", r);
   }//end file in PLAN
  else if (fid==1)//telemetry file
   {
    sprintf(r,"FWRITE,FNUM=1,ID=0,STR=\"%s\"", s);
     cprintf(  "%s\n", r);
   } //end telemetry file
  else return(0); //0 or 1 are only valid numbers here
  
  //send the string
  mode = ntk_inq(); //store old mode, switch to cmnd if needed 
  //cprintf("FWRITE: old mode=%d\n",mode);
  if ( mode !=  NTK_CMD_MODE ) ntk_sw_mode( NTK_CMD_MODE );  
  //cprintf("FWRITE: NEW mode=%d\n",mode);
  TURxFlush  ( tup ); // flush input buffer
  tputs(tup, r); // send the string
  
  if ( mode != NTK_CMD_MODE ) ntk_sw_mode(mode);  //go back to old mode
  
  return(1); //should return status.

} //***************************************************************************

short ntk_get_sample(short type) // ********************
{ // waits for NTK sample, & stores result.  assumes ntk is on, sampling, and 
  // transmitting packets over the serial lines (PLAN.SO=1)
  //
  // type = 
  //       -1 = do not store scan 
  //        0 = store regular adp scan
  //        1 = store altimeter scan
  // returns:
  // 0 = successful
  // 1 = fail, <10 bytes read
  // 
  
  unsigned char sget[400],c;
  short i=0,nbytes=0,sr=20;
  struct ntk_param *ntk;
  long j=0;
  long nticks;    //* # of ticks to wait for 1st char
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  
  ntk = all.ntk;
  //sr=UeeGetWord(ee_ntk_sr); //seconds/sample
  sr = 8; //JUL13 hardwire to 8 seconds

        // cprintf("ntk_get_sample:\n");

  
  //flush input buffer
  TURxFlush  ( tup ); // flush input buffer
  
  //if in middle of xmission we will see a char soon
  DelayMilliSecs(50);
  
  // *** get bytes until xmission is finished
   while (TURxQueuedCount(tup) && (i<399) )  
   {
	 i++;  				//* increment i
	 c = TURxGetByte(tup,FALSE);  	//* read in character
   	 if (!TURxQueuedCount(tup) ) 	//*wait if nothing there
		DelayMilliSecs(50);
   }
  
  //JUL13 will be in powerdown mode, wake up then restart taking data
  //cprintf("brk:");
  ntk_brk();
  //cprintf("sw_mode:");
  ntk_sw_mode(NTK_MEASURE_MODE);
 
  //next transmission should start in ntk->micp seconds
   nticks = 20*(sr+1);      // = #20HZ max waits to wait for 1st char
   j=0;  //* wait up to nticks for first char
   
   //flush input buffer
  TURxFlush  ( tup ); // flush input buffer
  
   while (!TURxQueuedCount(tup) && j++<nticks )  //wait up to sr + 1 sec.
   { // wait up to nticks for the first character
	 DelayMilliSecs(50);
	 //cprintf("m1\n");
   }
   
   //read in until too many, or timed out
   while (TURxQueuedCount(tup) && (nbytes<399) )  
   {
	 sget[nbytes] = TURxGetByte(tup,FALSE);  	//* read in character
   	 if (!TURxQueuedCount(tup) ) 	//*wait if nothing there
		DelayMilliSecs(50);
	 nbytes++;
   }
  
  
  //cprintf("\NBYTES = %d, sget: \n",nbytes);
  //for(i=0;i<nbytes;i++) cprintf("%02x ",sget[i]);
  //cprintf("\n");
  
  //cprintf("store:"); // debug
  if(nbytes>10 && type >= 0)
   {
    
    ntk_store(sget,nbytes);
    if(type == 0)ntk_pack(); //pack into regular adp append buffer
    //if(type==1) -->pack into alt truncated buffer
    
    // aug15, delay to avoid spi errors
    DelayMilliSecs(1500);
    
    
    return(0); //successful
   }
  
  else return(1);
} //***************************************************************************

void ntk_wait_xmit( short sec ) // ********************************************
{ // waits for a complete NTK serial data transmission to finish.
  // If it is in a middle of a xmit, will wait for it to finish, and
  // then wait for the next complete transmission.
  // ---
  // input (sec+1) = maximum seconds to wait.
  //   if sec<0  OR sec>60, considered illegal, and sets sec=0;
  // returns: void.

  // 
  short nbytes=0,i;
  long j=0;
  long nticks;    //* # of ticks to wait for 1st char
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  
   
   i = ntk_partial_wait();
   // i = byte-count for partial xmit
   // if i>50, big enough of a snippet that 
   // we believe we caught the tail-end of a real packet.
   // if (i>50) return; 
   
   //---make sure sec is legal range
   if ( sec<0 || sec>60 ) sec=0;
   
   //next transmission should start by sec seconds
   nticks = 20*(sec+1);      // = #20HZ max waits to wait for 1st char
   j=0;  //* wait up to nticks for first char
   while (!TURxQueuedCount(tup) && j++<nticks )  //wait up to sec + 1 sec.
   { // wait up to nticks for the first character
	 DelayMilliSecs(50);
	 //cprintf("m1\n");
   }  
   
      //read in until too many, or timed out
   while (TURxQueuedCount(tup) && (nbytes<399) )  
   {
	 TURxGetByte(tup,FALSE);  	//* read in character
   	 if (!TURxQueuedCount(tup) ) 	//*wait if nothing there
		DelayMilliSecs(50);
	 nbytes++;
   }
   
   return;
} //***************************************************************************

short ntk_store(unsigned char *b,short nbytes) //*****
{ //store sample to ntk struct in memory, return stat
  //
  // 0 -> good crc, success storing
  // 1 -> bad crc
  // 2 -> didnt find sync char
  // 
  // JUL13 update for data packet version 3
  
  struct ntk_param *ntk;
  struct adp_param *adp;
  //unsigned char *abuf;  // points to place to store
  //unsigned char out[N_NTK_OUT]; //=max size of returned stream
  short idx = 0,nb=0;
  short velInc,ampInc,corrInc;
  short NB=0,ncell=0;
  short i=0,j=0;
  short stat=9; //set to fail
  ushort crc=0, crcD;
  long nout = N_NTK_OUT; //=size of one ensemble in buffer array
  
  ntk = all.ntk;  // point to the ntk structure
  adp = all.adp;  // point to adp structure
  
    // 0702 keep track of minimum pressure
  if (adp->pmin > all.dat->dbar ) adp->pmin = all.dat->dbar;
  
  while(b[idx] != 0xA5 && idx < nbytes)idx++; //find start of header
  idx++;
  if(idx==nbytes)return(2); //didnt find sync char
  
  //else read header info
  ntk->hdrSize =      b[idx++];  
  ntk->ID =           b[idx++];
  //cprintf("hdr size = %d, ID=%02x\n",ntk->hdrSize,ntk->ID);
  ntk->family =       b[idx++];
  ntk->dataSize =     ntk_rd16(b[idx++],b[idx++]);
  //cprintf("dataSize=%d\n", ntk->dataSize);
  ntk->dataChecksum = ntk_rd16(b[idx++],b[idx++]);
  ntk->hdrChecksum =  ntk_rd16(b[idx++],b[idx++]); 
 
  //--do checksum check immediately ----------------------
  
  crcD   = ntk->dataChecksum; // expected checksum
  crc = ntk_calc_CRC( (ushort*) b, ntk->dataSize,idx);
  crc = crc - crcD; // should equal 0 
  if(crc) //bad crc +++what should we do with a bad crc?
   {
    cprintf("crc = %d\n",crc); //debug
    stat=1;
   }
  
  //now get data -------------------------------------------
  ntk->version =         b[idx++];
  ntk->offsetOfData =    b[idx++];
  ntk->config =          ntk_rd16(b[idx++],b[idx++]);
  ntk->serialNumber =    ntk_rd32(b[idx++],b[idx++],b[idx++],b[idx++]);
  ntk->year =            b[idx++];
  ntk->month =           b[idx++];
  ntk->day =             b[idx++];
  ntk->hour =            b[idx++];
  ntk->minute =          b[idx++];
  ntk->seconds =         b[idx++];
  ntk->microSeconds100 = ntk_rd16(b[idx++],b[idx++]);
  ntk->soundSpeed =      ntk_rd16(b[idx++],b[idx++]);
  ntk->temperature =     ntk_rd16(b[idx++],b[idx++]);
  ntk->pressure =        ntk_rd32(b[idx++],b[idx++],b[idx++],b[idx++]);
  ntk->heading =         ntk_rd16(b[idx++],b[idx++]); 
  ntk->pitch =           ntk_rd16(b[idx++],b[idx++]);
  ntk->roll =            ntk_rd16(b[idx++],b[idx++]);
  ntk->beams_cy_cells =  ntk_rd16(b[idx++],b[idx++]);
  //cprintf("beams_cy_cells=%d\n", ntk->beams_cy_cells);
  ntk->cellSize =        ntk_rd16(b[idx++],b[idx++]);
  ntk->blanking =        ntk_rd16(b[idx++],b[idx++]);
  ntk->velocityRange =   ntk_rd16(b[idx++],b[idx++]);  
  ntk->battery =         ntk_rd16(b[idx++],b[idx++]);
  ntk->magnHxHyHz[0] =   ntk_rd16(b[idx++],b[idx++]);
  ntk->magnHxHyHz[1] =   ntk_rd16(b[idx++],b[idx++]);
  ntk->magnHxHyHz[2] =   ntk_rd16(b[idx++],b[idx++]);
  ntk->acc13D[0] =       ntk_rd16(b[idx++],b[idx++]);
  ntk->acc13D[1] =       ntk_rd16(b[idx++],b[idx++]);
  ntk->acc13D[2] =       ntk_rd16(b[idx++],b[idx++]);
  ntk->ambVelocity =     ntk_rd16(b[idx++],b[idx++]);
  ntk->DataSetDescription =       ntk_rd16(b[idx++],b[idx++]);
  ntk->transmitEnergy =  ntk_rd16(b[idx++],b[idx++]);
  ntk->velocityScaling = b[idx++];
  ntk->powerlevel =      b[idx++];
  ntk->magnTemperature = ntk_rd16(b[idx++],b[idx++]);
  ntk->rtcTemperature =  ntk_rd16(b[idx++],b[idx++]);
  ntk->error =           ntk_rd32(b[idx++],b[idx++],b[idx++],b[idx++]);
  ntk->status =          ntk_rd32(b[idx++],b[idx++],b[idx++],b[idx++]);
  //cprintf("Error = %hd, Status = %hd\n",ntk->error,ntk->status);
  ntk->ensemblecnt =     ntk_rd32(b[idx++],b[idx++],b[idx++],b[idx++]);
  

  velInc = (ntk->config & 0x20)>>5; //1 if velocity data included
  ampInc = (ntk->config & 0x40)>>6; //1 if amplitude data included
  corrInc= (ntk->config & 0x80)>>7; //1 if correlation data included
  
  ncell  = (ntk->beams_cy_cells & 0x3FF); //bits 9-0 is # of cells
  //cprintf("ncell=%d\n",ncell);
  if (ncell > NTK_NCELL) ncell=NTK_NCELL; //dont go over max alloc
  ntk->ncell = ncell; // mar13 save for packing purposes
  
  NB     = (ntk->beams_cy_cells & 0xF000)>>12; //bits 15-12 is # of beams
  //cprintf("debug idx=%d, ncell=%d,NB=%d\n",idx,ncell,NB);
  if (NB > 4)NB=4; //keep legal
  
  
  //initialize array
  for (i=0;i<NB;i++)
   {
    for (j=0;j<ncell;j++)
     {
      ntk->data_vel[i][j]=-99;
      ntk->data_amp[i][j]=-99;
      ntk->data_cor[i][j]=-99;
     }
   }
 
  if(velInc)
   {
    for (i=0;i<NB;i++)
     {
      for (j=0;j<ncell;j++)ntk->data_vel[i][j]=ntk_rd16(b[idx++],b[idx++]);
     }
   }
  //cprintf("debug idx=%d, ncell=%d,NB=%d\n",idx,ncell,NB);
  if(ampInc)
   {
    for (i=0;i<NB;i++)
     {
      for (j=0;j<ncell;j++)ntk->data_amp[i][j]= b[idx++];
     }
   }
  //cprintf("debug idx=%d, ncell=%d,NB=%d\n",idx,ncell,NB);
  if(corrInc)
   {
    for (i=0;i<NB;i++)
     {
      for (j=0;j<ncell;j++)ntk->data_cor[i][j]= b[idx++];
     }  
   }
   

  //AUG13, read velocity scaling and store in ntk->Vscale
  ntk->Vscale = 10; // default if ntk->velocityScaling = -3
  if ( ntk->velocityScaling == -4)
        { ntk->Vscale = 1;
            cprintf("Vscaling = -4: NOT EXPECTED\n"); //catch change in scaling from Nortek
            // this will alert us if scaling has changed from Jul13
        } 
        
  /*cprintf("Vel Amp Corr\n");
  for (i=0;i<NB;i++)
   {
    cprintf("Beam=%d\n",i+1);
    for (j=0;j<ncell;j++)
     {
      cprintf("%02d %04x %02x %02x\n",j,ntk->data_vel[i][j],ntk->data_amp[i][j],ntk->data_cor[i][j]);
     }
   }  */    
 
  stat=0;
  //cprintf("debug idx=%d\n",idx);
  return(stat);
} //***************************************************************************

void ntk_pack(void) //****************************************
{ //average and pack data for use in adp parsing routines

  struct ntk_param *ntk;
  struct adp_param *adp;
  short i,j,cell,beam,tmp=0;
  unsigned char *abuf;  // points to place to store
  //unsigned char out[N_ADP_BYTES]; //=max size of returned stream
  long nout = N_ADP_OUT; //=size of one ensemble in buffer array
  short navg, ncell, n_used;
  
  ntk = all.ntk;  // point to the ntk structure
  adp = all.adp;  // point to adp structure
  
  abuf = adp->buf + adp->iscan* nout ; //append  
  
  navg = iparam [ IA_ntk_tmCD ]; // # of cells to avg per output
  if (navg<1) navg=1; // set legal lower limit.
  
  ncell = ntk->ncell; // # of cells for this scan.
  if ( ncell > NTK_NCELL )
       ncell = NTK_NCELL; //dont go over max RAM alloc

  n_used = ADP_NCELL*navg; // # of input cells needed for ADP_NCELL output
  if ( n_used > ncell ) 
  { // EXCEEDED available input
    navg = ncell / ADP_NCELL; //=max averaging w/o exceeding input limit
    if (navg<1) navg=1; // make sure it is still legal
  }
  //--everything should be OK now ------------------------
  //--will average navg cells together per one output cell,
  //--and write out ADP_NCELL output cells

  
  //perform averaging

  //velocity first.  Average and shift down the values
  cell=0; // start with the first cell
  for (i=0;i<ADP_NCELL;i++)
   {
    for(beam=0;beam<4;beam++)
    {
     tmp=0;
     for (j=0; j<navg; j++)
         tmp += ntk->data_vel[beam][cell+j];
     //cprintf("i=%d,j=%d,beam=%d,cell=%d\n",i,j,beam,cell);
     ntk->data_vel[beam][i] = tmp/navg;
    }
    cell += navg;
   }
  //amplitude.  Average and shift down the values
  cell=0;
  for (i=0;i<ADP_NCELL;i++)
   {
    for(beam=0;beam<4;beam++)
    {
     tmp=0;
     for ( j=0; j<navg; j++)
          tmp += ntk->data_amp[beam][cell+j];
     ntk->data_amp[beam][i] = tmp/navg;
    }
    cell += navg;
   }
  //corr.  Average and shift down the values
  cell=0;
  for (i=0;i<ADP_NCELL;i++)
   {
    for(beam=0;beam<4;beam++)
    {
     tmp=0;
     for ( j=0; j<navg; j++)
         tmp += ntk->data_cor[beam][cell+j];
     ntk->data_cor[beam][i] = tmp/navg;
    }
    cell += navg;
   }   
  
   //begin packing data by saving hdr data
   *(unsigned short*) &abuf[0] = all.dat->ds.p;
   *(short*) &abuf[2] = all.dat->es.comp;  // compass heading
   // save pitch & roll angle at lower res of 0.25 degrees
   // which gets it into a byte format, and is certainly at/better
   // than true accuracy of the compass.
   // originally pitch/roll counts are 10 cnts = 1 degree

   abuf[4] = (char) ( all.dat->es.pitch / 4); // 1 cnt = 0.25 degrees
   abuf[5] = (char) ( all.dat->es.roll  / 4);   
   
   //Beam 1 = aft
   //Beam 2 = stbd
   //Beam 3 = fwd
   //Beam 4 = port
   
   //pack data vel1[]vel2[]vel4[]o1[]o2[]o4[]a1[]a2[]a4[] so it will
   //go through old Sontek packing functions

   //NOTE:  the physical beam number is the array index+1.  We could
   //also compact this into another for loop but Im explicitly writing
   //them out so we know what is going on.  Eventually, I see the loop
   //that conditionally increments the first array index to skip beam3.

   j=6; //skip past header
   // Beam 1
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)(  ntk->data_vel[ntk->AFT][i] & 0x00ff);
    abuf[j++] = (uchar)( (ntk->data_vel[ntk->AFT][i] & 0xff00 ) >> 8 );
   }
   // Beam 2
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)(  ntk->data_vel[ntk->STBD][i] & 0x00ff);
    abuf[j++] = (uchar)( (ntk->data_vel[ntk->STBD][i] & 0xff00 ) >> 8 );
   }
   // Beam 4
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)(  ntk->data_vel[ntk->PORT][i] & 0x00ff);
    abuf[j++] = (uchar)( (ntk->data_vel[ntk->PORT][i] & 0xff00 ) >> 8 );
   }
   //cor[Beam 1]
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)( ntk->data_cor[ntk->AFT][i] & 0x00ff);
   }
   //cor[Beam 2]
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)( ntk->data_cor[ntk->STBD][i] & 0x00ff);
   }
   //cor[Beam 4]
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)( ntk->data_cor[ntk->PORT][i] & 0x00ff);
   }
   //amp[Beam 1]
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)( ntk->data_amp[ntk->AFT][i] & 0x00ff);
   }
   //amp[Beam 2]
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)( ntk->data_amp[ntk->STBD][i] & 0x00ff);
   }
   //amp[Beam 4]
   for (i=0; i<ADP_NCELL; i++) 
   { 
    abuf[j++] = (uchar)( ntk->data_amp[ntk->PORT][i] & 0x00ff);
   }
       

  
   //point to next storage area
   adp->iscan++;
   if (adp->iscan >= adp->nscans) adp->iscan = adp->nscans - 1; //keep legal
  
 return;
} //***************************************************************************

short ntk_rd16(uchar ch1, uchar ch)//********************************************
{
 //cprintf("ch=%02x, ch1=%02x\n",ch,ch1);
 return( ch + (ch1<<8) );
} //**************************************************************************

long ntk_rd32(uchar ch3, uchar ch2, uchar ch1, uchar ch)//************************
{
 return( ch + (ch1<<8) + (ch2<<16) + (ch3<<24) );
} //**************************************************************************

ushort ntk_calc_CRC   ( ushort *pData,  ushort size, short idx )
{ // compute the checksum
  // pData points to the data,
  // size = size, in bytes 
  // idx = byte in string where to start summing
  //---mar13, below doesn't seem to work always...
  // seems like it can be off by +/-256

    ushort checksum = 0, x;
    ushort nbshorts = (size >> 1); // size/2 = #shorts
    int i;
    uchar ch,ch1;
    
    pData+=idx/2;
    
    //cprintf("CRC #bytes= %hd, pData=%02x\n", size,*pData);
    for (i = 0; i < nbshorts; i++)
    {
        //checksum += misaligned_load16(pData); 
        x  = *pData;
        ch = (x & 0xff00)>>8;
        ch1 = x & 0x00ff;
        //cprintf("x = %hx, ch=%02x, ch1=%02x\n",x,ch,ch1);
        x = ntk_rd16(ch1,ch);
        checksum += x;
        //checksum += ( (x & 0xff00) + ( (x & 0x00ff)<<8) ); 
        size  -= 2;   
        //cprintf("%d %hx %hu %hu \n", i,x, x, checksum );
        pData++; // point to next short
    }
    
    if (size > 0)
    { // odd byte on the end
        x = ((ushort)(*pData)) << 8;
        checksum += x;
    }
    
    // 0xB58C = 46476
    checksum += 0xB58C; //now should equal the returned checksum
    
    return checksum;
} //***************************************************************************

void ntk_sbd_param(void) //********************** 23APR13
{ // add the adp parameter list to the sbd message
  short n=3;
  unsigned char b[20];
  
  b[0] = 5*0x10 + 14; // flag type of data type 5, & version=14
  // b[1], b[2] = # of bytes, fill in at end
  
  b[n++]  = (unsigned char) iparam [ IA_ntk_nc ];   // # of cells to process
  b[n++]  = (unsigned char) iparam [ IA_ntk_cs ];   // cell size * 10
  b[n++]  = (unsigned char) iparam [ IA_ntk_tmCD ]; //cell averaging
  b[n++]  = (unsigned char) iparam [ IA_ntk_tmDZ ]; //subsampling in depth
  b[n++]  = (unsigned char) iparam [ IA_ntk_sr ];   //sample rate
  b[n++]  = ntk_exc; 								 //ntk status
  
  
  /**** apr14, remove the following
  // the following additions are on hold, as they are fixed.
  // calibration code output has been changed instead.
  // 0702 added the rest of ADP params; presently are fixed variables.
  //		this should make the 'B' line a complete parameter list.
  b[n++]  = (unsigned char) K1_ABS; // added back-scatter processing info
  b[n++]  = (unsigned char) K2_ABS; // added back-scatter processing info
  b[n++]  = (unsigned char) BD; // added blanking distance
  b[n++]  = (unsigned char) ALPHA; // added absorption factor
  /****/
  
  b[n++] = ';'; // tack on the end data character
  
  // n= total # bytes written out
  // which gets stored after the sensor id byte:
  // aug03 removed (char) type-casting below
  b[1] =  ( n & 0xff00 ) >> 8; // = MSB
  b[2] =  ( n & 0xff ); // LSB
  
  // append_lifo(all,n, b );  // tack onto end of lifo
  new_msg_lifo(n, b );  // create new lifo
  // 0702, start with a new message for ADP
  //		all ADP data will end up in it's own message this way
  //		so the 'B' info 

  //==== apr14, add in storing the header info to flash===================
  // store info to flash as well, so post-processing =====================
  // doesn't have to look up elsewhere
  b[0] = BD; // blanking distance
  b[1] = ALPHA; // alpha used in calcs
  b[2] = all.ncyc;
  n--; // throws way the ';'
  //store the min press, used in post-process for surface
  n = b2_store(n, b, all.flt->pmin ); 
  flash_store( n, b, CF_ADP_H ); 
  //=====================================================================

  return;
} //***************************************************************************

// ntk_start_pro called once at the start of ascend (mimics old ADP code)
//   for day test, we will turn it on earlier (what the heck)
// calling fnx has to decide what to do if start-up was bad
// i.e. set status flags, and turn off the ad2cp

//>>>there is no equivalent of set_params for each dive; ok for day-test,
//   but will need more for a real mission.

short ntk_start_pro(void) //**********************************
{ //turn on the NTK and begin taking data
  //--RETURNS:
  //  0 = failed,
  //  NTK_MEASURE_MODE = if succeeded.
  
 short status=0;
 short i=0;
 char s[81]; //string to tag files with
 
 #if DEBUG ==1
         cprintf("ntk_start_pro:\n");
 #endif
 
 
 ntk_exc = 0; //23APR13 init status byte
 ntk_set_beam(); //aug14
 ntk_on();    //turn on ntk
 DelayMilliSecs(750); //let it do startup stuff
  
 while(i<3 && status!= NTK_CMD_MODE ) //try 3x to get to command mode
  {
   status = ntk_sw_mode( NTK_CMD_MODE );
   DelayMilliSecs(100);
   i++;
  }
 
 if (status !=NTK_CMD_MODE)return(0); //something wrong, cant get to cmd mode, bailout
 // if bails out here, then ntk_exc bit0=0 = failure
 
 //setup PLAN & BURST parameters
  ntk_plan(1);
  ntk_burst(1);
 
 //tag files 
 sprintf(s,"DIVE!%04d!%ld",iparam [ EA_prof_num ],RTCGetTime( 0, 0));
 ntk_fwrite(s,0); //tag the binary PLAN file
  DelayMilliSecs(300);
  // mar13, remove the TM file write, as being hard-coded NOT to do TM
 //  ntk_fwrite(s,1); //tag the TM file
 flash_store(strlen(s),(uchar*)s,CF_ACA);
 
 status=0;
 status=ntk_sw_mode( NTK_MEASURE_MODE ); //switch to measurement mode
 // above starts the data acquisition
 
 ntk_exc |= NTK_EXC_START; //set status bit that we started up OK.
 
 return(status);
} //***************************************************************************

short ntk_stop_pro(void) //**********************************
{ // stop taking data.  Leaves power on to the NTK 
  // Returns:
  //   0 = error
  //   NTK_CMD_MODE = successfully got to the command mode.
 short status=0;
 short i=0;
 char s[81]; //string to tag files with
 
 while(i<3 && status!= NTK_CMD_MODE ) //try 3x to get to command mode
  {
   status = ntk_sw_mode( NTK_CMD_MODE );
   DelayMilliSecs(100);
   i++;
  }
 
 if (status != NTK_CMD_MODE) //something wrong, cant get to cmd mode,turn off & bailout
  { ntk_off();return(0);}
   // this leaves the ntk_exc bit 0x02=0 = stop failed
 //tag files.  NTK doesnt like . or , or : in the str
 sprintf(s,"END!%04d!%ld",iparam [ EA_prof_num ],RTCGetTime( 0, 0));
 ntk_fwrite(s,0); //tag the binary PLAN file
  DelayMilliSecs(300); //had to slow it down here.  maybe send as 1 line to both
                       //files like a scripts???  TODO                     
 //ntk_fwrite(s,1); // mar13, remove the TM file write, as being hard-coded NOT to do TM
 flash_store(strlen(s),(uchar*)s,CF_ACA);
 
 ntk_pwrdwn();
 DelayMilliSecs(500); //give it time to power down
 ntk_off();
 
 ntk_exc |= NTK_EXC_STOP; //set status bit = successful stop
  
 return(status);
} //***************************************************************************


//===aug13 addition for altimeter processing ==================================
#define NTK_ALT_NCELL 15   // #of cells for altimeter
#define NTK_ALT_CS    2.0  // cell size
short ntk_alt_start ( void )  //******************************
{ 
  // Turn on the nortek ad2cp
  // setup up the ad2cp for collecting altimeter data,
  // and start collecting data
  // ------------
  //--RETURN
  //   0 = failed
  //  >0 = OK

  short stat=0; //default to bad return value
  short nget=0, nc,  i, found;
  char r[81]; // returned string
  float cs;
  char s[81]; //string to tag files with
  struct ntk_param *ntk;
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer
  

  ntk = all.ntk; //point to the ntk structure
  ntk_set_beam(); //aug14
  all.adp->on_adp = ntk_on();    //turn on ntk
  DelayMilliSecs(750); //let it do startup stuff
  
  i=0;
  while(i<3 && stat!= NTK_CMD_MODE ) //try 3x to get to command mode
  {
    stat = ntk_sw_mode( NTK_CMD_MODE );
    DelayMilliSecs(100);
    i++;
  }
 
  if ( stat != NTK_CMD_MODE) 
    return(0); //something wrong, cant get to cmd mode, bailout

 
  ntk_plan(1); //uses the same PLAN settings as profile-mode
  DelayMilliSecs(300);
  //--- Setup the BURST mode
  //--- hardwire for the best values for the altimeter
  nc  = NTK_ALT_NCELL; // # of cells
  cs  = NTK_ALT_CS; // cell size, [m]
  // this gives a 30m range for the altimeter.
  
    
    sprintf(s,"SETBURST,NC=%d,CS=%2.1f,PL=0.0,NS=1,SR=8",
                       nc       ,      //NC = #of cells
                       cs              //CS = cell size
                       //NS=1 for altimeter = 1 sample per burst
                       );
     TURxFlush  ( tup ); // flush input buffer
     tputs(tup, s); // send the string
     nget = stat = tgets(tup,r,40,2,'\n',&found); //1ST response = OK 
     // do NOT save the settings, so profile settings are not disturbed.
     
     if (nget>0 && r[0]!='O') stat=0; // did not get an 'OK'
     if (stat==0) cprintf("alt setburst; sent %s\n err = %d:%s;\n",s,nget,r);
 //tag the ad2cp 
 sprintf(s,"ALT!%04d!%ld",iparam [ EA_prof_num ],RTCGetTime( 0, 0));
 ntk_fwrite(s,0); //tag the binary PLAN file
 DelayMilliSecs(300);

 
 stat = ntk_sw_mode( NTK_MEASURE_MODE ); //switch to measurement mode
 // above starts the data acquisition
 

 return (stat);
} //***************************************************************************


short ntk_altimeter ( void ) //*******************************
{ // gets an altimeter reading from the Nortek ad2cp: aug13
  // ------
  // RETURNS meters above the bottom
  // 80 = no bottom detect
  // 85 = no response at all from the ad2cp
  // 
  short stat=0;

  stat = ntk_get_sample( 1); // get a response: '1' = altimeter; don't save to profile space
  
  if (stat !=0 )
  { // then we never got a response
    all.adp->alt_db = 0; 
    all.adp->alt_z0 = 85; // set an error value for the engineering message
    return(85); // and return
  }
    
  // we're here because we have valid data, try to find the bottom!
  stat = process_ntk_alt(); //distance to the bottom: 80=none seen.
  all.adp->alt_z0 = stat; // save value for the engineering message
  
  return (stat);
} //***************************************************************************


#define NTK_DB_MAX 130 // in counts: 130 = 65 dB.
#define NTK_DDB 30 // in counts: 30 counts = 15 dB jump
#define NTK_KC0  3 // start at cell #3
short process_ntk_alt ( void ) //*****************************
{ // take the nortek data & try to find the bottom
  // return meters from the bottom,
  // 80 = no bottom detected
  short iz=80, tmp, ithr, iddb, zbot[4], dz1, dz2;

  // reset threshold values from the above default values
  // this option is never used, but might come in handy if the 
  // behavior in the field says it needs a different sensitivity.
  tmp  = iparam [ IA_use_alt ]; // can be changed from shore
  tmp  = ( tmp & 0xff00 ) >> 8; // msb, contains new threshold and diff-db info
  ithr = ( tmp & 0xf0 ) >> 4; // msnibble = threshold
  iddb = ( tmp & 0x0f ); // lsnibble = diff-db
  ithr = 120 + ithr*10;  // range = 120..250
  if (ithr<121) ithr = NTK_DB_MAX; // if val=0, then use the above default
  iddb = 10 + iddb*3; // range = 10..55
  if (iddb< 11) iddb = NTK_DDB; // if val=0, then use the above default
  cprintf("Using threshold = %d, diff-threshold= %d \n",ithr, iddb);
  	
  //beam  1 OR 3 = forward looking beam = index 0 or 2
  //beams 2 and 4 look sideways = indices 1, 3
  zbot[0] = find_ntk_alt( iddb, ithr, all.ntk->FWD );
  //--can falsely detect the bottom if it is just a fish hit.
  if (zbot[0]<80 ) //============================================
  { // fwd beam detects the bottom: check the 2 side-beams
    zbot[1] = find_ntk_alt(iddb, ithr, all.ntk->STBD); //side-beam
    zbot[2] = find_ntk_alt(iddb, ithr, all.ntk->PORT); //side-beam
    // when descending:
    // fwd beam is looking 30deg fwd,
    // side beams looking 17deg aft
    // for a bottom 30m away, flat bottom,
    // fwd beam path =  35m, side-beam path = 31m
    // for a sloping bottom, can be disagreement on distances to bottom.
    dz1 = abs( zbot[1] - zbot[0] );
    dz2 = abs( zbot[2] - zbot[0] );
    //if ( dz1<10 || dz2<10 ) 
    if ( zbot[1]<80 || zbot[2]<80 ) //much-less strict
    { // then at least 2 beams agree seeing the bottom!
      iz = zbot[0];  // this is the one we will believe
    }
  } //===========================================================
  

  return(iz);
} //***************************************************************************

short find_ntk_alt( short iddb, short ithr, short ib )
{ //***************************************************************************
  // search the ib beam data for the bottom
  // ib = 0..3 = beams 1-4, beam 3=looks fwd, 2,4 side-ways.
  // iddb = threshold change in amplitude [counts]
  // ithr = max amp. [counts] used to discern the bottom.
  // ------
  // return the distance to the bottom
  // 80 = no bottom detected
  
  short iz = 80, k;
  float z, db, zb=0, dbm,dd, max_db=0;
  struct ntk_param *ntk;
  ntk = all.ntk;  // point to the ntk structure

  if (ib<0 || ib>3 ) return(80); // out of bounds
  
  //---the data is in the ntk->data_amp[ibeam][jcell] array
  z = NTK_KC0*NTK_ALT_CS; // distance to the cell prior to the first cell
  dbm = ntk->data_amp[ib][NTK_KC0 -1]; // first return value
  
  //===================================================================
  for ( k=NTK_KC0; k<NTK_ALT_NCELL; k++)
  {  // check each cell
     z += NTK_ALT_CS; // this cell's location
     db = ntk->data_amp[ib][k]; // = intensity
     if (db>max_db) max_db = db; // keep track of maximum value
     
     dd = db - dbm; // = jump in intensity
     if ( dd >iddb  || db >ithr ) // big jump from the running mean
     {  // we think it sees the bottom!
        zb = z; // save altimeter value
        max_db = db; // and the value of the bottom-detect
        break; // break out of the for loop
     } // end if we think we detected the bottom
     
     // else compute a new weighted average of the return
     dbm = dbm*0.6 + db*0.4; // new weighted average
     // hopefully the weighted mean will help detect a ramp-up in depth
  } //=================================================================
  
  if (zb>1) iz = (short) zb; // set value to return
  // else iz = 80
  
  if (ib == 2) // fwd-looking beam, save the value
     all.adp->alt_db = max_db; 
  //it is transferred over in bottom_turn

  return (iz);
} //***************************************************************************


void   fake_ntk_pro ( void ) //************************************************
{ // set up to test nortek profile mode
  // aug15, in particular, for SPI conflicts with Nortek
  char ch = ' ';
  int   i =  0;
  ulong tnow;   // present time
  short   dt;

  tnow = RTCGetTime(0,0);  // get the present time
  dt   = SAMP_DT_UP;    // 0903 feb11: time between samples for ascent
  
  // initialize settings
  //Verbose = 1; // force to verbose
  all.dat->sbe_pro_on = 1;  // set up to profile
  all.dat->take_adp   = 1; // we want to take adp
  all.dat->p_adp      = 1000; // take data
  all.adp->on_adp     = 0;  // start with adp off
  
  flash_open('D'); // open a new  file (adds a dive mark )
  
  while ( ch != 'X' && ch != 'x' && i++<500 ) //=======================
  { // keep collecting until we see an X or x, or 500 samples
    hibernate( &tnow, dt, PIT_IRQ2 );  // updates tnow
    all.dat->p_adp  = 1000; // take data
    take_data();
    ch = SCIRxGetCharWithTimeout( 100 ); // get a new character
    SerInFlush();
  } //=================================================================
  
  flash_close();
    
  return;
} //***************************************************************************

void test_ntk( void )  //***test above functions ***************
{ char ch=' ';
  short adp_pwr_on;  // =true if adp is on, false if it is off
  short status, n, reply,tmo=0;
  short adp_stat=0, ib, found;
  char r[81]; // returned string
  struct ntk_param *ntk;
  struct adp_param *adp;
  //unsigned char *abuf;
  //char *sptr; // mar13 stack pointer
  TUPort    *tup;

  tup = all.tu_port[TU_ADP].tup;  // correct tpu uart port pointer

  
  ntk = all.ntk;
  adp = all.adp;
  ntk_set_beam(); //aug14
  cprintf("\nNTK %s \n",__DATE__);
  cprintf(" Select operation to perform  :\n");
 
  adp_pwr_on = ntk_off();

  menu_ntk();
  while ( ch !='Q')
  {
	SerInFlush();  // flush any characters
            if (ch !=' ' && ch>0 ) 
            cprintf("V_1>\n"); // display directory prompt
	    ch = -1; // illegal value - means it timed out
	    ch = SCIRxGetCharWithTimeout( 1000 ); // get a new character
	    tmo = check_tmo ( &ch, tmo );
	    // increments the tmo counter if ch<0, and
	    // goes to sleep mode after max_tmo.  Returns *ch as upper-case
	    
    switch (ch) { // call the desired function
        case 'Q' : break;  // will quit the program
        case '?' :  break; // causes directory prompt to be displayed
        case 'U' : menu_ntk(); break;
        case  -1 :  break; // wait for another character
          		   
        case 'W' : // turn on adp
            ntk_set_beam(); //aug14
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
			TURxFlush  ( tup ); // flush input buffer
			DelayMilliSecs(1000); // wait for a response
			n = tgets(tup,r,79,1,'\n',&found);
			ib = 0; // count lines
			if(n)
			 { // something is spewing out
			  cprintf("%s",r);
			  while (   TURxQueuedCount(tup) && ib<10 )
			   { n = tgets(tup,r,79,1,'\n',&found);
			     cprintf("%s",r);
			     ib++; // aug15, keep upper limit on #lines
			   }
			  }  
			else  cprintf("NOT responding\n");
			break;  // turn on adp		
        case 'I' :  // inquire which mode we are in
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
			cprintf("In mode %d\n",ntk_inq());  
			break;  // inquire mode
	    case 'B' :  // issue a break
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
			cprintf("Send BRK: ");
			cprintf("In mode %d\n",ntk_brk());  
			break;  // inquire mode
        case 'O' : // turn off
            ntk_led(0); // oct16, make sure LED is disabled.
			adp_pwr_on = ntk_off();  
			cprintf("NTK is off\n");
			break;  // turn off adp   
		case 'P' : // set/get plan
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
		    cprintf("0->Get plan, 1->Set plan :");
	        n = get_num(&reply);
	        if(reply==1) //set new values for cp
	         { cprintf("Loading values from EEPROM (change there if needed)\n");
	         }//end if reply
	        else reply=0;
			status = ntk_plan(reply);  
			//cprintf("\nstatus=%d\n",status);
			cprintf("PLAN:\n");
			cprintf("Profile interval in seconds : %3d\n",iparam [ IA_ntk_sr ]);
			break;  // plan
/*		case '1' : // set/get CP
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
		    cprintf("0->Get cp, 1->Set cp :");
	        n = get_num(&reply);
	        if(reply==1) //set new values for cp
	         { cprintf("Loading values from EEPROM (change there if needed)\n");
	         }//end if reply
	        else reply=0;
			status = ntk_cp(all,reply);  
			//cprintf("\nstatus=%d\n",status);
			cprintf("CP:\n");
			cprintf("# of cells : %3d\n",UeeGetWord(ee_ntk_nc));
			printf("cell size  : %3.1f\n",ntk->cscp); fflush(stdout);
			//printf("power level: %3.1f\n",ntk->plcp); fflush(stdout);
			break;  // CP*/
		case '2' : // set/get BURST
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
		    cprintf("0->Get BURST, 1->Set BURST :");
	        n = get_num(&reply);
	        if(reply==1) //set new values for BURST	
	         { cprintf("Loading values from EEPROM (change there if needed)\n");
	         }//end if reply
	        else reply=0;
			status = ntk_burst(reply);  
			//cprintf("\nstatus=%d\n",status);
			cprintf("BURST:\n");
			cprintf("# of cells : %3d\n",iparam [ IA_ntk_nc ]);
			printf("cell size  : %3.1f\n",ntk->cscp); fflush(stdout);
			//printf("power level: %3.1f\n",ntk->plcp); fflush(stdout);
			break;  //BURST
/*		case 'T' : // set/get Telemetry
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
		    cprintf("0->Get TM, 1->Set TM (FORCE TO ALL OFF) :");
	        n = get_num(&reply);
	        if(reply==1) //set new values for TM
	         {
	         }//end if reply
	        else reply=0;
			status = ntk_tm(all,reply);  
			//cprintf("\nstatus=%d\n",status);
			cprintf("TM:\n");
			cprintf("Store data descend : %3d\n",ntk->sd);
			cprintf("Store data ascend  : %3d\n",ntk->sa);
			cprintf("Cells divisor      : %3d\n",ntk->cd);
			cprintf("Packets divisor    : %3d\n",ntk->pd);
			break;  // TM */
		case 'C' : // set/get Clock (set not implemented yet)
			status = ntk_clk();  
			cprintf("CLK: %02d-%02d-%04d, %02d:%02d:%02d\n",
				     ntk->dd, ntk->mm, ntk->yy,
				     ntk->hr, ntk->mn, ntk->ss);
			break;  // clock
	    case 'S' : //switch op mode
	        cprintf("GOTO what mode (1 or 2):");
	        n = get_num(&reply);
			n = ntk_sw_mode(reply);  
			cprintf("In mode %d\n",n);
			break;  //switch op mode
		case 'E' : // erase files
		    cprintf("0->Erase PLAN FP, 1->Erase TM FP :");
	        n = get_num(&reply);
	        ntk_erase(reply);
	        //if(ch=='0' || ch=='1') //erase
	        // {
	         // cprintf("\nARE YOU SURE(Y/N)? ");
	         // if (YesNo() ) ntk_erase(reply);
	         // cprintf("\n");
	        // }//end if reply
	        break;
	    case 'F' : // write to files
		    cprintf("0->PLAN FP, 1->TM FP :");
	        n = get_num(&reply);
	        ntk_fwrite("2222",reply);
			break;  // erase
		case 'L' : // turn on LED
            ntk_led(1);     // oct16, enable for bench tests.
			break; 
			
		case '3' : //Powerdown
			n = ntk_pwrdwn();  
			break;  //powerdown
/*	 	case '4' : //for testing only
	 	    status=30; //start with 30s wait
	 	    while(1)
	 	    {cprintf("Begin Cycle\n");
             adp_stat = ntk_start_pro(all);
             cprintf("adp_stat=%d\n",adp_stat);
             if (adp_stat == 0) //,,,,,,,,,,,,,,,,,,,,,,,,
             { // start-up failed !
               all->adp->on_adp   = ntk_off(); // turn off
               all->dat->take_adp = FALSE; // don't take adp data
             }
             else //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
             { // it started up OK, set flags
               all->adp->on_adp   = TRUE; // it is on
               all->dat->take_adp = TRUE; // we are taking data
             } //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

           // #sleep for 30-42 seconds (should get a few scans)
           cprintf("Delay %ds\n",status);
           for (n=0;n<status;n++)DelayMilliSecs(1000);
           status++;
           if(status>43)status=30; //go back to 30s wait

           if (all->dat->take_adp) //=============================
            { // sampling data: stop, collect data & store
              cprintf("attempting to stop ntk\n");
              adp_stat=ntk_stop_pro(all);
              cprintf("adp_stat=%d\n",adp_stat);
              all->dat->take_adp   = FALSE; // quit taking doppler
            } //================================================

           } //end while 
	 	    break;
	 	case '5' :
	 	    cprintf("ms to wait");
	        n = get_num(&reply);
	        ntk_sw_mode(1);
	        ntk_get_sample(all,0);
	 	    DelayMilliSecs(reply); // wait for a response 	    
	 	    ntk_brk();
	 	    Transparent();
	 	    break;
*/
	 	case '5' :
	 	    //run the ctd+optical+nortek ascent profile code
	 	    fake_ntk_pro();  // aug15
	 	    break;
	 	case '6' :
	 	    //load up the adp buffer, CALL GET SAMPLE FIRST (Case=G)
	 	    adp->iscan=0;
	 	    for (n=0;n<ADP_NSCANS;n++)
	 	     {
	 	      all.dat->ds.p = (1020-(4*n))/0.04;
	 	      ntk_pack();
	 	      //adp->iscan++; //this is done in ntk_pack()
	 	     }
	 	    break;
        case '7' : // Post-process for Iridium message
			//all->klifo = assign_lifo(all->lifo,1,0);
			cprintf("calling post-process\n");
			//sptr = (char *) GetStackPtr();
			//cprintf("stack ptr = %p  \n", sptr );
			adp_post_process();
			break;
		case '8' : // aug13 Altimeter setup
			n = ntk_alt_start(  );  
			cprintf("NTK altimeter mode set up ");
			if (n>0) cprintf("OK\n");
			else cprintf("BAD\n");
			break; 
			
		case '9' : // aug13 Get altimeter
			n = ntk_altimeter(  );
			cprintf("NTK altimeter value = %d\n",n);  
			break; 
			

		case 'X' : //talk direct to NTK
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
			Transparent();  
			break;  //
		case 'Y' : //start profiling
			n = ntk_start_pro(); 
			if(n<1) cprintf("Start Pro FAILED, n=%d!\n",n);
			else cprintf("n=%d\n",n);
			break;  //powerdown
		case 'Z' : //stop profile and turn off
			n = ntk_stop_pro();  
			if(n<1) cprintf("Stop Pro FAILED, n=%d!\n",n);
			else cprintf("n=%d\n",n);
			break; 
        case 'G' : // get a sample
            if(iparam[IA_ntk_fwd] ) //beam 1 facing fwd (DO6)
              cprintf("EEPROM thinks Beam 1 is FWD/serial cable pointing AFT\n");
            else
              cprintf("EEPROM thinks Beam 1 is AFT/serial cable pointing FWD\n");
			if (!adp_pwr_on) adp_pwr_on=ntk_on();
            adp->iscan=0;
			n = ntk_get_sample(0);
			//cprintf("G status = %d  ",n);
			if (n!=0) { cprintf("BAD "); }
			cprintf("OK ");
			//adp_dump(all);
			//parse_last(all);
			
			//abuf =  adp->buf;
			//cprintf("AMP1 = %4d; ",abuf[6 +  9*ADP_NCELL]);
			//cprintf("AMP2 = %4d; ",abuf[6 + 10*ADP_NCELL]);
			//cprintf("AMP4 = %4d; ",abuf[6 + 11*ADP_NCELL]);
			
			cprintf("\n    AFT  STBD   FWD   PORT\n");
			cprintf("a= %4d  %4d  %4d  %4d\n", 
			        all.ntk->data_amp[all.ntk->AFT ][3],
			        all.ntk->data_amp[all.ntk->STBD][3],
			        all.ntk->data_amp[all.ntk->FWD ][3],
			        all.ntk->data_amp[all.ntk->PORT][3]);
			cprintf("v= %4d  %4d  %4d  %4d\n", 
			        all.ntk->data_vel[all.ntk->AFT ][3],
			        all.ntk->data_vel[all.ntk->STBD][3],
			        all.ntk->data_vel[all.ntk->FWD ][3],
			        all.ntk->data_vel[all.ntk->PORT][3]);
			cprintf("\n");
						
			break;  
        default  : cprintf(" input unknown \n");
    } // end switch
  }  //*** end while 

   ntk_off();  // make sure adp is off
   cprintf("NTK is off\n");
   
   return;
}  // end test_NTK ***************************************************

void menu_ntk(void)
{ //print out menu selections *****************************************
 cprintf("    NTK MENU   :  Q.uit NTK test :  U.pdate menu\n"
        "O.ff ADP       :  I.NQ           :  S.witch mode \n" 
        "W.akeup ADP    :  B.REAK         :  P.lan\n"
        "2.BURST Param  :  T.M OFF        :  \n"
        "C.lock         :  E.rase file    :  F.write\n"
        "G.et Sample    :  X.Talk to NTK  :\n"
        "3.PwrDwn       :  Y.start pro    :  Z.stop pro\n"
        "8.Altim Setup  :  9.Get Altim    :  5.Fake profile\n"
        "L.ED ON \n"
       );
 return;
} //*****end menu ****************************************************
