#include <DOS.H>
#include <TIME.H>
int BASE; //BASE COM PORT ADRESS

/* REGISTERS */

#define OUT_REG			BASE
#define IN_REG			BASE
#define LOW_DIV			BASE
#define HIGH_DIV		BASE+1
#define INT_REG			BASE+1
#define INT_ID_REG	BASE+2
#define CONTROL			BASE+3
#define MODEM				BASE+4
#define STATUS			BASE+5
#define M_STATUS		BASE+6

/* CONSTANTS */
//               PORT SPEED:
#define B_110				1040
#define B_150				768
#define B_300				384
#define B_600				192
#define B_1200			96
#define B_2400			48
#define B_4800			24
#define B_9600			12
#define B_19200			6
#define B_38400			3
#define B_57600			2
#define B_115200		1

/* Interrupt masks */

#define DATA_REC		0x01 //Data recieved
#define EMPTY_BUF		0x02 //Transmitter buffer empty
#define ERROR				0x04 //Recieve error
#define MODEM_INT		0x08 //???

/* Control masks */

#define DIVISOR			0x80 //DIV register access
#define BIT_5				0x00 //5 bits in package
#define BIT_6				0x01 //6 bits in package
#define BIT_7				0x02 //7 bits in package
#define BIT_8				0x03 //8 bits in paskage
#define STOP_1			0x00 //1 Stop bit
#define STOP_2			0x04 //2 Stop bits
#define NOPARITY		0x00 //No parity mode
#define EVEN				0x18 //Even (2,4,8...)
#define ODD					0x08 //Odd (1,3,5...)
#define FIXPARITY		0x20 //??? I don`t know...
#define DTR					0x01 //DTR line control
#define RTS					0x02 //RTS line control
#define OUT1				0x01 //OUT1 line control
#define OUT2				0x01 //OUT2 line control
#define LOOPBACK		0x10 //Self test mode

/* Ready masks */

#define DATA_IN			0x01 //Incoming data!
#define OVERRUN			0x02 //Overfull...
#define PARITY_ERR	0x04 //Parity error
#define FRAME_ERR		0x08 //Wrong package format
#define DATA_OUT		0x20 //Ready to transmitt!

/* Static signals masks */

#define CTS					0x10 //CTS line status
#define DSR					0x20 //DSR line status
#define RI					0x40 //RI line status
#define DCD					0x80 //DCD line status

void init_serial(void);
int out_sym(int symbol);
int in_sym(int *symbol, int timeout, int *error_code);

void init_serial(void)
{
	// PORT SPEED SETTINGS
	outportb(CONTROL, DIVISOR); //Getting access
	outportb(LOW_DIV, B_9600);
	outportb(HIGH_DIV, B_9600>>8);

	// PORT MODE SETTINGS
	outportb(CONTROL, BIT_8+STOP_2+NOPARITY);

	// Disable interrupts
	outportb(INT_REG, 0);
}

int out_sym(int symbol)
{
	long timeout;
	timeout=clock();
	do {
			if((clock()-timeout)==3) return -1; //Timeout
		 } while ((inportb(STATUS) & DATA_OUT) == 0);
		 //Previous byte transmitted, continue...

	outportb(OUT_REG, symbol);
	return 0;
}

int in_sym(int *symbol, int timeout, int *error_code)
{
	long tmp;
	tmp=clock();
	do {
			if((clock()-tmp)>=timeout) return 1; *error_code=inportb(STATUS);
		 } while ((*error_code & DATA_IN)==0);
	//Recieve error?
	if(*error_code & (FRAME_ERR+OVERRUN)!=0)
		{return 2;}
	else
		{*symbol=inportb(IN_REG); return 0;}
}

int main(void)
{
	// Serial Port operation program
	// code by Alexander Kurmis 1085/1

	//Don`t forget to check the Base adress!
	BASE=0x3F8;
	init_serial(); //You can change the configuration in this function code.
	//Now it is 9600bps, 2 Stop-bits, No parity.
	//COM Ports are ready to work!

	//out_sym(); returns:
	// 0  if sucsess
	// -1 if error

	//in_sym(); returns:
	// 0  if sucsess
	// -1 if error
	// 2 if timeout

	out_sym('A');
  delay(10);
	out_sym('T');
	delay(10);
	out_sym('A');
	return 0;
}



