/*------------------------------------------------------------------*/
/*	Sio.c:  Serial I/O for Amiga Version of PCMail		    */
/*	Created: 27Jun87 by J.A. Lydiatt			    */
/*								    */
/* Exports the following routines required by PCMail:		    */
/*  SIOInit():		Initialize Serial Port			    */
/*  SIOClose():		Close and free Serial Port resources	    */
/*  SIOSpeed():		Set bps					    */
/*  SIORead():		read characters from serial port	    */
/*  SIOWrite():		write characters to serial port		    */
/*  SIOInBuffer():	Set Buffer size for read & writes.	    */
/*  SIOOutBuffer():	(Has no effect in Amiga Version)	    */
/*------------------------------------------------------------------*/

#include <stdio.h>
#ifndef TRUE
#define TRUE -1
#define FALSE 0
#endif

/*--- Timer Function Declarations --- */

extern void CloseTimer();	/* Return Timer's resources to the System */
extern int  OpenTimer(); 	/* Returns True if Timer Device Opened OK */ 
extern void StartTimer();	/* (long)seconds, (long)microseconds      */
extern int  TimerExpired();     /* Returns True if Timer interval expired */

/*--- SerialIO Function Declarations --- */

extern struct EOExtSer *InitSerialIO(); /* problems? return NULL	  */
extern void CloseSerialIO();		/* Return SerialIO resources	  */
extern int  CheckSerIO();		/* TRUE if character available    */
extern char SerIORead();		/* Returns a Char from serial port*/
extern void SerIOWrite(); 		/* Writes one byte to serial port */ 
extern void SetSerBaud();		/* (int)baud - set baud rate	  */

/*--------------------------------------------------------------*/
/*	 getspeed/getbaud: check for valid baud parameters	*/
/*--------------------------------------------------------------*/

static struct {
	unsigned baudr;
	int speedcode;

} speeds[] = {
	300,	300,
	1200,	1200,
	2400,	2400,
	4800,	4800,
	9600,	9600,
	19200, 19200,
	0,
};

static unsigned getspeed(code)
{
	register n;

	for (n=0; speeds[n].baudr; ++n)
		if (speeds[n].speedcode == code)
			return speeds[n].baudr;
	return 0;
}


static unsigned getbaud(code)
char *code;
{
	register n;
	register int Baudrate;
	
	Baudrate = atoi(code);
	
	for (n=0; speeds[n].baudr; ++n)
		if (speeds[n].baudr == Baudrate)
			return speeds[n].speedcode;
	return 0;
}

/*--------------------------------------------------------------*/
/*	SIOInit: initialize serial I/O				*/
/*--------------------------------------------------------------*/


SIOInit ( whichport, speed )
char * whichport;
char * speed;
{
	unsigned int baud;
	extern void SetXonMode();

	/*  fprintf( stderr, "sioinit %s %s\n", whichport, speed ); /* */

	if ( InitSerialIO() == NULL ) {
		fprintf( stderr, "Can't open Serial Port\n" );
		return( -1 );
	}

     if ( baud = getbaud( speed ) )
	SetSerBaud( baud );

     if ( !OpenTimer() )
	{
	   CloseSerialIO();
	   fprintf( stderr, "Can't open the Timer Device\n" );
	   return -1;
        }

     SetXonMode( (int)FALSE );
     return( 0 );
}

/*--------------------------------------------------------------*/
/*	SIOSpeed:  set the serial Baud rate 			*/
/*--------------------------------------------------------------*/

SIOSpeed( speed )
char *speed;
{
    unsigned int baud;

    if ( baud = getbaud( speed ) )
	SetSerBaud( baud );
}

/*--------------------------------------------------------------*/
/*	SIOInBuffer/ SIOOutBuffer:	Set Buffer Size.	*/
/*--------------------------------------------------------------*/

SIOInBuffer ( buf, size )
char * buf;
int size;
{
}

SIOOutBuffer ( buf, size )
char * buf;
int size;
{
}

/*--------------------------------------------------------------*/
/*	SIOClose:	Close Serial port.			*/
/*--------------------------------------------------------------*/

SIOClose ( dtr )
{
   CloseSerialIO();
   CloseTimer();
}

/*--------------------------------------------------------------*/
/*	SIOWrite: send count characters to serial port		*/
/*--------------------------------------------------------------*/

SIOWrite ( buf, count )
register char * buf;
int count;
{
	register int nsent;

	nsent = count;
	while ( nsent-- )
	   SerIOWrite( *buf++ );

	return count;
}

/*--------------------------------------------------------------*/
/*	SIORead: read mincount <= #characters <= maxcount	*/
/*	return  # of characters read, or -1 if timed out after	*/
/*	after tenths / 10 seconds.				*/
/*--------------------------------------------------------------*/


int SIORead ( buf, mincount, maxcount, tenths )
register char *buf;
int	mincount;
int	maxcount;
int	tenths; /* timeout is in tenth's of seconds */
{
        /* A bit of a Kludge to get the project started */

	long seconds, microSeconds;
	unsigned long waitMask;
	int  timerON ;
	register int received;

	/* fprintf (stderr, "Read  m= %d T= %ld", maxcount, Ticks  );/**/



	if ( tenths == 0 )
	   {
		if ( !CheckSerIO() )
		   return -1;
		tenths = 10;
	   }
        seconds = tenths / 10;
	microSeconds = ((long)(tenths) - seconds * 10L) * 100000L;
        
	received = 0;
	waitMask = (1L << GetSerialSigBit()) | (1L << GetTimerSigBit() ); 
	timerON = FALSE;
	do
	  {
	     if ( CheckSerIO() )
	        {
	     	   *buf = SerIORead();
		   ++buf;
		   ++received;
		   if ( mincount <= received && received <= maxcount )
		      return received;
		}
	     if ( !timerON )
		{
		   StartTimer( seconds, microSeconds );
		   timerON = TRUE;
		}
	     Wait( waitMask );

	  }	while ( !TimerExpired() );

	return -1;
}

