/******************************************************************************
//	test_1.c				Persistor and PicoDOS starter C file  
//	
//*****************************************************************************
//	
//	Apr2011, used to initialize CF2 EEPROM and MSP430 modules.
//  Used to do calibration of MSP430 sensors
//
//	
//*****************************************************************************
//
//==== Future Expansion =======================================================
//		last update:  
//
*******************************************************************************/

#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 <cf1bios.h>  // BDR for time??

#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    "setup.h"



// 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

// bdr definitions (unused for the new ADG stuff below)
#define PRIME_PUMP        0   // prime the pump before each outer cycle?
#define PRIME_PUMP_FANCY  0   // prime the pump in a fancy manner, during increental pump-ups?


// -------------- AutoDeGas (ADG) definitions, bdr may15 -------------------------- //
// state definitions for state machine 
#define ADG_ST_IDLE             0
#define ADG_ST_PUMPING          1
#define ADG_ST_PAUSING_PRE_VENT 2
#define ADG_ST_VENTING          3
#define ADG_ST_BLEEDING         4
#define ADG_ST_DONE             5

// maximum sizes for data array allocation 
// for 25 cycles x 60 degas increments, total packet comes to 1651 bytes (see spreadsheet),
// but only send what we use, this is just for largest possible allocation.
#define N_CYCLES_MAX  25
#define N_INCR_MAX   60
 

// 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

// modular variables
  // for timer: 
  static ulong unixTime_start;
  static ulong unixTime_now1;

// local modular variables for ADG output data packet
  // initialize output 'big' data and data arrays here:
  // for now I'm just allocating some big arrays (maximums defined above),
  static uchar  adgOut_Ncycles = 0;                               // number of total cycles completed so far (eventually will be n_cycles when done)
  static uchar  adgOut_Nincr = 0;                                 // number of incremental pumps to do, set to n_incr at start of machine
  static ushort adgOut_pumpTimeMax = 0;                           // max time to pump at each increment, set at start of machine (s)
  static uchar  adgOut_bleedTime  = 0;                            // time of bleeding for each cycle (minutes)
  static uchar  adgOut_totalTime = 0;                             // total time of the whole process, in 0.1 hr ticks.
  static uchar  adgOut_pumpTime[N_CYCLES_MAX] = {0};              // total pump time for each outer cycle
  static uchar  adgOut_oilCount[N_CYCLES_MAX][N_INCR_MAX] ={{0}}; // oil pressure at end of each incremental pump, /10
  static ushort adgOut_ventTime[N_CYCLES_MAX] = {0};              // vent time total for each outer cycle, in 0.1s ticks
  static uchar  adgOut_pumpVoltageAve[N_CYCLES_MAX] = {0};        // average voltage for each outer cycle, in 0.1V
  static uchar  adgOut_pumpCurrentAve[N_CYCLES_MAX] = {0};        // average of the average current in 0.1A
  static uchar  adgOut_pumpCurrentMax[N_CYCLES_MAX] = {0};        // max of the max currents for each outer cycle, in 0.1A


// prototypes -----------------------------------------------------------------
void     main_menu       ( void    );
void     vent_test       ( void    );
int      multi_pump_vent ( int k_cyc, int n_degas, int tm_pmp, int tm_open );

// new bdr may15 functions for auto-degassing:
void  adg_PrintState(int state);
void  adg_VentTest2(uchar n_cycles, ushort n_incr, int tm_pump_secs, int tm_bleed_secs  );
uchar adg_VentTest2Loop(uchar myState, uchar n_cycles, ushort n_incr, int tm_pump_secs, int tm_bleed_secs  );
void  adg_PrintState(int state);
void  adg_GetPumpInfo(short *pump_status, short *pump_oil, short *pump_time, short *pump_volts, short *pump_amps, short *pump_ampsMax);
void  adg_PrintPacket();

//--------------------------------------------------------------------
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  );


/******************************************************************************\
**	main
\******************************************************************************/
int main(int argc, char **argv)
	{
	short	i, done, err = 0;
	short	result = 0, tmo;
	
  
	char ch;
	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
	
	// 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
	     
	     //BDR additional vars:
	short n;  // for lld return
	short  val, nval, use_oil, oil;  // bdr new ones for more menu stuff

	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

//	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]);
		/**/
		
// ensure continuous venting (also set in test_vent)
		
  iparam [ IA_cntl_vent ] = 22; // set so will always try to vent
  iparam [ IA_tm_vent ]   =  8; // let it run up to 4s
	
//
//	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)

	
	LEDInit();
	PITAddChore(hibernate_task,3);  // empty chore for PIT
	
	// initialize the TPU serial ports
	all.tu_port = tu_port; // set all.tu_port address same as the local
	for (i=0;i<N_TU_PORTS; i++) //iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
	{
	  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;
	  }
	} //iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
	


	// assign rest of 'all' structure =================================
	all.sspi = &ss1;     // spi comms structure
	all.time = &ti;      // UX time of various events
	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
	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.
	
	// initialize parameters ==========================================
	init_all (); // initialize params in all, independent of op_mode
    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
    
    
	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 'U' :  main_menu(); break;
	    case '+' :  toggle_verbose(); // toggle verbose mode
				    break;


	    case 'L' :  // get the liquid-level-detect
	                n = get_lld( );
	                cprintf("LLD detects ");
	                if (n) cprintf("air\n");
	                  else cprintf("oil\n");
				    break;


	    case '>' :  // run the air vent
//	                val = iparam [ IA_cntl_vent ]; // save value
//	                iparam [ IA_cntl_vent ] = 2;   // set to test
	                check_vent();
//	                iparam [ IA_cntl_vent ] = val; // restore
				    break;
                    
                    
                    
	    case '1' :  // test hydraulic vent fnx
	                vent_test ( );
				    break;
                    
                    
                    
	    case '2' :  // test hydraulic vent 2, with state machine
	               adg_VentTest2(4, 15, 15, 600 );  // 1-hour test
	               // adg_VentTest2(20, 30, 30, 1200 );  // overnight longer test
	                 //adg_VentTest2(3, 2, 6, 10 );  // quick lab test
	                //            n_cycles, n_incr, pump_time_sec
				    break;
				    
	    case '3' :  // display the values from a previous (or current!) run
	                adg_PrintPacket(); 
				    break;
				    
	    case 'C' :  // close the valve
	                // spi_aux_pwr( HYD_CLOSE_VALVE, ss );
	                Close_Valve;
	                cprintf("Valve is closed\n");
				    break;
	    case 'O' :  // open the valve
	                // spi_aux_pwr( HYD_OPEN_VALVE, ss );
	                Open_Valve;
	                cprintf("Valve is opened\n");
				    break;

				    

	    case 'H' :  // run the pump for #seconds
			        printf("   give #s to run the pump \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // send command 
	                  cprintf("   OIL sense setting: 0=no, 1=after tmin, 2=yes \n");
	                  n = get_num(&oil);
	                  if (n==1) use_oil = oil;
	                  else      use_oil = 2; //default to yes
	                  
				       val = go_pump( nval, use_oil );
				       val = watch_pump( nval, 0); 
				       cprintf("Pump time= %d s\n",val);
				    }
				    break;
				    
	    case 'X' :  // send pump stop request
	                hyd_stop_pump(  );
	                cprintf("stop sent\n");
				    break;



	    case 'W' :  // watch the pump
			        cprintf("   give max #s to watch pump \n");
				    n = get_num(&nval);
				    if (n==1) //then a legal read of value
				    {  // send command 
				       val = watch_pump( nval, 0);
				       cprintf("Pump time= %d s\n",val);
				    }
				    break;

        default  :  cprintf(" input unknown \n");

	    } //==============================================================
	    
	  
	} // end while !done
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
  cprintf("freeing memory\n");
  // 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 *************************************************
 cprintf("INIT MAIN MENU, compiled %s %s\n", __DATE__, __TIME__ );
 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 Sensor,");
 cprintf("\n");
 if (DEBUG)  cprintf("********* in DEBUG mode !!! \n");
 cdrain(); // wait for the above to print
 cprintf("     ESC Abort prog  :  U.pdate menu \n"
         "     L.LD value      :  >.Vent air\n"  
         "     O.pen Valve     :  C.lose Valve \n"
         "     H.yd pump       :  X. STOP PUMP \n" 
         "     W.atch Pump   \n"
         "     1=bench-test self-vent hydraulics\n"
         "     2=bench-test self-vent hydraulics 2, now with data logging\n"  
         "     3=display data arrays from a previous ADG (junk if haven't run 2 yet)\n" );

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


void vent_test  (  void  ) //**************************************************
{ // bench-test of doing self degassing

  int n, n_cyc, tm_pmp, tm_open, n_degas, tm_idle_mins;
  int i=0, j=0, k, tvent;
  int awake = 0, tm_vent_val;
  int want_open = 20; // let oil get sucked back inside over this many minutes (Jeff had this as 15)
                      // for 300 ccs, bdr changed this to 10
  int wait_open, s; 
  ulong unixTime_temp=0;
     char line[80]; // for some inputs
     
  short tpump_temp; // temp value for time pump pumped 
  
  ushort unixTicks;
    
  RTCGetTime(&unixTime_start, &unixTicks);

  
/*
  
  for (i=0; i<10; i++)
  {
  cprintf("current unix time = %lu\n", unixTime);
    awake = sleep_check( 1, PIT_IRQ2_RXD, TRUE );
    

    }
  */  
       
  
  //cprintf("hello world!\n"); return;
  
  cprintf("Unix start time (0 for now): ");
  SerInFlush();
  gets(line);
  sscanf(line,"%lu",&unixTime_temp);
  if (unixTime_temp != 0L) { unixTime_start = unixTime_temp; }
  cprintf("\nUnix start time = %lu\n", unixTime_start);
  
  
  cprintf("Give total number of cycles to do \n");
  n = get_num( &n_cyc   );
  if (!n) { cprintf("NOT valid, quitting \n"); return; }
  
  cprintf("Give the tm_idle_mins [minutes] between each cycle \n");
  n = get_num( &tm_idle_mins );
  if (!n) { cprintf("NOT valid, quitting \n"); return; }
  
  
  cprintf("Give number of incremental pumps to do for each cycle\n");
  n = get_num( &n_degas );
  if (!n) { cprintf("NOT valid, quitting \n"); return; }
  
  cprintf("Give max time[s] for each incremental pump (also will stop when oil pressure hits limit)\n");
  n = get_num( &tm_pmp  );
  if (!n) { cprintf("NOT valid, quitting \n"); return; }

if (n_degas>1)  
{
  cprintf("Each incremental pump is followed by tm_open[s] before venting.\n"
          "IF all oil is pumped out, this time will be with the valve opened.\n"
          "Give value for tm_open (s)\n");
  n = get_num( &tm_open );
  if (!n) { cprintf("NOT valid, quitting \n"); return; }
}
else
{
  tm_open=10; // but not actually ever used in this case
}

  
  RTCGetTime(&unixTime_now1, &unixTicks);
  cprintf("\n* * TIME = %lu * * * * * * * * * BEGIN VENT_TEST * * * * * * * * * * * \n",
      unixTime_now1-unixTime_start);
  cprintf("Idle time between cycles (minutes) = %d; # incremental pumps for each cycle = %d;\n", tm_idle_mins,n_degas);
  cprintf("Max pump time for each incremental pump (s) = %d; ", tm_pmp);
  if (n_degas>1) cprintf("After each pump, if full bladders, valve open time before vent (s) = %d;", tm_open);  
  else cprintf("\n");
  

  
          RTCGetTime(&unixTime_now1, &unixTicks);
          cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now1-unixTime_start);
          Close_Valve;  // close the valve 


  
  //-- set up the time to wait with the valve open
  wait_open = want_open;                          // desired valve open wait time between outer cycles (set above, fixed to 15 minutes for now)
  if ( tm_idle_mins < wait_open ) wait_open = tm_idle_mins; // unless idle time given is less, in which case set wait_open to that
  tm_idle_mins = tm_idle_mins - wait_open;                  // shorten idle time by wait time minutes (will set to zero then if given idle time is less than wait open time)
  wait_open = wait_open*60;                       // convert wait time to seconds

  cprintf("\n##After automatic modification of idle time##\n");
  cprintf("Idle time between outer cycles with valve closed (minutes) = %d; # incremental pumps for each cycle = %d;\n", tm_idle_mins,n_degas);
//  cprintf("Max pump time for each incremental pump (s) = %d; After each pump, if full bladders, valve open time before vent (s) = %d;\n", tm_pmp, tm_open);
  cprintf("Max pump time for each incremental pump (s) = %d; ", tm_pmp);
  if (n_degas>1) cprintf("After each pump, if full bladders, valve open time before vent (s) = %d;", tm_open); 
  else cprintf("\n");
  cprintf("Time to wait between outer cycles, with valve open (s) = %d;\n", wait_open); 

  
  
  //-- set up the air vent --------------------------
  iparam [ IA_cntl_vent ] = 22;         // set so will always try to vent
  tm_vent_val = iparam [ IA_tm_vent ];  // original value
  iparam [ IA_tm_vent ]   =  40;         // let it run up to 4s
  
  i=0;
  while ( i++<n_cyc &&!awake ) //+++++++++++++++++++++++++++++++++++++
  { // do for each cycle
    RTCGetTime(&unixTime_now1, &unixTicks);
    cprintf("\n* * TIME = %lu * * * * * * * * starting outer cycle #%d * * * * * * * * * *\n", unixTime_now1-unixTime_start, i);
    
    // prime the pump here?
    if (PRIME_PUMP)
    {
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * priming the pump for 15 s with valve open...\n", unixTime_now1-unixTime_start);

       Open_Valve;
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * valve open.\n", unixTime_now1-unixTime_start );
       
            RTCGetTime(&unixTime_now1, &unixTicks);
            cprintf("\n* * TIME = %lu  * * * pump start * * * * * * * * *..\n", unixTime_now1-unixTime_start);
       go_pump( 15, OIL_YES ); // pay attn to the oil sensor
       tpump_temp = watch_pump ( 17, 0 ); // wait until  pump is done
       
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu  * * * pump stop. time on (s) = %d\n", unixTime_now1-unixTime_start, tpump_temp);
       
       Close_Valve;
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now1-unixTime_start);
     }  
       
    
      tvent = multi_pump_vent( i, n_degas, tm_pmp, tm_open );
      
      // pause for 5 minutes with valve open so can check bag for bubbles
      // but actually pump 3 short bursts so audio cues will alert me...
      for (k=0;k<3;k++) //wait ea minute
      {
       Open_Valve;
       sleep_check( 1, PIT_IRQ2_RXD, TRUE );
       go_pump( 1, OIL_YES ); // pay attn to the oil sensor
       Close_Valve;
       tpump_temp = watch_pump ( 2, 0 ); // wait until  pump is done
       
      }
      // now pause five mins
      cprintf("waiting another %d minutes for next outer cycle...\n", tm_idle_mins);
      cprintf("NOW IS A GREAT TIME TO CHECK FOR HOW WELL INTERNAL BAG IS PUMPED DRY!\n");
      for (k=0;k<tm_idle_mins;k++) //wait ea minute
      {
         cprintf("%d minutes left...\n", tm_idle_mins-k);
         awake = sleep_check( 60, PIT_IRQ2_RXD, TRUE );

      }
      cprintf("done. resuming whatever it is that i do...\n");
      
    
      //---- leave in state where the oil is back inside
       Open_Valve;
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * valve open.\n", unixTime_now1-unixTime_start );
       
       cprintf("pausing with valve open for %d s...\n", wait_open);
       
       awake = sleep_check( wait_open, PIT_IRQ2_RXD, TRUE );
       Close_Valve;
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now1-unixTime_start);
       
       if (n_degas==1)
       {
              // added a vent check here (28apr15) (because didn't do it in multi pump vent stuff)
          cprintf("doing the check vent thing...\n");
           s = check_vent(); // 0.1s that the air vent ran.
           if (s==0) {cprintf("THERE IS NO AIR TO VENT.\n");}
           RTCGetTime(&unixTime_now1, &unixTicks);
           cprintf("\n* * TIME = %lu * * VENTED TICKS (# 0.1s ticks) = %d  \n", unixTime_now1-unixTime_start, s);  
       }      
       
       cprintf("starting pump for 10 s (or until oil P sensor flags, just so outside bladder isn't completely empy?)\n");
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * pump start.\n", unixTime_now1-unixTime_start);
       
       go_pump( 10, OIL_YES ); // pay attn to the oil sensor
       tpump_temp = watch_pump ( 12, 0 ); // wait until  pump is done
       
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu  * * * pump stop. time on (s) = %d\n", unixTime_now1-unixTime_start, tpump_temp);
       
 
       
    if (i<n_cyc)
    {
      //---- wait for the next cycle --------
      cprintf("waiting another %d minutes for next outer cycle...\n", tm_idle_mins);
      cprintf("NOW IS A GREAT TIME TO CHECK FOR AIR BUBBLES IN BAG!\n");
      
      for (k=0;k<tm_idle_mins;k++) //wait ea minute
      {
                 cprintf("%d minutes left...\n", tm_idle_mins-k);
         awake = sleep_check( 60, PIT_IRQ2_RXD, TRUE );

      }
    }
       
  } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  iparam [ IA_tm_vent ] = tm_vent_val; // restore

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

void adg_VentTest2 (uchar n_cycles, ushort n_incr, int tm_pump_secs, int tm_bleed_secs  ) //**************************************************
{ // bench-test of doing auto-degassing v2, which is set to use variable inputs and store data to variables here
  // these variables could also be read from some larger global struct, where they are, say, set by the shore command.
  // this is really just a test function to call adg_VentTest2Loop, which is the function which performs the ADG.
  // for argument descriptions, see adg_VentTest2Loop
  //
  // bdr may15
  
  uchar state = ADG_ST_IDLE; // initial state is idle
    
  //-- set up the air vent --------------------------
  iparam [ IA_cntl_vent ] = 22;         // set so will always try to vent
  iparam [ IA_tm_vent ]   =  40;         // let it run up to 4s

  // start up the while loop for the state machine...    
  do 
  {
    // for now do this every call... so need a delay here somewhere
    adg_PrintState(state);

    // this delay here is just for testing purposes, for easy debugging. remove in the real version
    DelayMilliSecs( 1000 );
  
      // this is where other important things can be called, like check for new commands, see if underwater, 
      // or see if should stop this whole degas business early.
      state = adg_VentTest2Loop(state, n_cycles, n_incr, tm_pump_secs, tm_bleed_secs);
      
  }while(state != ADG_ST_DONE); // repeat the loop call while not done.
  
  // once we're done, print out the packet. (also in this version is printed out every few minutes within the loop)
  adg_PrintPacket();
}



uchar adg_VentTest2Loop(uchar myState, uchar n_cycles, ushort n_incr, int tm_pump_secs, int tm_bleed_secs )  //**************************************************
{ // this is the loop function that is to be called as often as feasible,
  // inside is a little state machine that keeps track of where we are in the auto-degassing process.
  // one cycle starts with incremental pumps, pauses, and ventings (n_incr # of times).
  //
  // bdr may15
  // inputs:  uchar n_cycles:   total number of outer cycles to complete
  //          ushort n_incr:    total number of incremental pumps to do per cycle
  //          int tm_pump_secs  max time for each incremental pump (or will stop when oil max reached)
  //          int tm_bleed_secs time to pause with valve open
  // outputs: uchar:  returns the state machine state at end of this call 
  //
  
  // variables which could be modified slightly but really aren't worth sending in as arguments:
  int tm_pause_pre_vent_secs = 5;  // time to pause before vent check (if ended due to oil sensor pressmre, valve open for this time) 
  
  //static uchar myState = ADG_ST_IDLE;   // keep track of what state we're in. first time, we start in the idle state.
                                          // commented out and made into an argument so can re-set or re-enter the state machine multiple times.
    
  static uchar i_cycle=0, i_incr=0; // running cycle counter (will presumably count 0 to n_cycles-1)

  // info to extract from pump stuff, from the most recent pumping  
  static short pump_status, pump_oil, pump_time, pump_volts, pump_amps, pump_ampsMax; 
  ushort ventTimeTicks; 
  
  // some temporary things for keeping track of volts, amps means at higher resolution than the chars they will be cast to later...
  static int pump_volts_totalTemp=0, pump_amps_totalTemp=0, pump_time_total=0;

  
  // for unix timing (these are set every time we check what time it is)
  ulong unixTime_temp=0, unixTime_now, tm_pump_on_secs;
  short unixTicks;
  
  // for unix timing keep track of persistent time stamps with static vars:
  static ulong unixTime_init, unixTime_pumpStart, unixTime_bleedStart, unixTime_pauseStart, unixTime_watchdog=0, unixTime_printData;
  static ulong total_timeTemp=0; // keep track of the time this thing has been running in total, for better precision than the adg output
  
  static uchar flagFirstRun = 1; 
  
/*// leaving this in here commented out, in case we ever want to define something big in the heap:
  static uchar *adgOut_oilCount[N_CYCLES_MAX];
  if (flagFirstRun)
  {
    cprintf("allocating memory for adgOut_oilCount...\n");
    for (i=0; i<N_CYCLES_MAX; i++)
      adgOut_oilCount[i] = (uchar *)malloc(N_INCR_MAX * sizeof(uchar));
      
    flagFirstRun=0;
  }
*/         
  if (flagFirstRun)
  {
    RTCGetTime(&unixTime_init, &unixTicks);
    flagFirstRun=0;
  }
  
  // check if time to service the watchdog?
  RTCGetTime(&unixTime_now, &unixTicks);
  if (unixTime_now - unixTime_watchdog > 30)
  {
    unixTime_watchdog = unixTime_now;
    cprintf("\n* * TIME = %lu * * * * * * * * * service watchdog * * * * * * * * * * * \n",unixTime_now-unixTime_init);
    service_wdog();
  }
  
  // if it's been xx a while (ever 6 hours, maybe?) then send a status thing over iridium. 
  // this could be taken care of in the outer wrapper loop as well.
  if (unixTime_now - unixTime_printData > 60)
  {
    unixTime_printData = unixTime_now;
    cprintf("\n* * TIME = %lu * * * * * * * * * DATA OUT * * * * * * * * * * * \n",unixTime_now-unixTime_init);
    adg_PrintPacket();
  }
  
  // can also check here for an over-arching command to end early, which could then put the state back to ADG_ST_DONE
  // and in the while loop above, will not re-enter the state machine.
  
  // enter the state machine switch statement (see diagram in AutoDegassPacketSizing_v1.2.xlsx)
  switch (myState)
  {
    case ADG_ST_IDLE:     // first time function called, get everything set up (timers and such), for getting into pumping right away next time...
       
      // reset the outer cycle counter and the incremental pump:
      i_cycle=0; i_incr=0;
      pump_volts_totalTemp=0; pump_amps_totalTemp=0; pump_time_total=0;

      // set the output packet variables that will be used for this run:
      adgOut_pumpTimeMax = (ushort)(tm_pump_secs/10);   // convert to 10s ticks
      adgOut_bleedTime = (uchar)(tm_bleed_secs/60); // convert to minutes
      
      //cprintf("// check if size ok? done if %d > %d || %d > %d\n",n_cycles , N_CYCLES_MAX, n_incr, N_INCR_MAX );
      if (n_cycles > N_CYCLES_MAX || n_incr > N_INCR_MAX)
      {
        cprintf("ERROR! n_cycles (=%d) or n_incr (=%d) over maxima\n", n_cycles, n_incr);
        myState = ADG_ST_DONE;
        return ADG_ST_DONE;
      }
      
      // print some startup messages
      RTCGetTime(&unixTime_now, &unixTicks);
      cprintf("\n* * TIME = %lu * * * * * * * * * BEGIN VENT_TEST * * * * * * * * * * * \n",
              unixTime_now-unixTime_init);
      cprintf("n_cycles=%d, n_incr=%d, tm_pump_secs = %d, tm_bleed_secs = %d \n",  
              n_cycles, n_incr, tm_pump_secs, tm_bleed_secs );
    
      cprintf("\n* * TIME = %lu * * * * * * * * starting outer cycle #%d * * * * * * * * * *\n", unixTime_now-unixTime_init, i_cycle);
    
      // close the valve
      Close_Valve; RTCGetTime(&unixTime_now, &unixTicks); cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now-unixTime_init);

      // start the pump, watch oil sensor
      go_pump(tm_pump_secs, OIL_YES ); RTCGetTime(&unixTime_pumpStart, &unixTicks);
      cprintf("\n* * TIME = %lu  * * * pump start #%d,%d* * * * * * * * *..\n", unixTime_pumpStart-unixTime_init, i_cycle, i_incr);
      
      // change the state, for next time
      myState = ADG_ST_PUMPING;
       
      break;
      
    case ADG_ST_PUMPING:
       // check if pump done OR if pump timer expired (i.e. if enough time passed since started pump)
      RTCGetTime(&unixTime_now, &unixTicks);
      tm_pump_on_secs = unixTime_now - unixTime_pumpStart;  // how long the incremental pump has been on

      // wait at least a few seconds to give some time for the pump SPI to do its thing and be sure it's running
      if ( tm_pump_on_secs < 3  )
        break;
        
      adg_GetPumpInfo(&pump_status, &pump_oil, &pump_time, &pump_volts, &pump_amps, &pump_ampsMax);
      
      if (pump_status != PUMP_WAIT  || tm_pump_on_secs > tm_pump_secs ) 
      {  // either it is off, or it is time to be turned off. 
      
        hyd_stop_pump();  // make sure it is truly off
        
        cprintf("pumped for %d seconds, final oil value = %d\n", pump_time, pump_oil);
      
        if (pump_status == PUMP_OIL_END)
        { // this allows multiple incremental pumps with most of oil outside
          Open_Valve; // since this opening will bleed some back in.
          RTCGetTime(&unixTime_now, &unixTicks); 
          cprintf("\n* * TIME = %lu * * * valve open \n", unixTime_now-unixTime_init);
        }
        
        cprintf("\n* * TIME = %lu  * * * pump stop * * * * * * * * *..\n", unixTime_now-unixTime_init);
        
        cprintf("db: writing %d/10 to adgOut_oilCount(%d)(%d)\n", pump_oil, i_cycle, i_incr);
        adgOut_oilCount[i_cycle][i_incr] = (uchar)(pump_oil/10); 
      
        // accumulate the "total" volts and amps things, to calculate the mean later
        pump_volts_totalTemp += pump_volts, 
        pump_amps_totalTemp  += pump_amps;
        
        // also record the highest amps
        if (pump_ampsMax > adgOut_pumpCurrentMax[i_cycle])
          adgOut_pumpCurrentMax[i_cycle] = pump_ampsMax;
        if (pump_ampsMax==0)
          adgOut_pumpCurrentMax[i_cycle] = pump_amps; // for some reason with really short pumps, this sometimes is necessary
          
        pump_time_total += pump_time;         // and keep track of the total pump time for this cycle:
        
        RTCGetTime(&unixTime_pauseStart, &unixTicks);         // record pause start time..
        myState = ADG_ST_PAUSING_PRE_VENT;
      }
      break;
      
    case ADG_ST_PAUSING_PRE_VENT:
      // check if little pause timer expired
      RTCGetTime(&unixTime_now, &unixTicks);
      
      if ((unixTime_now - unixTime_pauseStart) > ((ulong)tm_pause_pre_vent_secs )) 
      {
        if (pump_status == PUMP_OIL_END)  // this variable hasn't been modified since the pumping stopped and valve was open a few seconds ago.
        { // then we've bled some oil back in; 
          Close_Valve; // close valve so we can pump it back out
          RTCGetTime(&unixTime_now, &unixTicks); 
          cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now-unixTime_init);
        }
      
        RTCGetTime(&unixTime_now, &unixTicks);
        cprintf("\n* * TIME = %lu  * * * venting start * * * * * * * * *..\n", unixTime_now-unixTime_init);
        myState = ADG_ST_VENTING;
      }
      break;
      
    case ADG_ST_VENTING:
      // if see air, vent here. for now, only stay in here for one call.
      
      // do the venting tick thing here in blocking code
      // (but what if stuck venting forever? has that ever happened? maybe should vent a few ticks at a time up to a max.)
      ventTimeTicks = check_vent(); // 0.1s that the air vent ran.

      RTCGetTime(&unixTime_now, &unixTicks);
      cprintf("\n* * TIME = %lu * * VENTED TICKS (# 0.1s ticks) = %d  \n", unixTime_now-unixTime_init, ventTimeTicks);

      cprintf("db: adding %d ticks to adgOut_ventTime(%d)\n", ventTimeTicks, i_cycle);
      adgOut_ventTime[i_cycle] += ventTimeTicks;      
     
      i_incr++;
        
      // now see which state to jump into next call...
      if (i_incr < n_incr)
      {
        Close_Valve; 
        RTCGetTime(&unixTime_now, &unixTicks); 
        cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now-unixTime_init);

        // start the pump, watch oil sensor
        go_pump(tm_pump_secs, OIL_YES ); 
        RTCGetTime(&unixTime_pumpStart, &unixTicks); 
        cprintf("\n* * TIME = %lu  * * * pump start #%d,%d* * * * * * * * *..\n", unixTime_pumpStart-unixTime_init, i_cycle, i_incr);
        
        // change the state, for next time
        myState = ADG_ST_PUMPING;
      }
      else  // bleed time!
      {
        // after venting, 
       
        RTCGetTime(&unixTime_bleedStart, &unixTicks);

        Open_Valve; 
        RTCGetTime(&unixTime_now, &unixTicks);
        cprintf("\n* * TIME = %lu  * * * bleed start for %d seconds * * * * * * * * *..\n", unixTime_bleedStart-unixTime_init, tm_bleed_secs);
        cprintf("\n* * TIME = %lu * * * valve open \n", unixTime_now-unixTime_init);

        // change the state, for next time
        myState = ADG_ST_BLEEDING;
      }
      break;
      
    case ADG_ST_BLEEDING: // DONE with inner pump cycle; time to bleed all out and get ready for another outer cycle.
      RTCGetTime(&unixTime_now, &unixTicks);
      
      if ((unixTime_now - unixTime_bleedStart) > ((ulong)tm_bleed_secs  ) ) 
      {
        // now that done bleeding, calculate mean of the mean volts and amps, and max of the amps for that cycle
        adgOut_pumpVoltageAve[i_cycle] = (uchar)((pump_volts_totalTemp)/n_incr/100);
        adgOut_pumpCurrentAve[i_cycle] = (uchar)((pump_amps_totalTemp)/n_incr);
        adgOut_pumpTime[i_cycle] = (uchar)(pump_time_total/10);
        
        // what if over the type cast limit? force to max.
        if (pump_time_total > 2550)
          adgOut_pumpTime[i_cycle] = 255;
        
        // some debug printing:
        cprintf("db: adgOut_pumpTime[%d] = %d\n", i_cycle, adgOut_pumpTime[i_cycle]);
        cprintf("db: adgOut_pumpVoltageAve[%d] = %d (pump_volts_totalTemp=%d)\n", i_cycle, adgOut_pumpVoltageAve[i_cycle], pump_volts_totalTemp);
        cprintf("db: adgOut_pumpCurrentAve[%d] = %d (pump_amps_totalTemp=%d)\n", i_cycle, adgOut_pumpCurrentAve[i_cycle], pump_amps_totalTemp);
        cprintf("db: adgOut_pumpCurrentMax[%d] = %d\n", i_cycle, adgOut_pumpCurrentMax[i_cycle]);
        
        pump_volts_totalTemp=0, pump_amps_totalTemp=0; pump_ampsMax=0; pump_time_total=0; //re-zero these guys for the next cycle
        // close the valve
        Close_Valve; 
        RTCGetTime(&unixTime_now, &unixTicks); 
        cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now-unixTime_init);

        i_cycle++;  // time for next cycle
          
        if (i_cycle < n_cycles)
        {
          i_incr=0;   // reset the incremental pump ctr (otherwise leave it for printing/knowing how many were done later)
          cprintf("\n* * TIME = %lu * * * * * * * * starting outer cycle #%d * * * * * * * * * *\n", unixTime_now-unixTime_init, i_cycle);
          
          // start the pump, watch oil sensor
          go_pump(tm_pump_secs, OIL_YES ); 
          RTCGetTime(&unixTime_pumpStart, &unixTicks); 
          cprintf("\n* * TIME = %lu  * * * pump start * * * * * * * * *..\n", unixTime_pumpStart-unixTime_init);
          
          // change the state, for next time
          myState = ADG_ST_PUMPING;
        }
        else
        {
          myState = ADG_ST_DONE;
          cprintf("\n* * TIME = %lu * * * * * * * * DONE! * * * * * * * * * *\n", unixTime_now-unixTime_init);
        }
      }
      
      break;
    
  } // end switch state machine
  
  
  // as long as we're not done, then update the total timer and the cycle counter
  if (myState != ADG_ST_DONE)
  {
    total_timeTemp = unixTime_now-unixTime_init;  // this one is to keep a higher resolution during
    adgOut_totalTime = (uchar)(total_timeTemp/360);   // this one is to send in the end as only 1 byte... (0.1 hr units)
    adgOut_Ncycles = i_cycle+1;          // update this as we go, in case we send data or stop this whole thing early
  }
  
    
  return myState;
} //***************************************************************************


void adg_PrintPacket()
{
  // print out all the output ADG packet info stored thus far.
  // this is where could send to iridium in addition.
  //
  // bdr may15
  // inputs:  none
  // outputs: none
  // 
/*  
adgOut_Ncycles
adgOut_Nincr
adgOut_pumpTimeMax
adgOut_bleedTime
adgOut_totalTime
adgOut_pumpTime
adgOut_oilCount
adgOut_ventTime
adgOut_pumpVoltageAve
adgOut_pumpCurrentAve
adgOut_pumpCurrentMax
*/
  int i,j;
  
    // (see AutoDegassPacketSizing_v1.2.xlsx)
    
    // for now let's print out our final data arrays to the screen as a check...
    cprintf("\n* * DATA OUT * * * * * * \n");
    cprintf("adgOut_Ncycles = %d\n",    adgOut_Ncycles);
    cprintf("adgOut_Nincr = %d\n",      adgOut_Nincr);
    cprintf("adgOut_pumpTimeMax = %d\n",adgOut_pumpTimeMax);
    cprintf("adgOut_bleedTime = %d\n",  adgOut_bleedTime);
    cprintf("adgOut_totalTime = %d\n",  adgOut_totalTime);
    
    cprintf("adgOut_pumpTime = [\n");
    for(i=0; i<adgOut_Ncycles; i++)
      cprintf("%d\n", adgOut_pumpTime[i]);
    cprintf("]\n adgOut_oilCount = [\n");
    for(i=0; i<adgOut_Ncycles; i++)   
    {
      for(j=0; j<adgOut_Nincr; j++)   
        cprintf("%d\t", adgOut_oilCount[i][j]);
      cprintf(";\n");
    }
    cprintf("]\n adgOut_ventTime = [\n");
    for(i=0; i<adgOut_Ncycles; i++)
      cprintf("%d\n", adgOut_ventTime[i]);
    cprintf("]\n adgOut_pumpVoltageAve = [\n");
    for(i=0; i<adgOut_Ncycles; i++)
      cprintf("%d\n", adgOut_pumpVoltageAve[i]);
    cprintf("]\n adgOut_pumpCurrentAve = [\n");
    for(i=0; i<adgOut_Ncycles; i++)
      cprintf("%d\n", adgOut_pumpCurrentAve[i]);
    cprintf("]\n adgOut_pumpCurrentMax = [\n");
    for(i=0; i<adgOut_Ncycles; i++)
      cprintf("%d\n", adgOut_pumpCurrentMax[i]);
    cprintf("]\n");
  
}

void adg_GetPumpInfo(short *pump_status, short *pump_oil,  short *pump_time, 
                     short *pump_volts,  short *pump_amps, short *pump_ampsMax)
{ 
  // extract pump info from the most recent pump run. Not sure if this is the most 
  // efficient way to do this, but copied some code frorm watch_pump().
  // bdr may15

  struct spi_param *ss; // jeff I think I still need this so can access the data below.
  

  //short merr, oil, jt, amp, volt,total,max_amp, ti_max, err;
  short err;
  //long tmp;
  short *w; // point to a word (2-byte value)
  struct hyd_param *hyd;


  err = get_hyd_ad();   // get the latest status
  // above calls display_pump, which loads values into the hyd.struct
  
  hyd = all.hyd; // local pointer to the hydraulic struct
  /*  jts may15: this is already done in display_pump, called from get_hyd_ad()
  ss = all.sspi; // point to the spi structure
  hyd->status = merr = ss->sdat[1]; // pump status
  w    = (short*) &(ss->sdat[2]); // have w point to the next char value
  jt   = *w++;   // time (0.1s incr)
  hyd->ti = jt/10; // #s run so far
  amp  = *w++;   // last measured amps
  volt = *w++;   // last measured volts
  hyd->oil = oil  = *w++;   // last oil reading
  hyd->max_amp =max_amp = *w++; // maximum amp [counts]
  hyd->ti_max  = ti_max = *w++; // time of max amp
  hyd->total   = total  = *w++;   // total #s accumulated so far
  */
  
  ss = all.sspi;
  // these variables are the ones we care about in this function:
  *pump_status = ss->sdat[1];
  w = (short *) &(ss->sdat[2]);
  *pump_time = (*w++)/10; 
  *pump_amps    = *w++;
  *pump_volts   = *w++;
  *pump_oil     = *w++;
  *pump_ampsMax = *w++;

  // if there was an error, force all pump info variables to zero, 
  if (err != SPI_CRC_OK)
  {
    cprintf("error in getting pump info: get_hyd_ad err = %d\n", err);
    
    *pump_status = PUMP_WAIT; // force it to think it's still busy? then will call this function again in next state machine loop
    *pump_oil = 0;
    *pump_time = 0;
    
    *pump_volts = 0;
    *pump_amps = 0;
    *pump_ampsMax = 0;
  }
/*

  printf( "PUMP " );
  switch ( merr )
  { // display motor status
    case PUMP_WAIT    :   cprintf("Is running... "); break;
    case PUMP_OK      :   cprintf("Ran OK,            "); break;
    case PUMP_OIL_END :   cprintf("off via oil sensor "); break;
    case PUMP_AMPS    :   cprintf("AMPS >max allowed  "); 
         hyd->bad_amp = TRUE;  //flag that max amps was exceeded
         hyd->nbad++; // increment counter
         break;
    case PUMP_STOP    :   cprintf("stopped by user    "); break;
    case PUMP_TMAX    :   cprintf("AT MAX TIME        "); break;
    case PUMP_OFF     :   cprintf("Pump is off        "); break;

    default       :   printf("UNKOWN[%d] = ",merr);
  }
*/

}

void adg_PrintState(int state)
{
  // only for printing out what state the state machine is currently in.
  // states are #defined above.
  // bdr may15
  
  switch (state)
  {
    case ADG_ST_IDLE:       cprintf("ADG_ST_IDLE"); break;
    case ADG_ST_PUMPING:    cprintf("ADG_ST_PUMPING"); break;
    case ADG_ST_PAUSING_PRE_VENT: cprintf("ADG_ST_PAUSING_PRE_VENT"); break;
    case ADG_ST_VENTING:    cprintf("ADG_ST_VENTING"); break;
    case ADG_ST_BLEEDING:   cprintf("ADG_ST_BLEEDING"); break;
  }
  cprintf("\n");
}

//*****************************************************************************
int   multi_pump_vent  ( int k_cyc, int n_degas, int tm_pmp, int tm_open )
{ // do multiple pump/vent cycles to try to degas the oil
  // inputs:
  //   k_cyc   = pump cycle #: used for output display
  //   n_degas = #attempts to do.
  //   tm_pmp  = #s to pump the oil for each try.
  //   tm_open = #s to wait after tm_pmp before venting.
  //             if all oil is outside, tm_open also opens the valve
  // returns:
  //   accumulative time that the air pump ran [# ticks]
  
  int tvent=0, tpmp = 0, s, secs;
  int i, all_out;
  short tpump_temp;
  
  short prime_ctr, prime_next;
  float v;
  ushort unixTicks;
    
  if (n_degas==1)
  {
    cprintf("starting pump for max %d s...\n", tm_pmp);
            RTCGetTime(&unixTime_now1, &unixTicks);
            cprintf("\n* * TIME = %lu  * * * pump start * * * * * * * * *..\n", unixTime_now1-unixTime_start);
            
         go_pump( tm_pmp, OIL_YES ); // pay attn to the oil sensor
         tpump_temp = watch_pump ( tm_pmp + 4, 0 ); // wait until  pump is done
         secs = tpump_temp;
         
         RTCGetTime(&unixTime_now1, &unixTicks);
         cprintf("\n* * TIME = %lu  * * * pump stop. time on (s) = %d\n", unixTime_now1-unixTime_start, tpump_temp);
            
        
  }
  
  else
  {
  prime_next = 5; // wait at least this many cycles between each prime
  prime_ctr = 0; // keep track of 
    for (i=0; i<n_degas; i++) //+++++++++++++++++++++++++++++++++++++++++
    {  // do individual pumps
         cprintf("starting pump (increment #%d) for max %d s...\n", i, tm_pmp);
         RTCGetTime(&unixTime_now1, &unixTicks);
         cprintf("\n* * TIME = %lu  * * * pump start * * * * * * * * *..\n", unixTime_now1-unixTime_start);
            
         go_pump( tm_pmp, OIL_YES ); // pay attn to the oil sensor
         tpump_temp = watch_pump ( tm_pmp + 4, 0 ); // wait until  pump is done
         secs = tpump_temp;
         
         RTCGetTime(&unixTime_now1, &unixTicks);
         cprintf("\n* * TIME = %lu  * * * pump stop. time on (s) = %d\n", unixTime_now1-unixTime_start, tpump_temp);
            
         all_out  =  ( all.hyd->status == PUMP_OIL_END ); // True if all pumped out
         cprintf("pump done. now opening valve if ended due to oil P check.\n");
         if (all_out) 
         {
            RTCGetTime(&unixTime_now1, &unixTicks);
            cprintf("\n* * TIME = %lu  * * * valve open..\n", unixTime_now1-unixTime_start);
            Open_Valve; // let some back in
         }
         cprintf("pausing for %d s...\n", tm_open);
         sleep_check( tm_open, PIT_IRQ2_RXD, TRUE );
         
         if (all_out) 
         {
            RTCGetTime(&unixTime_now1, &unixTicks);
            cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now1-unixTime_start);
            Close_Valve;  // close the valve
         }

if (PRIME_PUMP_FANCY) 
{           
  if (prime_ctr >= prime_next && all.hyd->oil < 100)
  {            
                // prime the pump here?
       RTCGetTime(&unixTime_now1, &unixTicks);
    cprintf("\n* * TIME = %lu * * * priming the pump for 10 s with valve open (because oil P = %d which is <100 and on >=10th increment...\n", unixTime_now1-unixTime_start, all.hyd->oil);

       Open_Valve;
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * valve open.\n", unixTime_now1-unixTime_start );
       
            RTCGetTime(&unixTime_now1, &unixTicks);
            cprintf("\n* * TIME = %lu  * * * pump start * * * * * * * * *..\n", unixTime_now1-unixTime_start);
       go_pump( 10, OIL_YES ); // pay attn to the oil sensor
       tpump_temp = watch_pump ( 12, 0 ); // wait until  pump is done
       
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu  * * * pump stop. time on (s) = %d\n", unixTime_now1-unixTime_start, tpump_temp);
       
       Close_Valve;
       RTCGetTime(&unixTime_now1, &unixTicks);
       cprintf("\n* * TIME = %lu * * * valve close.\n", unixTime_now1-unixTime_start);
       prime_ctr=0;
  }
}
            
         cprintf("doing the check vent thing...\n");
         RTCGetTime(&unixTime_now1, &unixTicks);
         s = check_vent(); // 0.1s that the air vent ran.
         if (s==0) {cprintf("THERE IS NO AIR TO VENT.\n");}
         
         cprintf("\n* * TIME = %lu * * VENTED TICKS (# 0.1s ticks) = %d  \n", unixTime_now1-unixTime_start, s);  
         
         tvent += s;    // accumulate
         tpmp  += secs; // accum.
         // display info
         cprintf("VENTi %4d %2d %4d %4d   %3d %3d \n",
                      k_cyc, i, tpmp, secs, tvent, s );
                      
         RTCGetTime(&unixTime_now1, &unixTicks);
         cprintf("\n* * TIME = %lu * * * total vented air so far within this cycle (# 0.1s ticks) = %5d  \n", unixTime_now1-unixTime_start, tvent);
         prime_ctr++;

         
    } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  }
  v = tvent*0.1;  // now in seconds
  printf("VENT  %4d  %4d  %4.1f cyc, pmp_tm, vent_tm \n",
               k_cyc, tpmp, v );
  
  return tvent;
} //***************************************************************************







//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*** 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 |= 0x8000;   // flag that it is a divide-by-zero
	// RTE(); this is added by the IEV_C_FUNCT
} //***************************************************************************


