/***************************************************************
 *  Alcuin: A HP48 emulator for Amiga Computers
 * 
 *  (C) 1995 Stephan Schupfer (schupfer@sbox.tu-graz.ac.at)
 *
 */
#include <devices/serial.h>

#include "main.h"
#include "hp48.h"
#include "device.h"

#define NR_BUFFER 256

extern int rece_instr;

struct IOExtSer *serout;
struct IOExtSer *serin;
struct MsgPort *serport;


char *SPortName = "Alcuin Serial";
int seropen=0;
int wire_fd=0;
int ir_fd=0;

/************************************************************/
void openserial()
{
if ((serport = (struct MsgPort *) CreatePort(SPortName,0))==NULL)
	stirb ("Can't create %s.",101,"MessagePort");
if ((serout = (struct IOExtSer *) CreateExtIO(serport,sizeof(struct IOExtSer))) ==NULL)
	stirb ("Can't create %s.",101,"ExtIO");
if ((serin = (struct IOExtSer *) CreateExtIO(serport,sizeof(struct IOExtSer))) ==NULL)
	stirb ("Can't create %s.",101,"ExtIO");
if (key) wire_fd=1;
ir_fd=0;
if ((seropen=!OpenDevice(Serial,(long)Unit,serout,0L)) ==NULL) {
	wire_fd=0;
	sage ("Can't open %s.",100,Serial);
	}
else CopyMemQuick(serout,serin,sizeof(struct IOExtSer));
}

/************************************************************/
void closeserial()
{
if (seropen)		CloseDevice(serout);
if (serin)			DeleteExtIO(serin);
if (serout)			DeleteExtIO(serout);
if (serport)		DeletePort(serport);
}

/************************************************************/
void update_connection_display()
{
}

/************************************************************/
void serial_baud(int baud)
{
baud &= 0x7;
if (wire_fd) {
	switch (baud) {
		case 0:
			serout->io_Baud = 1200;
			break;
		case 1:
			serout->io_Baud = 1920;
			break;
		case 2:
			serout->io_Baud = 2400;
			break;
		case 3:
			serout->io_Baud = 3840;
			break;
		case 4:
			serout->io_Baud = 4800;
			break;
		case 5:
			serout->io_Baud = 7680;
			break;
		case 6:
			serout->io_Baud = 9600;
			break;
		case 7:
			serout->io_Baud = 15360;
			break;
		}
	serout->IOSer.io_Command = SDCMD_SETPARAMS;
	if (DoIO(serout) != NULL)
		stirb ("Can't set %s.",12,"BaudRate");
	CopyMemQuick(serout,serin, sizeof(struct IOExtSer));
	}
}
/************************************************************/
void transmit_char()
{
if (saturn_ir_ctrl & 0x04) {
	if (!ir_fd) {
		saturn_tcs &= 0x0e;
		if (saturn_io_ctrl & 0x04) do_interupt();
		return;
    	}
	} 
else {
	if (!wire_fd) {
		saturn_tcs &= 0x0e;
		if (saturn_io_ctrl & 0x04) do_interupt();
		return;
		}
	}
if (saturn_ir_ctrl & 0x04) {
	serout->IOSer.io_Command=CMD_WRITE;
	serout->IOSer.io_Length=1;
	serout->IOSer.io_Data=(APTR) &saturn_tbr;
	if (!DoIO(serout)) {
		saturn_tcs &= 0x0e;
		if (saturn_io_ctrl & 0x04) do_interupt();
		} 
	else {
		sage("Failed: %s.",113,"DoIO()");
		saturn_tcs &= 0x0e;
		if (saturn_io_ctrl & 0x04) do_interupt();
		}
	} 
else {
	serout->IOSer.io_Command=CMD_WRITE;
	serout->IOSer.io_Length=1;
	serout->IOSer.io_Data=(APTR) &saturn_tbr;
	if (!DoIO(serout)) {
		saturn_tcs &= 0x0e;
		if (saturn_io_ctrl & 0x04) do_interupt();
		} 
	else {
		sage("Failed: %s.",113,"DoIO()");
		saturn_tcs &= 0x0e;
		if (saturn_io_ctrl & 0x04) do_interupt();
		}
	}
}

/************************************************************/
void receive_char()
{
int length;
static unsigned char buf[NR_BUFFER + 1];
static int nrd = 0, bp = 0;


/*rece_instr = 0;*/
/*printf("receive:\n");*/
if (saturn_ir_ctrl & 0x04) {
	if (!ir_fd) return;
	}
else {
	if (!wire_fd) return;
	}

if (saturn_rcs & 0x01) return;

if (nrd == 0) {
	if (saturn_ir_ctrl & 0x04) {
		serin->IOSer.io_Command = SDCMD_QUERY;
		serin->IOSer.io_Actual = 0;
		if (DoIO(serin) != NULL)
			sage("Failed: %s.",113,"DoIO()");
		if ((length = serin->IOSer.io_Actual) > 0) {
			serin->IOSer.io_Command=CMD_READ;
			serin->IOSer.io_Length=length;
			serin->IOSer.io_Data=buf;
			if (DoIO(serin))
				sage("Failed: %s.",113,"DoIO()");
			nrd = length;
			bp = 0;
			}
		}
	else {
		serin->IOSer.io_Command = SDCMD_QUERY;
		serin->IOSer.io_Actual = 0;
		if (DoIO(serin) != NULL)
			sage("Failed: %s.",113,"DoIO()");
		if ((length = serin->IOSer.io_Actual) > 0) {
			serin->IOSer.io_Command=CMD_READ;
			serin->IOSer.io_Length=length;
			serin->IOSer.io_Data=buf;
			if (DoIO(serin))
				sage("Failed: %s.",113,"DoIO()");
			nrd = length;
			bp = 0;
			}
		}
	}
if (!nrd) return;
if (!(saturn_io_ctrl & 0x08)) {
	nrd = 0;
	return;
	}
saturn_rbr = buf[bp++];
/*printf("%c\n",saturn_rbr);*/
nrd--;
saturn_rcs |= 0x01;
if (saturn_io_ctrl & 0x02) do_interupt();
}
/************************************************************/
