/******************************************************************************
// GPIO and MUX functions for Spray2008 SPI controller
// CS assignment = CS_GPIO is done in spi_cmd.h
// created Oct2008
//
//==== Future Expansion =======================================================
//		last update: Feb2009
//	1. DONE: resetting cf2 time (ux-base) using the gps time
//  2. wdog interaction (update_wdog, etc. )
//
 *****************************************************************************/
#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	<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    "pitch_roll.h"
#include    "gpio_mux.h"
#include    "setup.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;

// internal prototypes
void gp_main_menu    ( void );
void gpio_debug_menu ( void );
void gpio_debug      ( void );

//*****************************************************************************
short spi_mux ( short on, short chan, struct spi_param *ss ) //****************
{  // send the command for configuring the mux and corresponding serial ports
   // chan = channel requested
   // the msp430 code interprets to configure the correct mux + rs232 device
   // channels are defined in gpio_mux.h
   
   // returns TRUE if OK, else 0
   

  short rstat;
  
  ss->mdat[0] = SPI_MUX;     // dat[0] = cmd byte
  ss->mdat[1] = chan; // send the value
  ss->mdat[2] = on;   // whether to turn on or off
  ss->nbyte = 3; // send the above
  
  rstat = spi_try_send (  ss, 3 );  // try 3x to send
  
  return ( rstat == SPI_CRC_OK );
  
} //***************************************************************************


//*****************************************************************************
short spi_wdog (  char sub_cmd ) //********************************************
{  // send the SPI_WDOG command with subset cmd sub_cmd
   // command subset defined in spi_cmd.h
   
  short rstat;
  struct spi_param *ss;
  
  ss = all.sspi;
  setup_spi ( CS_GPIO, ss ); // re-init the SPI info
  
  ss->mdat[0] = SPI_WDOG; // dat[0] = cmd byte
  ss->mdat[1] = sub_cmd;  // send the sub-cmd
  ss->nbyte = 2; // send the above 
  
  rstat = spi_try_send ( ss, 3 ); // send the command
  
  if ( sub_cmd == WDT_QUERY ) //---------------------------------
  { // request for query info
     DelayMilliSecs(10); 
     rstat = spi_query( ss ); // get the reply
     display_gp_query (rstat, ss ); // and display
  } //-----------------------------------------------------------
  

  return ( rstat );
  
} //***************************************************************************

void  reset_gpio ( void ) //***************************************************
{ // reset the gpio/wdog msp430 reset line
  
	cprintf("Resetting WDOG/GPIO MSP430 chip\n");
	PIOClear ( RES_WDOG ); // set the reset line LOW  to the wdog msp430
	DelayMilliSecs(100); // wait 0.1 s
	PIOSet   ( RES_WDOG ); // reset HIGH
	DelayMilliSecs(200); // wait 0.2 s
    all.exc->serr[4] &= 0x20; // set flag that had to reset the wdog
    flash_spi_error( 4, 0x20); //dec14, write to flash
  return;
} //***************************************************************************

short try_update_wdog ( void ) //**********************************************
{ // try 3x to service the watchdog
  // returns ERR if no good
  short rstat, err, i=0;
  
  do //================================================================
  { // try to wake up
    rstat = Update_Wdog;  
    err = ( rstat != SPI_CRC_OK );
    if (err) DelayMilliSecs(200); //dec14 changed to 200 ms 
  } while ( i++<3 && err ); //=========================================
  
  if (i>1) cprintf("update_wdog failure %d times\n",i);
  if (err) 
  {   cprintf("update_wdog FAILED\n");
      all.exc->serr[4] &= 0x10; // set flag that had it failed
      flash_spi_error( 4, 0x10); //dec14, write to flash
  }
    
  return ( err );
} //***************************************************************************


short service_wdog ( void ) //*************************************************
{ // try to update the watchdog
  // if fails after 2x, try resetting & try again
  // if still fails, disable using the CF2_ATTN line
  
  short  err, i=0;
  
  err = try_update_wdog(); // try updating the watchdog
  if (err) //==========================================================
  { // still no good
    reset_gpio(); // try resetting
  
    err = try_update_wdog(); // try updating the watchdog again
  } //=================================================================
  
  if (err) 
  {  
    all.exc->wdog_error = TRUE; // set flag that wdog is NOT responding
    all.exc->serr[4] &= 0x40; // set flag that wdog is NOT responding
    flash_spi_error( 4, 0x40); //dec14, write to flash
  }
  else     all.exc->wdog_error = FALSE; // otherwise, ok
  
  return (err);
} //***************************************************************************

//*****************************************************************************
short spi_set_wdog (  short wdmult, short action ) //**************************
{  // set the wdog multuplier and action values
   // the msp430 sets these from eeprom on its own reset
   // they then reside as global params in ram 
   // This fnx sets them to the desired values, without
   // changing the default action due to a msp430 reset.
   
  short rstat, *w, i=1;
  struct spi_param *ss;
  
  ss = all.sspi;
  setup_spi ( CS_GPIO, ss ); // re-init the SPI info
  
  ss->mdat[0] = SPI_WDOG;   // dat[0] = cmd byte
  ss->mdat[1] = WDT_SET_PRM; // set-parameter sub-cmd
  
  w = (short*) &( ss->mdat[0] ); // address of mdat[0]
  w[i++]    = wdmult; // store the value into the next 2 bytes
  w[i++]    = action; // store the value into the next 2 bytes
  ss->nbyte = 2*i;    // total # of bytes
  
  rstat = spi_try_send ( ss, 3 ); // send the command
  DelayMilliSecs(10);   // delay for computation
  rstat = spi_query( ss ); // get the reply
  
  display_gp_query (rstat, ss ); // display the results
  

  return ( rstat );
} //***************************************************************************



void gp_flash_menu  ( struct spi_param *ss ) //********************************
{ // display flash options in the GPIO msp430
  short  nval, ncnts, n1, n2;


  cprintf(" Give flash-eeprom addr to update \n" );

  cprintf(" %2d : MSP430 Board Serial Number \n", F_SER_NO );
  //Firmware version is set at compile for msp430, & returned as if at addr[2]
  //cprintf(" %2d : MSP430 Firmware Version # \n", F_VERSION );
  cprintf(" %2d : Wdog default time multiplier \n",   F_WDT_MULT  );
  cprintf(" %2d : Wdog tmo ticks for CF2_ATTN \n" ,   F_MAX_ATTN  );
  cprintf(" %2d : Wdog tmo ticks for CF2 RST! \n" ,   F_MAX_RST   );
  cprintf(" %2d : Wdog tmo ticks for 430 RST! \n" ,   F_MAX_MAX   );
  cprintf(" %2d : Wdog Default Action flag \n",       F_WDT_ACT   );
  cprintf(" %2d : 14Volts*100 = (COEF*counts/100)\n", F_G_C2U_V14 );
  cprintf(" %2d : 07Volts*100 = (COEF*counts/100)\n", F_G_C2U_V07 );
  cprintf(" %2d : In-Hg*100 = (COEF*counts/100)\n",   F_G_C2VAC   );
  cprintf(" %2d : Vacuum Offset (cnts@ 0 in-Hg)\n",   F_G_VOFF    );
  cprintf(" %2d : counts*COEF/10,000 = milliV\n",     F_G_C2MV    );
  
  cprintf(" Give address \n");
  n1 = get_num(&nval);
  if (n1 ==1 )
  {  
     cprintf(" Give the new value to store \n");
     n2 = get_num(&ncnts);
  }
  
  if (n1 ==0  || n2 ==0 )
  { cprintf(" ILLEGAL VALUE \n");
    return;
  }
  // else proceed
  
   switch ( nval ) 
   { // make sure it is legal
     case F_SER_NO : 
     case F_WDT_MULT : 
     case F_MAX_ATTN : 
     case F_MAX_RST : 
     case F_MAX_MAX : 
     case F_WDT_ACT : 
     case F_G_C2U_V14 : 
     case F_G_C2U_V07 : 
     case F_G_C2VAC : 
     case F_G_VOFF : 
     case F_G_C2MV : 

     
     // these are all legal values
     
       spi_flash_write( nval, ncnts, ss );
       break;

     default : cprintf("ILLEGAL address \n");

    } // end switch
         
  
  return ;
}//****************************************************************************




void display_wdog ( struct spi_param *ss ) //**********************************
{ // display the wdog information
   short  *w, i=0;
   
   
   // display IRQ information
   cprintf("Pin_IRQ2=%d, IRQ Flag=%d (2=Wdog,4=RxD, 8=spurious)\n",
            PinRead( IRQ2 ), IRQ_Flag );
   // display the data from the msp430
   i=0;
   w = ( short*) &(ss->sdat[2]); // point to even addr of msb
   cprintf("msp430 wdog accum = %4d\n", w[i++] );
   cprintf("     Max_tmo_Attn = %4d\n", w[i++] );
   cprintf("  Max_tmo_CF2_Rst = %4d\n", w[i++] );
   cprintf("  Max_tmo_430_Rst = %4d\n", w[i++] );
   cprintf("    wdog_tmo_mult = %4d\n", w[i++] );
   cprintf(" wdog_action_flag = %4x\n", w[i++] );
   cprintf(" #of CF2 updates  = %4d\n", w[i++] );
   cprintf(" #FAILED Cycles   = %4d\n", w[i++] );
   
   
   return;
} //***************************************************************************

short  init_gpio_iparam ( void ) //********************************************
{ // read in the wdog module flash data block,
  // and assign the iparam[] arrays accordingly
  short rstat;
  
  rstat = spi_cmd_ver  ( CS_GPIO );
  if (rstat==0)
    display_gpflash ();
  else cprintf("%d Error getting MSP430 GPIO flash \n", rstat );
  
  return ( rstat );
} //***************************************************************************



void   display_gpflash  ( void ) //********************************************
{ // display flash eeprom values
  // first flash data (addr=0 offset in MSP430) is at sdat[2]
  // msp430 is lsb, msb convention, but is swapped before it is sent

  short *w, val=0, i=0;
  short wdt_mult, wdt_max_attn, wdt_max_rst, wdt_max_max, wdt_act;
  short sn, ver, c2v14, c2v07;
  short c2vac, voff, c2mv;
  struct spi_param *ss;
  
  ss = all.sspi;

  ver = ss->sdat[1]; // code-compilation version
  w = ( short * ) &( ss->sdat[2] ); // flash data starts at sdat[2]

  
  sn    = w[i++]; // serial #
  wdt_mult     = w[i++]; // multiplier for watchdog
  wdt_max_attn = w[i++]; // max sec before attn line is asserted
  wdt_max_rst  = w[i++]; // max sec before resetting the cf2
  wdt_max_max  = w[i++]; // max sec before resetting itself
  wdt_act      = w[i++]; // what actions to take
  
  c2v14 = w[i++]; // gain for 14V
  c2v07 = w[i++]; // gain for 07V
  c2vac = w[i++]; // gain for the vacuum
  voff  = w[i++]; // offset for the vacuum
  c2mv  = w[i++]; // cnts 2 mV
  
  iparam [ MA_wdt_sn     ] = sn; //oct14 store this info
  iparam [ MA_wdt_ver    ] = ver;
  iparam [ SA_gpio_ver   ] = ver;
  iparam [ MA_wdt_action ] = wdt_act;
  iparam [ MA_wdt_attn   ] = wdt_max_attn;
  iparam [ MA_wdt_cf2_rst] = wdt_max_rst;
  iparam [ MA_wdt_430_rst] = wdt_max_max;
  iparam [ MA_wdt_mult   ] = wdt_mult;
  iparam [ MA_wdt_c2v_14 ] = c2v14;
  iparam [ MA_wdt_c2v_07 ] = c2v07;
  iparam [ MA_wdt_c2vac  ] = c2vac;
  iparam [ MA_wdt_Voff   ] = voff;
  iparam [ MA_wdt_c2mv   ] = c2mv;
  
  
  cprintf("MSP430 EEPROM settings for the GPIO/WDOG Module\n");
    
  cprintf(" %5d : Wdog MSP430 Board Serial Number \n", sn     );
  cprintf(" %5d : Wdog MSP430 Firmware Version # \n",  ver    );
  cprintf(" %5d : 14Volts = cnts * c2v14 / 100 \n",   c2v14  );
  cprintf(" %5d : 07Volts = cnts * c2v07 / 100 \n",   c2v07  );
  cprintf(" %5d : Vacuum OFFSET counts\n",             voff   );
  cprintf(" %5d : In-Hg*100=(cnt-Voff)*c2vac/1000\n",  c2vac  );
  cprintf(" %5d : opt mV = cnts*c2mv/10,000\n\n",      c2mv   );

  cprintf(" %5d : WDT_Max_tmo_Attn\n", wdt_max_attn );
  cprintf(" %5d : Max_tmo_CF2_Rst \n", wdt_max_rst   );
  cprintf(" %5d : Max_tmo_430_Rst \n", wdt_max_max );
  cprintf(" %5d :   wdog_tmo_mult \n", wdt_mult );
  cprintf(" %5d : wdog_action_flag\n", wdt_act );


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

void gp_set_default  ( void ) //***********************************************
{ // apr11: set gpio flash values to default
  // this is used for a brand-new board
  short  nval, n1, tmso = 300;
  struct spi_param *ss;
  
  ss = all.sspi;
  setup_spi ( CS_GPIO, ss ); // re-init the SPI info


  cprintf(" Give New MSP430 GPIO serial # \n");
  n1 = get_num(&nval);
  if (n1 !=1  || nval<1 || nval>32767 )
  { cprintf(" ILLEGAL s/n\n");
    return;
  }
  // else proceed
  spi_flash_write( F_SER_NO  , nval, ss );
  DelayMilliSecs(tmso);
  spi_flash_write( F_WDT_MULT,    1, ss ); // WDT_tmo_multiplier
  DelayMilliSecs(tmso);
  spi_flash_write( F_MAX_ATTN,  600, ss ); // WDT_Max_tmo_Attn 
  DelayMilliSecs(tmso);
  spi_flash_write( F_MAX_RST ,  900, ss ); // WDT_Max_tmo_cf2_reset
  DelayMilliSecs(tmso);
  spi_flash_write( F_MAX_MAX , 1200, ss ); // WDT_Max_tmo_430_reset
  DelayMilliSecs(tmso);
  spi_flash_write( F_WDT_ACT ,  255, ss ); // WDT_action_flag
  DelayMilliSecs(tmso);
  
  spi_flash_write( F_G_C2U_V14,  66, ss ); // 14Volts = cnts * c2v14 
  DelayMilliSecs(tmso);
  spi_flash_write( F_G_C2U_V07,  40, ss ); // Volts*100 = (F_C2U_V * counts/100)
  DelayMilliSecs(tmso);
  spi_flash_write( F_G_C2VAC  , 967, ss ); // In-Hg*100=(cnt-Voff)*c2vac/1000
  DelayMilliSecs(tmso);
  spi_flash_write( F_G_VOFF   ,3000, ss ); // Vacuum offset counts
  DelayMilliSecs(tmso);
  spi_flash_write( F_G_C2MV , IC2mV, ss ); // opt mV = cnts*c2mv/10,000
  DelayMilliSecs(tmso);

  // display contents
  init_gpio_iparam(  );
         
  
  return ;
}//****************************************************************************


void  display_gp_query (short rstat, struct spi_param *ss ) //*****************
{ // display the query results

  short cmd;
  
  cmd = parse_query_ss(rstat, ss);
  
  switch ( cmd ) //====================================================
  { // display results accordingly
    case 0           : break;  // not valid!
    case SPI_VER     : display_ver (  );
                   break;

    case AUX_PWR    : display_aux_pwr ( ss );
                   break;

    case SPI_MUX    : display_spi_mux ( ss );
                   break;
                   
    case SPI_MEASURE : display_general_ad12 (  ss );
                   break;

    case SPI_WDOG    : display_wdog ( ss );
                   break;
                   
    case FL_BLOCK_RD : display_dump ( ss );
                         
                   break;
                   
    default          : display_dump ( ss );
                   break;
  } //=================================================================
  
  
  return;
} //***************************************************************************

void display_aux_pwr  ( struct spi_param *ss ) //******************************
{ // display the power switch info
  short val, off, stat;
  
  val = ss->sdat[1]; // sensor channel switched
  off = ss->sdat[2]; // whether turned on or off
  stat= ss->sdat[3]; // whether it was successful
  
  printf("Power Sensor ID %3d was turned ",val);
  if (off) printf("OFF"); else printf("ON");
  if (stat>0) printf(" OK"); else printf(" FAILED");
  printf("\n");
  
  return ;
} //***************************************************************************


void display_spi_mux  ( struct spi_param *ss ) //******************************
{ // display the serial mux
  short val, on , stat;
  
  val = ss->sdat[1]; // serial channel configured
  on  = ss->sdat[2]; // whether turned on or off
  stat= ss->sdat[3]; // whether it was successful
  
  printf("MUX channel %3d was turned ",val);
  if (on) printf("ON"); else printf("OFF");
  if (stat>0) printf(" OK"); else printf(" FAILED");
  printf("\n");
  
  return ;
} //***************************************************************************

void ant_switch(short unit, short wing) // ************************************
{ // configure the antenna transfer switch for the right unit and wing.
  // unit = GPS_UNIT or SBD_UNIT, depending upon which one we want
  // wing = PORT_WING(1) or STBD_WING (0) depending upon which wing.

  short w;
  
  if ( unit== GPS_UNIT) //=============================================
  { // select accordingly
    if ( wing == PORT_WING )
        w = ANT_GPS_2_PORT;
    else
        w = ANT_GPS_2_STBD;
  }
  else // must be the SBD_UNIT, use the opposite setting
  {
    if ( wing == PORT_WING )
        w = ANT_GPS_2_STBD; // GPS->STBD means SBD->PORT
    else
        w = ANT_GPS_2_PORT; // GPS->PORT means SBD->STBD

  } //=================================================================
    
  ant_select ( w );
  
  return;
} //***************************************************************************



void test_gpio( void ) //******************************************************
{
  char ch;  //input char
  short  done, tmo;
  long tnow;
  struct spi_param *ss;
  
  ss = all.sspi;

	cprintf("         Test of GPIO and MUX : %s \n", __DATE__);
	gp_main_menu();
  
	done = false;
	tnow = RTCGetTime(0,0);  // gets present time
	while (!done) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	{  //cycle until we get a quit command

	    // re-init the SPI info
	    setup_spi ( CS_GPIO, ss );
	    EIAEnableRx(1);
		
        if (ch !=' ' && ch>0 ) cprintf("W_1>\n"); // display directory prompt
        
		while ( SCIRxQueuedCount() )
		    SCIRxFlush(); // delete any old stuff 
	    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) //====================================================
	    { // and depending upon the cmd, do the appropriate action =======
	    
        case 'Q' :  done=1; break; //quit function
        case 'U' :  gp_main_menu(); break;
        case 'D' :  gpio_debug(); 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 'A' : Argos_On;
        			cprintf("Argos is ON\n"); 
        			break;
        case 'B' : Burn_On; 
        			cprintf("Burn wire is ON\n");
        			break;
        case 'O' : // turn off both Argos and the burn wire
	               cprintf("Turning off Argos\n");
	               Argos_Off;
	               cprintf("Turning off the burn wire\n");
	               Burn_Off;
                   break;

                    
        default  : cprintf(" input unknown \n");
	    } //==============================================================
	     
	  
	} // end while !done
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	cprintf("Turning off Argos\n");
	Argos_Off;
	cprintf("Turning off the burn wire\n");
	Burn_Off;
	
  return;
} //***************************************************************************


void gp_main_menu ( void )
{ //print out menu selections *************************************************
cprintf("              Watchdog/GPIO Menu\n"
		"                        Q.uit menu      :  U.pdate menu \n"
        "     A.rgos ON       :  O.ff argos AND burn \n"
        "     B.urn wire ON   :  D.ebug menu \n" );
 return;
} //***************************************************************************


void gpio_debug( void ) //******************************************************
{
  char ch;  //input char
  short  done, n, val, nval, rstat, on, action, tmo;
  long tnow;
  struct spi_param *ss;
  
  ss = all.sspi;

	cprintf("         DEBUG of GPIO and MUX : %s \n", __DATE__);
	gpio_debug_menu();
  
	done = false;
	tnow = RTCGetTime(0,0);  // gets present time
	while (!done) //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	{  //cycle until we get a quit command

	    // re-init the SPI info
	    setup_spi ( CS_GPIO, ss );
	    EIAEnableRx(1);
		
        if (ch !=' ' && ch>0 ) cprintf("W_2>\n"); // display directory prompt
        
		while ( SCIRxQueuedCount() )
		    SCIRxFlush(); // delete any old stuff 
	    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) //====================================================
	    { // and depending upon the cmd, do the appropriate action =======
	    
        case 'Q' : done=1; break; //quit function
        case 'U' : gpio_debug_menu(); 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 'A' :  // a/d sample
			        cprintf("   give a/d channel to sample [0,1,2] \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // send command 
				       val = spi_ad12( nval, ss );
				    }
				    break;
				    
	    case 'D' :  // 64-byte information dump
			        init_gpio_iparam ();
			        /*
			        cprintf("   64-byte Info flash to dump [0,1,2,3] \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // send command 
				       val = spi_flash_dump( nval, ss );
				       if (nval==0 ) 
				          display_gpflash (  );
				    } /**/
				    break;
				    
	    case 'F' :  // write one word to flash
	                gp_flash_menu( ss );
				    break;

        case 'G' :  val = spi_query  ( ss );
                    display_gp_query (val, ss ); // display the results
                    break; 

	    case 'M' :  // configure a serial/mux device
			        cprintf("   give serial/mux channel to configure \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value nnnnnnnnnn
				    {  // send command nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
				       cprintf(" turn on(1) or off(0) ? \n");
				       n = get_num(&on);
				       if (n==1)
				       { // then legal -------------------
				         val = spi_mux( on, nval, ss );
				         DelayMilliSecs(5); // delay for computation
				         rstat = spi_query( ss ); // get the reply
                         display_gp_query (val, ss ); // display the results
                       } //--------------------------------
				    } // nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
				    break;

	    case 'P' :  // power on/off a sensor
			        cprintf("   give sensor id to control power \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // send command 
				       val = spi_aux_pwr( nval, ss );
				       DelayMilliSecs(5); // delay for computation
				       rstat = spi_query( ss ); // get the reply
                       display_gp_query (val, ss ); // display the results
				    }
				    break;

	    case 'S' :  // hibernate for the desired time
			        cprintf("   give #s to sleep  \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // go to sleep
				       n=sleep_check(  nval, PIT_IRQ2_RXD, 0 );
				       cprintf("return from hibernate, wakeup=%d\n",n);
				       Query_Wdog;
				    }
				    break;
				    

        case 'V' :  val = spi_cmd_ver  ( CS_GPIO );
                    if (val==0) display_ver ();
                    break; 

        case 'W' :  val = Query_Wdog;
                    break; 
                    
	    case 'X' :  // set wdog values
			        cprintf("   give wdog time-multiplier \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // send command 
				       cprintf("  give wdog action flag \n");
				       n = get_num(&action);
				       if (n==1)
				       { // send the command
				         val = spi_set_wdog( nval, action );
				       }
				    }
				    break;
 
        case 'Z' :  val = service_wdog();
                    val =  Query_Wdog;
                    break; 
                   
        case '8' :  val = xfr_SPI_byte(CS_GPIO, SPI_RESET);
                    cprintf("soft reset return = %c",val);
                    if (val==' ') cprintf("OK");
                    cprintf("\n");
                    break; 
                    
        case '9' :  reset_gpio();
                    break; 
                    
        case '!' :  // set flash msp430 eeprom to default values
                    cprintf("Do you really want to reset GPIO flash to default (y/n)? >\n");
                    if (YesNo() )
                      { gp_set_default ( ); } 
                    break;
        default  : cprintf(" input unknown \n");
	    } //==============================================================
	     
	  
	} // end while !done
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	
  return;
} //***************************************************************************


void gpio_debug_menu ( void )
{ //print out menu selections *************************************************
cprintf("              Watchdog/GPIO DEBUG Menu\n"
		"                        Q.uit menu      :  U.pdate menu \n"
        "     A./D sample     :  D.ump Flash     :  F.lash write word \n"
        "     G.et queued info:  +Toggle Verbose :  V.ersion, s/n \n" 
        "     P.ower Control     M.ux Control    :  W.dog counter\n"
        "     S.leep             Z.ero Wdog      :  X.set wdog vals \n"
        "     8.Soft Reset    :  9.Hard Reset Wdog/GPIO chip\n" 
        "     !.reset msp430 to default params \n");
 return;
} //***************************************************************************
