{ File: [Iris]<WMicro>DLion>BisyncInterrupts.asm
Modification History:
Dennis Grundler: 1-Sep-84 16:51:46: Add copyright notice.
Dennis Grundler: 9-Oct-83 17:33:41: Siemens 9750 support.
Dennis Grundler: 29-Jun-83 14:15:54: ITB fixes.
Tom Chang : 17-May-83 14:34:54Make sure use just 3 SIO interrupt bits
Chuck Fay : 11-Nov-82 9:39:35: Move POPs before EIs to avoid possible stack
overflow.
Jim Frandeen : May 20, 1982 6:53 PM
Jim Frandeen : May 6, 1982 9:49 AM: Created file.
}
{ Copyright (C) 1982, 1983 by Xerox Corporation. All rights reserved.}
Get "SysDefs"
Get "RS232CDefs"
IMP CurrentSyncCharacter ;From RS232CMisc
IMP IllegalBisyncCharacterFlag ;From RS232CPut
IMP PutCompletedFlag ;From RS232CPut
IMP RestartSIOCharacter ;From RS232CPut
IMP SetBisyncCompletion ;From BisyncInput
IMP StatusChangeFlag ;From RS232CGet
IMP TerminateBisyncFrame ;From BisyncInput
IMP TxBufferPointer ;From RS232CInterrupts
IMP TxUnderrunDetectedFlag ;From RS232CInterrupts
IMP TxWR5 ;From RS232CMisc
EXP BisyncRS232CInterrupt
EXP BEL1
EXP DisableTxCRC1
EXP EnableTxCRC1
EXP ENQ1
EXP ENQ2
EXP ENQ4
EXP ENQ12
EXP EOT1
EXP ETB2
EXP ETB4
EXP ETB5
EXP ETB6
EXP ETB12
EXP NAK1
EXP PrevBisyncDCD
EXP SYN1
EXP SYN2
EXP SYN3
EXP SYN4
EXP SYN5
EXP SYN6
EXP SYN12
EXP OneSecondTimerLow
EXP OneSecondTimerHigh
EXP RxBisyncExternalInt
EXP RxBisyncSpecialInt
EXP SyncCharacterCount
EXP TxBisyncInitial
EXP TxBisyncStateSwitch
EXP TxInitBiSyncInterrupts
;
{NOTE: These routines are written for speed. Much code has been duplicated. If necessary, space could be saved by making the exit code common.
The following characters are used in Bisync mode. Characters marked with an asterisk are the same in Ascii and Ebcdic. Other characters are different depending on the character set. Characters that differ are initialized by Misc.
AltoETX* Alto ETX so that Dandelions can talk to Altos.
BEL is a special 860 character used to change to voice mode. It has meaning when it appears at the beginning of a frame. In the middle of a frame, it is treated as data.
DLE* Data Link Escape is used for two character sequences.
ENQ Enquiry is used to bid for the line when using point to point connections. It indicates the end of a selection sequence. It is also used to request retransmission of the ACK/NAK response.
EOT End of Transmission indicates the end of a message which may contain a number of blocks.
ETB End of Transmission Block indicates the end of a block of characters that started with SOH or STX and indicates that the block check is coming next.
ETX* End of Text terminates a block which started with SOH or STX. It is the same as ETB except that it also means that there are no more data blocks to be sent.
ITB* End of Intermediate Transmission Block is used to separate the message into sections for error detection purposes. ITB indicates that the block check is coming next.
NAK Negative Acknowledgement indicates that the previous block was received in error.
SOH* Start of Heading
STX* Start of Text
SYN Sync character
}
;
BisyncRS232CInterrupt:
{ Come here in Bisync mode from Common when we get a RST 6.5 Interrupt from the Zilog SIO chip. Save state }
PUSH PSW
PUSH H
{Read the interruptVector to determine the cause of the interrupt. Multiply the vector by 2. This gives us a number which we can OR into the low bits of the jump table address. The jump table is in the Common so that we can assure its exact address and guarantee that the low 5 bits of the address are zero. }
MVI A,PointToWR2
OUT TxCont
IN TxCont ; Read Interrupt Vector
{Test for TxDataInt first. We want to call this routine so that we can also call it from the input end of frame routine if necessary.}
{ remove ORA A, replaced by the following}
ANI 0EH ;use just 3 bits from SIO 5/17/83
DB opJZ
TxBisyncStateSwitch:
DW TxBisyncInitial
DispatchOnBisyncInterruptVector:
RLC ;Interupt Vector * 2
ORI 40H ;Low address is 40H
MOV L,A
MVI H,20H ;High address is 20H
PCHL ;Jump to JumpTable
{BisyncJumpTable: @2040H
JMP TxIllegalInt ;When Vecter =0 Tx Buffer Empty
DB 0
JMP TxBisyncExternalInt ;When Vecter =2 Ex Stat
DB 0
JMP TxIllegalInt ;When Vecter =4 Tx Char
DB 0
JMP ExitInterrupt ;When Vecter =6 Sp Tx Cond
DB 0
JMP RxIllegalInt ;When Vecter =8 Tx Buffer Empty
DB 0
JMP RxBisyncExternalInt ;When Vecter =A Ex Stat
DB 0
DB opJMP ;When Vecter =C Rx Char
RxBisyncStateSwitch:
DW RxBisyncInitial
DB 0
JMP RxBisyncSpecialInt ;When Vecter =E Sp Rx Cond
DB 0
}
;
{TxSubroutines used to simplify transmission so that most of the code used for Bisync can also be used for 9750}
TxDisableCRC:
{This routine disables, turns off, the CRC generator}
NOP ;In 9750 mode we replace this NOP with a RET
LXI H,8000H+TxCont
MVI M,PointToWR5+ResetExternalStatusInterrupts
DB opMVIM
DisableTxCRC1:
DB 0
RET
TxEnableCRC:
{This routine enables, turns on, the CRC generator}
NOP ;In 9750 mode we replace this NOP with a RET
LXI H,8000H+TxCont
MVI M,PointToWR5+ResetExternalStatusInterrupts
DB opMVIM
EnableTxCRC1:
DB 0
RET
SendChWithCRCorBCC:
{Transmit this character and accumulate the BCC}
OUT TxData
OptRet:
RET ;This RET is replaced by a NOP for 9750 mode.
PUSH PSW
PUSH H ;Save contents of HL
LXI H,TxBCC ;Point to the BCC
XRA M ;Accumulate the BCC
ANI 7FH ;Mask off the parity bit.
MOV M,A ;Restore the BCC
POP H ;Restore the contents of HL
POP PSW
RET ;Continue with next instruction
TxBCC:
DB 0
TxInitBiSyncInterrupts:
PUSH PSW
PUSH H
CPI Siemens9750Correspondent
JNZ BiSyncSetup
SiemensSetup:
MVI A,opRET
STA TxDisableCRC
STA TxEnableCRC
XRA A ;MVI A,opNOP
LXI H,TxInterBlockBCCNext
SHLD TxITBCRCSwitch
LXI H,TxEndingBCCNext
JMP SetupExit
BiSyncSetup:
XRA A ;MVI A,opNOP
STA TxDisableCRC
STA TxEnableCRC
MVI A,opRET
LXI H,TxInterBlockCRCNext
SHLD TxITBCRCSwitch
LXI H,TxEndingCRCNext
SetupExit:
SHLD EndBCCorCRCSwitch
STA OptRet
POP H
POP PSW
RET
;
TxBisyncInitial:
{Come here to initialize the transmitter. We sent one ModemSYN character (alternate ones and zeros) to prime the transmitter. We send two more ModemSYN characters in this state.}
LXI H,TxBCC ;Set accumulated BCC to 0
MVI M,0
MVI A,ModemSYN
OUT TxData
{Turn on the one second timer (i8253 Programmable Interval Timer Counter # 2).}
MVI A,TimeCMD
OUT OSCCont
DB opMVIA ;A ← OneSecondTimerLow
OneSecondTimerLow:
DB 0
OUT TimeReg
DB opMVIA ;A ← OneSecondTimerHigh
OneSecondTimerHigh:
DB 0
OUT TimeReg
LXI H,TxInitial1
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
TxInitial1:
{We sent one ModemSYN character to prime the transmitter and one more ModemSYN character. Send one more ModemSYN character.}
MVI A,ModemSYN
OUT TxData
{Initialize WR6 and WR7 with the current sync character. These characters will be sent by the chip automatically whenever we get transmit underrun.}
LXI H,8000H+TxCont
MVI M,PointToWR6
LDA CurrentSyncCharacter
MOV M,A
MVI M,PointToWR7+ResetTxCRCGenerator
MOV M,A
LXI H,SendSyncCharacters
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
SendSyncCharacters:
{We send the number of Sync Characters specified by the client.}
LDA CurrentSyncCharacter
OUT TxData
DB opMVIA ;A ← SyncCharacterCount
SyncCharacterCount:
DB 0
DCR A ;Decrement SyncCharacterCount
JZ SyncCharactersSent
STA SyncCharacterCount
POP H
POP PSW
EI ;Enable Interrupts
RET
SyncCharactersSent:
LXI H,StartTx
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
StartTx:
{This is the first Transmit state. We have sent the initial characters, and we are looking for SOH or STX. Send the next character from the client's buffer. The CRC generator is not turned on, and the next character sent will not be included in the CRC.}
LHLD TxBufferPointer
MOV A,M
OUT TxData ;Send the next character
INX H
SHLD TxBufferPointer
CPI ETX
JZ TxEndingBCCorCRCNext
CPI STX
JZ FirstTxCharIsSTX
CPI SOH
JZ FirstTxCharIsSOH
CPI DLE
JZ FirstTxCharIsDLE
DB opCPI
EOT1: DB 0
JZ TxEndOfFrameNext
DB opCPI
BEL1: DB 0
JZ TxEndOfFrameNext
DB opCPI
NAK1: DB 0
JZ TxEndOfFrameNext
DB opCPI
ENQ1: DB 0
JZ TxEndOfFrameNext
{Continue if the character is not any of the above. We stay in this state.}
POP H
POP PSW
EI ;Enable Interrupts
RET
;
TxHeaderSyn:
{Come here if we got a SYN character in the header. The SYN character does not get included in the checksum, so we must turn off the CRC generator.}
CALL TxDisableCRC
OUT TxData ;Send the next character
{The next time we get a TxData interrupt, we want to turn the CRC generator back on.}
FirstTxCharIsSOH:
LXI H,StartTxHeader
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
StartTxHeader:
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
DB opCPI
SYN5: DB 0
JZ StartHeaderSyn
{We are about to send the first Header character following SOH. Turn on the CRC generator. If the CRC generator is turned on before the character is shifted into the serial shift register, the character will be included in the CRC.}
CALL TxEnableCRC
CALL SendChWithCRCorBCC ;Send the next character
CPI STX
JZ ContinueTxNonTransparentMode
CPI DLE
JZ LookForSTXAfterTxDLE
CPI ETX
JZ TxEndingBCCorCRCNext
DB opCPI
ETB5: DB 0
JZ TxEndingBCCorCRCNext
{Continue if the character is not any of the above. Pass to TxHeader state.}
LXI H,TxHeader
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
StartHeaderSyn:
{Come here if we got a SYN character in the header. The SYN character does not get included in the checksum.}
StartNonTransparentModeSYN:
{Come here if we got a SYN character in non transparent mode. The SYN character does not get included in the checksum.}
TxInterBlockSYN:
{Come here if we got a SYN character following the ITB character. The SYN character does not get included in the checksum.}
OUT TxData ;Send the next character
POP H
POP PSW
EI ;Enable Interrupts
RET
TxHeader:
{We are sending header characters. The CRC generator is on. The next character will be included in the CRC unless we turn off the CRC checker.}
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
DB opCPI
SYN6: DB 0
JZ TxHeaderSyn
CALL SendChWithCRCorBCC ;Send the next character
CPI STX
JZ ContinueTxNonTransparentMode
CPI DLE
JZ LookForSTXAfterTxDLE
CPI ETX
JZ TxEndingBCCorCRCNext
DB opCPI
ETB6: DB 0
JZ TxEndingBCCorCRCNext
{Continue if the character is not any of the above. Stay in this state.}
POP H
POP PSW
EI ;Enable Interrupts
RET
;
TxNonTransparentModeSYN:
{Come here if we got a SYN character in non transparent mode. The SYN character does not get included in the checksum, so we must turn off the CRC generator.}
CALL TxDisableCRC
OUT TxData ;Send the next character
{The next time we get a TxData interrupt, we want to turn the CRC generator back on.}
FirstTxCharIsSTX:
LXI H,StartTxNonTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
StartTxNonTransparentMode:
{We are about to send the first character in NonTransparent Mode, or we are continuing after a one second timeout or a SYN character. The CRC generator is off.}
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
DB opCPI
SYN2: DB 0
JZ StartNonTransparentModeSYN
{Turn on the CRC generator. If the CRC generator is turned on before the character is shifted into the serial shift register, the character will be included in the CRC.}
CALL TxEnableCRC
CALL SendChWithCRCorBCC ;Send the next character
CPI ETX
JZ TxEndingBCCorCRCNext
DB opCPI
ETB2: DB 0
JZ TxEndingBCCorCRCNext
CPI ITB
JZ TxInterBlockBCCorCRCNext
DB opCPI
ENQ2: DB 0
JZ TxEndOfFrameNext
{Continue if the character is not any of the above. We pass to NonTransparent Mode.}
ContinueTxNonTransparentMode:
LXI H,TxNonTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
TxNonTransparentMode:
{We are sending characters in NonTransparent mode. The CRC generator is on.}
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
DB opCPI
SYN12: DB 0
JZ TxNonTransparentModeSYN
CALL SendChWithCRCorBCC ;Send the next character
CPI ETX
JZ TxEndingBCCorCRCNext
DB opCPI
ETB12: DB 0
JZ TxEndingBCCorCRCNext
CPI ITB
JZ TxInterBlockBCCorCRCNext
DB opCPI
ENQ12: DB 0
JZ TxEndOfFrameNext
{Continue if the character is not any of the above. We stay in NonTransparent Mode. Check the timer to see if one second has elapsed since we started sending.}
IN RS366Reg
ANI TimeUp
JNZ ExitTxDataInt ;Enable Interrupts
{The one second timer has expired. We must send two sync characters.}
LXI H,NonTransparentModeTimeout1
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
NonTransparentModeTimeout1:
{Come here to send the first sync character after a one second timeout. The sync character does not get included in the checksum, so we must turn off the CRC generator.}
CALL TxDisableCRC
LDA CurrentSyncCharacter
OUT TxData
LXI H,NonTransparentModeTimeout2
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
NonTransparentModeTimeout2:
{Come here to send the second sync character after a one second timeout. Turn the timer back on.}
LDA CurrentSyncCharacter
OUT TxData
MVI A,TimeCMD
OUT OSCCont
LDA OneSecondTimerLow
OUT TimeReg
LDA OneSecondTimerHigh
OUT TimeReg
LXI H,StartTxNonTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
TxInterBlockBCCorCRCNext:
DB opJMP
TxITBCRCSwitch:
DW TxInterBlockCRCNext
; DW TxInterBlockCRCNext
; DW TxInterBlockBCCNext
TxInterBlockBCCNext:
LXI H,TxInterBlockBCC
JMP TxITBSet
TxInterBlockCRCNext:
{Come here when we have just sent an ITB character. The next time we get an interrupt for Transmit Buffer Empty, we will simply clear the interrupt. This will cause the CRC to be sent if we reset the Transmit Underrun/EOM bit.}
MVI A,ResetTxEOM
OUT TxCont
LXI H,TxInterBlockCRC
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
TxInterBlockBCC:
LDA TxBCC
CALL SendChWithCRCorBCC
TxInterBlockCRC:
{Send the InterBlock CRC. Set SendSyncFlag for the Put routine. We will never get another wakeup unless the Put routine primes the chip again by sending a sync character. Disable the CRC generator so that the Sync character will not be included in the CRC.}
LXI H,8000H+TxCont
MVI M,PointToWR5+ResetTxIntPending
CALL TxDisableCRC
LDA CurrentSyncCharacter
STA RestartSIOCharacter
LXI H,ContinueAfterTxInterBlockCRC
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
ContinueAfterTxInterBlockCRC:
{Continue here when the CRC has been sent following the ITB character. Start sending data again. The CRC generator is off.}
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
DB opCPI
SYN3: DB 0
JZ TxInterBlockSYN
CALL TxEnableCRC
CALL SendChWithCRCorBCC ;Send the next character
CPI DLE
JZ LookForSTXAfterTxDLE
{In transparent mode we expect DLE after the BCC (CRC) or SYN SYN. Mod. to meet IBM spec.s 6/29/83}
LDA TransparentDataFlag
ORA A
JNZ IllegalTxSequence
{Continue if the character is not any of the above. We go back to Non Transparent state.}
LXI H,TxNonTransparentMode
TxITBSet:
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
FirstTxCharIsDLE:
{Come here if the first Tx character is DLE. Look for STX to enter transparent mode. Any other character will be EndOfFrame. The CRC generator is off. The STX is NOT included in the checksum.}
LXI H,LookForSTXAfterFirstTxDLE
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
LookForSTXAfterFirstTxDLE:
LHLD TxBufferPointer
MOV A,M
OUT TxData ;Send the next character
INX H
SHLD TxBufferPointer
CPI STX
JNZ TxEndOfFrameNext
LXI H,StartTxTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
LookForSTXAfterTxDLE:
{Come here after the sequence ITB DLE or SOH DLE. The only valid character that can follow is STX to start Transparent Mode. The CRC generator is on. The STX in included in the CRC.}
LHLD TxBufferPointer
MOV A,M
CALL SendChWithCRCorBCC ;Send the next character
INX H
SHLD TxBufferPointer
CPI STX
JNZ IllegalTxSequence
{In Transparent Mode, we must change WR6 to DLE so that the SIO will send DLE SYN when it gets TxUnderrun.}
LXI H,8000H+TxCont
MVI M,PointToWR6
MVI M,DLE
ContinueTransparentMode:
LXI H,TxTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
{ITB fix of 6/29/83}
TransparentDataFlag:
DB 0
StartTxTransparentMode:
{We are about to send the first character in Transparent Mode or continue after a one second timeout. Turn on the CRC generator. If the CRC generator is turned on before the character is shifted into the serial shift register, the character will be included in the CRC.}
MVI A,1 ;Store non-zero value to indicate we are in transparent mode.
STA TransparentDataFlag ;mod of 6/29/83
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
CPI DLE
JZ StartTransparentModeDLE
CALL TxEnableCRC
CALL SendChWithCRCorBCC ;Send the next character
{In Transparent Mode, we must change WR6 to DLE so that the SIO will send DLE SYN when it gets TxUnderrun.}
LXI H,8000H+TxCont
MVI M,PointToWR6
MVI M,DLE
LXI H,TxTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
TxTransparentMode:
{We are sending characters in Transparent mode. The CRC generator is on. The only interesting character to look for is DLE.}
LHLD TxBufferPointer
MOV A,M
INX H
SHLD TxBufferPointer
CPI DLE
JZ TxTransparentModeDLE
CALL SendChWithCRCorBCC ;Send the next character
{Check the timer to see if one second has elapsed since we started sending.}
IN RS366Reg
ANI TimeUp
JNZ ExitTxDataInt ;Enable Interrupts
{The one second timer has expired. We must send DLE and a sync character.}
LXI H,TransparentModeTimeout1
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
TransparentModeTimeout1:
{Come here to send the DLE after a one second timeout. The DLE character does not get included in the checksum, so we must turn off the CRC generator.}
CALL TxDisableCRC
MVI A,DLE
OUT TxData
LXI H,TransparentModeTimeout2
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
TransparentModeTimeout2:
{Come here to send the sync character after a one second timeout. Turn the timer back on.}
LDA CurrentSyncCharacter
OUT TxData
{Turn the timer back on.}
MVI A,TimeCMD
OUT OSCCont
LDA OneSecondTimerLow
OUT TimeReg
LDA OneSecondTimerHigh
OUT TimeReg
LXI H,StartTxTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
TxTransparentModeDLE:
{Come here if we got a DLE character in Transparent Mode. The DLE character does not get included in the checksum, so we must turn off the CRC generator. We want to turn the CRC generator back on when we get the next interrupt.}
CALL TxDisableCRC
StartTransparentModeDLE:
OUT TxData ;Send the next character
LXI H,LookForTxDataAfterDLE
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
LookForTxDataAfterDLE:
{Turn on the CRC generator and send the character following DLE in Transparent Mode.}
CALL TxEnableCRC
LHLD TxBufferPointer
MOV A,M
CALL SendChWithCRCorBCC ;Send the next character
INX H
SHLD TxBufferPointer
MOV H,A ;Save character sent in H
CPI DLE
JZ ContinueTransparentMode
{Assume we may exit Transparent Mode. Restore WR6 to the sync character. WR6 and WR7 get sent automatically by the SIO when it gets TxUnderrun.}
LXI H,8000H+TxCont
MVI M,PointToWR6
DB opMVIM ;M ← SYN
SYN1: DB 0
DB opCPI
ENQ4: DB 0
JZ TxEndOfFrameNext
DB opCPI
ETB4: DB 0
JZ TxEndingBCCorCRCNext
CPI ETX
JZ TxEndingBCCorCRCNext
CPI AltoETX
JZ TxEndingBCCorCRCNext
CPI ITB ;We should not leave Transparent Mode.
JZ TxInterBlockBCCorCRCNext
DB opCPI
SYN4: DB 0
JNZ IllegalTxSequence
{Come here if we got a SYN character in transparent mode. The SYN character does not get included in the checksum, so we must turn off the CRC generator. HL still points to TxCont.}
CALL TxDisableCRC
{The next time we get a TxData interrupt, we want to turn the CRC generator back on.}
LXI H,StartTxTransparentMode
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
;
IllegalTxSequence:
MVI A,1
STA IllegalBisyncCharacterFlag
{Fall through to TxEndOfFrameNext. 6/29/83}
TxEndOfFrameNext:
{Come here to end a frame with no CRC.}
XRA A ;clear transparent mode.
STA TransparentDataFlag ;mod of 6/29/83
LXI H,EndOfFrameNoCRC
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
EndingBCC:
LDA TxBCC
CALL SendChWithCRCorBCC
EndOfFrameNoCRC:
{Turn on the TxUnderrunDetectedFlag. Since we are not sending a CRC, we will not get underrun.}
MVI A,1
JMP TxEndOfFrame
TxEndingBCCorCRCNext:
XRA A ;clear transparent mode.
STA TransparentDataFlag ;mod of 6/29/83
DB opJMP
EndBCCorCRCSwitch:
DW TxEndingCRCNext
; DW TxEndingCRCNext
; DW TxEndingBCCNext
TxEndingBCCNext:
LXI H,EndingBCC
JMP EndCheckSumSet
TxEndingCRCNext:
{Come here when we have sent the last character of the frame. The next time we get an interrupt for Transmit Buffer Empty, we will simply clear the interrupt. This will cause the CRC to be sent if we reset the Transmit Underrun/EOM bit.}
MVI A,ResetTxEOM
OUT TxCont
LXI H,EndingCRC
EndCheckSumSet:
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
EndingCRC:
{Reset TxUnderrunDetected. When the CRC has been sent, TxUnderrunDetectedFlag will be set again. This lets the Put routine know that the CRC has been sent and it is OK to begin sending the Filler characters.}
XRA A
TxEndOfFrame:
{Reset TxIntPending. This will cause the CRC to be sent if TxEOM is reset. The chip will then send whatever is loaded into WR6 and WR7. We will load WR6 and WR7 with filler characters. We must send at least 3 filler characters. We will set RestartSIOCharacter so that the Put routine will send a filler character to get us started again. Otherwise we will never get another wakeup. We also reset TxUnderrunDetected. When the CRC has been sent, TxUnderrunDetectedFlag will be set again. This lets the Put routine know that the CRC has been sent and it is OK to begin sending the Filler characters.}
STA TxUnderrunDetectedFlag
LXI H,8000H+TxCont
MVI A,Filler
STA RestartSIOCharacter
MVI M,PointToWR6
MOV M,A
MVI M,PointToWR7+ResetTxIntPending
MOV M,A
LXI H,SendFiller2
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
SendFiller2:
{Come here when the Put routine has restarted the chip by sending a filler character. Send the second filler character.}
MVI A,Filler
OUT TxData
LXI H,SendFiller3
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
SendFiller3:
{Send the last filler character.}
MVI A,Filler
OUT TxData
PutCompletedNext:
LXI H,PutCompleted
SHLD TxBisyncStateSwitch
POP H
POP PSW
EI ;Enable Interrupts
RET
PutCompleted:
MVI A,ResetTxIntPending
OUT TxCont
STA PutCompletedFlag
ExitTxDataInt:
POP H
POP PSW
EI ;Enable Interrupts
RET
;
RxBisyncExternalInt:
{ Come here when we get an External/Status interrupt. Register RR0 indicates the cause of the interrupt:
08: 00001000 Data Carrier Detect (DCD)}
IN RxCont ;Read RR0
ANI DCD
DB opCPI ;Compare to previous DCD
PrevBisyncDCD:
DB 0
STA PrevBisyncDCD ;Save current DCD
MVI A,ResetExternalStatusInterrupts
OUT RxCont
JNZ ExitBisyncInterrupt
{Continue if DataCarrierDetect has changed state. Notify the Get loop so that it will do a NakedNotify. We store ResetExternalStatusInterrupts in StatusChangeFlag.}
STA StatusChangeFlag
ExitBisyncInterrupt:
MVI A,38H ; Issue Return From Int Command (Ch-A Only)
OUT RxCont
POP H
POP PSW
EI ;Enable interrupts
RET
;
RxBisyncSpecialInt:
{ Come here when we get a Special interrupt. Register RR1 indicates the cause of the interrupt:
20: 00100000 RxOverrun
10: 00010000 Parity error
RxOverrun means data is being overwritten because the channel's three-byte receiver buffer is full and a new character is being received.
A Parity Error occurs when the parity bit of the character does not match with the programmed parity. Once this bit is set, it remains set until the Error Reset Command is given.}
PUSH D ;Save DE
{Read the character that caused the interrupt and place it in the RxFifo as we would a normal character.}
IN RxData ;A ← RxData
STAX B ;Store character in Fifo
INX B
LXI H,8000H+RxCont ;Point to RxCont register
MVI M,PointToWR1
MOV A,M ;Read CompletionCode from RR1
ANI 0F0H
MVI M,ErrorReset
JMP SetBisyncCompletion ;In BisyncInput
END