[net.micro.mac] Using serial drivers

thomas@utah-gr.UUCP (Spencer W. Thomas) (09/23/86)

A recent article in the Delphi digest asked for working code using the
serial drivers.  Here is some code that (at least used to -- I haven't
tried it since I upgraded to the 128K roms) work for me.  It is written
in SUMACC, but should be close to whatever you are using.

Since these are fragments of a larger program, there are undefined
routines referenced, but I think everything necessary to use the serial
lines is here.  Good luck!

First I open the serial driver
#define sPortA 0
int XL_outRefNum, XL_inRefNum;
    if ( RomSDOpen( sPortA ) < 0 )
	... appropriate error code ...
(Actually, I followed this by attempting to open the RAM driver.)

RomSDOpen( sPort )
int sPort;
{
    XL_outRefNum = OpenDriver( ".AOut" );
    if ( XL_outRefNum == 0 )
	return -1;
    XL_inRefNum = OpenDriver( ".AIn" );
    if ( XL_inRefNum == 0 )
	return -1;
    return 0;
}

Then I set up the communications parameters:
int XL_baud = baud9600;
char * XL_serBuffer;

    struct SerShk shk;
    SerReset( XL_inRefNum, XL_baud | stop10 | noParity | data8 );
    SerReset( XL_outRefNum, XL_baud | stop10 | noParity | data8 );
    if ( XL_serDriver )	/* If RAM driver open succeeded */
    {
	shk.fXOn = 1;			/* Do XON/XOFF Flow control */
	shk.fCTS = 0;			/* No CTS Flow control */
	shk.xOn = '\21';		/* Control Q */
	shk.xOff = '\23';		/* Control S */
	shk.fInX = 1;			/* Generate Xon/Xoff flow control */
    }
    else
    {
	shk.fXOn = 0;			/* no Flow control */
	shk.fCTS = 0;			/* at all */
	shk.fInX = 0;
    }
    shk.errs = 0;			/* Ignore errors */
    shk.evts = 0;			/* No events */
    SerHShake( XL_inRefNum, &shk );
    SerHShake( XL_outRefNum, &shk );
    /* Create a big buffer so we don't lose anything */
    if ( XL_serBuffer == NIL )
    {
	XL_serBuffer = NewPtr( XL_serBufSize );
	SerSetBuf( XL_inRefNum, XL_serBuffer, XL_serBufSize );
    }

}


Here is the input code.  This routine should be called frequently enough
to keep the serBuffer from filling up between calls.  The testFlag
argument was added to permit other events to "get in" even if the serial
line was receiving like mad.  My top loop gave preference to serial
input over other events, so needed some way to break out every so often.

/* 
 * Simulate getchar() from serial line.  Return -1 if nothing there.
 * If testFlag is TRUE, just see if there's any more in the internal
 * buffer.
 */
static char SGBuffer[256];
static int SGptr, SGsize = 0;

XL_SerGetChar(testFlag)
{
    int count, err;
    if ( SGsize > 0 && SGptr < SGsize )
	return SGBuffer[SGptr++] & 0x7f;	/* strip parity */
    if ( testFlag )
	return -1;
    /* Check for more available */
    SerGetBuf( XL_inRefNum, &SGsize );
    if ( SGsize > 0 )
    {
	if ( SGsize > sizeof SGBuffer )
	    SGsize = sizeof SGBuffer;
	if ( (err = FSRead( XL_inRefNum, &SGsize, SGBuffer )) < 0 )
	{
	    XL_Error( "Read error", err );
	    SGsize = 0;
	}
	else
	{
	    SGptr = 1;
	    return SGBuffer[0] & 0x7f;	/* strip parity */
	}
    }

    return -1;				/* Nothing there */
}

And, of course, output code.

/* Put a string to the serial line */
XL_SerPutBuf( buf, len )
char *buf;
int len;
{
    int err, wrlen;

    while ( len > 0 )
    {
	wrlen = len;
	if ( (err = FSWrite( XL_outRefNum, &wrlen, buf )) < 0 ||
	     wrlen == 0 )
	{
	    XL_Error( "Serial Write Error, Code=", err );
	    return;
	}
	len -= wrlen;
    }
}
-- 
=Spencer   ({ihnp4,decvax}!utah-cs!thomas, thomas@utah-cs.ARPA)