home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
microcrn
/
issue_36.arc
/
SIOLIB.INC
< prev
next >
Wrap
Text File
|
1979-12-31
|
8KB
|
310 lines
{ KAYPRO 4/83 INTERRUPT DRIVEN SERIAL I/O }
{ INTERFACE FOR TURBO PASCAL }
{ FRANK A. KURUCZ }
{ 2360 PASEO DE LAURA #20 }
{ OCEANSIDE CA, 92056 }
{ H- (619) 721-8530 }
{ W- (619) 433-6406 }
{ THIS PROGRAM INTERFACES WITH AN ASSEMBLY LANGUAGE PROGRAM }
{ SIOINT.ASM, TO PROVIDE BUFFERED SERIAL I/O }
{ THE PROGRAMMER HAS 3 PROCEDURES/FUNCTIONS AT HIS DISPOSITION: }
{ INITSIO - INITIALIZES SIO, SETS UP INTERRUPTS AND FIFOS }
{ WRITEBYTE - OUTPUTS A BYTE TO SERIAL OUTPUT }
{ READBYTE - IF ANY DATA PRESENT IN FIFO, IT IS RETURNED }
{ NOTE ************************************************************* }
{ WHEN COMPILING THE COM FILE MAKE SURE THAT THE END OF MEMORY }
{ PARAMETER IS SET BELOW THE INTERRUPT VECTOR }
{ OTHERWISE THE INTERRUPT PROCEDURES ARE AT RISK OF BEING OVERWRITTEN }
{$A+}
Const
{ ADDRESSES OF POINTERS, COUNTERS AND BUFFERS USED BY INTERRUPTS }
VectorAddr = $E000; { INTERRUPT VECTOR }
InSerialFifoAddr = $E100; { SERIAL INPUT FIFO }
InFifoCountAddr = $E300; { FIFO COUNTER }
InFifoInPtrAddr = $E301; { INPUT POINTER }
InFifoOutPtrAddr = $E303; { OUTPUT POINTER }
OutSerialFifoAddr = $E200; { SERIAL OUTPUT FIFO }
OutFifoCountAddr = $E305; { FIFO COUNTER }
OutFifoInPtrAddr = $E306; { INPUT POINTER }
OutFifoOutPtrAddr = $E308; { OUTPUT POINTER }
OutIntExpectedAddr = $E30A; { OUTPUT INTERRUPT ENABLED FLAG }
{ I/O PORT ADDRESSES }
Control_Port_A = $06;
Control_Port_B = $07;
Baud_Port = $00;
Data_Port_A = $04;
{ ######################################################################## }
{ ######################################################################## }
{ INITIALIZE THE SIO }
{ PARAMETERS }
{ BAUD: 0 = 50 8 = 1800 }
{ 1 = 75 9 = 2000 }
{ 2 = 110 10 = 2400 }
{ 3 = 134 11 = 3600 }
{ 4 = 150 12 = 4800 }
{ 5 = 300 13 = 7200 }
{ 6 = 600 14 = 9600 }
{ 7 = 1200 15 = 19200 }
{ DATASIZE: 5 = 5 DATA BITS }
{ 6 = 6 DATA BITS }
{ 7 = 7 DATA BITS }
{ 8 = 8 DATA BITS }
{ PARITY: 0 = NO PARITY }
{ 1 = ODD PARITY }
{ 2 = NO PARITY }
{ 3 = EVEN PARITY }
{ STOPBITS: 0 = ILLEGAL VALUE }
{ 1 = 1 STOP BIT }
{ 2 = 1.5 STOP BITS }
{ 3 = 2 STOP BITS }
Procedure InitSIO(Baud,DataSize,Parity,StopBits:Integer);
Var
Vector: Byte;
{ INITIALIZE THE INPUT AND OUTPUT FIFOS AND COUNTERS AS WELL AS }
{ OUTPUT INTERRUPT EXPECTED FLAG }
{1} Procedure InitFifos;
Var
InFifoCount: Byte Absolute InFifoCountAddr;
InFifoInPtr: Integer Absolute InFifoInPtrAddr;
InFifoOutPtr: Integer Absolute InFifoOutPtrAddr;
OutFifoCount: Byte Absolute OutFifoCountAddr;
OutFifoInPtr: Integer Absolute OutFifoInPtrAddr;
OutFifoOutPtr: Integer Absolute OutFifoOutPtrAddr;
OutIntExpected: Byte Absolute OutIntExpectedAddr;
Begin
InFifoCount:= 0;
OutFifoCount:= 0;
InFifoInPtr:= InSerialFifoAddr;
InFifoOutPtr:= InSerialFifoAddr;
OutFifoInPtr:= OutSerialFifoAddr;
OutFifoOutPtr:= OutSerialFifoAddr;
OutIntExpected:= 0;
End;
{ NOW INITIALIZE THE SIO }
Begin
Inline($F3); { DISABLE INTERRUPTS }
InitFifos; { SET UP FIFOS }
{ SET UP THE INTERRUPT VECTOR REGISTER TO THE MOST SIGNIFICANT }
{ BYTE OF THE INTERRUPT VECTOR ADDDRESS }
{ AND SET UP INTERRUPT MODE 2 }
Vector:= VectorAddr Div $100;
Inline($3A/Vector/ { LD A,(Vector) }
$ED/$47/ { LD I,A }
$ED/$5E); { IM 2 }
{ RESET THE SIO }
Port[Control_Port_A]:=$18;
{ PROGRAM THE SIO FOR INTERRUPTS }
Port[Control_Port_B]:= 2;
Port[Control_Port_B]:= 0;
Port[Control_Port_B]:= 1;
Port[Control_Port_B]:= 4;
{ SET UP THE SERIAL CHARACTERISTICS OF PORT A }
{ CAUTION - PORT B IS USED FOR KEYBOARD DATA ENTRY }
{ SO DON'T MESS WITH IT }
{ MAKE SURE STOP BITS HAS A VALID VALUE }
StopBits:=(StopBits Mod 4) Shl 2;
If (StopBits = 0) Then Stopbits:=4;
{ MAKE SURE PARITY HAS A VALID VALUE AND PROGRAM IT }
{ ALONG WITH STOPBITS AND CLOCK MODE = 32X }
Port[Control_Port_A]:=4;
Port[Control_Port_A]:= $40 Or (Parity Mod 4) Or StopBits;
{ PROGRAM RECEIVE DATA BYTE SIZE }
Case (DataSize) Of
5: DataSize:= 0;
6: DataSize:= $40;
7: DataSize:= $80;
8: DataSize:= $C0;
Else
DataSize:= $C0;
End;
{ AND ENABLE RECEIVE }
Port[Control_Port_A]:=3;
Port[Control_Port_A]:=DataSize Or 1;
{ ALSO PROGRAM TRANSMIT DATA SIZE }
{ SETTING DTR AND CTS TO 1 AND ENABLING TRANSMISSION }
Port[Control_Port_A]:=5;
Port[Control_Port_A]:=$8A Or (DataSize Shr 1);
{ ENABLE TRANSMIT AND RECEIVE INTERRUPTS }
Port[Control_Port_A]:=1;
Port[Control_Port_A]:=$1B;
{ SET THE BAUD RATE, MAKING SURE THE PARAMETER IS VALID }
Baud:=Baud Mod 16;
Port[Baud_Port]:=Baud;
Inline($FB); { RE-ENABLE INTERRUPTS }
End;
{ ######################################################################### }
{ ######################################################################### }
{ WRITE A BYTE TO SERIAL OUTPUT }
Procedure WriteByte(Data:Byte);
Var
OutFifoCount: Byte Absolute OutFifoCountAddr;
OutFifoInPtr: Integer Absolute OutFifoInPtrAddr;
OutFifoInPtrByte: Byte Absolute OutFifoInPtrAddr;
OutIntExpected: Byte Absolute OutIntExpectedAddr;
Begin
{ IF FIFO IS FULL WAIT FOR OUTPUT INTERRUPT TO MAKE ROOM }
While (OutFifoCount = $FF) Do ;
{ DISABLE INTERRUPTS }
Inline($F3);
{ ARE WE EXPECTING AN OUTPUT INTERRUPT ?}
If (OutIntExpected <> 0) Then
Begin
{ YES, INSERT DATA IN TO THE OUTPUT FIFO }
{ INCREMENT THE FIFO COUNT }
OutFifoCount:= OutFifoCount + 1;
{ SAVE THE DATA IN THE FIFO }
Mem[OutFifoInptr]:= Data;
{ INCREMENT THE FIFO POINTER }
OutFifoInPtrByte:= OutFifoInPtrByte + 1;
End
Else
Begin
{ OUTPUT INTERRUPTS HAVE BEEN SUSPENDED }
{ OUTPUT DATA AND RE-ENABLE THE INETRRUPT }
Port[Data_Port_A]:= Data;
OutIntExpected:=$FF;
End;
{ RE-ENABLE INTERRUPTS }
Inline($FB);
End;
{ ######################################################################## }
{ ######################################################################## }
{ RETURNS A BYTE }
{ IF THERE IS DATA IN THE SERIAL INPUT FIFO THEN THE FUNCTION }
{ RETURNS THE FIRST BYTE IN THE FIFO AND NODATA = FALSE }
{ OTHERWISE A GARBAGE BYTE IS RETURNED AND NODATA = TRUE }
Function ReadByte(Var NoData:Boolean):Byte;
Var
InFifoCount: Byte Absolute InFifoCountAddr;
InFifoOutPtr: Integer Absolute InFifoOutPtrAddr;
InFifoOutPtrByte: Byte Absolute InFifoOutPtrAddr;
Data: Byte;
Begin
{ DISABLE INTERRUPTS }
Inline($F3);
{ IS THE FIFO EMPTY ? }
If (InFifoCount <> 0) Then
Begin
{ THERE IS DATA }
{ DECREMENT THE FIFO COUNTER }
InFifoCount:= InFifoCount - 1;
{ GET THE DATA FROM THE FIFO }
Data:= Mem[InFifoOutPtr];
{ INCREMENT THE FIFO POINTER WITH WRAP AROUND }
InFifoOutPtrByte:= InFifoOutPtrByte+1;
{ LOWER NODATA FLAG }
NoData:=False;
End
{ IT IS EMPTY, RAISE THE NODATA FLAG }
Else NoData:=True;
{ RE-ENABLE INTERRUPTS }
Inline($FB);
{ RETURN THE BYTE }
ReadByte:=Data;
End;