{File: SIOSubs.asm
Modification History:
Last change by Jim Frandeen : May 25, 1982 3:57 PM
Created by Jim Frandeen : March 25, 1982 8:58 AM
}

Get"SysDefs.asm"
Get"CommonDefs.asm"
Get"RS232CDefs.asm"

IMPAsyncTimerValue;From RS232CInterrupts
IMPCurrentRS366Status;From RS232CMisc
IMPRxWR1;From Rs232CMisc
IMPRxWR3;From Rs232CMisc
IMPRxWR4;From Rs232CMisc
IMPTxWR1;From Rs232CMisc
IMPTxWR4;From Rs232CMisc
IMPTxWR5;From Rs232CMisc

EXPAsynchronousDivisor
EXPAsyncTimerCounter
EXPAsyncTimerStoppedFlag
EXPBisyncTimerTable
EXPHLPlus2A
EXPResetChannels
EXPSetAsyncTimer
EXPSetBaudRate
EXPSetRS366
EXPSynchronousDivisor
EXPTestAsyncTimer
;
SetAsyncTimer:
{This entry is called whenever a new timeout value is set. This is called by Misc when we get a SetParameters command. The client supplies the timeout value in RS232CParameer4. We set the TimerStoppedFlag.}
STAAsyncTimerStoppedFlag; set/reset timer stopped flag
SHLDAsyncTimerValue; set initial iteration counter value
SHLDAsyncTimerCounter; set iteration counter

StartAsyncTimer:
{This entry is called by TestAsyncTimer when we get a timeout. We restart the timer.}
MVIA,0B0H;timer channel 2, mode 0, binary
OUTTimerMode
LXIH,TimerCount2+8000H
MVIM,0FEH;Send low byte of 1840 decimal
MVIM,47H;Send high byte
RET

TestAsyncTimer:
{This entry is called by the Async Get Loop while we are waiting for the interrupt routine to fill a frame. When we get a timeout, we end the current frame. Note that we will not get a timeout until we have received at least one character because the TimerStoppedFlag is set until we receive the first character. When we return:
Condition Flag = Zero if timeout
Condition Flag # Zero if no timeout
}
DBopMVIA;A ← AsyncTimerStoppedFlag
AsyncTimerStoppedFlag:
DB0
ORAA
RNZ; if timer not running

{Continue if timer is running. AsyncTimerStoppedFlag=0.}
INIntReq; read timer service request register
ANIMiscTimerReqMask; test timer output
RNZ; if timer output not active (Z flag false!)

{Continue if 1 msc timeout.}
CALLStartAsyncTimer; restart timer chip

DBopLXIH;HL ← AsyncTimerCounter
AsyncTimerCounter:
DW0
DCXH; update iteration counter
MOVA,L
ORAH
JNZTestAsyncTimer10; if iteration counter not exhausted
LHLDAsyncTimerValue; - else restart with initial value

TestAsyncTimer10:
SHLDAsyncTimerCounter; update iteration counter
RNZ;No timeout

{Continue if timeout. Set the TimerStoppedFlag.}
CMA;A ← FF
STAAsyncTimerStoppedFlag; set timer stopped flag
RET; Z flag set if timeout occurred
;
ResetChannels:
{Reset Rx and Tx channels. If the DMA Channel2 is being used for Rx, or if DMA Channel3 is being used for Tx, disable these also. This subroutine is called by Off and by SetParameters.}
MVIA,ChannelReset
DI
OUTTxCont
OUTRxCont
EI
RET
;
SetBaudRate:
{ This Routine sets the Frequency Divisor and Oscillation Mode for the i8253 Programmable Interval Timer. Counter #1 of i8253 is used for the Tx Clock generator, #2 is used for the Rx generator.On entry, HL points to Baud rate divisor table: AsynchronousDivisor or SynchronousDivisor.}
CALLHLPlus2A
MVIA,OSCCMD; Frequncy and Mode Set to i8253
OUTOSCCont; Counter#1, LSB & MSB, Mode3, Binary
MOVA,M; A ← ((H,L))
OUTOSCReg
INXH; H,L ← (H,L)+1
MOVA,M; A ← ((H,L))
OUTOSCReg
{Fall through to SetRS366}

SetRS366:
{Set the RS366 register to the value in A. We do this for the SetRS366Status command. This comes from the SetStatus366 procedure in the head. Parameter bits are as follows:
10callRequest
11digitPresent
12..15digit
The two high order bits are not disturbed:
8test loop back enable bit
9local OSC Enable bit
}
XRIRS366InvMask;30H
MOVD,A
LDACurrentRS366Status; Read Current RS366 Status
ANIRS366ResetMask; Save Loop connection and Clock Sel.
ORAD
OUTRS366Reg
RET
;
HLPlus2A:
{ On entry:
A = number to add to HL.
On exit:
HL = HL + 2A }

ADDA;A*2 Makes Table Reference Address
MOVE,A
MVID,0
DADD;HL ← (H,L)+(B,C)
RET

AsynchronousDivisor:
DW2304; Divisor for 50Hz Asynchronus mode
DW1536; Divisor for 75Hz Asynchronus mode
DW1047; Divisor for 110Hz Asynchronus mode
DW856; Divisor for 134.5Hz Asynchronus mode
DW768; Divisor for 150Hz Asynchronus mode
DW384; Divisor for 300Hz Asynchronus mode
DW192; Divisor for 600Hz Asynchronus mode
DW96; Divisor for 1200Hz Asynchronus mode
DW48; Divisor for 2400Hz Asynchronus mode
DW32; Divisor for 3600Hz Asynchronus mode
DW24; Divisor for 4800Hz Asynchronus mode
DW16; Divisor for 7200Hz Asynchronus mode
DW12; Divisor for 9600Hz Asynchronus mode
DW6; Divisor for 19200Hz Asynchronus mode
DW3; Divisor for 38400Hz Asynchronus mode
DW2; Divisor for 57600Hz Asynchronus mode

SynchronousDivisor:
DW36864; Divisor for 50Hz Synchronus mode
DW24576; Divisor for 75Hz Synchronus mode
DW16756; Divisor for 110Hz Synchronus mode
DW13704; Divisor for 134.5Hz Synchronus mode
DW12288; Divisor for 150Hz Synchronus mode
DW6144; Divisor for 300Hz Synchronus mode
DW3072; Divisor for 600Hz Synchronus mode
DW1536; Divisor for 1200Hz Synchronus mode
DW768; Divisor for 2400Hz Synchronus mode
DW512; Divisor for 3600Hz Synchronus mode
DW384; Divisor for 4800Hz Synchronus mode
DW256; Divisor for 7200Hz Synchronus mode
DW192; Divisor for 9600Hz Synchronus mode

BisyncTimerTable:
DW50; 50Baud 1 Sec
DW75; 75Baud 1 Sec
DW110; 110Baud 1 Sec
DW135; 134.5Baud 1 Sec
DW150; 150Baud 1 Sec
DW300; 300Baud 1 Sec
DW600; 600Baud 1 Sec
DW1200; 1200Baud 1 Sec
DW2400; 2400Baud 1 Sec
DW3600; 3600Baud 1 Sec
DW4800; 4800Baud 1 Sec
DW7200; 7200Baud 1 Sec
DW9600; 9600Baud 1 Sec
DW19200; 19200Baud 1 Sec

END