{ File: [Idun]<WDLion>TTYTask.asm
Modification History:
Last Modified by Jim Frandeen: October 7, 1982 9:14 AM: Fix SendBreak. Implement AbortPut command. Refresh TTY device status after On and after SetParameters.
Last Modified by Jim Frandeen: August 4, 1982 3:27 PM: new IO Page
Last Modified by Jim Frandeen: 22-Jun-82 15:23:09: add Break command 6
Rewritten by Jim Frandeen: April 1, 1982 8:09 AM
Created by Ken Yamanaka: August 7, 1980 11:22 AM
}
Get "SysDefs" ; system defs
Get "CommonDefs" ; Common defs
IMP DoNakedNotify ; From CPSubs
IMP HLPlus2A ; From RS232CSubs
IMP PortBusyFlag ; From CPSubs
IMP ReadCPBuffer ; From CPsubs
IMP TTYCommand ; From Common
IMP TTYOutData ; From Common
IMP WriteCPBuffer ; From CPsubs
TTYInTask:
DB opJMP ;JMP TTYInTaskYield
TTYInTaskActiveSwitch:
DW TTYInTaskYield
; JMP BeginTTYInTask
TTYOutCSB:
{The TTY CSB is read in for some TTY commands.}
TTYParameter:
DS 1 ;14022 low
TTYParameterHi:
DS 1 ;14022 high byte
TTYTaskWakeMask:
DS 2 ;14023
TTYInCSB:
{The TTY In CSB is written to the IOPage when TTY input or status is ready to send to the CP.}
TTYInStatus:
DB 0 ;14024 low
TTYInDataReady:
{TTYInDataReady is set to 80H by the TTYInTask when a character is ready to send to the CP. The CP resets this byte when the character has been processed. The TTYIn Task will not send a new character to the CP until this byte is zero.}
DB 0 ;14024 high
TTYDeviceStatus:
DB 0 ;14025 low
TTYInData:
DB 0 ;14025 high
BKDet EQU 40H ;Break Detected
BreakCode EQU 0 ;Break Code
CRCode EQU 0DH ;Carrige Return Code
CTS EQU 20H ;Clear To Send Command (RTS)
DefaultBaud EQU 7 ;Default Baud Rate index
DefaultMode EQU 0CAH ;2 stop, parity none, 7 bits, 16X
DSR EQU 2 ;Data Set Ready Command (DTR)
DTR EQU 80H ;Data Terminal Ready Flag of UART Status (DSR)
EReset EQU 10H ;Error Reset Command
FE EQU 20H ;Framing Error
LFCode EQU 0AH ;Line Feed Code
OE EQU 10H ;Rx Over Run Error bit
OSCcmd EQU 36H ;Counter#0, LSB & MSB, Mode3, Binary
PE EQU 8H ;Parity Error bit
Reset0 EQU 80H ;First character of reset sequence
Reset1 EQU 0 ;Second character of reset sequence
Reset2 EQU 40H ;Third character of reset sequence
SendBK EQU 8H ;Send Break Command
SUBCode EQU 1AH ;Erase Screen Code
RxEnable EQU 4 ;Rx Enable Command
RxError EQU PE+OE+FE+BKDet ;Framing, Overrun, Parity Error and Break detected
RxRDY EQU 2 ;Rx Ready Status
TxEmpty EQU 4 ;Tx TTYData Empty Status
TxEnable EQU 1 ;Tx Enable Command
TxRDY EQU 1 ;Tx Ready Status
UARTOff EQU 0 ;Rx/Tx Disable, CTS off.
DefaultCommand EQU CTS+RxEnable+TxEnable ; Rx /TxEnable, CTS On.
{Internal Constants}
FlagMask EQU 80H ;FlagMask
DoneMask EQU 7FH ;Flag erase Mask
KindMask EQU 7H ;Kind of Parameter Separate Mask
ValueMask EQU 0FH ;Parameter Value Mask
CPCTSMask EQU 2 ;CP clearToSend change Value Mask
CPDSRMask EQU 1 ;CP dataSetReady change Value Mask
InitialCount EQU 0FFH ;Initial Count of Interval Counter
TimeToSend EQU InitialCount+1 ;Up to date count of Interval Counter
; [UART Mode Clear Mask]
StopBitClear EQU 3FH ;Stopbit Mode bit clear Mask
ParityClear EQU 0CFH ;Parity Mode bit clear Mask
CharLClear EQU 0F3H ;Character Length Mode bit clear Mask
; [ UART Mode Mask]
StopBitMask EQU 0C0H ;Stopbit Mode bit Separate Mask
ParityMask EQU 30H ;Parity Mode bit Separate Mask
CharLMask EQU 0CH ;Character Length Mode bit Separate Mask
BaudMask EQU 0FH ;Baud RateMode bit Separate Mask
; [Head Command]
PutCommand EQU 80H ;Character Put Command
SetParameter EQU 81H ;SetParameter Command
On EQU 83H ;On Command
Off EQU 84H ;Off Command
AbortPut EQU 85H ;Off Command
TTYBreakOn EQU 86H ;Break On command
TTYBreakOff EQU 87H ;Break Off command
; [Head Status]
NotReady EQU 1 ;UART Not Ready Status
ParityError EQU 8H ;Parity ErrorStatus
DataLost EQU 10H ;Rx Overrun Error Status
FrameErr EQU 20H ;Framing Error Status
BreakDet EQU 40H ;UART Break Detected Status
Success EQU 80H ;R/W Succeeded Status
FullFlag EQU 80H ;Character Full Flag on Get Command
; [Parameter Change Mask]
DTRChangeMask EQU 1 ;Change DTR Mask
RTSChangeMask EQU 2 ;Change RTS Mask
CharacterChangeMask EQU 4 ;Change Character Length Mask
ParityChangeMask EQU 8H ;Change Parity Mask
StopBitChangeMask EQU 10H ;Change Stop Bits Mask
BaudChangeMask EQU 20H ;Change BaudRate Mask
; [SetParameter constants]
SetOnlyCommand equ 1 ;Set only the Command
SetModeCommand equ 3 ;Set both Mode and Command
; [Internal Storage Area]
CurrentMode:
DB 0 ;For UART Current Mode
CurrentCommand:
DB 0 ;For UART Current Command
ResetCommand:
DB Success ;Success status in low byte
DB 0 ;Reset full flag in high byte
; PCB to read TTY Out CSB
ReadTTYOutCSB:
DW TTYOutCSBLoc ;CP Buffer Pointer(Low)
DW CPIOPageHi ;CP Buffer Pointer(Hi)
DW TTYOutCSBSize ;CP Buffer Count (Bytes)
DW TTYOutCSB ;Pointer to IOP Buffer
; PCB to Reset TTY Out Command and return Status in low byte
ResetTTYCommand:
DW TTYCommandLoc ;CP Buffer Pointer(Low)
DW CPIOPageHi ;CP Buffer Pointer(Hi)
DW 2 ;CP Buffer Count (Bytes)
DW ResetCommand ;Pointer to IOP Buffer
ReadTTYInCSB:
DW TTYInCSBLoc ;CP Buffer Pointer(Low)
DW CPIOPageHi ;CP Buffer Pointer(Hi)
DW TTYInCSBSize ;CP Buffer Count (Bytes)
DW TTYInCSB ;Pointer to IOP Buffer
SendTTYDeviceStatus:
DW TTYDeviceStatusLoc ;CP Buffer Pointer(Low)
DW CPIOPageHi ;CP Buffer Pointer(Hi)
DW 2 ;CP Buffer Count (Bytes)
DW TTYDeviceStatus ;Pointer to IOP Buffer
;
BeginTTYInTask:
LDA PortBusyFlag
ORA A
JNZ TTYInTaskYield ;Jump if port is busy
IN IntReq ;Watch Condition of USART
ANI PtrRxReqMask
JNZ CheckTTYStatus ;IF Not RxRDY check status
LXI H,ReadTTYInCSB ;Read TTY In CSB
CALL ReadCPBuffer
LDA TTYInDataReady ;Check CP Ready
ORA A ;See if CP has processed last char
JM TTYInTaskYield ;If Not Ready, Yield
MVI A,80H
STA TTYInDataReady ;Set flag: DataReady
STA TTYInStatus ;Assume Success
IN PrinterData ;Read character
STA TTYInData
IN PrinterStatus ;Check Error
ANI RxError
JZ SendTTYInData
STA TTYInStatus ;Error bit set
LDA CurrentCommand ; Issue Error Reset Command
ORI EReset ; Error Reset bit Set
OUT PrinterCommand
SendTTYInData:
LXI H,ReadTTYInCSB
CALL WriteCPBuffer
LHLD TTYTaskWakeMask
CALL DoNakedNotify
JMP TTYInTaskYield
;
RefreshTTYDeviceStatus:
{Device Status Refresh Routine
This routine refreshes the contents of Device Status in Main memory intermittently. This task is not executed when a character is received, and it is not executed when the Tx buffer is not empty because CTS cannot be checked. The counter resets itself to zero when it gets up to FF. When we come here, we know the port is free.}
IN PrinterStatus ;IF Yes, Read UART Status
STA TTYDeviceStatus ;and check TxBuffer Empty
ANI TxEMPTY ;IF Not Empty, Cannnot check CTS
RZ ;Because TxRDY Pin =TxEmpty (CTS=0)(TxEn=1)
IN IntReq ;Watch Condition of USART
ANI PtrTxReqMask ;IF TxNot Ready, then CTS might be Off.
JZ SendTTYStatus ;IF Tx Ready, then CTS might be On.
CTSOff:
LDA TTYDeviceStatus ;Reset clearToSend bit
SUI TxEMPTY
STA TTYDeviceStatus
SendTTYStatus:
LXI H,SendTTYDeviceStatus
JMP WriteCPBuffer ;and RET
CheckTTYStatus:
DB opMVIA ;A ← IntervalCounter
IntervalCounter:
DB 0
INR A
STA IntervalCounter
CZ RefreshTTYDeviceStatus ;IF No, Check Count value
TTYInTaskYield:
;
TTYOutTask:
LDA PortBusyFlag
ORA A
JNZ TTYOutTaskYield
{For the rest of TTYOutTask, we know we can use the CP Port.}
DB opJMP ; JMP BeginTTYOutTask
TTYOutTaskResumeAddress:
DW BeginTTYOutTask
; JMP WaitForPrinter
BeginTTYOutTask:
LDA TTYCommand ; Check if bit 0 #0
ORA A ; Set Flags
JP TTYOutTaskYield ; z => Don't Activate the TTY task.
CPI PutCommand
JZ TTYPutTask
LXI H,ReadTTYOutCSB
CALL ReadCPBuffer ;Read the CSB
LDA TTYCommand ;Check the requested command
CPI SetParameter
JZ TTYSetParameter
CPI Off
JZ TTYOff
CPI TTYBreakOn
JZ TurnOnBreak
CPI TTYBreakOff
JZ TurnOffBreak
TTYOn:
MVI A,InitialCount ;Send Status on first entry to TTYInTask
STA IntervalCounter
MVI A,DefaultBaud ; Set Default Frequency into OSC
CALL SetBaud
MVI A,DefaultMode ; Set Default Mode & Command...
STA CurrentMode ; ... into UART
MVI A,DefaultCommand
STA CurrentCommand
CALL RefreshTTYDeviceStatus
LXI H,BeginTTYInTask
SHLD TTYInTaskActiveSwitch
JMP ResetTTYOutFlag
TurnOnBreak:
LDA CurrentCommand
ORI SendBK
OUT PrinterCommand
JMP ResetTTYOutFlag
TurnOffBreak:
LDA CurrentCommand
OUT PrinterCommand
JMP ResetTTYOutFlag
TTYSetParameter:
LDA TTYOutData
ANI BaudChangeMask
CNZ ChangeBaudRate ; No UART Mode or Command
LDA TTYOutData
ANI StopBitChangeMask
CNZ ChangeStopBit ; UART Mode, Command
LDA TTYOutData
ANI ParityChangeMask
CNZ ChangeParity ;UART Mode, Command
LDA TTYOutData
ANI CharacterChangeMask
CNZ ChangeCharLength ;UART Mode, Command
LDA TTYOutData
ANI RTSChangeMask
CNZ ChangeRTS ;UART Command
LDA TTYOutData
ANI DTRChangeMask
CNZ ChangeDTR ;UART Command
{ This sequence will guarantee correct initialization after both a hardware (expecting Mode), or a software (expecting Command) reset. After the subroutne is executed, a command must be sent to the UART.}
LXI H,8000H+PrinterCommand
MVI M,Reset0 ; Reset UART
MVI M,Reset1
MVI M,Reset2
NOP ; Needed for B-step chips
LDA CurrentMode ; Set UART Mode
MOV M,A
LDA CurrentCommand ; Set UART Command
MOV M,A ;Send command
CALL RefreshTTYDeviceStatus
JMP ResetTTYOutFlag
; RTS bit:
ChangeRTS:
LDA TTYParameter ;Check required RTS Condition
ANI CPCTSMask
MOV D,A
LDA CurrentCommand ;Check Current RTS Condition
ANI CTS
ADD D
RZ ;z => no change
CPI CPCTSMask+CTS ; IF both 1, make no change as well
RZ ; z => no change
CPI CPCTSMask ; IF required=1, current=0
JZ SetRTS ; ..then must be set
ResetRTS:
LDA CurrentCommand ; IF required =0, current=1...
SUI CTS ; ..then must be reset.
FinishRTS:
STA CurrentCommand
RET
SetRTS:
LDA CurrentCommand ; Set routine
ADI CTS
JMP FinishRTS
ChangeDTR:
LDA TTYParameter ;Check required DTR Condition
ANI CPDSRMask
MOV D,A
LDA CurrentCommand ;Check Current DTR Condition
ANI DSR
ADD D
RZ ;z => no change
CPI CPDSRMask+DSR ;IF both 1, make no change as well
RZ ;z => no change
CPI CPDSRMask ;IF required=1, current=0
JZ SetDTR ;..then must be set
ResetDTR:
LDA CurrentCommand ;IF required =0, current=1...
SUI DSR ;..then must be reset.
JMP FinishRTS
SetDTR:
LDA CurrentCommand ;Set routine
ADI DSR
JMP FinishRTS
; Stop bits: (change both Mode and Command)
ChangeStopBit:
LDA CurrentMode ;Stop bits mode change
ANI StopBitClear ;Clear old contents of Stopbit
MOV D,A
LDA TTYParameter ;Set new Stopbits Mode
ANI StopBitMask
FinishStopBit:
ORA D
STA CurrentMode ;Rewrite Current Mode
RET
; Parity bit: (change both Mode and Command)
ChangeParity:
LDA CurrentMode ; Parity mode Change
ANI ParityClear ; Clear old contents of Parity
MOV D,A
LDA TTYParameter
ANI ParityMask ; Set new Stopbits Mode
JMP FinishStopBit
; Character length: (change both Mode and Command)
ChangeCharLength:
LDA CurrentMode ; Character Length mode change
ANI CharLClear ; Clear old contents of Character Length
MOV D,A
LDA TTYParameter
ANI CharLMask ; Set new Character Length Mode
JMP FinishStopBit
ChangeBaudRate:
LDA TTYParameterHi ; OSC frequency change
ANI BaudMask
{Fall through to SetBaud.}
SetBaud:
{ This Routine sets suitable Frequency Divisor and Oscillation Modefor i8253 Programmable Interval Timer. On entry, A = Baud rate.}
LXI H,Divisor
CALL HLPlus2A ;HL ← HL + 2*CurrentBaud
MVI A,OSCcmd
OUT TimerMode
MOV A,M ; A ← ((H,L))
OUT TimerCount0
INX H ; H,L ← (H,L)+1
MOV A,M ; A ← MSB,
OUT TimerCount0
RET
Divisor:
{ Asynchronous Mode ( SIO 16Xmode) Divisors Table
Unfortunately, this is not quite like the table in RS232CSubs}
DW 2304 ; Divisor for 50Hz
DW 1536 ; Divisor for 75Hz
DW 1047 ; Divisor for 110Hz
DW 856 ; Divisor for 134.5Hz
DW 768 ; Divisor for 150Hz
DW 384 ; Divisor for 300Hz
DW 192 ; Divisor for 600Hz
DW 96 ; Divisor for 1200Hz
DW 64 ; Divisor for 1800Hz
DW 58 ; Divisor for 2000Hz
DW 48 ; Divisor for 2400Hz
DW 32 ; Divisor for 3600Hz
DW 24 ; Divisor for 4800Hz
DW 16 ; Divisor for 7200Hz
DW 12 ; Divisor for 9600Hz
DW 6 ; Divisor for 19200Hz
TTYOff:
LXI H,TTYInTaskYield
SHLD TTYInTaskActiveSwitch
MVI A,UARTOff ;TTYOff Command
OUT PrinterCommand
JMP ResetTTYOutFlag
PrinterNotReady:
LXI H,WaitForPrinter
SHLD TTYOutTaskResumeAddress
JMP TTYOutTaskYield
WaitForPrinter:
IN IntReq ; Watch Condition of USART
ANI PtrTxReqMask
JZ SendCharacter
LDA TTYCommand
CPI AbortPut
JNZ TTYOutTaskYield
JMP InitializeOutTaskResumeAddress
TTYPutTask:
{ PutCommand : Send one character to the Printer.}
IN IntReq ; Watch Condition of USART
ANI PtrTxReqMask
JNZ PrinterNotReady
SendCharacter:
LDA TTYOutData ; Character Data Load
OUT PrinterData ; Data Send to TTY
InitializeOutTaskResumeAddress:
LXI H,BeginTTYOutTask
SHLD TTYOutTaskResumeAddress
ResetTTYOutFlag:
LXI H,ResetTTYCommand
CALL WriteCPBuffer
LHLD TTYTaskWakeMask
CALL DoNakedNotify
TTYOutTaskYield:
{Pass control to the next task specified in Domino.cfg}
DS 0
END