Skip to content. | Skip to navigation

Personal tools

parse.cpp

parse.cpp

parse.cpp

/////////////////////////////////////////////////////////////////////////////
// PARSE.CPP
//
//  Last updated: 7/14/2005
//
//  Part of the source code for the Vane End Actuator Control System
//
// This file contains the functions that parse serial and keyboard input,
// and execute the appropriate functions to carry out the commands.
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// ParseKB: Parse a keyboard command line
int ParseKB(char *line,int SerialCommand,char *errmsg)
// This routine parses a keyboard command-line, and executes the
// appropriate code to accomplish the command.
// Returns a 0 if OK, >= 1 on a parse error
// SerialCommand = 1 if this is a free-form serial line we're parsing,
// SerialCommand = 0 if this is a local keyboard command.
// errmsg is filled with an error message to send to upstream computers.
{
	int i,j,e,itemp;
	float ftemp,ftemp2;
	char s[255],command[255],temp[255];
	int CmdError = 0;
	float newx,newy,newz,newh,newv; // Temp variables
	int MotorNum; // Motor to move for the I commands
	int Dist; // Distance to move for the I commands
	int Corner; // Corner # for the TP and TV commands
	int OnOff;  // On or off for the TP and TV commands
	char* Cmds[10];	// Tokenized command line
	int CmdCount = 0;		// Number of command tokens

	if (!SerialCommand)
	{
		// Display the entered command
		InputLog.Add("* %s",0,line);
		InputLog.DisplayAll();
  }

	Log.Add("ParseKB(%d): Parsing \"%s\"",VERBOSE,__LINE__,line);

	// Blank input line
	if (strlen(line) == 0)
		return(0);

	// Break the line up into command tokens
	Cmds[0] = strtok(line," ");
	while ((Cmds[CmdCount] != NULL) && (CmdCount < 9))
	{
		CmdCount++;
		Cmds[CmdCount] = strtok(NULL," ");
	}

	// Adjust tensions
	if (!strcmp(Cmds[0],"A") && (CmdCount == 2) && !SerialCommand)
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%d",&Dist) == 1)
		{
			Dist = abs(Dist); // No negative tensions allowed
			AdjustTension(Dist);
		}
		else
			CmdError = 1;
	}
	// Toggle tension display from pounds to mV and back
	else if (!strcmp(Cmds[0],"P") && (CmdCount == 1) && !SerialCommand)
		Flags.ToggleTensionDisplay();
	// Edit VANE.INI on the fly
	else if (!strcmp(Cmds[0],"EDIT") && (CmdCount == 1) && !SerialCommand)
	{
		PauseUpdate();
		EditVane();
	}
	// Individual motor move on radial controller
	else if (!strcmp(Cmds[0],"IR") && (CmdCount == 3))
	{
		PauseUpdate();
		if ( (sscanf(Cmds[1],"%d",&MotorNum) == 1) &&
				 (sscanf(Cmds[2],"%d",&Dist) == 1) )
			if ((abs(Dist) <= MaxManualMove) && (MotorNum >= 1) && (MotorNum <= 4))
			{
				if (e = MoveIndividualMotor(Radial,MotorNum,Dist))
					EDSLog.Add(13,"Individual move error %d",e);
			}
			else
			{
				CmdError = 2;
				strcpy(errmsg,"Request too large");
			}
		else
			CmdError = 1;
	}
	// Individual motor move on axial controller
	else if (!strcmp(Cmds[0],"IA") && (CmdCount == 3))
	{
		PauseUpdate();
		if ( (sscanf(Cmds[1],"%d",&MotorNum) == 1) &&
				 (sscanf(Cmds[2],"%d",&Dist) == 1) )
			if ((abs(Dist) <= MaxManualMove) && (MotorNum >= 1) && (MotorNum <= 4))
			{
				if (e = MoveIndividualMotor(Axial,MotorNum,Dist))
					EDSLog.Add(13,"Individual move error %d",e);
			}
			else
			{
				CmdError = 2;
				strcpy(errmsg,"Request too large");
			}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"TR") && (CmdCount == 1) && !SerialCommand)
	// Radial DMC Terminal
	{
		PauseUpdate();
		DMCTerminal(Radial);
	}
	else if (!strcmp(Cmds[0],"TA") && (CmdCount == 1) && !SerialCommand)
	// Axial DMC Terminal
	{
		PauseUpdate();
		DMCTerminal(Axial);
	}
	else if (!strcmp(Cmds[0],"TD") && (CmdCount == 1) && !SerialCommand)
	// DGH Terminal (on COM2:)
	{
		PauseUpdate();
		DGHTerminal();
	}
	else if (!strcmp(Cmds[0],"T3") && (CmdCount == 1) && !SerialCommand)
	// DGH Terminal (on COM2:) at 300 baud for setup
	{
		PauseUpdate();
		SetComPortSpeed(Guest,300);
		DGHTerminal();
		RestoreComPortSpeed(Guest);
	}
	else if (!strcmp(Cmds[0],"TIR") && (CmdCount == 2) && !SerialCommand)
	// Terminal with instrument rotators
	{
		if (sscanf(Cmds[1],"%d",&itemp) == 1)
		{
			PauseUpdate();
			IRTerminal(itemp);
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"TP") && (CmdCount == 3))
	// Toggle vane end pressure (extension)
	{
		PauseUpdate();
		if ( (sscanf(Cmds[1],"%d",&Corner) == 1) &&
				 (sscanf(Cmds[2],"%d",&OnOff) == 1) )
		{
			if ((Corner < 1) || (Corner > 4) || (OnOff < 0) || (OnOff > 1))
				CmdError = 1;
			else
			{
				Corner--;
				if (OnOff)
				{
					// Turn vacuum off
					sprintf(command,"SB%d\r",Corner*2+1);
					BDMCCommand(Axial,command,temp,DMCFastCommand);
					// Turn pressure on
					sprintf(command,"CB%d\r",Corner*2+2);
					BDMCCommand(Axial,command,temp,DMCFastCommand);
				}
				else
				{
					// Turn pressure off
					sprintf(command,"SB%d\r",Corner*2+2);
					BDMCCommand(Axial,command,line,DMCFastCommand);
				}
			}
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"TV") && (CmdCount == 3))
	// Toggle vane end "vacuum" (retraction)
	{
		PauseUpdate();
		if ( (sscanf(Cmds[1],"%d",&Corner) == 1) &&
				 (sscanf(Cmds[2],"%d",&OnOff) == 1) )
		{
			if ((Corner < 1) || (Corner > 4) || (OnOff < 0) || (OnOff > 1))
				CmdError = 1;
			else
			{
				Corner--;
				if (OnOff)
				{
					// Turn pressure off
					sprintf(command,"SB%d\r",Corner*2+2);
					BDMCCommand(Axial,command,temp,DMCFastCommand);
					// Turn vacuum on
					sprintf(command,"CB%d\r",Corner*2+1);
					BDMCCommand(Axial,command,temp,DMCFastCommand);
				}
				else
				{
					// Turn vacuum off
					sprintf(command,"SB%d\r",Corner*2+1);
					BDMCCommand(Axial,command,line,DMCFastCommand);
				}
			}
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"TE") && (CmdCount == 2))
	// TE: toggle tension (DGH) enabled 1-4 = axial, 5-8 = radial
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%d",&Corner) == 1)
		{
			if ((Corner < 1) || (Corner > 8))
				CmdError = 1;
			else
			{
				Corner--;
				Cell.DGHs[Corner].Disabled = !Cell.DGHs[Corner].Disabled;
				Cell.DGHs[Corner].Display();
			}
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"!") && (CmdCount == 1))
	// Stop Motors
	{
		Flags.ClearStatus(SFMoveInProgress);
		Flags.ClearFatal(FFNoMotorResponse);
	}
	else if ((!strcmp(Cmds[0],"Q") || !strcmp(Cmds[0],"EXIT"))
					&& (CmdCount == 1) && !SerialCommand)
		Quit = 1;
	else if (!strcmp(Cmds[0],"R") && (CmdCount == 1))
	// Reset all possible fatal flags
	{
		// Errors reading VANE.INI can only be rectified
		// by exiting and restarting the program.
		// Homing errors can only be fixed by re-executing
		// a Home command ("HOME").
		PauseUpdate();
		DMCStep = 0;
		MoveStep = 0;
		GetEncodersStep = 0;
		UpdateStep = 0;
		CheckFatalStep = 0;
		GetSwitchesStep = 0;
		UpdateEncodersStep = 0;
		MoveAllMotorsStep = 0;
		BacklashStep = 0;
		PauseOK = 0;
		Flags.Fatal &= FFINIFile | FFHome;
		Flags.Status = 0;
		Flags.SetMoveStage(MSIdle);
		Flags.DisplayAll();
		Cell.Init();
		if (e = ConfigDMCs())
		{
			EDSLog.Add(8,"DMC config error %d",e);
			Flags.SetFatal(FFEncoders);
		}
		else if (e = ResetEmergency())
		{
			EDSLog.Add(9,"Emerg stop reset error %d",e);
			Flags.SetFatal(FFEmergencyStop);
		}
		// Put tensions within legal bounds until they're next read
		for (i=0;i<=7;i++)
			Cell.DGHs[i].Tension = (Cell.DGHs[i].MaxTension + Cell.DGHs[i].MinTension) / 2;
		// Put encoders within legal bounds until they're next read
		for (i=0;i<=3;i++)
		{
			Cell.AE[i] = (Cell.MaxAE[i] + Cell.MinAE[i]) / 2;
			Cell.RE[i] = (Cell.MaxRE[i] + Cell.MinRE[i]) / 2;
		}
		Cell.DisplayAll();
	}
	else if (!strcmp(Cmds[0],"HOME") && (CmdCount == 1))
	// Home
	{
		PauseUpdate();
		// Force logs to display every log entry during home
		Log.ForceDisplay = 1;
		InputLog.ForceDisplay = 1;
		if (e = Cell.Home())
		{
			EDSLog.Add(3,"Encoder homing error %d",e);
			Flags.SetFatal(FFHome);
		}
		else
		{
			Flags.ClearFatal(FFHome);
			EDSLog.Add(996,"Encoder homing success");
		}
		// Resume asynchronous logs
		Log.ForceDisplay = 0;
		InputLog.ForceDisplay = 0;
	}
	else if (!strcmp(Cmds[0],"W") && (CmdCount == 1) && !SerialCommand)
	// Write current location as the new zero-point
		WriteZero();
	else if (!strcmp(Cmds[0],"VERB") && (CmdCount == 2) && !SerialCommand)
	// Verbose level
	{
		if (sscanf(Cmds[1],"%d",&itemp) != 1)
			CmdError = 1;
		else if ((itemp < 0) || (itemp > 3))
			CmdError = 1;
		else
		{
			Log.VerboseLevel = itemp;
			InputLog.Add("Verbose level: %d",BRIEF,itemp);
		}
	}
	else if (!strcmp(Cmds[0],"X") && (CmdCount == 2))
	// X Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newx) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dx = newx;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"Y") && (CmdCount == 2))
	// Y Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newy) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dy = newy;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"Z") && (CmdCount == 2))
	// Z Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newz) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dz = newz;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"H") && (CmdCount == 2))
	// H Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newh) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dh = newh;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"V") && (CmdCount == 2))
	// V Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newv) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dv = newv;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"G") && (CmdCount == 6))
	// Motion: go to x,y,z,h,v
	{
		PauseUpdate();
		if ( (sscanf(Cmds[1],"%f",&newx) == 1) &&
				 (sscanf(Cmds[2],"%f",&newy) == 1) &&
				 (sscanf(Cmds[3],"%f",&newz) == 1) &&
				 (sscanf(Cmds[4],"%f",&newh) == 1) &&
				 (sscanf(Cmds[5],"%f",&newv) == 1) )
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dx = newx;
			Cell.dy = newy;
			Cell.dz = newz;
			Cell.dh = newh;
			Cell.dv = newv;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	// Delta versions of above motions (X,Y,Z,H,V,G)
	else if (!strcmp(Cmds[0],"DX") && (CmdCount == 2))
	// DX Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newx) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dx += newx;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"DY") && (CmdCount == 2))
	// DY Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newy) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dy += newy;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"DZ") && (CmdCount == 2))
	// DZ Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newz) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dz += newz;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"DH") && (CmdCount == 2))
	// DH Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newh) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dh += newh;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"DV") && (CmdCount == 2))
	// DV Motion
	{
		PauseUpdate();
		if (sscanf(Cmds[1],"%f",&newv) == 1)
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dv += newv;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	else if (!strcmp(Cmds[0],"DG") && (CmdCount == 6))
	// Delta Motion: go to x,y,z,h,v
	{
		PauseUpdate();
		if ( (sscanf(Cmds[1],"%f",&newx) == 1) &&
				 (sscanf(Cmds[2],"%f",&newy) == 1) &&
				 (sscanf(Cmds[3],"%f",&newz) == 1) &&
				 (sscanf(Cmds[4],"%f",&newh) == 1) &&
				 (sscanf(Cmds[5],"%f",&newv) == 1) )
		{
			Flags.SetStatus(SFMoveInProgress);
			Flags.SetMoveStage(MSBacklash);
			Cell.dx += newx;
			Cell.dy += newy;
			Cell.dz += newz;
			Cell.dh += newh;
			Cell.dv += newv;
			Cell.DisplayDestination();
		}
		else
			CmdError = 1;
	}
	// All instrument rotator commands
	else if ( ((!strcmp(Cmds[0],"NASW")) ||
						 (!strcmp(Cmds[0],"NASE")) ||
						 (!strcmp(Cmds[0],"CASS")) ||
						 (!strcmp(Cmds[0],"AUX1")) ||
						 (!strcmp(Cmds[0],"AUX2")) ||
						 (!strcmp(Cmds[0],"AUX3")))
						&& (CmdCount >= 2) )
	{
		if (!strcmp(Cmds[0],"NASW")) itemp = IRNASW;
		else if (!strcmp(Cmds[0],"NASE")) itemp = IRNASE;
		else if (!strcmp(Cmds[0],"CASS")) itemp = IRCASS;
		else if (!strcmp(Cmds[0],"AUX1")) itemp = IRAUX1;
		else if (!strcmp(Cmds[0],"AUX2")) itemp = IRAUX2;
		else itemp = IRAUX3; // AUX3
		// Enable IR communication
		if (!strcmp(Cmds[1],"ENABLE") && (CmdCount == 2))
		{
			IRs[itemp].Enable();
			ActiveIR = itemp;
			for (i=0;i<=5;i++)
				IRs[i].DisplaySelection();
			IRErr2Chart.Reset();
			IRErrChart.Reset();
			IRVel2Chart.Reset();
			IRVelChart.Reset();
			IRVoltChart.Reset();
		}
		// Disable IR communication
		else if (!strcmp(Cmds[1],"DISABLE") && (CmdCount == 2))
			IRs[itemp].Disable();
		// Allow IR to spin freely.  VERY DANGEROUS!!
		//else if (!strcmp(Cmds[1],"FREE") && (CmdCount == 2) && !SerialCommand)
		//	IRs[itemp].Free();
		// Stop motion
		else if (!strcmp(Cmds[1],"STOP") && (CmdCount == 2))
			IRs[itemp].Stop();
		// Disable Galil's internal position servo
		else if (!strcmp(Cmds[1],"MO") && (CmdCount == 2))
		{
			PauseIR();
			IRs[itemp].BSerDMCCommand("MO\r",command,200);
		}
		// Enable Galil's internal position servo
		else if (!strcmp(Cmds[1],"SH") && (CmdCount == 2))
		{
			PauseIR();
			IRs[itemp].BSerDMCCommand("SH\r",command,200);
		}
		// Toggle IR motor power
		else if (!strcmp(Cmds[1],"POWER") && (CmdCount == 2))
			IRs[itemp].TogglePower();
		// Move given number of steps, relative, immediately
		else if (!strcmp(Cmds[1],"MOVE") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%d",&i) == 1)
				IRs[itemp].MoveSteps(i);
		}
		// Move given number of degrees, relative, immediately
		else if (!strcmp(Cmds[1],"MOVEA") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
				IRs[itemp].MoveAngle(ftemp);
		}
		// Move given number of degrees, absolute
		else if (!strcmp(Cmds[1],"GOA") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
      {
				if (!IRs[itemp].Homed)
  	     	EDSLog.Add(500,"Warning! Instrument Rotator not homed");
				IRs[itemp].Go(ftemp,0);
      }
		}
		// Move given number of degrees, relative
		else if (!strcmp(Cmds[1],"GOR") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
				IRs[itemp].Go(ftemp,1);
    }
    // Move given number of degrees(abs), at certain speed, accurate servo
    // 3rd argument is the UT the TCS sent this command so that we can do jitter
    // correction for serial link random delays (30-70 msecs).
    else if (!strcmp(Cmds[1],"GOS") && (CmdCount == 5))
    {
      if ( (sscanf(Cmds[2],"%f",&ftemp ) == 1) &&
           (sscanf(Cmds[3],"%f",&ftemp2) == 1) &&
           (sscanf(Cmds[4],"%s",&temp) == 1) )
      {
        //EDSLog.Add(900,"%f  %f  %s",ftemp,ftemp2,temp);
        if (!IRs[itemp].Homed)
          EDSLog.Add(500,"Warning! Instrument Rotator not homed");
        IRs[itemp].GoS(ftemp,ftemp2,temp);
      }
		}
		else if (!strcmp(Cmds[1],"JOG") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
				IRs[itemp].Jog(ftemp);
		}
		else if (!strcmp(Cmds[1],"HOME") && (CmdCount == 2))
			IRs[itemp].Home();
		else if (!strcmp(Cmds[1],"VEL") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].Spd = ftemp * IRs[itemp].Revolution / 360.0;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
		// Set IR active (display info on charts)
		else if (!strcmp(Cmds[1],"DISPLAY") && (CmdCount == 2) && !SerialCommand)
		{
			ActiveIR = itemp;
			for (i=0;i<=5;i++)
				IRs[i].DisplaySelection();
			IRErr2Chart.Reset();
			IRErrChart.Reset();
			IRVel2Chart.Reset();
			IRVelChart.Reset();
			IRVoltChart.Reset();
		}
		// Reset IR communication
		else if (!strcmp(Cmds[1],"RESET") && (CmdCount == 2))
			IRs[itemp].Reset();
		// Set IR acceleration
		else if (!strcmp(Cmds[1],"ACC") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].Acc = ftemp * IRs[itemp].Revolution / 360.0;
				IRs[itemp].Reset();
			}
			else
				CmdError = 1;
		}
		// Set IR deceleration
		else if (!strcmp(Cmds[1],"DEC") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].Dec = ftemp * IRs[itemp].Revolution / 360.0;
				IRs[itemp].Reset();
			}
			else
				CmdError = 1;
		}
		// Set max IR velocity
		else if (!strcmp(Cmds[1],"SPD") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].Spd = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
		// Set IR's Kp
		else if (!strcmp(Cmds[1],"P") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].P = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
		// Set IR's Ki
		else if (!strcmp(Cmds[1],"I") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].I = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
    // Set IR's Kd
		else if (!strcmp(Cmds[1],"D") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].D = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
    // Set IR's Speed servo P
		else if (!strcmp(Cmds[1],"SPDP") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].SpdP = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
    // Set IR's Speed servo I
		else if (!strcmp(Cmds[1],"SPDI") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].SpdI = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
    // Set IR's Speed servo D
		else if (!strcmp(Cmds[1],"SPDD") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].SpdD = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
    // Set IR's Speed servo IL
		else if (!strcmp(Cmds[1],"SPDIL") && (CmdCount == 3))
		{
			if (sscanf(Cmds[2],"%f",&ftemp) == 1)
			{
				ftemp = fabs(ftemp);
				IRs[itemp].SpdIL = ftemp;
				IRs[itemp].ResetParams();
			}
			else
				CmdError = 1;
		}
    // Displays servo numbers
		else if (!strcmp(Cmds[1],"DISPS") && (CmdCount == 2))
			IRs[itemp].dispflag = !IRs[itemp].dispflag;
    // Toggle display of IR's speed servo err
		else if (!strcmp(Cmds[1],"SPDERR") && (CmdCount == 2))
    {
      if (IRs[itemp].GoSDisplayError)
        IRs[itemp].GoSDisplayError = 0;
      else
        IRs[itemp].GoSDisplayError = 1;
      IRs[itemp].DisplayMCurrent = 0;
      IRs[itemp].DisplayMEStatus = 0;
      IRs[itemp].DisplaySEStatus = 0;
		}
    // Toggle display of IR's motor current in Error graph
		else if (!strcmp(Cmds[1],"MCURR") && (CmdCount == 2))
    {
      if (IRs[itemp].DisplayMCurrent)
        IRs[itemp].DisplayMCurrent = 0;
      else
        IRs[itemp].DisplayMCurrent = 1;
      IRs[itemp].GoSDisplayError = 0;
      IRs[itemp].DisplayMEStatus = 0;
      IRs[itemp].DisplaySEStatus = 0;
		}
    // Toggle display of IR's master encoder status in Error graph
		else if (!strcmp(Cmds[1],"MESTAT") && (CmdCount == 2))
    {
      if (IRs[itemp].DisplayMEStatus)
        IRs[itemp].DisplayMEStatus = 0;
      else
        IRs[itemp].DisplayMEStatus = 1;
      IRs[itemp].GoSDisplayError = 0;
      IRs[itemp].DisplayMCurrent = 0;
      IRs[itemp].DisplaySEStatus = 0;
		}
    // Toggle display of IR's slave encoder status in Error graph
		else if (!strcmp(Cmds[1],"SESTAT") && (CmdCount == 2))
    {
      if (IRs[itemp].DisplaySEStatus)
        IRs[itemp].DisplaySEStatus = 0;
      else
        IRs[itemp].DisplaySEStatus = 1;
      IRs[itemp].GoSDisplayError = 0;
      IRs[itemp].DisplayMCurrent = 0;
      IRs[itemp].DisplayMEStatus = 0;
		}
    else if (!strcmp(Cmds[1],"PROG") && (CmdCount == 2))
	  // Download IRSERVO.DMC to the given IR
	  {
		  PauseUpdate();
      ProgIR(itemp);
    }
    // All CASS-MAG2 related commands.
    // CASS Clamping system
    // Shortcut to move CASS to an observing port
		else if ((Telescope == 2) && (itemp == IRCASS) && (CmdCount == 2))
		{
      if (!strcmp(Cmds[1],"CLAMP"))
        M2Cass.EngageClamp();
      else if (!strcmp(Cmds[1],"RELEASE"))
        M2Cass.ReleaseClamp();
      // Only feeds/cuts the air. Use it with care!
      else if (!strcmp(Cmds[1],"BRAKE"))
      {
			  PauseIR();
        if (IRs[itemp].Brake)
          IRs[itemp].BSerDMCCommand("CB1\r",command,200);
        else
          IRs[itemp].BSerDMCCommand("SB1\r",command,200);
      }
			else if (!strcmp(Cmds[1],"NASW"))
			{
				if (!IRs[itemp].Homed)
					EDSLog.Add(500,"Warning! Instrument Rotator not homed");
				//IRs[itemp].Go(M2Cass.CPNASW,0);
				M2Cass.ChangePort(M2Cass.CENASW,M3NASW);
			}
      else if (!strcmp(Cmds[1],"NASE"))
			{
				if (!IRs[itemp].Homed)
					EDSLog.Add(500,"Warning! Instrument Rotator not homed");
				//IRs[itemp].Go(M2Cass.CPNASE,0);
				M2Cass.ChangePort(M2Cass.CENASE,M3NASE);
			}
			else if (!strcmp(Cmds[1],"AUX1"))
			{
				if (!IRs[itemp].Homed)
					EDSLog.Add(500,"Warning! Instrument Rotator not homed");
				//IRs[itemp].Go(M2Cass.CPAUX1,0);
				M2Cass.ChangePort(M2Cass.CEAUX1,M3AUX1);
			}
			else if (!strcmp(Cmds[1],"AUX2"))
			{
				if (!IRs[itemp].Homed)
					EDSLog.Add(500,"Warning! Instrument Rotator not homed");
				//IRs[itemp].Go(M2Cass.CPAUX2,0);
				M2Cass.ChangePort(M2Cass.CEAUX2,M3AUX2);
			}
			else if (!strcmp(Cmds[1],"AUX3"))
			{
				if (!IRs[itemp].Homed)
					EDSLog.Add(500,"Warning! Instrument Rotator not homed");
				//IRs[itemp].Go(M2Cass.CPAUX3,0);
				M2Cass.ChangePort(M2Cass.CEAUX3,M3AUX3);
			}
		  else
			  CmdError = 1;
		}
		else
			CmdError = 1;
	}
	// Set Error chart scale
	else if (!strcmp(Cmds[0],"ERROR") && (CmdCount == 2) && !SerialCommand)
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1)
		{
			ftemp = fabs(ftemp);
			if (ftemp > 99999)
				ftemp = 99999;
			IRErr2Chart.SetScale(ftemp);
			IRErrChart.SetScale(ftemp);
			DisplayScales();
		}
		else
			CmdError = 1;
  }
  // Set velocity chart scale
	else if (!strcmp(Cmds[0],"VEL") && (CmdCount == 2) && !SerialCommand)
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1)
		{
			ftemp = fabs(ftemp);
			if (ftemp > 9.999)
				ftemp = 9.999;
			IRVel2Chart.SetScale(ftemp);
			IRVelChart.SetScale(ftemp);
			DisplayScales();
		}
		else
			CmdError = 1;
	}
	// Set voltage chart scale
	else if (!strcmp(Cmds[0],"VOLT") && (CmdCount == 2) && !SerialCommand)
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1)
		{
			ftemp = fabs(ftemp);
			if (ftemp > 99.9)
				ftemp = 99.9;
			IRVoltChart.SetScale(ftemp);
			DisplayScales();
		}
		else
			CmdError = 1;
	}
	// Pressure/vacuum control commands
	// Toggle pressure
	else if (!strcmp(Cmds[0],"PRES") && (CmdCount == 1))
	{
		PauseUpdate();
		if (pflag)
		{
			BDMCCommand(Radial,"CB3\r",temp,DMCFastCommand);	// Turn on air
    	pflag = 0;
		}
		else
    {
			BDMCCommand(Radial,"SB3\r",temp,DMCFastCommand);	// Turn off air
    	pflag = 1;
    }
  }
	// Toggle vacuum
	else if (!strcmp(Cmds[0],"VAC") && (CmdCount == 1))
	{
		PauseUpdate();
		if (vflag)
		{
			BDMCCommand(Radial,"CB4\r",temp,DMCFastCommand);	// Turn on vacuum
    	vflag = 0;
		}
		else
    {
			BDMCCommand(Radial,"SB4\r",temp,DMCFastCommand);	// Turn off vacuum
    	vflag = 1;
    }
	}
	// Toggle pressure/vacuum control mode
	else if (!strcmp(Cmds[0],"PVM") && (CmdCount == 1))
	{
		PauseUpdate();
		if (PresVacMode == PVMAuto)
		{
			PresVacMode = PVMIdle;

			if (f11Present && !f5Present) {
				// Turn off pressure
				BDMCCommand(Radial,"CB3\r",temp,DMCFastCommand);
				pflag = 0;
				// Turn off vacuum
				BDMCCommand(Radial,"CB4\r",temp,DMCFastCommand);
				vflag = 0;
			}

			// F5
			if (f5Present) {
				ValvesToAct = 0x00;
				// Close all F5 valves
				ParPortOut(&parport, 0xFF);
				for (i = 11; i <= 16 ; i++) {
					PresVac[i].vaccom = 0;
					PresVac[i].precom = 0;
				}
			}
		}
		else {
			PresVacMode = PVMAuto;
			ValvesToAct = 0xFF;
		}

		if (f11Present && !f5Present) PresVac[0].Display();
		else if (f5Present) F5PresVacDisplay();
	}
	// Set Pres/Vac DGHsmillivolt chart scale
	else if (!strcmp(Cmds[0],"PVS") && (CmdCount == 2) && !SerialCommand)
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1) {
			ftemp = fabs(ftemp);
			if (ftemp > 10.0)
				ftemp = 10.0;
			if (f11Present && !f5Present) {
				PresVacCharts[0].SetScale(ftemp);
			}
			else if (f5Present) {
				PresVacCharts[1].SetScale(ftemp);
				PresVacCharts[2].SetScale(ftemp);
				PresVacCharts[3].SetScale(ftemp);
				PresVacCharts[4].SetScale(ftemp);
			}
			DisplayScales();
		}
		else
			CmdError = 1;
	}
	// Set Pres/Vac Kp gain
	else if (!strcmp(Cmds[0],"PVKP") && (CmdCount == 2))
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1)
			PresVac[0].Kp = ftemp;
		else
			CmdError = 1;
	}
	// Set Pres/Vac Ki gain
	else if (!strcmp(Cmds[0],"PVKI") && (CmdCount == 2))
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1)
			PresVac[0].Ki = ftemp;
		else
			CmdError = 1;
	}
	// Set Pres/Vac Kd gain
	else if (!strcmp(Cmds[0],"PVKD") && (CmdCount == 2))
	{
		if (sscanf(Cmds[1],"%f",&ftemp) == 1)
			PresVac[0].Kd = ftemp;
		else
			CmdError = 1;
	}
	else
		CmdError = 1;
	if (CmdError == 1)
		strcpy(errmsg,"Command decode error");
	// Display error message locally if necessary
	if ((CmdError >= 1) && (!SerialCommand))
		InputLog.Add("  %s",BRIEF,errmsg);
	return(CmdError);
}

/////////////////////////////////////////////////////////////////////////////
// ParseSer: Parse a serial command line
void ParseSer(char line[80])
// This routine parses a command line from the serial port, and executes the
// appropriate code to accomplish the command.
{
	int i,e;
	char s[255];
	float newx,newy,newz,newh,newv; // Temp variables
	char temp[80];
	struct dostime_t t;
  int ParsedOK = 0;

	Log.Add("ParseSer(%d): Parsing \"%s\"",VERBOSE,__LINE__,line);
	// Is message for us?
	if ((line[0] == Prompt) && (line[1] == Address))
	{
		switch (line[2])
		{
			// Send next EDS message
			case '2':
      {
				EDSLog.SendNextMessage();
        ParsedOK = 1;
			} break;
			// Repeat last EDS message
			case '3':
      {
				EDSLog.RepeatLastMessage();
        ParsedOK = 1;
			} break;
			// Set UT
			case '4':
			{
				if (VerifyChecksum(line) ||
						(sscanf(&line[3],"%2d%2d%2d%2d",&t.hour,&t.minute,&t.second,
						 &t.hsecond) != 4))
				{
					RespondToHost("40\r");
					EDSLog.Add(19,"Incorrectly formatted UT message from TCS");
				}
				else
				{
					EDSLog.Add(986,"UT set by TCS to %02d %02d %02d.%02d",
										 t.hour,t.minute,t.second,t.hsecond);
					settime(&t);
					RespondToHost("41\r");
          ParsedOK = 1;
				}
			}	break;
			// Free-form command
			case '9':
			{
				if (VerifyChecksum(line) ||
						(line[3] < '0') || (line[3] > '9') ||
						(line[4] < '0') || (line[4] > '9'))
					RespondToHost("?\r");
				else
				{
					i = (line[3] - '0') * 10 + line[4] - '0';
					if (strlen(line) != i + 7)
						RespondToHost("?\r");
					else
					{
						strncpy(s,&line[5],i);
            s[i] = 0;
		        ParsedOK = 1;
						if (e = ParseKB(s,1,temp))
						{
							sprintf(s,"9%d%02d%s",e,strlen(temp),temp);
							RespondToHostWithChecksum(s);
						}
						else
							RespondToHostWithChecksum("9000");
					}
				}
			} break;
			default:
				RespondToHost("?\r");
		}

    if (ParsedOK)
    {
		  if (HostComErr > 2)
			  EDSLog.Add(983,"Host error messages resumed");
    	HostComErr = 0;
      HostTimer = Timer;
    }
    else
    {
    	HostComErr++;
		  // Don't display more than 2 com errors in a row
		  if (HostComErr <= 2)
			  EDSLog.Add(21,"Host com error 1");
		  else if (HostComErr == 3)
			  EDSLog.Add(22,"Host error messages suspended");
    }
	}
}

/////////////////////////////////////////////////////////////////////////////
// Parse: Checks for keyboard and serial input
void Parse()
{
	int c,i;
	char temp[255];

	// Check for scroll-lock, and pause log if necessary
	Log.Paused = (*((byte *)0x417)) & 0x10;

	// Check for a character from the keyboard
	if (kbhit())
	{
		c = toupper(getch());
		// Restore display if help screen is visible
		if (HelpFlag)
		{
			HelpFlag = 0;
			DisplayEnable = 1;
			// Restore normal display
			InitDisplay();
			Cell.DisplayAll();
			return;
		}

		// On a carriage return, we either need to parse a keyboard command
		// line (local mode), or check for the serial to keyboard mode change
		// password.
		if (c == 0)
		{
			// Check for arrow and pgup/pgdn keys for log scrolling
			c = getch();
			switch(c)
			{
				case 72:
				// Up arrow
				{
					Log.Up();
				} break;
				case 80:
				// Down arrow
				{
					Log.Down();
				} break;
				case 73:
				// Page up
				{
					Log.PageUp();
				} break;
				case 81:
				// Page down
				{
					Log.PageDown();
				} break;
				case 71:
				// Home
				{
					Log.Home();
				} break;
				case 79:
				// End
				{
					Log.End();
				} break;
				case 75:
				// Left
				{
					Log.Left();
				} break;
				case 77:
				// Right
				{
					Log.Right();
				} break;
				case 59:
				// User hit F1, so display help
				{
					DisplayHelp();
					DisplayEnable = 0;
					HelpFlag = 1;
				} break;
				case 60:
				// User hit F2, so dump log
				{
					Log.Dump(0);
				} break;
				case 61:
				// F3 = Dump Screen
				{
					ScreenDump();
					EDSLog.Add(990,"Screen dumped to SCREEN.BMP");
				} break;
			}
		}
		else if (c == 27)
		// Abort any move in progress
		{
			if (Flags.CheckStatus(SFMoveInProgress))
			{
				Flags.ClearStatus(SFMoveInProgress);
				Flags.SetMoveStage(MSIdle);
				// Clear PC Emergency Stop Output bit, to disable power to motors
				BDMCCommand(Radial,"CB2\r",temp,DMCFastCommand);
				BDMCCommand(Radial,"CB2\r",temp,DMCFastCommand);
				// Turn the motors off via DMCs as well
				BDMCCommand(Axial,"MO\r",temp,DMCSlowCommand);
				BDMCCommand(Radial,"MO\r",temp,DMCSlowCommand);
				EDSLog.Add(20,"Movement aborted! (via ESC key)");
			}
      for (i=0;i<NumberIRs;i++)
      	if (IRs[i].Enabled)
				{
					IRs[i].Stop();
          if (!IRs[i].DMCMoving)
            IRs[i].ServoOff();
          EDSLog.Add(20,"Movement aborted! (via ESC key)");
				}
		}
		else if (c == 13)
		// User hit enter
		{
			CmdLine("");
			// Parse the command held in kbline
			ParseKB(kbline,0,temp);
			// After processing a keyboard line, clear the buffer
			kbline[0] = 0;
			CmdLine(kbline);
		}
		// Process a backspace
		else if (c == '\b')
		{
			if (strlen(kbline) > 0)
			{
				kbline[strlen(kbline) - 1] = 0;
				CmdLine(kbline);
			}
		}
		else if (strlen(kbline) < 70)
		{
			// Otherwise, add the new character to the current buffer
			kbline[strlen(kbline)+1] = 0;
			kbline[strlen(kbline)] = c;
			CmdLine(kbline);
		}
	}

	// Check for a command from the serial port
	while (SerialCharReady(Host))
	{
		c = SerialGetChar(Host);
		// On a carriage return, parse the serial command line
		if (c == 13)
		{
			ParseSer(serline);
			serline[0] = 0;
			ClearSerialBuffer(0);
		}
		// On receiving our prompt character, flush the serial receive line
		else if (c == Prompt)
		{
			serline[0] = Prompt;
			serline[1] = 0;
		}
		// Otherwise, add the character to the buffer
		else if (strlen(serline) < 79)
		{
			serline[strlen(serline)+1] = 0;
			serline[strlen(serline)] = c;
		}
		else
		{
			serline[0] = 0;
		}
	}

  // Check for a host (TCS) timeout
  if (Timer - HostTimer > 1000)
  {
  	HostTimer = Timer;
    HostComErr++;
		// Don't display more than 2 com errors in a row
		if (HostComErr <= 2)
			EDSLog.Add(21,"Host com error 2");
		else if (HostComErr == 3)
			EDSLog.Add(22,"Host error messages suspended");
  }
}

Generated by GNU Enscript 1.6.5.2.
Document Actions