Sériová komunikace
Pøíloha 1.

program serial;

uses dos, crt;

const
{------------------- COM ports in PC -------------------}
COM1= $3f8;
COM2= $2f8;
Intr: Integer = $0b;

{------------------- 8250 registers --------------------}
RBR= 0;						{ received data - read only -  if DLAB=0 }
THR= 0;						{ transmit data - write only - if DLAB=0 }

DLL= 0;						{ baud generator (LSB) - if DLAB=1 }
DLM= 1;						{ baud generator (MSB) - if DLAB=1 }

IER= 1;						{ interrupt enable - r/w }
IIR= 2;						{ interrupt identification - read only }
LCR= 3;						{ line control register - r/w }
MCR= 4;						{ modem control register - r/w }
LSR= 5;						{ line status - read only }
MSR= 6;						{ modem status register - read only }

{------------------- 8250 register bits ----------------}
IER_RX= 1;					{ intr on received data - priority 2 }
IER_TX= 2;					{ intr on data transmitted - priority 3 }
IER_ERR= 4;					{ intr on receive error (see LSR) - priority 1 }
IER_MS= 8;					{ intr on modem sts change (see MSR) - priority 4 }

IIR_PEND= 1;					{ active intr request }
IIR_MASK= 6;					{ source id mask }
IIR_MS= 0;					{ modem sts change }
IIR_TX= 2;					{ data transmitted }
IIR_RX= 4;					{ data received }
IIR_ERR= 6;					{ receive error }

LCR_5BIT= 0;					{ byte length codes }
LCR_6BIT= 1;
LCR_7BIT= 2;
LCR_8BIT= 3;

LCR_2STOP= 4;					{ two stop bits }
LCR_PTYEN= 8;					{ parity enabled }
LCR_EVPTY= $10;					{ even parity }
LCR_FIXPTY= $20;				{ fixed parity }
LCR_INTREN= $40;				{ interrupt enabled }
LCR_DLAB= $80;					{ baud gen. access enabled }

MCR_DTR= 1;					{ DTR modem signal }
MCR_RTS= 2;					{ RTS modem signal }
MCR_OUT1= 4;					{ user signal }
MCR_OUT2= 8;					{ user signal - wired to 3 state IRQ driver }
MCR_LOOP= $10;					{ test loop }

LSR_RX= 1;					{ data received  }
LSR_OR= 2;					{ overrun - read once }
LSR_PR= 4;					{ parity error - read once }
LSR_FR= 8;					{ frame error - read once }
LSR_BT= $10;					{ break error - read once }
LSR_BF= $20;					{ tx buffer empty }
LSR_TX= $40;					{ serializer empty }

MSR_CSR_CH= 1;					{ CSR has changed - read once }
MSR_DSR_CH= 2;					{ DSR has changed - read once }
MSR_RI_END= 4;					{ RI ended - read once }
MSR_RLSD_CH= 8;					{ RLSD changed - read once }
MSR_CSR= $10;
MSR_DSR= $20;
MSR_RI= $40;
MSR_RLSD= $80;

DLM_300= 1;					{ 300 Baud }
DLM_HIGH= 0;					{ more than 300 Baud }

DLL_300= $80;					{ 300 Baud }
DLL_600= $c0;					{ 600 Baud }
DLL_1200= $60;					{ 1200 Baud }
DLL_2400= $30;					{ 2400 Baud }
DLL_4800= $18;					{ 4800 Baud }
DLL_9600= $0c;					{ 9600 Baud }
DLL_19200= $06;					{ 19200 Baud }

{-------------------------------------------------------------------}
type word= 0..65535;

{-------------------------------------------------------------------}
var
	com: word;
	c: char;
	xp,yp,xv,yv: byte;
{-------------------------------------------------------------------}
procedure init_com (portaddr: word);
begin
	port[portaddr + LCR]:= LCR_DLAB;	{ path to baud gen on }
	port[portaddr + DLM]:= DLM_HIGH;	{ more than 300 Baud  }
	port[portaddr + DLL]:= DLL_1200;	{ 1200 Baud }
	port[portaddr + LCR]:= LCR_8BIT;	{ baud gen off, 8 bit, no par }
	port[portaddr + IER]:= 0;		{ no interrupt }
	port[portaddr + MCR]:= MCR_DTR;
end;

{-------------------------------------------------------------------}
function rx_rdy (portaddr: word): boolean;
begin
	rx_rdy:= ((port[portaddr + LSR] and LSR_RX) <> 0);
end;

{-------------------------------------------------------------------}
function tx_rdy (portaddr: word): boolean;
begin
	tx_rdy:= ((port[portaddr + LSR] and LSR_BF) <> 0);
end;

{-------------------------------------------------------------------}
function rx_get (portaddr: word): char;
begin
	rx_get:= chr(port[portaddr + RBR]);
end;

{-------------------------------------------------------------------}
procedure tx_put (portaddr: word; c: char);
begin
	port[portaddr + THR]:= ord(c);
end;

{-------------------------------------------------------------------}
begin
	com:= COM1;

	xp:= 1;yp:= 1;xv:= 1;yv:= 1;

	clrscr;
	writeln('Press Esc to exit');
	writeln('Send:');
	gotoxy(1,11);
	writeln('----------------------------------------------------------------');
	gotoxy(1,12);
	writeln('Receive:');
	c:= #59;

	init_com (com);				{ init }

	while (ord(c) <> 27) do			{ end via Esc key }
	begin
		if (rx_rdy(com)) then		{ new data available? }
		begin
			window(1, 13, 80, 25);
			gotoxy(xp, yp);
			c:= rx_get(com);	{ read new data... }
			write(c);		{ ...and write it on screen }
			if c= chr(13) then
				writeln;
			xp:= wherex;
			yp:= wherey;
		end;
		if keypressed then		{ if key pressed... }
		begin
			if tx_rdy(com) then	{ ...and out buffer is empty... }
			begin
				window(1, 3, 80, 10);
				gotoxy(xv, yv);
				c:= readkey;	{ ...read character from keyboard...}
				tx_put (com,c);	{ ...send it... }
				write(c);	{ ...and copy it also on screen }
				if c= chr(13) then
					writeln;
				xv:= wherex;
				yv:= wherey;
			end;
		end;
	end;
	c:= readkey;
end.