{ File: [Iris]<WMicro>DLion>BisyncInput.asm
Modification History:
Dennis Grundler: 6-Nov-84 15:34:54: Call DisableCRCSub after recieving DLE STX to disable sync stripping
Dennis Grundler: 1-Sep-84 16:52:20: Add copyright notice.
Dennis Grundler: 3-Apr-84 22:14:04: ITB checksum error in 2780 mode.
Dennis Grundler: 12-Jan-84 16:43:57: screwup after ITB character.
Dennis Grundler: 10-Jan-84 23:38:07: Another transparent data bug.
Dennis Grundler: 30-Nov-83 20:20:49: Fix bug in 9750 mode of not throwing out filler character.
Dennis Grundler: 28-Nov-83 11:37:09: Fix handling of transparent data.
Dennis Grundler: 26-Oct-83 17:41:42: Fix bug introduced during changes to support 9750.
Dennis Grundler: 9-Oct-83 16:40:47: Changes to support 9750.
Dennis Grundler: 30-Jun-83 11:08:27: More fixes to meet IBM spec.
Dennis Grundler: 29-Jun-83 15:01:50: ITB fixes
Chuck Fay : 11-Nov-82 10:05:45: Move POPs before EI to avoid possible stack
overflow.
Jim Frandeen : September 17, 1982 9:28 AM: Allow Async mode to have client
buffer size larger than our Rx buffer.
Jim Frandeen : September 8, 1982 2:05 PM: Fix DLE SYN bug.
Jim Frandeen : May 20, 1982 1:57 PM
Jim Frandeen : May 10, 1982 8:10 AM: Created file.
}
{ Copyright (C) 1982, 1983 by Xerox Corporation. All rights reserved.}
Get "SysDefs"
Get "RS232CDefs"
IMP RxBisyncStateSwitch ;From BisyncInterrupts
IMP StoreFrameHeader ;From RS232CInterrupts
IMP CharactersUntilBoundary ;From RS232CInterrupts
IMP CurrentCharLengthMask ;From RS232CMisc
EXP BEL6
EXP EnableRxCRC1
EXP EnableRxCRC2
EXP EnableRxCRC3
EXP EnableRxCRC4
EXP EndOfBisyncFrame
EXP EOTEndFrameSwitch
EXP EOT3270
EXP DisableRxCRC1
EXP DisableRxCRC2
EXP DisableRxCRC3
EXP ENQ6
EXP ENQ9
EXP ENQ10
EXP ENQ11
EXP EnterHuntMode1
EXP EnterHuntMode2
EXP EOT6
EXP ETB7
EXP ETB8
EXP ETB9
EXP ETB10
EXP ETB11
EXP NAK6
EXP RxBisyncInitial
EXP RxInitBiSyncInput
EXP RxMaxFrameSize
EXP SetBisyncCompletion
EXP SYN7
EXP SYN8
EXP SYN9
EXP SYN10
EXP SYN11
EXP SYN13 {6/30/83}
EXP SYN14 {6/30/83}
EXP TerminateBisyncFrame
;
{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
}
;
BisyncSwitches:
DW SOHContinue
DW RxHeaderSyn
DW Non9750CRCEnable
DW RxNonTransparentModeSYN
DW RxInterBlockCRC1
DW TModeCRCEnable
DW Non9750CRCDisable
DW RxEndingCRC1
DW RxDataAfterDLE
DW StoreBisyncChar
Siemens9750Switches:
DW SOH9750Mode
DW RxHeaderSyn1
DW CRC9750Enable
DW RxNTModeSYN1
DW RxBCCNext
DW ContinueRxTransparentMode
DW DisableCRC9750
DW RxEndingBCC1
DW SkipCRCEnAfterDLE
DW Filler9750Mode
RxInitBiSyncInput:
{RxInitBiSync is a procedure which on input contains the current correspondent (Siemens 9750 or other bisync correspondents). On exit all registers are unchanged.}
PUSH D ;Save the contents of the DE register pair
PUSH H ;Save the contents of the HL register pair
LXI H,0 ;Prepare to get the value of the Stack Pointer
DI ;Make sure that stack does not get modified
DAD SP ;Find out where the stack lives
XCHG ;save the old SP in DE
CPI Siemens9750Correspondent
JNZ BisyncSetup
SiemensSetup:
LXI SP,Siemens9750Switches
JMP SetBisyncSwitches
BisyncSetup:
LXI SP,BisyncSwitches
SetBisyncSwitches:
POP H
SHLD InputSOHSwitch
POP H
SHLD RxHeaderSwitch
POP H
SHLD CRCEnableSwitch
POP H
SHLD RxNTModeSwitch
POP H
SHLD RxITBCRCSwitch
POP H
SHLD TModeCRCSwitch
POP H
SHLD Non9750CRC1Switch
POP H
SHLD RxEndingCRCorBCCSwitch
POP H
SHLD ContRxAfterDLESwitch
POP H
SHLD ThrowOutFiller
XCHG ;Prepare to restore old stack pointer
SPHL ;Restore old stack pointer
EI ;It is now safe to allow stack to change
POP H ;Restore HL
POP D ;Restore DE
RET
InputChar:
{This routine masks off all uninteresting bits, ie. if the character length is 8 nothing happens to it otherwise the 8-n upper bits get masked off for n = 5..7. The routine is re-entrant as long as the PSW is not needed. On exit the Accumulator will have the input data}
IN RxData
PUSH H
LXI H,CurrentCharLengthMask
ANA M
POP H
RET
RxBisyncInitial:
{This is the initial receive state. The CRC generator is off. We are waiting for the first character. The receiver is in Hunt mode, which means it is searching for two contiguous sync characters. The SIO chip is set for SyncCharacterLoadInhibit so that leading Sync characters will not be loaded or cause interrupts. Come here when we receive the first character that is not a sync character.}
XRA A ;set the BCC to zero (important only for
STA BlockCheckChar ; 9750 mode)
CALL InputChar ;Read character
CPI STX
JZ FirstRxCharIsSTX
CPI SOH
JZ FirstRxCharIsSOH
CPI DLE
JZ FirstRxCharIsDLE
{EOT is a special character if the host is a 3270. In this case, we enter Hunt mode right away. If the host is not a 3270, we simply end the frame. This switch is set by Misc when the mode and the Correspondent is determined.}
DB opCPI
EOT6: DB 0
DB opJZ
EOTEndFrameSwitch:
DW EOT3270
; JZ EOT3270
; JZ EndOfBisyncFrame
DB opCPI
BEL6: DB 0
JZ EndOfBisyncFrame
DB opCPI
NAK6: DB 0
JZ EndOfBisyncFrame
DB opCPI
ENQ6: DB 0
JZ EndOfBisyncFrame
DB opJMP
ThrowOutFiller:
DW StoreBisyncChar
; DW Filler9750Mode
Filler9750Char EQU 7FH
Filler9750Mode:
CPI Filler9750Char
JZ ExitBisyncDataInt
{Continue if the character is not any of the above. We stay in this state.}
JMP StoreBisyncChar
EOT3270:
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;M ← EnterHuntMode
EnterHuntMode1:
DB 0
JMP StoreBisyncChar
;
FirstRxCharIsSOH:
LXI H,StartRxHeader
JMP ChangeStateAndStoreBisyncChar
StartRxHeader:
{We are about to read the first Header character following SOH or continue after a SYN character. The CRC generator is off. Unless the next character is a SYN, we want to include it in the CRC.}
CALL InputChar
DB opCPI
SYN7: DB 0
JZ ExitBisyncDataInt
{The following code up to and including the label SOHContinue were added for Siemens 9750 support. In Siemens 9750 mode we turn on the BCC generator after the first SOH or first STX and it remains on until we finish receiving the message including the ETB or ETX.}
DB opJMP
InputSOHSwitch:
DW SOHContinue
; DW SOHContinue
; DW SOH9750Mode
SOH9750Mode:
LXI H,AccumulateBCC
SHLD InputBCCSwitch
JMP RejoinSOH
SOHContinue:
{If the first character of the header is not SYN, turn on the CRC generator to include the character in the CRC. During receive, the CRC accumulation is delayed eight bits. We must read a character, decide whether or not to continue CRC accumulation, and disable/enable CRC before the next character is transferred to the buffer.}
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCEnable
EnableRxCRC1:
DB 0
RejoinSOH:
CPI STX
JZ ContinueRxNonTransparentMode
CPI DLE
JZ LookForSTXAfterRxDLENext {modified 6/30/83}
CPI ETX
JZ RxEndingCRCNext
DB opCPI
ETB7: DB 0
JZ RxEndingCRCNext
{Continue if the character is not any of the above. Pass to RxHeader state.}
LXI H,RxHeader
JMP ChangeStateAndStoreBisyncChar
;
RxHeader:
{We are about to read the next Header character. The CRC generator is on. Unless the next character is a SYN, we want to include it in the CRC.}
CALL InputChar
DB opCPI
SYN8: DB 0
DB opJZ
RxHeaderSwitch:
DW RxHeaderSyn
; JZ RxHeaderSyn
; JZ RxHeaderSyn1
CPI STX
JZ ContinueRxNonTransparentMode
CPI DLE
JZ LookForSTXAfterRxDLENext {modified 6/30/83}
CPI ETX
JZ RxEndingCRCNext
DB opCPI
ETB8: DB 0
JZ RxEndingCRCNext
{Continue if the character is not any of the above. Stay in this state. Leave the CRC generator on.}
JMP StoreBisyncChar
RxHeaderSyn:
{Come here if we got a SYN character in the header. The SYN character does not get included in the checksum, and it does not get stored in the input buffer. Disable the CRC generator.}
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCEnable
DisableRxCRC1:
DB 0
RxHeaderSyn1:
LXI H,StartRxHeader
SHLD RxBisyncStateSwitch
JMP ExitBisyncDataInt
;
FirstRxCharIsSTX:
LXI H,StartRxNonTransparentMode
JMP ChangeStateAndStoreBisyncChar
EnableCRCSub:
DB opJMP
CRCEnableSwitch:
DW Non9750CRCEnable
; DW Non9750CRCEnable
; DW CRC9750Enable
CRC9750Enable:
LXI H,AccumulateBCC
SHLD InputBCCSwitch
RET
Non9750CRCEnable:
{If the first character of the header is not SYN, turn on the CRC generator to include the character in the CRC. During receive, the CRC accumulation is delayed eight bits. We must read a character, decide whether or not to continue CRC accumulation, and disable/enable CRC before the next character is transferred to the buffer.}
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCEnable
EnableRxCRC2:
DB 0
RET
StartRxNonTransparentMode:
{We are about to read the first character in NonTransparent Mode or continue after a SYN character. The CRC generator is off. Unless the next character is SYN, we want to include it in the CRC.}
CALL InputChar
DB opCPI
SYN9: DB 0
JZ ExitBisyncDataInt
{The following code up to and including the label Non9750CRCEnable were added for Siemens 9750 support. In Siemens 9750 mode we turn on the BCC generator after the first SOH or first STX and it remains on until we finish receiving the message including the ETB or ETX.}
CALL EnableCRCSub
RejoinSTX:
CPI ETX
JZ RxEndingCRCNext
DB opCPI
ETB9: DB 0
JZ RxEndingCRCNext
CPI ITB
JZ RxInterBlockCRCNext
DB opCPI
ENQ9: DB 0
JZ EndOfBisyncFrame
ContinueRxNonTransparentMode:
LXI H,RxNonTransparentMode
JMP ChangeStateAndStoreBisyncChar
;
DisableCRCAndExit:
CALL DisableCRCSub
JMP ExitBisyncDataInt
RxITBContinueNTMode:
{After ITB we may optionally receive SYN (without including them in the checksum). }
CALL InputChar
DB opCPI
SYN13: DB 0
JZ DisableCRCAndExit
CALL EnableCRCSub
LXI H,RxNonTransparentMode
SHLD RxBisyncStateSwitch
JMP RxNTMode
RxNonTransparentMode:
{We are receiving characters in NonTransparent mode. The CRC generator is on. Unless the next character is SYN, we want to include it in the CRC.}
CALL InputChar
RxNTMode:
DB opCPI
SYN10: DB 0
DB opJZ
RxNTModeSwitch:
DW RxNonTransparentModeSYN
; JZ RxNonTransparentModeSYN
; JZ RxNTModeSYN1
CPI ETX
JZ RxEndingCRCNext
DB opCPI
ETB10: DB 0
JZ RxEndingCRCNext
CPI ITB
JZ RxInterBlockCRCNext
DB opCPI
ENQ10: DB 0
JZ EndOfBisyncFrame
{Continue if the character is not any of the above. We stay in NonTransparent Mode.}
JMP StoreBisyncChar
RxNonTransparentModeSYN:
{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.}
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCDisable
DisableRxCRC2:
DB 0
RxNTModeSYN1:
LXI H,StartRxNonTransparentMode
SHLD RxBisyncStateSwitch
JMP ExitBisyncDataInt
;
RxInterBlockCRCNext:
{Come here when we have just read an ITB character. The next two characters we receive will be CRC characters. The CRC generator is on.}
{LXI H,RxInterBlockCRC1}
DB opLXIH
RxITBCRCSwitch:
DW RxInterBlockCRC1
; DW RxInterBlockCRC1
; DW RxBCCNext
JMP ChangeStateAndStoreBisyncChar
RxInterBlockCRC1:
{Read and store the first Interblock CRC character.}
CALL InputChar
LXI H,RxInterBlockCRC2
JMP ChangeStateAndStoreBisyncChar
RxBCCNext:
{Read and store the Block Check Character. This is what the 9750 uses for vertical parity checking.}
RxInterBlockCRC2:
{Read and store the second Interblock CRC character. The result of the CRC will not be available until two characters later. Maybe someday we will get around to checking the CRC. For now, we will wait until the end of the block.}
CALL InputChar
PUSH PSW ;save character
LDA TransparentDataFlag ;If we were in transparent mode then
ORA A ;stay there. 6/29/83
JNZ ContinueITBRxTransparentMode
ContinueITBRxNonTransparentMode:
{6/30/83}
LXI H,RxITBContinueNTMode
JMP SaveLastByteChecksum
ContinueITBRxTransparentMode:
LXI H,RxITBContinueTMode
SaveLastByteChecksum:
POP PSW ;restore character
JMP ChangeStateAndStoreBisyncChar
;
FirstRxCharIsDLE:
{Come here if the first Rx character is DLE. Look for STX to enter transparent mode. Any other character will be EndOfFrame. The CRC generator is not on. The STX is NOT included in the checksum.}
LXI H,LookForSTXAfterFirstRxDLE
JMP ChangeStateAndStoreBisyncChar
LookForSTXAfterFirstRxDLE:
CALL InputChar
CPI STX
JNZ EndOfBisyncFrame
CALL DisableCRCSub
LXI H,StartRxTransparentMode
JMP ChangeStateAndStoreBisyncChar
;
{ITB fixes. 6/29/83}
TransparentDataFlag:
DB 0
StartRxTransparentMode:
{We are about to receive the first character in Transparent Mode or continue after DLE SYN. We want to include the next character in the CRC unless it is DLE.}
MVI A,1 ;Indicate Transparent mode. 6/29/83
STA TransparentDataFlag
CALL InputChar
CPI DLE
JZ DisableCRCNow
DB opJMP
TModeCRCSwitch:
DW TModeCRCEnable
; DW TModeCRCEnable
; DW ContinueRxTransparentMode
TModeCRCEnable:
{Turn on the CRC generator to include the character in the CRC. During receive, the CRC accumulation is delayed eight bits. We must read a character, decide whether or not to continue CRC accumulation, and disable/enable CRC before the next character is transferred to the buffer.}
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCEnable
EnableRxCRC3:
DB 0
JMP ContinueRxTransparentMode
RxITBContinueTMode:
{We can have SYN* followed by DLE STX only, after ITB in Transparent mode. The CRC generator is off.}
CALL InputChar
DB opCPI
SYN14: DB 0
JZ DisableCRCAndExit
CPI DLE
JNZ IllegalRxSequence
CALL EnableCRCSub ;Make sure the CRC generator is on.
LookForSTXAfterRxDLENext:
LXI H,LookForSTXAfterRxDLE
JMP ChangeStateAndStoreBisyncChar
LookForSTXAfterRxDLE:
{Come here after the sequence ITB BCC SYN* DLE or SOH DLE. The only valid character that can follow is STX to start Transparent Mode. The CRC generator may or may not be on. The STX needs to be included in the CRC.}
CALL InputChar
CPI STX
JNZ IllegalRxSequence
CALL EnableCRCSub
JMP ContinueRxTransparentMode
NoRoomForDLE:
{This is a sneaky way of saving the contents of the registers and faking a subroutine call while in the middle of a subroutine. E contains the completion code.}
PUSH H ;Save the HL register temporarily.
LXI H,RetAddr ;RetAddr is where we enventually want to return to.
XTHL ;This restores HL while putting the return address on the stack.
PUSH PSW ;Now set up the stack with the registers that the new subroutine is going to POP in the correct order.
PUSH H
PUSH D
MVI E,4 ;Set EndOfBlock CompletionCode
{The stack should now look like:
TOS: DE
HL
PSW
RetAddr
Where TOS is what the Stack pointer is pointing to.}
JMP SetNewBisyncBoundary ;CALL the subroutine.
RetAddr:
DI ;unfortunately we had an EI executed on us.
JMP ReEnter
RxTransparentMode:
{We are receiving characters in Transparent mode. The only interesting character to look for is DLE. The CRC generator is on.}
CALL InputChar
CPI DLE
JNZ StoreBisyncChar
DisableCRCNow:
CALL DisableCRCSub
LookForRxDataNext:
LXI H,LookForRxDataAfterDLE
SHLD RxBisyncStateSwitch
JMP ExitBisyncDataInt
DisableCRCSub:
DB opJMP
Non9750CRC1Switch:
DW Non9750CRCDisable
; DW Non9750CRCDisable
; DW DisableCRC9750
DisableCRC9750:
LXI H,CheckBoundary
SHLD InputBCCSwitch
RET
Non9750CRCDisable:
{Come here when we want to turn the CRC generator off.}
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCDisable
DisableRxCRC3:
DB 0
RET
LookForRxDataAfterDLE:
{Read the character following DLE in Transparent mode. The CRC geneator is off. Unless the character is SYN, we will include it in the checksum.}
CALL InputChar
DB opCPI
SYN11: DB 0
JZ DLESyn
DB opJMP
ContRxAfterDLESwitch:
DW RxDataAfterDLE
; DW RxDataAfterDLE
; DW SkipCRCEnAfterDLE
RxDataAfterDLE:
LXI H,8000H+RxCont
MVI M,PointToWR3
DB opMVIM ;RxCont ← WR3 OR RxCRCEnable
EnableRxCRC4:
DB 0
SkipCRCEnAfterDLE:
{This next section is to insert a DLE in the clients buffer except in the case of DLE SYN where the DLE SYN are both removed}
PUSH PSW
MVI A,DLE
CALL StoreBSCChar
JZ NoRoomForDLE
ReEnter:
POP PSW
CPI DLE
JZ ContinueRxTransparentMode
DB opCPI
ENQ11: DB 0
JZ EndOfBisyncFrame
DB opCPI
ETB11: DB 0
JZ RxEndingCRCNext
CPI ETX
JZ RxEndingCRCNext
CPI AltoETX
JZ RxEndingCRCNext
CPI ITB
JZ RxInterBlockCRCNext
IllegalRxSequence:
STAX B
INX B
PUSH D
MVI E,8 ;Set CompletionCode IllegalSequence
MVI A,38H ;Issue Return From Int Command
OUT RxCont
JMP TerminateBisyncFrame
DLESyn:
{Come here if we found DLE SYN in Transparent mode.}
LXI H,StartRxTransparentMode
SHLD RxBisyncStateSwitch
JMP ExitBisyncDataInt
;
RxEndingCRCNext:
{Come here when we have received the last character of the frame. The next two characters we receive will be CRC characters. The CRC generator is on.}
LXI H,TransparentDataFlag ;set non-transparent mode. 6/29/83
MVI M,0
DB opLXIH
RxEndingCRCorBCCSwitch:
DW RxEndingCRC1
; DW RxEndingCRC1
; DW RxEndingBCC1
JMP ChangeStateAndStoreBisyncChar
RxEndingBCC1:
{Read and store the BCC. If all has went well the accumulated BCC should be zero after storing the BCC in the buffer.}
CALL InputChar
LXI H,RxEndingBCC2
JMP ChangeStateAndStoreBisyncChar
RxEndingBCC2:
PUSH D ;Save DE
LDA BlockCheckChar
ORA A ;Check to make sure BCC shows column parity (all zero).
MVI A,80H ;Set up as good (does not affect flags)
JZ SetBisyncCompletion
ORI 40H ;Indicate bad BCC (CRC)
JMP SetBisyncCompletion
RxEndingCRC1:
{Read and store the first Interblock CRC character.}
CALL InputChar
LXI H,RxEndingCRC2
JMP ChangeStateAndStoreBisyncChar
RxEndingCRC2:
{Read and store the second Interblock CRC character.}
CALL InputChar
LXI H,RxEndingCRC3
JMP ChangeStateAndStoreBisyncChar
RxEndingCRC3:
{Read and throw away the character following the second CRC character. We are guaranteed at least three fill characters following the CRC, so we are only throwing away fill characters. The CRC result will not be available until one character later.}
CALL InputChar
LXI H,RxEndingCRC4
SHLD RxBisyncStateSwitch
JMP ExitBisyncDataInt
EndOfBisyncFrame:
STAX B ;Store character
INX B
PUSH D
MVI E,80H ;E ← EndOfFrame CompletionCode
JMP SendEndingReturnFromInt
RxEndingCRC4:
{Read and throw away the second fill character following the second CRC character. The result of the CRC is now available in WR1.}
PUSH D ;Save DE
CALL InputChar
LXI H,8000H+RxCont
MVI M,PointToWR1
MOV A,M
ANI 40H ;A ← 40 if CRC error
ORI 80H
SetBisyncCompletion:
{Come here from RxSpecialInt in BisyncInterrupts.}
MOV E,A ;Set CompletionCode
SendEndingReturnFromInt:
MVI A,38H ;Issue Return From Int Command
OUT RxCont
TerminateBisyncFrame:
{We get called here from Get in case an abort is requested. The CompletionCode is in E. Turn off the CRC generator, Enter Hunt Phase, turn on InhibitSyncCharacterLoad.}
LXI H,8000H+RxCont
MVI M,ResetRxCRCChecker+PointToWR3
DB opMVIM
EnterHuntMode2:
DB 0
LXI H,TransparentDataFlag ;set non-transparent mode. 6/29/83
MVI M,0
LXI H,CheckBoundary ;Turn off the BCC mechanism
SHLD InputBCCSwitch
LXI H,RxBisyncInitial
SHLD RxBisyncStateSwitch
JMP SetNewBisyncBoundary
StoreBSCChar:
{A = last character read. Store this character in the RxFifo. Decrement CharactersUntilBoundary and test for boundary. If we have filled a block, ship this frame back to the CP and start a new frame.}
STAX B
INX B
{The code from here up to and including the label CheckBoundary were added for Klamath 11.0b and beyond to support Siemens' 9750 terminal. The major problem with the Siemens terminal is that it does not use the standard Cyclic Redundancy Check mechanism so we need to support their flakey method.
In the normal case we will always jump to CheckBoundary, thereby only paying only a 10 state time penalty for the JMP instruction. In 9750 mode we will jump to CheckBoundary until the character following the first SOH (start of heading) or STX (start of text) is found.}
DB opJMP
InputBCCSwitch:
DW CheckBoundary
; JMP CheckBoundary
; JMP AccumulateBCC
BCCMask EQU 7FH
BlockCheckChar:
DB 0
AccumulateBCC:
CPI AsciiSYN ;check to see if character is sync character.
JZ CheckBoundary ;If it is then do not modify BCC.
LXI H,BlockCheckChar ;Reference the Block Check Character.
XRA M ;calculate the modulo 2 sum of each column.
ANI BCCMask ;mask off the parity bit.
MOV M,A ;save the new Block Check Character.
CheckBoundary:
LHLD CharactersUntilBoundary
DCX H
SHLD CharactersUntilBoundary
MOV A,H
ORA L
RET
ContinueRxTransparentMode:
LXI H,RxTransparentMode
ChangeStateAndStoreBisyncChar:
SHLD RxBisyncStateSwitch
StoreBisyncChar:
CALL StoreBSCChar
JZ BisyncBlockFull
ExitBisyncDataInt:
MVI A,38H ;Issue Return From Int Command
OUT RxCont
POP H
POP PSW
EI ;Enable interrupts
RET
BisyncBlockFull:
{End this Bisync frame and start a new frame. Then continue in the same state when we get the next input character.}
PUSH D ;Save DE
MVI E,4 ;Set EndOfBlock CompletionCode
MVI A,38H ;Issue Return From Int Command
OUT RxCont
SetNewBisyncBoundary:
{RxMaxFrameSize is the number of characters until our next boundary.}
DB opLXIH ;HL ← RxMaxFrameSize
RxMaxFrameSize:
DW 0
SHLD CharactersUntilBoundary
JMP StoreFrameHeader
END