Skip to content. | Skip to navigation

Personal tools

dgh.cpp

dgh.cpp

dgh.cpp

/////////////////////////////////////////////////////////////////////////////
// DGH.CPP
//
//  Last updated: 07/03/2003
//
//  Part of the source code for the Vane End Actuator Control System
//
// This file contains all DGH communication constants/routines
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// CDGH::Init - Initializes the DGH module
int CDGH::Init(int dghType,char address,int X0,int Y0)
{
// Pass the DGH type in dghType, either AXIAL or RADIAL.  Pass the DGH
// address in address, the maximum allowable tension in maxTension,
// the minimum allowable tension in minTension, and the 0 order,
// first order, and second order calibration constants in cal0,
// cal1, and cal2.
//
// Returns a 0 on success, non-0 on failure
	char temp[80],s[255],convert[255];
	int Error = 0;

	Disabled = 0;  // By default have all DGH's enabled
	ErrorCount = 0;
	Address = address;
	DGHType = dghType;
	x0 = X0;
	y0 = Y0;
	QueryFlag = 0;
	// Set the tension reading to a legal value until it's read
	Tension = (MaxTension + MinTension) / 2;
	Alarm = 0;
   // Establish DGH initialization string
	if (DGHType == F11)
		strcpy(InitString,DGHInitStringF11);
	else if (DGHType == F5)
		strcpy(InitString,DGHInitStringF5);
	else
		strcpy(InitString,DGHInitString);

	sprintf(temp,"%2X",Address);
	InitString[0] = temp[0];
	InitString[1] = temp[1];
	// Verify DGH setup is correct
	Log.Add("CDGH::Init(%d): Checking setup of DGH %c",VERBOSE,__LINE__,Address);
	// Query the DGH module for its current setup, and check it
	if (Command("RS\r",temp,DGHTimeout))
	{
		Log.Add("!CDGH::Init(%d): DGH Timed Out (DGH %c)",VERBOSE,__LINE__,Address);
		// An error (timeout, no response, etc) occurred in communication
		return(1);
	}
	else if (strncmp(InitString,&temp[1],8))
	{
		Log.Add("!CDGH::Init(%d): DGH had wrong setup (DGH %c)",VERBOSE,__LINE__,Address);
		// The DGH responded, but had the wrong setup string
		return(2);
	}
	// Configure the hardware tension limits in the DGH modules
	if (DGHType == AXIAL)
	{
		Log.Add("CDGH::Init(%d): Configuring DGH %c",VERBOSE,__LINE__,Address);

		/* Set high alarm point */
		if (Command("WE\r",temp,DGHTimeout)) Error = 3;
		DGHFormat((MaxTension - Cal0) * 1.1 / Cal1,convert);
		sprintf(s,"HI%sM\r",convert);
		if (Command(s,temp,DGHTimeout)) Error = 4;

		/* Set low alarm point */
		if (Command("WE\r",temp,DGHTimeout)) Error = 3;
		DGHFormat((MinTension - Cal0) * 1.1 / Cal1,convert);
		sprintf(s,"LO%sL\r",convert);
		if (Command(s,temp,DGHTimeout)) Error = 4;

		/* Clear any existing alarm condition */
		if (Command("WE\r",temp,DGHTimeout)) Error = 5;
		if (Command("CA\r",temp,DGHTimeout)) Error = 6;
		/* Clear the digital outputs in case alarms are disabled */
		if (Command("DO00\r",temp,DGHTimeout)) Error = 7;
		// Clear the internal zero-offset
		if (Command("WE\r",temp,DGHTimeout)) Error = 13;
		if (Command("CZ\r",temp,DGHTimeout)) Error = 14;
	}
	else if (DGHType == RADIAL)
	{
		// DGH h (NE Radial corner) at Mag1 is acting strange.
		// After setting alarms as below, its set-up string changes.
		// I've adjusted its limits manually and I'll put it out of this update
    // for now, but I think it needs to be replaced.
		if ( ((Telescope == 1) && (Address != 'h')) || (Telescope == 2))
		{
			Log.Add("CDGH::Init(%d): Configuring DGH %c",VERBOSE,__LINE__,Address);

			/* Set high alarm point */
			if (Command("WE\r",temp,DGHTimeout)) Error = 8;
			DGHFormat((MinTension - Cal0) * 1.1 / Cal1,convert);
			sprintf(s,"HI%sM\r",convert);
			if (Command(s,temp,DGHTimeout)) Error = 9;

			/* Set low alarm point */
			if (Command("WE\r",temp,DGHTimeout)) Error = 8;
			DGHFormat((MaxTension - Cal0) * 1.1 / Cal1,convert);
			sprintf(s,"LO%sL\r",convert);
			if (Command(s,temp,DGHTimeout)) Error = 9;
		}

		/* Clear any existing alarm condition */
		if (Command("WE\r",temp,DGHTimeout)) Error = 10;
		if (Command("CA\r",temp,DGHTimeout)) Error = 11;
		/* Clear the digital outputs in case alarms are disabled */
		if (Command("DO00\r",temp,DGHTimeout)) Error = 12;
		// Clear the internal zero-offset
		if (Command("WE\r",temp,DGHTimeout)) Error = 13;
		if (Command("CZ\r",temp,DGHTimeout)) Error = 14;
	}
	if (Error)
	{
		Log.Add("!CDGH::Init(%d): Communication error with DGH %c",VERBOSE,__LINE__,Address);
		return(Error);
	}
	return(0);
}

/////////////////////////////////////////////////////////////////////////////
// CDGH::Send - Sends a string to the DGH module
void CDGH::Send(char *Data)
//	Output a string (Data) to the DGH.
{
	char temp[80];

	strcpy(&temp[2],Data);
	temp[0] = '$';
	temp[1] = Address;
	Log.Add("CDGH::Send(%d): Sending \"%s\" to DGH %c",3,__LINE__,temp,Address);
#ifdef ENABLEIO
	// Send the command
	SerialBufPutString(Guest,temp);
#endif

}

/////////////////////////////////////////////////////////////////////////////
// CDGH::Receive - Waits for a properly terminated message from the module
int CDGH::Receive(char *Response,int Timeout)
//	Put the DGH's response in Response, and wait for Timeout
//	milliseconds before giving up.
//	Returns a 0 on success, 1 on a failure
//	See the DGH manual for more info on communication with the DGH cards.
{
	int i; // Index variable
	int Done; // Flag: 1 when routine is done, otherwise 0
	unsigned long savetime; // Stores initial time in milliseconds

	i = 0;
	Done = 0;
	savetime = Timer;
#ifdef ENABLEIO
	// Wait for response
	do
	{
		Watchdog();
		if (SerialCharReady(Guest) && (i < 79))
		{
			Response[i++] = SerialGetChar(Guest);
			if ((Response[i-1] == '\r') && (Response[0] == '*'))
				Done = 1;
		}
	// Stop getting data when a '\r' is received, or the timeout has been reached.
	// (Timer - savetime) gives the time in milliseconds since we started looking
	// for data.
	}
	while (((Timer - savetime) < Timeout) && !Done);
#endif

	// Null-terminate the string
	Response[i] = 0;
	if (Done)
	{
		Log.Add("CDGH::Receive(%d): Received \"%s\" from DGH %c",3,__LINE__,Response,Address);
		if (ErrorCount >= MaxDGHErrors)
			EDSLog.Add(989,"DGH %c error messages resumed",Address);
		ErrorCount = 0;
		return(0);
	}
	else
	{
		// Count the number of communication failures.
		// A communication failure means that a 'cr' was not received
		// before a Timeout occurred
		Log.Add("!CDGH::Receive(%d): Timeout!, Received \"%s\" from DGH %c",VERBOSE,__LINE__,Response,Address);
		ErrorCount++;
		if (ErrorCount < MaxDGHErrors)
			EDSLog.Add(10,"DGH %c com error",Address);
		if (ErrorCount == MaxDGHErrors)
			EDSLog.Add(14,"DGH %c error messages suspended",Address);
		return(1);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CDGH::Command - Sends a command and then waits for a response
int CDGH::Command(char *Data,char *Response,int Timeout)
{
	// This routine sends the command in string Data to the DGH on port Port,
	// and puts the response from the DGH in string Response.  The routine will
	// timeout after Timeout milliseconds.
	// Returns a 0 on success, non-0 on failure.
	// A 1 means that the DGH timed-out (didn't give a '*' prompt back
	//  before Timeout milliseconds)

	SafeDelay(DGHPrePause);
	ClearSerialBuffer(Guest);
	Send(Data);
	return(Receive(Response,Timeout));
}

/////////////////////////////////////////////////////////////////////////////
// CDGH::Update - Reads the current tension from the DGH module
int CDGH::Update()
// This routine reads the DGH's tension and alarm.
// -1 = not done, 0 = done, 1 = error
{
	int Done = 0;

	if ((Address >= 'i' && Address <= 'k') && (!f11Present)) return 0;
	if ((Address >= 'l' && Address <= 'q') && (!f5Present)) return 0;

	if ((Address >= 'a') && (Address <= 'h'))
	{
	  if (Disabled)
	  {
		  Display();
		  return(0);  // Don't do anything if DGH disabled.
	  }
	}
	if (QueryFlag == 0)
	{
		Log.Add("CDGH::Update(%d): Reading tension of DGH %c",VERBOSE,__LINE__,Address);
		// Query the DGH for its tension
		ClearSerialBuffer(Guest);
		Send("RD\r");
		QueryTime = Timer;
		QueryFlag = 1;
		ResponseLength = 0;
		return(-1);
	}
	else if (QueryFlag == 1)
	{
		while (SerialCharReady(Guest) && (ResponseLength < 79) && !Done)
		{
			Response[ResponseLength++] = SerialGetChar(Guest);
			if ((Response[ResponseLength-1] == '\r') && (Response[0] == '*'))
				Done = 1;
		}
		if (Done)
		{
			// Null-terminate the string
			Response[ResponseLength] = 0;
			Log.Add("CDGH::Receive(%d): Received \"%s\" from DGH %c",VERBOSE,__LINE__,Response,Address);
			if (sscanf(&Response[1],"%f",&Reading) == 1)
			{
				Log.Add("CDGH::Update(%d): Reading: %f (For DGH %c)",VERBOSE,__LINE__,Reading,Address);
        if ((Address >= 'a') && (Address <= 'h'))
        {
				  Tension = Cal0 + Cal1 * Reading + Cal2 * Reading * Reading;
				  Log.Add("CDGH::Update(%d): Tension: %f (For DGH %c)",VERBOSE,__LINE__,Tension,Address);
				  QueryFlag = 2;
        }
        else
					QueryFlag = 0;

		if ((Address >= 'a') && (Address <= 'k')) Display();

				if (ErrorCount >= MaxDGHErrors)
					EDSLog.Add(989,"DGH %c error messages resumed",Address);
				ErrorCount = 0;
				return(0);
			}
			else
			{
				Log.Add("!CDGH::Update(%d): Error in DGH Response (DGH %c)",VERBOSE,__LINE__,Address);
				ErrorCount++;
				if (ErrorCount < MaxDGHErrors)
					EDSLog.Add(10,"DGH %c com error",Address);
				if (ErrorCount == MaxDGHErrors)
					EDSLog.Add(14,"DGH %c error messages suspended",Address);
				QueryFlag = 0;
				return(1);
			}
		}
		else if (Timer - QueryTime > DGHTimeout)
		{
			// Count the number of communication failures.
			// A communication failure means that a '\r' was not received
			// before a Timeout occurred
			// Null-terminate the string
			Response[ResponseLength] = 0;
			Log.Add("!CDGH::Receive(%d): Timeout!, Received \"%s\" from DGH %c",VERBOSE,__LINE__,Response,Address);
			ErrorCount++;
			if (ErrorCount < MaxDGHErrors)
				EDSLog.Add(10,"DGH %c com error",Address);
			if (ErrorCount == MaxDGHErrors)
				EDSLog.Add(14,"DGH %c error messages suspended",Address);
			QueryFlag = 0;
			return(1);
		}
		return(-1);
	}
	else if (QueryFlag == 2)
	{
		Log.Add("CDGH::Update(%d): Reading alarm of DGH %c",VERBOSE,__LINE__,Address);
		// Query the DGH for its alarm
		ClearSerialBuffer(Guest);
		Send("DI\r");
		QueryTime = Timer;
		QueryFlag = 3;
		ResponseLength = 0;
		return(-1);
	}
	else if (QueryFlag == 3)
	{
		while (SerialCharReady(Guest) && (ResponseLength < 79) && !Done)
		{
			Response[ResponseLength++] = SerialGetChar(Guest);
			if ((Response[ResponseLength-1] == '\r') && (Response[0] == '*'))
				Done = 1;
		}
		if (Done)
		{
			// Null-terminate the string
			Response[ResponseLength] = 0;
			Log.Add("CDGH::Receive(%d): Received \"%s\" from DGH %c",VERBOSE,__LINE__,Response,Address);
			if (Response[2] == '1')
				Alarm = 1;
			else
				Alarm = 0;
			Log.Add("CDGH::Update(%d): Alarm: %d (For DGH %c)",VERBOSE,__LINE__,Alarm,Address);
			Display();
			QueryFlag = 0;
			if (ErrorCount >= MaxDGHErrors)
				EDSLog.Add(989,"DGH %c error messages resumed",Address);
			ErrorCount = 0;
			return(0);
		}
		else if (Timer - QueryTime > DGHTimeout)
		{
			// Count the number of communication failures.
			// A communication failure means that a '\r' was not received
			// before a Timeout occurred
			// Null-terminate the string
			Response[ResponseLength] = 0;
			Log.Add("!CDGH::Receive(%d): Timeout!, Received \"%s\" from DGH %c",VERBOSE,__LINE__,Response,Address);
			ErrorCount++;
			if (ErrorCount < MaxDGHErrors)
				EDSLog.Add(10,"DGH %c com error",Address);
			if (ErrorCount == MaxDGHErrors)
				EDSLog.Add(14,"DGH %c error messages suspended",Address);
			QueryFlag = 0;
			return(1);
		}
		return(-1);
	}
	return(-1);
}

/////////////////////////////////////////////////////////////////////////////
// CDGH::Display: Displays the DGHs tension onscreen
void CDGH::Display()
{
	char s[255];
	byte color;

  if ((Address >= 'a') && (Address <= 'h'))
  {
	  // Display the tension
	  if (Disabled)
	  {
		  PutString16("#####",x0,x0+40,y0,BLACK,SHECMEDGRAY);
		  PutChar16('þ',x0+48,y0,BLACK,SHECMEDGRAY);
		  return;
	  }
	  if (Flags.TensionDisplay == TDmV)
		  sprintf(s,"%5.2f",Reading);
	  else
		  sprintf(s,"%5.0f",Tension);
	  if ((Tension < MinTension) || (Tension > MaxTension))
	  {
		  color = SHECRED;
		  TensionOK = 2;	// Tension beyond limits
	  }
	  else if ((Tension - MinTension < TensionWarningRange) ||
					   (MaxTension - Tension < TensionWarningRange))
	  {
		  color = SHECYELLOW;
		  TensionOK = 1;	// Tension near limits
	  }
	  else
	  {
		  color = BLACK;
		  TensionOK = 0;	// Tension within limits
	  }
	  PutString16(s,x0,x0+40,y0,color,SHECMEDGRAY);
	  if (Alarm)
		  PutChar16('þ',x0+48,y0,SHECRED,SHECMEDGRAY);
	  else
		  PutChar16('þ',x0+48,y0,BLACK,SHECMEDGRAY);
  }
  else
	{
		sprintf(s,"%+6.3f",Reading); //millivolts (mV)
		PutString16(s,x0,x0+7*8,y0,BLACK,SHECMEDGRAY);
  }
}

/////////////////////////////////////////////////////////////////////////////
// DGHTerminal: opens a simple terminal with a DGH
void DGHTerminal()
// This routine acts as a simple terminal to the DGHs.
// It displays received characters, and transmits typed characters.
// Hitting ESC ends the terminal session.
{
	int c; // Holds received and typed characters
	char line[80]; // A buffer for received and transmitted characters

	CloseVideo();
	cprintf("DGH Terminal on COM2: (ESC to end)\r\n");
	do
	{
		// Don't let the watchdog go off during terminal mode
		Watchdog();
		// Check for incoming serial characters
		if (SerialCharReady(Guest))
		{
			c = SerialGetChar(Guest);
			cprintf("%c",c);
			if (c == '\r')
				cprintf("\n");
		}
		c = 0;
		// Check for outgoing characters
		if (kbhit())
		{
			c = getch();
			if (c != 27)
			{
				cprintf("%c",c);
				if (c == '\r')
					cprintf("\n");
				// Transmit the typed character
				SerialPutChar(Guest,c);
			}
		}
	// Quit on an <ESC>
	} while (c != 27);
	InitVideo();
	InitDisplay();
	Cell.DisplayAll();
}

/////////////////////////////////////////////////////////////////////////////
// ConfigDGHs - initializes all 17 DGH modules (by calling the Init routine)
int ConfigDGHs()
{
	int i,Error = 0;


	for (i=0;i<=3;i++)
		if (!Cell.DGHs[i].Disabled)
			if (Cell.DGHs[i].Init(AXIAL,i+'a',Cell.CornerX[i]+144,Cell.CornerY[i]))
				Error = 1+i;

	for (i=4;i<=7;i++)
		if (!Cell.DGHs[i].Disabled)
			if (Cell.DGHs[i].Init(RADIAL,i+'a',Cell.CornerX[i-4]+144,Cell.CornerY[i-4]+16))
				Error = 1+i;

	for (i=8;i<=10;i++)
		if (Cell.DGHs[i].Init(F11,i+'a',188,sbty+8+16+16*(i-8)))
			Error = 1 + i;

	if (Telescope == 2) {
		for (i = 11; i <= 16; i++) {
			if (!Cell.DGHs[i].Disabled) {
				if (Cell.DGHs[i].Init(F5,i+'a',188,sbty+8+16+16*(i-8))) {
					Error = 1 + i;
				}
			}
		}
	}
	else if (Error == 0) Error = 12;

	return(Error);
}

/////////////////////////////////////////////////////////////////////////////
// DGHFormat - returns a float in a string properly formatted for the DGHs
char * DGHFormat(float f,char *s)
// Pass the float to be formatted in f, and the string will be returned in s
// Returns f in the format "+00000.00"
{
	int i,j;

	i = f;
	j = round((f - i) * 100);
	if (i >= 0)
		sprintf(s,"+%05d.%02d",abs(i),abs(j));
	else
		sprintf(s,"-%05d.%02d",abs(i),abs(j));
	return(s);
}

Generated by GNU Enscript 1.6.5.2.
Document Actions