{ File: [Iris]<WMicro>DLion>TTYTask.asm Modification History: Dennis Grundler: 1-Sep-84 17:17:29: Added copyright notice. Jim Frandeen: October 7, 1982 9:14 AM: Fix SendBreak. Implement AbortPut command. Refresh TTY device status after On and after SetParameters. Jim Frandeen: August 4, 1982 3:27 PM: new IO Page 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 } { Copyright (C) 1980, 1982 by Xerox Corporation. All rights reserved.} 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