h45679
s 00703/00000/00000
d D 1.1 83/03/23 16:01:50 bog 1 0
c date and time created 83/03/23 16:01:50 by bog
e
u
4
U
t
T
I 1
	Title	HSFLCG	Beacon Buffered Host Communications
$Title('Operating System or Hardware Configuration Dependent Equates')
	.Z80
 
; Following equates depend upon the operating system.  They may need to be
;  changed if the operating system changes.
SetIV	Equ	0f236h		;Place to call to set up interrupt vector
IntVec	Equ	002h		;Receive character interrupt vector for SetIV
 
;Count for one-half millisecond delay in Foo: Dec A; Jr NZ,Foo loop
HalfMs	Equ	84
 
; Hardware I/O addresses
SIOD	Equ	021h		;Channel B data port
SIOC	Equ	023h		;Channel B control port
 
Clock1	Equ	052h		;If fact of two clocks implies separable
Clock2	Equ	060h		; Rx/Tx rates, code could be changed to
				;  reflect that capability.
 
;SIO and clock control equates
TxBufMT	Equ	2		;Bit number for Tx buffer empty
SelWr1	Equ	001h		;Select write register 1
IniWr1	Equ	018h		;Int on Rx chars; vector always xxxx 010x
DisInt	Equ	000h		;Disable Rx, Tx, external interrupts
SelWr2	Equ	002h		;Select write register 2
IniWr2	Equ	084h		;Interrupt vector
SelWr3	Equ	003h		;Select write register 3
IniWr3	Equ	001h		;Rx enable
SelWr4	Equ	004h		;Select write register 4
IniWr4	Equ	000h		;No sync
SelWr5	Equ	005h		;Select write register 5
IniWr5	Equ	08ah		;DTR; Tx enable; RTS
DTRWr5	Equ	080h		;DTR bit in Wr5
BREAKOn	Equ	010h		;Send BREAK in wr5
RxBREAK	Equ	7		;Bit number for BREAK received in Rr0
TxCTS	Equ	5		;Bit number for CTS status in Rr0
SelRr0	Equ	000h		;Select status register for read
SelRr1	Equ	001h		;Select read register 1
ResErrs	Equ	030h		;Command to reset receive errors
ResExts	Equ	010h		;Command to reset external/status interrupts
ChReset	Equ	018h		;Channel reset; select reg 0
 
ClkEna	Equ	057h		;Command to set clock counter mode, &c.
 
$Eject
$Title('GHxxxx/HSxxxx Dependent Equates')
;Queue equates
QLength	Equ	1024		;Allow a 1k char comm input queue
QXon	Equ	QLength/10	;Turn on hose when queue is 90% empty
QXOff	Equ	(QLength/4)*3	;Turn off hose when queue is 75% full
 
;Dimension of flag strings
FStDim	Equ	40		;40 ADE integer*2 characters
 
$Eject
$Title('HsRecv -- Return a Character from the Input Queue')
	CSeg
 
;Called by:
;	Call HsRecv(Ch,Error)
;		Output	Ch:	(^ in HL to) integer*2 ADE char
;				  in [BREAK,EMPTY,NUL..255]
;			Error:	(^ in DE to) integer*2 error code
;				  0:	No error
;				  1:	Parity error
;				  2:	Overrun error
;				  3:	Parity & overrun errors
;	    Return the next character from the host port or EMPTY if none.
;	    BREAK is returned if the port found a BREAK condition.
 
 
	Entry	HsRecv
HsRecv:	Push	IX		;Save registers -- index X
	Push	HL		; pointer to character parameter
	Push	DE		; pointer to error parameter
 
	Ld	HL,(QCount)	;Are there any characters there?
	Ld	A,H		;Check for zero
	Or	L
	Jr	NZ,MayXOn	;Jump if there is a character to return
	Ld	BC,EMPTY	;No char; return empty flag
	Ld	HL,0		; and no error
	Jr	Return
 
MayXOn:	Ld	A,(InStop)	;Have we sent an XOff?
	Or	A		;Non-zero if so
	Jr	Z,GivOne	;Jump if no XOff sent yet
 
	Ld	DE,-QXOn	;Low water mark
	Add	HL,DE		;Gone below XOn send point?
	Jr	C,GivOne	;Jump if not yet below XOn point
 
	Ld	A,(CIFMod)	;Flagging enabled?
	Or	A		;Non-zero if so
	Jr	Z,GivOne	;Jump if flagging not enabled
 
	Cp	2		;1: string, 2: DSR/DTR
	Jr	Z,HRXoHw	;Jump if hardware flagging
 
	Ld	HL,CInGoS	;Point to host go string
 
HRXoBL:	Push	HL		;Save pointer to string
	Ld	DE,Error	;Point to garbage error value
	Call	HsSend		;Send a character of go/stop string
	Pop	HL		;Restore pointer to string
	Ld	A,(Error)	;See if busy
	Or	A		;Non-zero if so
	Jr	NZ,HRXoBL	;Loop until not busy
	Jr	HREnFl		;Bypass h/w flagging
 
HRXoHw:	Di			;Turn off interrupts during cntl pair
	Ld	A,SelWr5	;Point to write register 5
	Out	(SIOC),A	;Select register 5
	Ld	A,(Wr5)		;Get current Wr5 value
	Xor	DTRWr5		;Set or reset DTR
	Ld	(Wr5),A		;Save for future users of Wr5
	Out	(SIOC),A	;Set/reset Data Terminal Ready
	Ei			;Re-enable interrupts
 
HREnFl:	Xor	A		;Tell the Isr that
	Ld	(InStop),A	; host is going
 
GivOne:	Di			; * Critical region
	Ld	HL,(QCount)	; *  Get count
	Dec	HL		; *  Decrement it
	Ld	(QCount),HL	; *  Stuff it back
	Ei			; * End critical region
	Ld	IX,(QTail)	;Get ptr to char word
	Ld	C,(IX)		;Get low-order byte
	Ld	B,(IX+1)	;Get high-order byte
	Call	IncPtr		;Wraparound increment HL
	Ld	(QTail),IX	; & stuff it back
 
; DE contains queue char word
	Ld	HL,0		;Assume no errors
	Bit	7,B		;BREAK?
	Jr	NZ,Return	;Yes -- return no error and BREAK
 
	Ld	L,B		;Error code to low order error code
	Ld	B,0		;Clear high half of character
 
; When arriving here, HL should contain error code and BC the character
Return:	Pop	IX		;Point to error parameter
	Ld	(IX),L		;Stuff error parameter
	Ld	(IX+1),H	; high byte
	Pop	IX		;Point to character
	Ld	(IX),C		;Stuff return character
	Ld	(IX+1),B	; high byte
	Pop	IX		;Restore index register
	Ret
$Eject
$Title('HsSend -- Send a Character to the Host')
;Called by:
;	Call HsSend(Ch,Error)
;		Input	Ch:	(^ in HL to) integer*2 ADE character
;				 in [BREAK,NUL..255]
;		Output	Error:	(^ in DE to) integer*2 busy flag
;				  -1:  busy; Ch not sent
;				   0:  Ch sent successfully
;	    Send a character out the host port
 
	Entry	HsSend
HsSend:	Push	IX		;Save index register
	Push	HL		;Pointer to char to send
	Pop	IX		; to index register
	Di			;Lock out input in critical region
	Ld	A,ResExts	;Have Rr0 show current CTS
	Out	(SIOC),A	; & select Rr0
	In	A,(SIOC)	;Get transmitter status
	Bit	TxBufMT,A	;Ready to send a character?
	Jr	NZ,HSFlMd	;Buffer empty.  Look for flagging
 
HSBusy:	Ld	A,-1		;Busy flag on in caller's variable
 
; Enter here with A containing 0 for not busy or -1 for busy
HSRetn:	Ei			;Reenable interrupts
	Ld	(DE),A		;Set busy or not busy
	Inc	DE		; in both halves
	Ld	(DE),A		; of caller's variable
	Pop	IX		;Restore index register
	Ret			; & return
 
HSFlMd:	Ld	HL,(COFMod)	;Look at output flagging mode
	Dec	L		; to -1: none, 0: string, 1: RTS/CTS
	Jp	M,HSTBrk	;Jump if no output flagging -- try BREAK
	Jr	Z,HSFStr	;Flagging with strings -- go check if stopped
 
				;Output RTS/CTS hardware flagging
	Bit	TxCTS,A		;Clear to send?
	Jr	Z,HSBusy	;Wait some more if not CTS
 
HSTBrk:	Ld	A,(IX+1)	;High byte of char to send to accum
	Inc	A		;Break?
	Ld	A,(IX)		;How about low byte -- preserve flags
	Jr	NZ,HSChar	;Jump if not break -- flags from Inc
	Cp	BREAK		;Is it a BREAK?
	Jr	Z,HSBreak	;Jump if yes
 
HSChar:	Out	(SIOD),A	;Poop out the char
 
HSSent:	Xor	A		;Not busy in caller's variable
	Jr	HSRetn		;Return setting not busy status
 
HSFStr:	Ld	A,(OutStop)	;Output flagged STOP?
	Or	A		;Non-zero if so
	Jr	NZ,HSBusy	;So spin until flag says GO
	Jr	HSTBrk		; else go ahead and send
 
HSBreak:
	Ld	A,SelWr5	;Select write register 5
	Out	(SIOC),A	; for setting BREAK
	Ld	A,(Wr5)		;Get the current write reg 5 value
	Or	BREAKOn		;Set the Sio as needed to send a break
	Ld	(Wr5),A		;Save it back in case someone else sets Wr5
	Out	(SIOC),A	;Turn on `send BREAK' bit
	Ei			;Now can enable interrupts
 
	Ld	HL,(CBkTim)	;Get BREAK time milliseconds
	Add	HL,HL		;Make it half milliseconds
 
BrkLpO:
	Ld	A,HalfMs	;Loop count for one-half millisecond
 
BrkLpI:	Dec	A		;Decrement inner loop count		 4t
	Jr	NZ,BrkLpI	; & loop until inner counted down	12t
 
	Dec	HL		;Decrement half-millisecond count
	Ld	A,H		;Test for zero
	Or	L		; both bytes
	Jr	NZ,BrkLpO	; & loop until BREAK timed out
 
	Di			;Disable interrupts
	Ld	A,SelWr5	;Select write register 5
	Out	(SIOC),A	; for resetting BREAK
	Ld	A,(Wr5)		;Get current Wr5 value
	And	0ffh-BREAKOn	;Turn off BREAK bit
	Ld	(Wr5),A		;Save for future users of Wr5
	Out	(SIOC),A	;Turn off `send BREAK' bit
	Jr	HsSent		;Return, enabling interrupts, not busy
 
$Eject
$Title('HsInit -- Initialize Communications Channel')
;Called by:
;	Call HsInit
;		Input	Parameters in Common /GHStat/
;	    Initialize communications channel with parameters in GHStat.
 
	Entry	HsInit
HsInit:	Ld	DE,(RBaudI)	;Baud rate index
	Ld	HL,Bauds-1	;1-base of divisor table
	Add	HL,DE		;Make indexed access
	Ld	A,(HL)		;Get divisor
	Ld	(Clk),A		;Save away
	Ld	HL,SIOClk-1	;1-base of SIO clock mode table
	Add	HL,DE		;Make indexed access
	Ld	A,(HL)		;Get SIO clock mode
 
	Ld	DE,(CurPar)	;Parity code
	Ld	HL,Parity	;0-base of parity table
	Add	HL,DE		;Make indexed access
	Or	(HL)		;Set parity bits in Wr4 appropriately
 
	Ld	DE,(StoBtI)	;Number of stop bits index
	Ld	HL,StopBits-1	;1-base of table
	Add	HL,DE		;Make indexed access
	Or	(HL)		;Set stop bits in Wr4
	Ld	(Wr4),A		;Save Wr4
 
	Ld	DE,(DatBtI)	;Number of data bits index
	Ld	HL,Dat3Bt-1	;1-base of table
	Add	HL,DE		;Make indexed access
	Ld	A,(HL)		;Get Wr3 data bits setting
	Ld	(Wr3),A		;Save Wr3
	Ld	HL,Dat5Bt-1	;1-base of table
	Add	HL,DE		;Make indexed access
	Ld	A,(HL)		;Get Wr5 data bits setting
	Ld	(Wr5),A		;Save Wr5
 
	Ld	A,ClkEna	;Clock counter mode etc.
	Out	(Clock1),A	; to first
	Out	(Clock2),A	; & second clocks
	Ld	A,(Clk)		;Baud rate divisor
	Out	(Clock1),A	; to first
	Out	(Clock2),A	; & second clocks
 
; Set QHead, QTail, QCount
	Ld	HL,Queue	;Point at beginning of queue
	Ld	(QHead),HL	;Isr puts next char at (QHead)
	Ld	(QTail),HL	;HsRecv gets next char from (QTail)
	Ld	HL,0		;Queue initially empty
	Ld	(QCount),HL	; so count is zero
 
; Show buffer not overrun
	Xor	A		;Need a zero
	Ld	(ORun),A	;Clear overrun bit
 
; Show Host not currently Stopped
	Ld	(InStop),HL	;Clear input & output stopped flags
 
; Reset our channel of the SIO
	Ld	A,ChReset	;Command channel reset
	Out	(SIOC),A	;Reset our channel of the SIO; must wait 4t
 
; Tell interrupt system we exist
	Ld	A,IntVec	;SIO interrupt vector
	Ld	DE,RxIsr	;SIO receive interrupt service routine
	Call	SetIV		;Go tell O/S about SIO interrupts
 
; Set up SIO completely
	Ld	HL,Commands	;Point to first command
	Ld	B,10		;Send 10 commands
	Ld	C,SIOC		; to SIO command port
	Otir			;Initialize Wr2, Wr4, Wr5, Wr3, Wr1
 
	Ret
$Eject
$Title('HsStop -- Close Communications Channel')
;Called by:
;	Call HsStop
;	    Close the open communications channel.
 
	Entry	HsStop
HsStop:	Di			;Disable interrupts during accesses
	Ld	A,SelWr1	;Select interrupt control register
	Out	(SIOC),A	;Wr1 is interrupt control
	Ld	A,DisInt	;Disable interrupts command
	Out	(SIOC),A	; into Wr1
	Ei			;Re-enable interrupts
 
; Note that probably this entry should tell the interrupt system that
;  the Isr is no longer active.
 
	Ret			; & return
$Eject
$Title('IncPtr -- Wraparound Increment QHead or QTail')
;Increment IX (QHead or QTail) and wrap around queue if necessary
; HL is crashed
 
IncPtr:	Inc	IX		;Point to next word
	Inc	IX
	Push	IX		;Incremented pointer
	Pop	DE		; to DE for arithmetic
	Ld	HL,QLast	;Addr of last char of queue to HL
	And	A		;Clear carry
	Sbc	HL,DE		;Last-Current
	Jr	NC,IncRet	;Jump if not beyond end
	Ld	IX,Queue	;Wrapped -- point at beginning
 
IncRet:	Ret			;& return
$Eject
$Title('How the ISR Works')
;I register in Z80 contains 0ffh as base page of interrupt vector table.
 
;SIO for modem (J1) is channel B at 021h (data), 023h (control)
 
;Register 2 of SIO contains 084h as interrupt vector offset from base page.
;So interrupt vectors are:
;	0ff80h		Channel B transmit buffer empty
;	0ff82h		Channel B external/status change
;	0ff84h		Channel B receive character available
;	0ff86h		Channel B special receive condition
 
;0ff84h points to Isr entry at 0f521h.
 
;@ 0f521h:
;IsrEntry:
;	Ld	(0f6b9h),Sp	;Save stack pointer
;	Ld	Sp,0ff80h	;Point to Isr stack
;	Push	HL		;Save interrupted routine's HL @0ff7eh
;	Ld	HL,**		;Originally 0f4ddh; Isr entry point replaces.
;MyIsrA	Equ	$-2
;	Jp	0f639h
 
;@ 0f639h:
;	Push	AF		;Save Psw @0ff7ch
;	Ld	A,(0fffeh)	;Interrupt controller mask?
;	And	03fh		; mask it with ?
;	Or	040h		; turn on ?
;	Out	(0a2h),A	; send it to ?
;	Ld	Sp,0ff7ah	;Again force Isr stack; equiv to Aspi -2
;	Jp	(HL)		;Go to my Isr (or 0f4ddh if mine not there)
 
;My routine returns with a Ret to address at 0ff7ah, or 0f647h
;@ 0f647h:
;IsrRet:
;	Ld	A,(0fffeh)	;Interrupt controller mask?
;	Out	(0a2h),A	; re-enable interrupts?
;	Pop	AF		;Restore interrupted routine's Psw
;	Pop	HL		; & HL
;	Ld	Sp,(0f6b9h)	;Restore interrupted routine's Sp
;	Ei			;Enable interrupts AFTER next instruction
;	Reti			;Return from interrupt
 
;One tells the O/S that a new Isr is here by:
;	Mov	A,Vector	;Interrupt level?
;	Mov	DE,MyIsr	;DE <- address of new Isr
;	Call	SetIV		;O/S routine to link in Isr
;@ 0f236h:
;SetIV:	Di			;Disable interrupts to avoid races
;	Push	HL		;Save caller's HL
;	Push	DE		;Save addr of new Isr
;	Ld	L,A		;Vector (level?) to HL
;	Ld	H,0		;Zero in high byte
;	Push	HL		;Move vector to DE, too
;	Pop	DE
;	Add	HL,HL		;HL <- Vector*2
;	Add	HL,HL		;      Vector*4
;	Add	HL,HL		;      Vector*8
;	Add	HL,DE		;      Vector*9
;	Add	HL,DE		;      Vector*10
;	Add	HL,DE		;      Vector*11
;	Add	HL,DE		;      Vector*12
;	Add	HL,DE		;      Vector*13
;	Add	HL,DE		;      Vector*14
;	Ex	DE,HL		;DE <- Vector*14, HL <- Vector
;	Ld	HL,MyIsrA[0]	;Vector 0 equivalent
;	Add	HL,DE		;Now my vector
;	Pop	DE		;DE <- new Isr address
;	Ld	(HL),E		;Low byte address to MyIsrA
;	Inc	HL		;Point to high byte of address
;	Ld	(HL),D		;Ld HL,** now loads new Isr address
;	Inc	HL		;Point to Jp opcode
;	Inc	HL		;Point to low byte of Jp address
;	Ld	(HL),039h	;Force Jp to be to 0f639h
;	Inc	HL		; high byte
;	Ld	(HL),0f6h
;	Pop	HL		;Restore caller's HL
;	Ei			;Re-enable interrupts
;	Ret			; & return to caller
 
;Upon entry to the Isr, the stack is at 0ff7ah and contains:
;	0ff7ah		0f647h	;Address of IsrRet
;	0ff7ch		<interrupted routine's AF>
;	0ff7eh		<interrupted routine's HL>
;and 0f6b9h contains the interrupted routine's Sp.
$Eject
$Title('RxIsr -- Receiver Interrupt Service Routine')
;Can crash A, HL; others restored
 
RxIsr:	Push	Ix		;Save index register
	Push	DE		; & scratch
	Ld	A,SelRr0	;Set up to read status register
	Out	(SIOC),A	; by pointing to read reg 0
	In	A,(SIOC)	;Get status, looking for BREAK
	Ld	D,A		;BREAK status in D
	Ld	A,SelRr1	;Set up to read error register
	Out	(SIOC),A	; by pointing to read register 1
	In	A,(SIOC)	;Get error status
	Rrca			;Move Overrun/Parity to bits 1/0
	Rrca
	Rrca
	Rrca
	And	3		;Mask to just Overrun/Parity
	Ld	HL,ORun		;Point to buffer overrun flag
	Or	(HL)		;Or in buffer overrun
	Ld	H,A		;Error status into H
	In	A,(SIOD)	;Data byte into A
	Ld	L,A		; then into L
	Ld	A,ResErrs	;Command to reset error flags
	Out	(SIOC),A	;Reset error flags
	Bit	RxBREAK,D	;Was BREAK set?
	Jr	Z,NBReset	;No -- bypass BREAK reset
	Ld	A,ResExts	;Command to reset external/status bits
	Out	(SIOC),A	;Reset BREAK latch
	Ld	HL,BREAK	; & return BREAK code
 
; HL contains word to buffer
NBReset:
	Ld	A,(COFMod)	;Get current output flagging mode
	Dec	A		;String output flagging?
	Jr	NZ,IsICnt	;Jump & increment count if not out str flag
 
	Ld	A,(OutStop)	;Currently stopped or going?
	Or	A		;Zero if going
	Ld	A,(COtStS)	;Assume looking for stop char. PRESERVE FLAGS
	Jr	Z,IsLStp	;Go look for stop char
	Ld	A,(COtGoS)	;Look for go char
 
IsLStp:	Cp	L		;This char match target go or stop char?
	Jr	NZ,IsICnt	;Jump if go or stop not found
 
	Ld	A,(OutStop)	;Get output stopped flag
	Cpl			;Complement it
	Ld	(OutStop),A	; & stuff it back to allow Tx to stop or cont
 
IsICnt:	Ld	DE,(QCount)	;Get count
	Inc	DE		;Increment it
	Ld	IX,-QXOff	;Test against hose turn-off value
	Add	IX,DE		;Current-XOffLevel
	Jr	NC,INXOff	;Jump if no XOff needed
	Ld	A,(InStop)	;XOff already?
	Or	A		;Non-zero if so
	Jr	NZ,INXOff	;Jump if no XOff needed
	Ld	A,(CIFMod)	;Input flagging enabled?
	Or	A		;Non-zero if so
	Jr	Z,INXOff	;Jump if flagging not enabled
 
	Cp	2		;1: string, 2: DSR/DTR
	Jr	Z,IsXoHw	;Jump if hardware flagging
 
IsXoBL:	Ld	A,SelRr0	;Point to status register
	Out	(SIOC),A	;Select Rr0
	In	A,(SIOC)	;Get Tx buffer ready status
	Bit	TxBufMT,A	;Is transmit ready?
	Jr	Z,IsXoBl	;Spin if not ready
	Ld	A,(CInStS)	;Get XOff
	Out	(SIOD),A	;Send XOff
	Jr	IsEnFl		; & bypass h/w flagging
 
IsXoHw:	Ld	A,SelWr5	;Point to write register 5
	Out	(SIOC),A	;Select register 5
	Ld	A,(Wr5)		;Get current Wr5 value
	Xor	DTRWr5		;Set DTR
	Ld	(Wr5),A		;Save for future users of Wr5
	Out	(SIOC),A	;Set Data Terminal Ready
 
IsEnFl:	Ld	A,0ffh		;Tell Recv that host is
	Ld	(InStop),A	; stopped
 
INXOff:	Ld	IX,-(QLength+1)	;Test against Max+1
	Add	IX,DE		;Current-(Max+1)
	Jr	C,IsrFull	;Jump if buffer is full
 
	Xor	A		;Make sure next char won't say
	Ld	(ORun),A	; buffer has overrun
 
	Ld	(QCount),DE	;Queue is now one fuller
	Ld	IX,(QHead)	;Pointer to place to stuff
	Ld	(IX),L		;Save data byte in buffer
	Ld	(IX+1),H	;Save error flag byte in buffer
	Call	IncPtr		;Wraparound increment buffer pointer
	Ld	(QHead),IX	; & stuff pointer back for next time
 
IsrRet:	Pop	DE		;Restore registers
	Pop	IX
	Ret			; & return
 
IsrFull:
	Ld	A,2		;Turn on overrun bit for next buffered
	Ld	(ORun),A	;  character
	Jr	IsrRet		; & return
$Eject
$Title('Fortran Common Parameters')
; Fortran length definitions
CHAR	Equ	1		;1-byte character
SMALL	Equ	1		;1-byte integer
INT	Equ	2		;2-byte integer
LONG	Equ	4		;4-byte integer
LOG	Equ	1		;1-byte logical
 
; Fortran funny characters
EMPTY	Equ	-1		;No characters ready
BREAK	Equ	-2		;BREAK condition
 
; Communications parameter area in Fortran Common
	Common	/GHStat/
COpen:	Dw	0		;NOT currently open
RBaudI:	Ds	INT		;Current receive baud rate index
CRBaud:	Ds	INT		;Current receive baud rate
TBaudI:	Ds	INT		;Current transmit baud rate index
CTBaud:	Ds	INT		;Current transmit baud rate
CurPar:	Ds	INT		;Current parity setting
DatBtI:	Ds	INT		;Current data bits per char index
CDatBt:	Ds	INT		;Current data bits per character
StoBtI:	Ds	INT		;Current stop bits per char index
CStoBt:	Ds	INT		;Current stop bits per character
CBkTim:	Ds	INT		;Current BREAK milliseconds
CIFMod:	Ds	INT		;Current receive flagging mode
COFMod:	Ds	INT		;Current transmit flagging mode
CInStL:	Ds	INT		;Current Rx stop str len
CInStS:	Ds	INT*FStDim	;Current Rx stop str
CInGoL:	Ds	INT		;Current Rx go str len
CInGoS:	Ds	INT*FStDim	;Current Rx go str
COtStL:	Ds	INT		;Current Tx stop str len
COtStS:	Ds	INT*FStDim	;Current Tx stop str
COtGoL:	Ds	INT		;Current Tx go str len
COtGoS:	Ds	INT*FStDim	;Current Tx go str
 
; Communications capability area in Fortran Common
	Common	/GHCmCp/
RBdCpL:	Dw	15		;Number of baud rates
RxBdCp:	Dw	50,75,110,134,150,200,300,600
	Dw	1200,1800,2000,2400,4800,9600,19200	;Rx baud rates 15
TBdCpL:	Dw	0		;Transmit matches receive (split capable?)
TxBdCp:	Dw	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
ParCap:	Dw	-1		;Can change parity
DtBCpL:	Dw	4		;Number of data bit formats
DtBtCp:	Dw	5,6,7,8		;Data bit formats
StBCpl:	Dw	3		;Number of stop bit formats
StBtCp:	Dw	1,2,3		;1, 1.5, 2 stop bits
TxBkCp:	Dw	-1		;Can send BREAK
TBkTCp:	Dw	-1		;Can change break timing
RHwFCp:	Dw	-1		;Can hardware flag receive
RStFCp:	Dw	1		;Can single-char string flag receive
THwFCp:	Dw	-1		;Can hardware flag transmit
TStFCp:	Dw	1		;Can single-char string flag transmit
SpFMCp:	Dw	-1		;Can have Rx & Tx flagging differ
 
$Eject
$Title('          Data Areas')
	DSeg
 
; Baud rate divisors for clocks
Bauds:
	Db	0c0h		;50 baud
	Db	080h		;75 baud
	Db	0afh		;110 baud (109.71 really -- 0.260% low)
	Db	08fh		;134.5 baud (134.27 really -- 0.174% low)
	Db	080h		;150 baud
	Db	0c0h		;200 baud
	Db	080h		;300 baud
	Db	040h		;600 baud
	Db	020h		;1200 baud
	Db	015h		;1800 baud (1828.57 really -- 1.587% high)
	Db	013h		;2000 baud (2021.05 really -- 1.053% high)
	Db	010h		;2400 baud
	Db	008h		;4800 baud
	Db	004h		;9600 baud
	Db	002h		;19200 baud
 
; SIO clock settings & initial value for Wr4
SIOClk:
	Db	IniWr4+0c0h	;50 baud
	Db	IniWr4+0c0h	;75 baud
	Db	IniWr4+080h	;110 baud
	Db	IniWr4+080h	;134.5 baud
	Db	IniWr4+080h	;150 baud
	Db	IniWr4+040h	;200 baud
	Db	IniWr4+040h	;300 baud
	Db	IniWr4+040h	;600 baud
	Db	IniWr4+040h	;1200 baud
	Db	IniWr4+040h	;1800 baud
	Db	IniWr4+040h	;2000 baud
	Db	IniWr4+040h	;2400 baud
	Db	IniWr4+040h	;4800 baud
	Db	IniWr4+040h	;9600 baud
	Db	IniWr4+040h	;19200 baud
 
; Parity setting in Wr4
Parity:	Db	000h		;No parity
	Db	001h		;Odd parity
	Db	003h		;Even parity
 
; Number of stop bits for Wr4
StopBits:
	Db	004h		;1 stop bit
	Db	008h		;1.5 stop bits
	Db	00ch		;2 stop bits
 
; Number of Rx data bits and Wr3 initial setting
Dat3Bt:	Db	IniWr3+000h	;5 data bits
	Db	IniWr3+080h	;6 data bits
	Db	IniWr3+040h	;7 data bits
	Db	IniWr3+0c0h	;8 data bits
 
; Number of Tx data bits and Wr5 initial setting
Dat5Bt:	Db	IniWr5+000h	;5 data bits
	Db	IniWr5+040h	;6 data bits
	Db	IniWr5+020h	;7 data bits
	Db	IniWr5+060h	;8 data bits
 
; Hardware register settings:  set at init, kept for futzing
Commands:			;Looped through at Init time
	Db	SelWr2		;Select Wr2
	Db	IniWr2		;Interrupt vector value
	Db	SelWr4		;Select Wr4
Wr4:	Db	0		;Stop bits, parity, etc.
	Db	SelWr5		;Select Wr5
Wr5:	Db	0		;Bits/char, Tx Enable, etc.
	Db	SelWr3		;Select Wr3
Wr3:	Db	0		;Bits/char etc.
	Db	SelWr1		;Select Wr1
	Db	IniWr1		;Interrupt enables, etc.
 
Clk:	Db	0		;Clock divisor
 
;Error location for internal call to HsSend
Error:	Ds	2
 
;Flag for buffer overrun
ORun:	Ds	1		;2 if buffer has been overrun
 
; Stopped/going state of send/receive hoses.  Must be ordered, adjacent.
InStop:	Db	0		;Non-zero if XOff has been sent to stop host
OutStop:
	Db	0		;Non-zero if output stop string received to
				; stop our sending
 
; Queue state and buffer area
QHead:	Dw	0		;Pointer to place to put next input char
QTail:	Dw	0		;Pointer to next char to return
QCount:	Dw	0		;Number of words in queue
Queue:	Ds	QLength*2	;Comm input queue
QLast	Equ	$-1		;Last char in queue
 
; Encoding in queue:
;	-2	BREAK
;	0..255	data byte
;	| 256	parity error on data byte (ORed in)
;	| 512	overrun error on data byte (ORed in)
 
	End
E 1
