/* $Id: comm.cpp 2.5 1997/10/08 10:38:34 leon Exp $
*/
#define Uses_TProgram
#define Uses_MsgBox
#include <tvision/tv.h>
#include "setup.h"
#include "serial.h"
#include "comm.h"
#include "log.h"
#include "gisel.h"
#include "translat.h"
#include <stdio.h> // sprintf()
#include <string.h> // strlen()
#include <ctype.h> // isdigit()
extern "C"
{
int getccb(void);
int setSerial(int port, int speed, int parity, int bits, int stopBit);
int serialOut(char byte);
void initSerial(void);
void closeSerial(void);
void flushComm(void);
}
/** Translate window for Job Status **/
extern Translate *trans;
/** Current Position **/
extern long position[3];
comData settings(B9600, COM1, P_NONE, 1, 8); // overriden by .ini file
/**
** Creates new comm channel
**/
Comm::Comm(TLogWindow **log)
{
logWindow = log;
reply = 0;
commIsOpen = False;
receiver = NULL;
enqueued = False;
dequeued = False;
paused = False;
depaused = False;
relativeSpeed[0] =
relativeSpeed[1] =
relativeSpeed[2] = 1.0;
}
/**
** Cheks for presence of the reply character. This function is intended
** to be called from TProgram::idle()
**/
void Comm::update()
{
static Boolean inPausedPosition = False; // Is paused and in pause position?
int c;
if (dequeued)
{
dequeued = False;
enqueued = False;
depaused = False;
if (trans)
{
message(trans, evCommand, cmCancel, 0);
messageBox( "\n\003Job dequeued", mfOKButton | mfInformation);
}
}
if ( ((c = getccb()) != -1) || depaused)
{
reply = c;
if (*logWindow ) // && c != '0')
(*logWindow)->insertErrMsg(reply);
if (enqueued)
{
depaused = False;
if (paused)
{
if (!inPausedPosition)
{
inPausedPosition = True;
sendCommand("@0a0,1000,0,1000,-1600,3000,0,30");
}
return;
}
else
{
if (inPausedPosition)
{
inPausedPosition = False;
sendCommand("@0a0,1000,0,1000,1600,3000,0,30");
return;
}
sendNextLine();
}
}
if (trans)
trans->update();
}
}
/**
** Returns reply char and clears internal reply char;
** If returns 0 this means that line was empty and no reply was expected
** If reply is -1 there was no ack
**/
int Comm::getReply()
{
if (reply > 0)
{
static int c;
c = reply;
reply = 0;
return c;
}
return reply;
}
/**
** Returns curent queue line number
**/
long Comm::getLineNumber()
{
return lineNumber;
}
/**
** Pause queue. Returns negative number ob error.
**/
short Comm::pauseQueue()
{
if (paused)
{
messageBox("\n\003Job already paused",
mfInformation | mfOKButton);
return -1;
}
if (!enqueued)
{
messageBox("\n\003No job to pause",
mfInformation | mfOKButton);
return - 2;
}
paused = True;
if (*logWindow )
(*logWindow)->insertLine("\nJob is currently paused...");
return 0;
}
/**
** Continue queue
**/
short Comm::continueQueue()
{
if (paused && enqueued)
{
if (*logWindow )
(*logWindow)->insertLine("\n Continuing with job execution.");
paused = False;
depaused = True;
return 0;
}
else
messageBox("\n\003No job available to continue",
mfInformation | mfOKButton);
return -1;
}
/**
** Sets relative speed for a given axis
**/
void Comm::setRelativeSpeed(short axis, double factor)
{
if (axis > 2)
return;
relativeSpeed[axis] = factor;
}
/**
** Opens buffered communication line over serial port
** If comm channel is alredy open it is reopened (closed and opened).
**/
Comm::open(int port, int speed, int parity, int bits, int stopBit)
{
if (commIsOpen == True)
close();
if(setSerial(port, speed, parity, bits, stopBit) != 0)
return -1;
initSerial();
commIsOpen = True;
return 0;
}
/**
** Opens comm channel with default settings
**/
Comm::open()
{
return open(settings.getComPort(), settings.getBaud(),
settings.getParity(), settings.getDataBits(),
settings.getStopBits());
}
/**
** Returns True if comm channel is open
**/
Boolean Comm::isOpen()
{
return commIsOpen;
}
/**
** Closes communication channel
**/
void Comm::close()
{
if (commIsOpen)
closeSerial();
commIsOpen = False;
}
/**
** Sends /count/ bytes to the communication line
** Appends CR at the end of line
**/
void Comm::sendCommand(const char *s, int count)
{
reply = -1; // line must be acknewledged or error will occur
flushComm(); // discard input buffer
for(int i = 0; i < count; i++)
serialOut( s[i] );
serialOut('\r');
serialOut('\n');
if (*logWindow)
{
(*logWindow)->insertLine("\n");
(*logWindow)->insertChars(s, count);
}
}
/**
** Sends string to the communication line
** Appends CR at the end of line
**/
void Comm::sendCommand(const char *s)
{
sendCommand(s, strlen(s));
}
/**
** Sends string. When reply is available /evBroadcast/ will be
** send to the /owner/ view with /cmReplyReceived/.
**/
void Comm::sendCommand(const char *s, TView *owner)
{
receiver = owner;
sendCommand(s, strlen(s));
}
/**
** Enqueues input stream. Be shure that /inStream/ lasts for
** a long time (at least for time of queue).
**/
int Comm::enqueue(istream& inStream, const char *jobName)
{
inStream.seekg(0L);
is = inStream;
Comm::jobName = jobName;
if (*logWindow)
{
(*logWindow)->insertLine("Starting ");
(*logWindow)->insertLine(jobName);
}
lineNumber = 0;
enqueued = True;
sendNextLine();
return 0;
}
/**
** Enqueues file
**/
int Comm::enqueue(const char *fileName)
{
ifs.open(fileName);
return enqueue(ifs);
}
/**
** Clears queue
**/
void Comm::dequeue()
{
if (enqueued)
{
dequeued = True;
paused = False;
}
}
// TODO
#define SPEEDCHANGE(axis, upperLimit) \
( (tmpSpeed = long(double(speed[axis])*relativeSpeed[axis])) < 30 ? \
30 : ( tmpSpeed > upperLimit ? 4000 : tmpSpeed))
/**
** Sends next line from queue
**/
void Comm::sendNextLine()
{
#define BUFFER_SIZE 100
char cmd[BUFFER_SIZE];
size_t cmdLen;
while ( is.getline(cmd, BUFFER_SIZE) )
{
//@0m000,2000,0001,2000,0002,3000,0,30
long pos[3], speed[3], lastArg;
char cmdPrefix, cmdType;
short device;
if ( sscanf(cmd, "%c%d%c%ld,%ld,%ld,%ld,%ld,%ld,%ld",
&cmdPrefix, &device, &cmdType,
&pos[0], &speed[0],
&pos[1], &speed[1],
&pos[2], &speed[2],
&lastArg
) == 10 )
{
if (cmdPrefix == '@')
{
long tmpSpeed;
switch (cmdType)
{
case 'm':
case 'M':
position[0] = pos[0];
position[1] = pos[1];
position[2] = pos[2];
case 'a':
case 'A':
sprintf(cmd, "@%d%c%ld,%ld,%ld,%ld,%ld,%ld,0,30",
device, cmdType,
pos[0], SPEEDCHANGE(0, 4000),
pos[1], SPEEDCHANGE(1, 4000),
pos[2], SPEEDCHANGE(2, 2000)
);
break;
case 'y':
case 'Y':
sprintf(cmd, "@%d%c%ld,%ld,%ld,%ld,%ld,%ld,%ld",
device, cmdType,
pos[0], SPEEDCHANGE(0, 4000),
pos[1], speed[1],
pos[2], speed[2],
lastArg);
break;
}
}
}
sendCommand(cmd);
lineNumber++;
return;
}
// The following lines are in effect only at end of stream
enqueued = False;
if (trans)
{
message(trans, evCommand, cmCancel, 0);
messageBox( "\n\003Job completed", mfOKButton | mfInformation);
}
else
{
if (*logWindow)
{
(*logWindow)->insertLine("\n");
(*logWindow)->insertLine(jobName);
(*logWindow)->insertLine(" Completed.\n");
}
}
return;
}
/**
** Checks if channel is open. If it's not it tries to open it.
** Then checks if it is safe for enqueuing. On any error shows messageBox()
** and retruns False. If there is no problem it returns True.
**/
Boolean Comm::clearToSend()
{
if (!commIsOpen)
{
if (open() != 0)
{
messageBox("Cannot open communication channel",
mfOKButton | mfError);
return False;
}
}
if (enqueued)
{
if ( messageBox( "\003Previous command has not completed!\n"
"\003OK to discard the previous command?",
mfOKCancel | mfConfirmation) == cmOK)
{
dequeued = True;
return True;
}
return False;
}
return True;
}
syntax highlighted by Code2HTML, v. 0.9.1