#include <exec/types.h>
#include <exec/io.h>
#include <intuition/intuition.h>
#include <devices/console.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <hardware/cia.h>
#include "defines.h"

extern struct IOExtSer *WriteSerReq, *ReadSerReq,
                       *AllocMem(),  *CreateExtIO();
extern struct timerequest *TimerMsg;
extern struct MsgPort  *WriteSerPort, *ReadSerPort, *TimerPort,
                       *CreatePort();
extern ULONG TimerSig, SerCharSig, ConCharSig, WindowSig;
extern UBYTE serin[200];
extern int TimeOut, SerEcho, Local;

struct CIA *cia_ptr;

int OpenSerial(Baud,DataLen,StopBits,SerFlags)
  ULONG Baud, SerFlags;
  UBYTE DataLen,StopBits;
{
int error;

cia_ptr = 0xBFD000;
if(!(ReadSerPort = CreatePort("ser.read",0L))) return(TRUE);
if(!(ReadSerReq  = CreateExtIO(ReadSerPort,(long)sizeof(struct IOExtSer))))
	return TRUE;
if(!(WriteSerPort= CreatePort("ser.write",0L))) return(TRUE);
if(!(WriteSerReq = CreateExtIO(WriteSerPort,(long)sizeof(struct IOExtSer))))
	return(TRUE);

if ((error = OpenDevice(SERIALNAME,0L,WriteSerReq,0L))) return(error);
Delay((long)10L);
ReadSerReq->IOSer.io_Device = WriteSerReq->IOSer.io_Device;
ReadSerReq->IOSer.io_Unit   = WriteSerReq->IOSer.io_Unit;

ReadSerReq->io_Baud           = Baud;
ReadSerReq->io_ReadLen        = DataLen;
ReadSerReq->io_WriteLen       = DataLen;
ReadSerReq->io_SerFlags       = (long)SerFlags;
ReadSerReq->io_StopBits       = StopBits;
ReadSerReq->io_CtlChar        = 0x13110000L;
ReadSerReq->IOSer.io_Command  = SDCMD_SETPARAMS;
DoIO(ReadSerReq);

WriteSerReq->IOSer.io_Command = CMD_WRITE;

ReadSerReq->IOSer.io_Length   = 1;
ReadSerReq->IOSer.io_Data     = serin;
ReadSerReq->IOSer.io_Command  = CMD_READ;
SendIO(ReadSerReq);
return(FALSE);
}

/*******************************************/
/* Check if char is available from serial  */
/*******************************************/
CheckSer()
{
return(CheckIO(ReadSerReq));
}

CloseSerial()
{
if(ReadSerReq)
	{
	CloseDevice(ReadSerReq);
	DeleteExtIO(ReadSerReq,(long)sizeof(struct IOExtSer));
	}
if(ReadSerPort) { DeletePort(ReadSerPort); }

if(WriteSerReq)
	{
	CloseDevice(WriteSerReq);
	DeleteExtIO(WriteSerReq,(long)sizeof(struct IOExtSer));
	}
if(WriteSerPort) { DeletePort(WriteSerPort); }
}

CheckCarrier()
{
int status;

WriteSerReq->IOSer.io_Command = SDCMD_QUERY;
DoIO(WriteSerReq);
status = WriteSerReq->io_Status & CIAF_COMCD;
WriteSerReq->IOSer.io_Command = CMD_WRITE;
return(status?FALSE:TRUE);
}

/*****************************************/
/* set serial DTR line                   */
/* false = DTR off; true = DTR on        */
/*****************************************/
SetDTR(set)
  int  set;
{
cia_ptr->ciaddra |= CIAF_COMDTR;     /* set DTR as output */
if(set) cia_ptr->ciapra &= ~CIAF_COMDTR; /* set DTR low  */
else cia_ptr->ciapra |=  CIAF_COMDTR; /* set DTR high */
}

SetBaud(rate)
  LONG rate;
{
PurgeLine();                 /* Flush recieve buffer */
AbortIO(ReadSerReq);         /* Abort PurgeLine's read req */
ReadSerReq->io_Baud = rate;  /* set baud rate */
ReadSerReq->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ReadSerReq);

ReadSerReq->IOSer.io_Command = CMD_READ; /* Restart read req */
SendIO(ReadSerReq);
}

SerPutChar(ch)
  UBYTE ch;
{   
WriteSerReq->IOSer.io_Data   = &ch;
WriteSerReq->IOSer.io_Length = 1;
DoIO(WriteSerReq);
}

SerPutStr(string)
  UBYTE *string;
{  
WriteSerReq->IOSer.io_Data   = string;
WriteSerReq->IOSer.io_Length = strlen(string);
DoIO(WriteSerReq);
}

SerPutBlk(block,length)
	UBYTE *block;
	int length;
{
WriteSerReq->IOSer.io_Data   = block;
WriteSerReq->IOSer.io_Length = length;
DoIO(WriteSerReq);
}

sendser(ch)
	UBYTE ch;
{
SerPutChar(ch);
}

GetSerKey(wait)
	int wait;
{
UBYTE ch;

if(CheckIO(ReadSerReq) || wait)
	{
	WaitIO(ReadSerReq);
	ch = serin[0];
	SendIO(ReadSerReq);
	return((int)ch);
	}
return(TIMEOUT);
}

/**********************/
/* read ser function  */
/**********************/
readser(wait)
	ULONG wait;
{
int ch;

SetTimer(wait,0L); /* wait for n seconds */
while(TRUE)
	{
	Wait( SerCharSig | TimerSig);
	CheckMessage();
	if(CheckSer())
		{
		AbortIO(TimerMsg);
		WaitIO(TimerMsg);
		WaitIO(ReadSerReq);
		ch = (int)serin[0];
		SendIO(ReadSerReq);
		return((int)ch);
		}
	if(CheckIO(TimerMsg))
		{
		WaitIO(TimerMsg);
		return(TIMEOUT);
		}
	}
}

/********************************/
/* Flush serial receive buffer  */
/* Removes characters in serial */
/* buffer to maintain line sync */
/********************************/
PurgeLine()
{
AbortIO(ReadSerReq);
ReadSerReq->IOSer.io_Command = CMD_CLEAR;
DoIO(ReadSerReq);
ReadSerReq->IOSer.io_Command = CMD_READ;
SendIO(ReadSerReq);
}
