/******************************************************************************
//	cfxmain.c				Persistor and PicoDOS starter C file  
//	
//*****************************************************************************
//	
//	Oct2008, updated for the Main Spray PCB, v1.0
//
//	
// dec11, force op_mode=1 on ANY power reset, and assume the user
// will ensure it doesn't go forward with restarting the mission.
//
// nov13, force argos off when user responds at reset:
// The gpio-msp430 turns on argos whenever it is reset (also when it resets the CF2)
// so now the CF2 must turn it off manually. 
//
// jan16, define global NV-ram for profile, surface counters.
//
//*****************************************************************************
//
//==== Future Expansion =======================================================
//		last update: Jan2009
//	1. 
//  2. diagnostic menu, for other tests
//  3. initialization of the parameters
//  4. install ISR's for all interrupt vectors
//
*******************************************************************************/

#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	<Max146.h>		// MAX146/147 SPI A-D QPB Driver 
#include	<cfxad.h>		// Generic SPI A-D QPB Driver for CFx

#include	<dirent.h>		// PicoDOS POSIX-like Directory Access Defines
#include	<dosdrive.h>	// PicoDOS DOS Drive and Directory Definitions
#include	<fcntl.h>		// PicoDOS POSIX-like File Access Definitions
#include	<stat.h>		// PicoDOS POSIX-like File Status Definitions
#include	<termios.h>		// PicoDOS POSIX-like Terminal I/O Definitions
#include	<unistd.h>		// PicoDOS POSIX-like UNIX Function Definitions
*/

#include    "cf2_qsm332.h"
#include    "spi_cmd.h"
#include    "tcm2.h"
#include    "pitch_roll.h"
#include    "gpio_mux.h"
#include    "pump.h"
#include    "dat_fnx.h"
#include    "gps.h"
#include    "nav.h"
#include    "sbd.h"
#include    "adp.h"
#include    "sbe.h"
#include    "lifo.h"
#include    "pplus.h"
#include    "miss_fnx.h"
#include    "setup.h"
#if BENTHOS==1 || NPS==1
  #include    "BenthCF2.h"     // Benthos Acoustic Modem
#endif
#if PH==1
  #include    "ph.h"  //ph sensor
#endif
#if NTK ==1
  #include    "ntk.h" //Nortek AD2CP
#endif
#if ZOOG ==1
  #include    "zooCam.h"
#endif

// definitions ----------------------------------------------------------------
#define	SCI_BAUD	9600L				// whatever is appropriate
// system clock is HIGH_CLOCK_SPEED defined in setup.h
#define	WTMODE		nsStdSmallBusAdj	// choose: nsMotoSpecAdj or nsStdSmallBusAdj
#define SCIWAIT		900					// # of milli-secs to wait btwn char before timeout

// globals --------------------------------------------------------------------
char Verbose  =0; // for diagnostics, can turn on/off more info
char IRQ_Flag =0; // flag, whose value determines what caused the interrupt
struct all_param     all;
short iparam [ MAX_PARAM ]; // global parameter settings MAX_PARAM
// jan16, moving Surf_N, Prof_N from eeprom to non-volatile RAM
//below are only used in param.c, so declared there.
//ulong NvRamSurf_N : 0xC010; // force addr at bottom of stack for Surf_N
//ulong NvRamProf_N : 0xC014; // ditto for Prof_N
#if BENTHOS==1 || NPS==1
    short TSerInUse;  //GLOBAL =1 if TSerial port of TPU is in use, else 0
                    //Used to prevent code from changing System clock or turning off
                    //the oscillator or TPU in low power states.To do so messes up 
                    //TSerial interrupt servicing and baud rates.
    struct acm_command modem_cmd_str;//Global modem command string
#endif
#if PH==1
    short TSerInUse;  //GLOBAL =1 if TSerial port of TPU is in use, else 0
                    //Used to prevent code from changing System clock or turning off
                    //the oscillator or TPU in low power states.To do so messes up 
                    //TSerial interrupt servicing and baud rates.
#endif
// prototypes -----------------------------------------------------------------
void     main_menu      ( void );
IEV_C_PROTO   ( Spur_ISR  );	// interrupt service routine prototype
IEV_C_PROTO   ( Irq2_ISR  );	// interrupt service routine prototype
IEV_C_PROTO   ( Irq4_ISR  );	// interrupt service routine prototype
//define others to safeguard
IEV_C_PROTO   ( Irq3_ISR  );
IEV_C_PROTO   ( Irq5_ISR  );
IEV_C_PROTO   ( Irq7_ISR  );
IEV_C_PROTO   ( Div0_ISR  );

int    test_stack ( int n );

/******************************************************************************\
**	main
\******************************************************************************/
int main(int argc, char **argv)
	{ 
	short	i, done, err, op_mode, awake;
	short	result = 0, tmo;
	char ch;
	struct pp_buf        ppb;   // struct for the ping-pong buffer
	struct spi_param     ss1;   // struct for spi comms
	struct time_param    ti;    // struct for timing of various events
	struct compass_param compass; // struct with compass parameters
	struct gps_param     gps;     // struct with gps parameters
	struct sbd_param     sbd;     // struct with Iridium SBD parameters
	struct lifo_param    lifo;    // struct with LIFO parameters
	struct flight_param  flight;  // flight params
	//struct miss_param    mis;     // struct with the mission parameters
	struct except_param  exc;     // exception parameter list
	struct eng_param     eng;     // engineering parameter list
	struct drift_param   drift;   // drift parameters
	struct hyd_param     hyd;     // hydraulics params
	struct dat_param     dat;     // daq/processing params
	struct adp_param     adp;     // adp parameters
	struct motor_stat    mot;     // motor stats for last op
	struct ublox_param   ubx;     // ublox gps positions, for surface drift
	struct pwr_param     pwr;     // power #'s for pitch, roll & hyd
	struct nav_param     nav;     // nav parameters
	struct route_param   rte;     // route parameters
	struct pp_daq         pp;     // mar11, polyplus daq struct
#if (BENTHOS==1 || NPS ==1)
	struct acm_param     acm;     // Benthos Acoustic Modem
#endif
#if NTK ==1
    struct ntk_param     ntk;     // Nortek AD2CP
#endif
#if PH ==1
	struct ph_param		 ph;
#endif    
#if ZOOG ==1
    struct zcam_param   zcam;     // Zooglider zoocam struct
    struct zonar_param zonar;     // Zooglider zonar  struct
    struct zonar_scan  zscan;     // zonar data struct for one scan
#endif    
	
	// TUChParams    tuart_cfg;
	
	struct tpu_uart tu_port[N_TU_PORTS] = {
	     FROM_SAT , TO_SAT , BAUD_SAT , 0,
	     FROM_MUX1, TO_MUX1, BAUD_MUX1, 0,
	     FROM_MUX2, TO_MUX2, BAUD_MUX2, 0, 
	     FROM_SBE,  TO_SBE,  BAUD_SBE,  0 }; // 4 TPU uart ports, defined as above

	
#if (BENTHOS==1 || NPS==1)  // if Benthos modem
  TSerInUse=0;  //the TSerial port on the TPU is not in use so it is ok to
                //change System clock rates and to stop the oscillator in low
                //power modes.
  modem_cmd_str.nbytes=0; //there is no command to be sent to remote modem
#endif
#if PH==1  // if pH
  TSerInUse=0;  //the TSerial port on the TPU is not in use so it is ok to
                //change System clock rates and to stop the oscillator in low
                //power modes.
#endif
	CSSetSysAccessSpeeds(nsFlashStd, nsRAMStd, nsCFStd, WTMODE);
	TMGSetSpeed(HIGH_CLOCK_SPEED);
	SCIConfigure(SCI_BAUD, 'N', true);
	SCIRxSetBuffered(true);		// enable the built-in 2k-word buffer
	init_pins(); // initialize the pins for other tasks
    // display_dbg(); // debug: looks like all are getting set to zero

//	INITIALIZE THE TPU UART MODULE
	TUInit(calloc, free);		// give TU manager access to our heap

	// Identify the progam and build
	cprintf("\nProgram: %s: %s %s \n", __FILE__, __DATE__, __TIME__);
	// Identify the device and its firmware
	cprintf("Persistor  CF%d SN:%ld   BIOS:%d.%02d   PicoDOS:%d.%02d\n", CFX,
		BIOSGVT.CFxSerNum, BIOSGVT.BIOSVersion, BIOSGVT.BIOSRelease, 
		BIOSGVT.PICOVersion, BIOSGVT.PICORelease);
	/* Identify the arguments */
	cprintf("\n%d Arguments:\n", argc);
	for (i = 0; i < argc; i++)
		cprintf("  argv[%d] = \"%s\"\n", i, argv[i]);
		/**/
		
//i = sizeof(nav); cprintf("size of nav_param  = %d\n", i );
//i = sizeof(lifo);cprintf("size of lifo_param = %d\n", i );
//i = sizeof(dat); cprintf("size of dat_param  = %d\n", i );
	
//
//	Install handlers for the interrupts we want to catch
//
	// IEVInsertAsmFunct (  Irq4RxISR, level4InterruptAutovector); //R
	// IEVInsertAsmFunct (  Irq4RxISR, spuriousInterrupt);
	IEVInsertCFunct   ( &Irq2_ISR,  level2InterruptAutovector);
	IEVInsertCFunct   ( &Irq4_ISR,  level4InterruptAutovector);
	IEVInsertCFunct   ( &Spur_ISR,  spuriousInterrupt        );
	// define others
	IEVInsertCFunct   ( &Irq3_ISR,  level3InterruptAutovector);
	IEVInsertCFunct   ( &Irq5_ISR,  level5InterruptAutovector);
	IEVInsertCFunct   ( &Irq7_ISR,  level7InterruptAutovector);
	IEVInsertCFunct   ( &Div0_ISR,  zeroDivision );


	TMGSetupCLKOUTPin(false, false);
	SCITxWaitCompletion();
	PITSet51msPeriod(PITOff);	// disable timer (drops power)

	// initialize the SPI and start up the watchdog ===================
	all.sspi = &ss1;  // spi comms structure
    spi_set_wdog( 1, 255 );
	
	
	LEDInit();
	PITAddChore(hibernate_task,3);  // empty chore for PIT
	
	// initialize the TPU serial ports
	// jan13 - moved to separate fnx, that can be called again if needed.
	all.tu_port = tu_port; // set all.tu_port address to same as the local
	err = setup_tpu_uart_all();
	if (err)
	{ //ERROR!!
	  cprintf("TPU UART OPEN ERROR first time\n");
	  err = setup_tpu_uart_all();
	  if (err) cprintf("TPU UART OPEN ERROR 2nd time\n");
	    // don't just return, since this would just kill the glider
	}
	/* old loop: now in setup_tpu_uart_all
	for (i=0;i<N_TU_PORTS; i++) //iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
	{
	  tu_port[i].tup = 
	     TUOpen( tu_port[i].rxch, tu_port[i].txch, tu_port[i].baud, 0);
       cprintf("    TUP: %lX    RX: %2u    TX: %2u    BAUD: %6lu\n",
			tu_port[i].tup, tu_port[i].rxch, 
			tu_port[i].txch, tu_port[i].baud);
	  if (tu_port[i].tup == 0 )
	  { //ERROR!!
	    cprintf("TPU UART OPEN ERROR, port#=%d\n",i);
	    return 0;
	  }
	} //iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
	*/
    // display_dbg(); // debug
	
	//=== allocate memory for various buffers =========================
    err = alloc_lifo(&lifo);  // allocate memory  for lifo
    if (err) 
    { cprintf("alloc_lifo err %d\n",err); return(0); } // abort if bad
    
    err = alloc_dat_ram(&dat);  // allocate memory  for data
    if (err) 
    { cprintf("alloc_dat err %d\n", err); return(0); } // abort if bad

    #if ADP==1 || NTK==1  // if ADP float,
       adp_alloc(&adp); // allocate memory for ADP
    #endif

    #if PPLUS==1  // mar11, if Polyplus float,
       pp_alloc(&pp); // allocate memory for polyplus
    #endif
#if BENTHOS==1 || NPS==1 //allocate memory for Benthos modem
    acm_off();  // make sure ac modem is turned off
    acm.buf = (unsigned char *) malloc(MOD_BLK_SZ);
    if ( acm.buf == NULL)
    { cprintf("acm.buf malloc err\n");
      acm.bufsize=0; // size of buffer
    }
    else
      acm.bufsize=MOD_BLK_SZ; // size of buffer
#endif
#if PH==1 //pH init
      ph_alloc(&ph);
#endif

	// assign rest of 'all' structure =================================
	all.time = &ti;      // UX time of various events
	all.ppb  = &ppb;     // ping-pong buffer
	all.comp = &compass; // compass structure
	all.gps  = &gps;     // gps structure
	all.sbd  = &sbd;     // sbd iridium structure
	all.lifo = &lifo;    // lifo area
	all.flt  = &flight;  // flight params
	//all.mis  = &mis;     // mission parameters
	all.exc  = &exc;     // exception parameters
	all.eng  = &eng;     // engineering params
	all.drift= &drift;   // drift params
	all.hyd  = &hyd;     // hydraulic params
	all.dat  = &dat;     // data params
	all.adp  = &adp;     // adp params
#if NTK==1
	all.ntk  = &ntk;
#endif
	all.mot  = &mot;     // motor statistics
	all.ubx  = &ubx;     // ublox params
	all.pwr  = &pwr;     // power #'s for hyd, pitch and roll
	all.nav  = &nav;     // point to the nav struct
	nav.route= &rte;     // point to the route in the nav.
	all.pp   = &pp;      // mar11, point to the polyplus struct.
#if ZOOG ==1
	all.zcam = &zcam;    // zooglider zoocam param struct
	all.zonar= &zonar;   // zooglider zonar  param struct
	all.zs   = &zscan;   // zonar data struct for one scan
    zooAlloc(&adp);      // allocate memory for zonar
#endif
#if BENTHOS==1 || NPS==1
	all.acm  = &acm;     // point to the ac modem struct
  //clear out the acm struct
  { char *s,*e,*p;
    s=(char *)all.acm;  //start of the acm struct to be cleared
    e=(char *)&all.acm->modem; //end just before start of modem info
    for(p=s;p<e;p++)*p='\0';
    all.acm->new_blk=all.acm->lnew_blk=all.acm->old_blk=all.acm->lold_blk =0;
  }
#endif
#if PH ==1
    all.ph   = &ph;      // ph data structure
#endif
  printf("  struct all addr = %p \n",&all   );
  printf("  struct exc addr = %p \n",&exc   );
  // display_dbg(); // debug
	
	// initialize parameters ==========================================
	init_all (); // initialize params in all, independent of op_mode
    clear_lifo_stat(all.lifo); // reset status of old messages but don't erase
    err =set_default_param();  // initialize the parameter array
    init_wpt_rte( false );     // initialize the route and waypoints
    read_hcal();               // initialize the compass correction table
  //--mar12, read in msp430 settings now, so their values are stored in param[]
  //-- retrieve the msp430 flash settings
  if ( init_pr_iparam ( CS_PITCH ) != 0 )
     cprintf("Error with pitch module: debug in M.otors\n");
  if ( init_pr_iparam ( CS_ROLL )  != 0 )
     cprintf("Error with roll  module: debug in M.otors\n");
  if ( init_hyd_iparam ( )         != 0 )
     cprintf("Error with hyd module: debug in P.ump\n");
  if ( init_gpio_iparam ( )         != 0 )
     cprintf("Error with GPIO/Watchdog module: debug in W.atchdog\n");
  if (err>1) // then flash card might be missing or corrupted
  {
     cprintf("******Config File Error %d: POSSIBLY NO FLASH CARD???\n", err);
  }
    

  //=== decide which way to branch, based on op_mode ======================
  //dec11, make sure it is the value in eeprom
  op_mode = (short) VEEFetchLong( "OPMODE", NO_VEE_VAL); // Spray mode of op
  if ( op_mode == 0 ) //-------------------
  { //dec11, catch any possiblity of restarting not in mission mode
    set_op_mode ( 1 ); // FORCE to be in mission mode
    op_mode = 1;
  } //-------------------------------------
  // op_mode = last operation mode of Spray;
  // op_mode = 0 = no dives have been done yet = normal entry into main
  // op_mode = 1 = we're doing the first dive cycle
  // op_mode > 0 = we're in the middle of a mission : must have gotten a
  //               spurious reset, go to the abort code.
  // op_mode = 2 = we've done first dive, in mission mode.
  // op_mode < 0 = we've issued a remote reset
  cprintf("START-UP op-mode = %d \n", op_mode);
  if (op_mode<0) //========================================================
  { // then we have gotten a remote restart command
    // everything above has set us up to restart,
    init_sensors(); // makes sure sensor flags=NONE ON
    mission ( ); // restart!
  } //=====================================================================
  else if ( op_mode > 0 ) //===============================================
  { // then we have spurious reset during the mission =====================
    // wait 60 s to see if someone is communicating
    all.exc->exc_stat |= EXC_SPURIOUS_RST;   
    // flag that it is a spurious reset
    all.exc->n_reset++; // increment the #reset counter
    // display_dbg(); // debug
    // dec14, show value of all.ppb->ipp as well.
    cprintf("# spurious resets = %d\n, data.buf=%d,", all.exc->n_reset, all.ppb->ipp);
    awake = sleep_check(60, PIT_IRQ2_RXD, FALSE);
    cprintf("Awake flag = %d\n", awake);
    // returns  TRUE if somebody's home
    
    if (!awake) //-----------------------------------------------
    { // decide what to do
      if ( iparam[ IA_max_reset ] > all.exc->n_reset ) //rrrrrrrrr
      {  cprintf("spurious reset, continuing the mission\n");
         mission( ); // restart the mission
      }
      else // too many resets, goto abort
      {   dat.sbe_pro_on = 0; // the SBE is not on.
          dat.take_adp   = 0; // do not take adp data
          adp.on_adp     = 0; // assumes that the adp is off
          abort_mission ( 1 );  // abort the mission. aug15 passing err code
      } //rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
    } //---------------------------------------------------------
  } //=====================================================================
  //=======================================================================

#if ZOOG ==1  // aug15, init params
  all.zcam->zcam_stat = 0;
  all.zcam->n_img     = 0;
  all.zcam->n_err     = 0;
  all.zcam->avg       = 0;
  all.zcam->uxti      = 0L;
#endif
  
  // else  we are here because op_mode ==0, = normal entry 
  // dec11, we're here because user awoke the system coming out of power-reset
  err = init_wpt_rte( true );      // initialize the route and waypoints
  if (err) // then flash card might be missing
     cprintf("******WAYPT/RTE FILE ERROR.  Flash Card Installed ??????????\n");
  
  // initialize the wdog so it is OFF
  spi_set_wdog( 10, 1 );
  Argos_Off; // nov13, turn off the argos transmitter (turned on by msp430).
  reset_lifo(all.lifo); // reset all of the lifo queue
  init_sensors();
  dat.i = 0; // reset the data buffer area to index=0
  all.exc->n_reset  = 0;  // no spurious resets yet
  all.exc->exc_stat = 0; // zero out the exception status
  all.ppb->ipp = 0; // set the ping-pong buffer to empty.
  all.time->ti0 = RTCGetTime ( 0, 0 );  // UX time for this dive
  all.time->ti_cyc = all.time->ti0; // UX time for this cycle

  check_flash_file(); // may16 checks flash card.
  
	main_menu();
	
	done = false;
	tmo = 0;
	while (!done) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	{  //cycle until we get a quit command


	    EIAEnableRx(1);
		SerInFlush(); // delete old anything in the buffer
        if (ch !=' ' && ch>0 ) cprintf("   BAS>\n"); // display directory prompt
	    ch = -1;  //illegal input char
	    ch = SCIRxGetCharWithTimeout(1000 ); // get a 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) //====================================================
	    { // and depending upon the ch, do the appropriate action =======
	    
        case 0x1B : //ESC key , abort program
                   
                    cprintf("Do you really want to quit (y/n)? >\n");
                    if (YesNo() )
                      { done=1; } // set flag to quit
                    else { ch = ' ';} 
                    break;
                    
        case '?' :  break; // causes directory prompt to be displayed
        case ' ' :  break; // wait for another character
        case  -1 :  break; // wait for another character
	    case '+' :  toggle_verbose(); // toggle verbose mode
				    break;


	    case 'C' :  // go test compass module
	                test_compass ( );
				    break;
	   
	    case 'D' :  // test the dat_fnx module
	                daq_test ( );
				    break;
	   
	    case 'F' :  // go test compass module
	                flash_test (  );
				    break;
	   
	    case 'G' :  // go test compass module
	                test_gps (  );
				    break;
	   
	    case 'H' :  // go test the hydraulic module
	                test_hyd (  );
				    break;
	   
	    case 'I' :  // go test Iridium SBD
	                test_sbd (  );
				    break;

	   #if PPLUS==1
	    case 'J' :  //  test the polyplus daq commands
	                test_pp (  );
				    break;
	   #endif

	    case 'L' :  // put into low-power mode
	                sleep_check ( STAY_LOWPWR, PIT_IRQ2_RXD, FALSE );
	                main_menu();
				    break;
	   
	    case 'M' :  // go test pitch and roll modules
	                test_pitch_roll (  );
				    break;

	    case 'N' :  // go test the navigation (waypoint + route)
	                test_nav ( );
				    break;
	   
	    case 'P' :  // go test SBE CTD module
	                test_param ( );
				    break;
				    
        case 'U' :  main_menu(); 
                    if (err) // then flash card might be missing
                       cprintf("******WAYPT/RTE FILE ERROR.  Flash Card Installed ??????????\n");
                    break; // show the main menu

	   #if ADP==1
	    case 'V' :  // go test the ADP
	                test_adp ( );
				    break;
	   #endif
	   #if NTK==1
	    case 'V' :  // go test the NTK
	                test_ntk ( );
				    break;
	   #endif
	   #if ZOOG==1
	    case 'V' :  // go test the ZooCam
	                test_zCam ( );
				    break;
	    case 'K' :  // go test the Zonar
	                testZonar ( );
				    break;
	   #endif

	    case 'W' :  // go test GPIO/MUX msp430
	                test_gpio (  );
				    break;
	   
	    case 'Z' :  // go test SBE CTD module
	                test_sbe ( );
				    break;

	    case '0' :  // reset the dive # and op_mode
	                set_surf_num ( 0 );
	                set_prof_num ( 0 ); //0902, include profile #
	                set_op_mode  ( 0 );
	                cprintf("Dive# and op_mode now = 0\n");
				    break;

	    case '8' :  // hidden test
                    all.exc->pgood     = TRUE;  // assume that pressure is good
	                glide( 1, 150 ); // test 50m pump
				    break;

	    case '9' :  // hidden test
	                cprintf("recursion test: type 'q' to quit \n");
	                test_stack( 0 );
	                i = 99 / iparam[ IA_use_set ];
	                cprintf("I divide-by-zero = %d, flag = %d\n",i, IRQ_Flag );
				    break;

        case '^' :  // start of mission
                    check_flash_file(); // may16 checks flash card.
                    if( check_nshore() < 1 )break; //JAN14 check to see if we defined a large enough array for
                                                   //all the shore commands. DONT start mission if this fails
                    if (DEBUG)  cprintf("in DEBUG mode !!! \n");
                      else     cprintf("in MISSION mode,");
                    cprintf("Present Profile # = %3d\n", iparam [ EA_prof_num ] );
                    cprintf("Present Surface # = %3d\n", iparam [ EA_surf_num ] );
                    cprintf("Minutes to wait before start %4d\n",
                      	iparam [ IA_delay_start] );
                    cprintf(" Start mission (y/n) ? >\n");
                    if (YesNo() ) 
                    {   
                      set_op_mode ( 0 ); // dec11, normal entry into mission
                      service_wdog();  //make sure watchdog is set
                      mission( );
                    } 
                    break; 
#if BENTHOS==1 || NPS==1
          case 'A' :
                   test_acm();  //test ac modem
                   break;
#endif

#if PH==1
          case 'A' :
                   test_ph();  //test pH sensor
                   break;
#endif
        default  :  cprintf(" input unknown \n");

	    } //==============================================================
	    
	  
	} // end while !done
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  cprintf("freeing memory\n");
  #if ADP==1  ||  NTK==1  || ZOOG==1 
    free( adp.buf);
  #endif
  #if PPLUS==1	
    free( pp.cell[0].dat);
    free( pp.cell[1].dat);
  #endif
 #if BENTHOS==1 || NPS==1 // if Benthos modem
    acm_off();  // make sure is off
    free( acm.buf ); //& free up memory 
 #endif
 #if PH==1 // if pH sensor
    ph_off();  // make sure is off
    free (ph.buf); 
 #endif 
  free(lifo.buf  );
  free( dat.dat  );
  free( dat.eptr );
  // Various exit strategies
  //	BIOSReset();			// full hardware reset
  //	BIOSResetToPBM();		// full reset, but stay in Pesistor Boot Monitor
      BIOSResetToPicoDOS();	// full reset, but jump to 0xE10000 (PicoDOS)
	return result;

}	//____ main() ____//
//*****************************************************************************

void main_menu ( void )
{ //print out menu selections *************************************************
#if BENTHOS==1
 cprintf("      MAIN MENU CORC Spray, compiled %s %s\n", __DATE__, __TIME__ );
#else
 cprintf("      MAIN MENU, compiled %s %s\n", __DATE__, __TIME__ );
#endif
 write_header ( NULL ); // display info
 if ( ADP) cprintf("  Acoustic Doppler Profiler, ");
 if ( NTK) cprintf("  Nortek AD2CP, ");
 if (ISUS) cprintf("  ISUS Nitrate Sensor,");
 if ( DOX) cprintf("  DOx 43 Sensor,");
 if ( DO6) cprintf("  DOx 63 Sensor,");
 if (BENTHOS) cprintf("  Benthos Ac. Modem");
 if (NPS) cprintf("  NPS DAT Modem");
 if (PH) cprintf("  pH");
 if (ZOOG) cprintf("  ZooGlider,");
  #if USE_ADG == 1 // jun15 if has auto-degas installed,
     cprintf("Auto-Degas_");
  #endif
 cprintf("\n");
 if (DEBUG)  cprintf("********* in DEBUG mode !!! \n");
 cdrain(); // wait for the above to print
 cprintf("                         ESC Abort prog :  U.pdate menu \n"
         "     C.ompass          : Flash Test     :  G.PS module \n"
         "     H.ydraulics       : I.ridium SBD   :  J=Polyplus \n"
         "     D.AQ test         : L.owpower         : M.otors Pitch&Roll\n"
         "     N.avigation       : + Toggle Verbose  : W.atchdog, GPIO-MUX\n" 
         "     P.arameter Settings:  Z.SBE menu\n"
         "     ^ Start Mission   : 0.Reset Dive#,op_mode\n");
#if ADP==1 || NTK==1
  cprintf(" V. ADP test\n");
#endif
#if ISUS==1
  cprintf(" K. ISUS test\n");
#endif
#if BENTHOS==1 || NPS==1
  printf("     A.c modem test \n");
#endif
#if PH==1
  printf("     A. ph test \n");
#endif
#if ZOOG ==1
  cprintf(" V. ZooCam test  : K. Zonar test \n");
#endif

 check_nshore(); //JAN14 check to see if we defined a large enough array for
                 //all the shore commands.
 return;
} //***************************************************************************

#define NY 226 //***size of array below to chew up 256 bytes= 0x100 ea time

//static char g_static[NY] = {0}; // shows up as 226 bytes on heap, Uninitialized far data
//       char g_static[NY] = {0}; // shows up as 226 bytes on heap, Uninitialized far data
//static char g_static[NY]; // shows up as 226 bytes on heap, Uninitialized far data
//         char g_static[NY]; // shows up as 226 bytes on heap, Uninitialized far data

int    test_stack ( int n ) //*************************************************
{ // code snippet to test stack register
  
  short  i, x, ch;
  long tmp;
  char *sptr;
  //static char y_static[NY] = {0}; // shows up on heap, Uninitialized far data
  //static char y_static[NY]; // shows up as 226 bytes on heap, Uninitialized far data
  char y[NY];  // total alloc = 256; stack should grow by 0x100 ea time
  
  for (i=0;i<NY; i++) 
  { 
     //y_static[i] = i; // init
     y[i] = i;
     // g_static[i] = i;
  }
	
	
	sptr  = ( char *) CPUReadStackReg(); // stack register
    tmp   = (long) sptr;
    x     = 0xffff & tmp; // low address
    printf("Recursion %4d: SR = %lx = %x = %p\n", n, tmp, x, sptr );
	ch = -1;  //illegal input char
	ch = SCIRxGetCharWithTimeout(1000 ); // get a character
    ch = ch_l2u( ch ); // make upper-case
    if ( ch != 'Q' )
	{
      n++;
      test_stack( n );
    }
    
  return n;
} //**************************************************************************


//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*** Interrupt Service Routines
//*****************************************************************************

/******************************************************************************\
**	Spur_ISR			Interrupt handler for Spurious interrupt
\******************************************************************************/
IEV_C_FUNCT( Spur_ISR )
{	// ISR when a spurious interrupt 
	#pragma unused(ievstack)
    IRQ_Flag = SPUR_F; // set global flag that RxD occurred
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************

/******************************************************************************\
**	Irq4_ISR			Interrupt handler for IRQ4 = rs232 RxD detected
\******************************************************************************/
IEV_C_FUNCT( Irq4_ISR )
{	// ISR when IRQ4 = rs232 RxD is detected
	#pragma unused(ievstack)
    IRQ_Flag = IRQ4_F; // set global flag that RxD occurred
	PinIO(IRQ4RXD);		// making it an input turns off ISR
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************



/******************************************************************************\
**	Irq2_ISR			Interrupt handler for IRQ2 (tied to GPIO msp430)
\******************************************************************************/
IEV_C_FUNCT( Irq2_ISR )
{	
	#pragma unused(ievstack)
    IRQ_Flag = IRQ2_F; // set global flag that RxD occurred
	PinIO(IRQ2);		// making it an input turns off ISR

	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************



/******************************************************************************\
**	Irq3_ISR			Interrupt handler for IRQ3
\******************************************************************************/
IEV_C_FUNCT( Irq3_ISR )
{	// ISR when a spurious interrupt 
	#pragma unused(ievstack)
    IRQ_Flag = IRQ3_F; // set global flag that RxD occurred
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************


/******************************************************************************\
**	Irq5_ISR			Interrupt handler for IRQ5
\******************************************************************************/
IEV_C_FUNCT( Irq5_ISR )
{	// ISR when a spurious interrupt 
	#pragma unused(ievstack)
    IRQ_Flag = IRQ5_F; // set global flag that RxD occurred
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************

/******************************************************************************\
**	Irq7_ISR			Interrupt handler for IRQ7
\******************************************************************************/
IEV_C_FUNCT( Irq7_ISR )
{	// ISR when a spurious interrupt 
	#pragma unused(ievstack)
    IRQ_Flag = IRQ7_F; // set global flag that RxD occurred
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************

/******************************************************************************\
**	zeroDivision			Interrupt handler for divide-by-zero
\******************************************************************************/
IEV_C_FUNCT( Div0_ISR )
{	// ISR when a divide-by-zero 
	#pragma unused(ievstack)
    IRQ_Flag = DIV0_F; // set global flag that divide-by-zero occurred
    all.exc->exc_stat |= EXC_NOT_SINKING;   // flag that it is a divide-by-zero
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************


