JMON_SCV01.asm
tec1group_Software/monitors/JMon/JMON_SouthernCrossVersion/JMON_SCV01.asm
;
; JMON - JIM'S MONITOR
; BY JIM ROBERTSON
;
; PORTED TO THE SOUTHERN CROSS COMPUTER BY CRAIG RS JONES   MAY 2021
;
;
; FILENAME : JMON_SCV01.ASM
; VERSION : 1
;
; A PORT OF JMON TO THE SOUTHERN CROSS COMPUTER (SC)
; THE MEMORY MAP OF THE SC IS DECODED INTO 8 X 8K BLOCKS. 
; THE ROM RESIDES AT 0000H TO 1FFFH (8K)
; THE RAM RESIDES AT 2000H T0 3FFFH (8K)
;
; CHANGES;
; * IO PORT NUMBERS HAVE CHANGED
;
; * RAM VARIABLES HAVE MOVED FROM 0800H TO THE START OF SC RAM 2000H 
;
; * 7 SEGMENT DISPLAY CODES HAVE CHANGED 
;
; * A NEW LCD INITIALISATION ROUTINE TESTS THE BUSY FLAG AND CG RAM ADDRESS FOR LCD DETECTION INSTEAD
;   OF LOOKING FOR THE SPACE (0X20) CHARACTER IN THE CGRAM
;
; * THE KEYBOARD ENTRY ROUTINE USES THE DA FROM THE KEYBOARD IO PORT INSTEAD OF THE FROM THE DATA LATCH OF THE (NON-EXISTANT) DAT BOARD  
;
; * THE KEY CODES HAVE REMAINED THE SAME FOR COMPATABILITY WITH EXISTING TEC-1 SOFTWARE.
;   THE KEY ASSIGNMENTS FOR THE SC ARE;
;   FN BECOMES +
;   AD BECOMES -
;   + BECOMES GO
;   - BECOMES AD
;
;GLOSSARY
;
;---CURRENT EDITING LOCATION (082E)---
;THIS IS THE ADDRESS THAT IS USUALLY DISPLAYED IN THE ADDRESS SECTION ON THE TEC LED 
;DISPLAY. IT IS THE ADDRESS THAT IS SUBJECT TO MODIFICATION BY JMON.
;
;---MONITOR CONTROL BYTE (MCB) (082B)---
;THIS BYTE CONTAINS THE INPORMATION OF THE CURRENT WORKING STATE OF JMON. THE INFORMATION 
;HELD IN THIS BYTE IS:
;
;1 - THE CURRENT MODE OF JMON.
;
;E.G. DATA, ADDRESS OR FUNCTION (NOT SHIFT AS SHIFT IS TESTED AND HANDLED DURING THE DATA 
;KEY HANDLER ROUTINE). BITS 4 AND 5 ENCODE THE CURRENT MODE IN THE FOLLOWING WAY. BOTH 
;BITS ARE LOW FOR THE DATA MODE, BIT 4 IS HIGH FOR THE ADDRESS MODE, BITS 4 AND 5 ARE HIGH 
;FOR THE FUNCTION MODE. BIT 4 IS CALLED THE ADDRESS/FUNCTION BIT As THE SOFTWARE ONLY 
;NEEDS TO TEST THIS BIT TO FIND IF EITHER THE ADDRESS OR FUNCTION MODE IS ACTIVE. BIT 5 
;IS THE FUNCTION MODE ENABLED BIT.
;
;2 - THE NUMBER OF THE CURRENT FUNCTION I.E. 1,2 OR 3.
;
;THIS IS ENCODED IN BITS 2 AND 3. IF NO FUNCTION OR FUNCTION-1 IS ENABLED THEN BOTH BITS 
;ARE LOW. IF FUNCTION-2 IS SELECTED THEN BIT 2 IS HIGH AND BIT 3 IS LOW. IF FUNCTION-3 IS 
;SELECTED THEN BIT 3 IS HIGH AND BIT 2 IS LOW.
;
;3 - THE NUMBER OF NIBBLES ENTERED
;
;THIS IS ENCODED IN BITS 0 AND 1. IF NO NIBBLES HAVE BEEN ENTERED IN THE CURRENT EDITING 
;LOCATION THEN BOTH BIT ARE LOW. IF ONE NIBBLE HAS BEEN ENTERED THEN BIT 0 IS HIGH AND 
;BIT 1 IS LOW IS TWO NIBBLES HAVE BEEN ENTERED THEN BIT 0 IS LOW AND BIT 1 IS HIGH. JMON 
;USES THESE BITS WHEN DECIDING ON THE AUTO-INCREMENT FEATURE. BITS 6 AND 7 ARE NOT USED.
;
;---DISPLAY BUFFER ADDRESS - (082C/D)---
;THE CONTENTS OF 082C/D POINTS TO THE LOCATION IN MEMORY OF THE 6 BYTE DISPLAY BUFFER 
;(0800 FOR JMON AND 0806 FOR THE STEPPER). THE DISPLAY BUFFER ADDRESS POINTS TO THE LOWEST 
;ADDRESS OF THE DISPLAY BUFFER WHICH CONTAINS THE LOW ORDER DATA DISPLAY BYTE.
;
;KEY PLANT
;THE KEY PLANT IS A FAKE KEY STROKE THAT MAY BE GENERATED BY THE "DURING SCAN/REY LOOP" 
;USER PATCH. THE PLANT ALLOWS JMON'S MONITOR FUNCTIONS TO BE SOFTWARE CONTROLLED E.G. YOU 
;MAY WISH TO VIEW THE CONTENTS ,OF MEMORY BYTE BY BYTE. WITH THE KEY PLANT YOU CAN SET JMON 
;UP TO AUTOMATICALLY INCREMENT THE CURRENT EDIT LOCATION EVERY FEW SECONDS.
;THE PLANT IS IDENTIFIED BY THE USER PATCH STORING THE REQUIRED KEY VALUE IN, AND SETTING 
;BIT 7 OF THE INPUT KEY BUFFER (0820).
;
;---AUTO KEY STATUS BYTE (082A)---
;THIS BYTE HOLDS THE INFORMATION REQUIRED FOR THE AUTO KEY REPEAT SECTION. THE INFORMATION 
;HELD IN THIS BYTE IS EITHER ONE OF THE FOLLOWING:
;A "NEXT KEY DETECTION WILL BE A FIRST DETECTION" SO JMON WILL PROCESS THE KEY IMMEDIATELY 
;(BIT 7 HIGH) . A TIMER (BITS 0-6) THAT COUNTS, A DELAY FOR THE AUTO. REPEAT TIMING.
;
;KEY PRESS FLAG (0825)
;THIS FLAG IS USED TO REMEMBER IF THE ONE KEY PRESS HAS ALREADY BEEN DETECTED AND PROCESSED. 
;THIS PREVENTS THE SAME KEY BEING PROCESSED EACH TIME THE SOFTWARE FINDS THAT IT IS PUSHED. 
;THIS IS THE WAY IT WORKS:
;THE KEY PRESS FLAG 1S ZEROED BY THE JMON DEFAULT VARIABLES AND THIS FLAGS A "NO KEY 
;PRESSED" STATE. WHEN A KEY IS DETECTED THEN THIS FLAG IS TESTED AND IF ZERO THEN THE KEY 
;IS ACCEPTED AS A FIRST KEY PRESS. IN THIS CASE THE KEY PRESS FLAG IS THEN SET TO FF TO 
;REMEMBER THAT THE KEY PRESS HAS BEEN DETECTED. IF A KEY IS DETECTED AND THIS FLAG BYTE 
;IS NOT ZERO, THEN THE KEY IS IGNORED. WHEN THE SOFTWARE FINDS THAT NO KEY IS BEING PRESSED, 
;THEN THIS FLAG IS CLEARED TO ALLOW THE NEXT KEY PRESS DETECTED TO BE PROCESSED.
;THIS FLAG IS USED BY THE RST 08, RST 10 RST 18 AND RST 20 KEYBOARD ROUTINES AS DESCRIBED 
;IN ISSUE 15 TALKING ELECTRONICS AND ALSO THE STEPPER SOFTWARE.
;THE AUTO KEY REPEAT ROUTINE DOES NOT USE THIS FLAG BYTE, DO NOT CONFUSE THIS FLAG WITH 
;THE AUTO KEY STATUS BYTE WHICH IS USED BY THE AUTO KEY REPEAT SECTION.

;TAPE FILE INFORMATION BLOCK
;THIS IS A 12 BYTE BLOCK THAT CONTAINS THE FOLLOWING INFORMATION:
;THE START ADDRESS OF THE BLOCK, THE NUMBER OF BYTES IN THE BLOCK, THE FILE NUMBER AND AN 
;OPTIONAL GO ADDRESS OR FFFF IF OPTIONAL GO IS DISABLED. THE OTHER 4 BYTES ARE NOT USED 
;AT THIS STAGE.
;THIS BLOCK IS OUTPUTTED AND INPUTTED TO AND FROM THE TAPE ON EACH TAPE OPERATION.
;
;"NEXT PC" BUFFER
;THIS IS A TEMPORARY PLACE TO SAVE THE RETURN ADDRESS WHICH IS THEN USED AS THE ACTUAL PC 
;VALUE FOR THE NEXT INSTRUCTION STEPPED.
;
;FORCED HARD RESET
;THIS IS ACHIEVED BY HOLDING DOWN A KEY WHEN RELEASING THE RESET. THE HARD RESET CAUSES 
;JMON TO RE-BOOT ITS VARIABLES AND ALSO MASK OFF ALL THE USER PATCHES (EXCEPT THE RESET 
;PATCH). THE MAIN PURPOSE OF A FORCED HARD RESET IS TO RECOVER THE TEC IF A USER PATCH 
;ENTERS A CONTINUOUS LOOP.

            ORG   2000H
L0800       RMB   4
L0804       RMB   1 
L0805       RMB   1             ;KEY BUFFER
L0806       RMB   26            ;DISPLAY BUFFER
L0820       RMB   1
L0821       RMB   1             ;LCD ON/OFF FLAG                     
L0822       RMB   1             ;SOUND ON/OFF
L0823       RMB   1             ;GO AT ALTERNATE GO ADDRESS IF AA  
L0824       RMB   1             ;STEPPER KEY CONTROL/TIMER  
L0825       RMB   1             ;KEY PRESS FLAG                    
L0826       RMB   1             ;UNUSED 
L0827       RMB   1             ;AUTO INCREMENT ON/OFF  
L0828       RMB   2             ;ALT GO ADDR/SOFT RESET EDIT LOCATION  
L082A       RMB   1             ;AUTO KEY STATUS BYTE
L082B       RMB   1             ;MONITOR CONTROL BYTE (MCB)
L082C       RMB   2             ;DISPLAY BUFFER ADDRESS
L082E       RMB   2             ;CURRENT EDITING LOCATION (CEL)
;
; JMON INDIRECT JUMP ADDRESSES - COPIED FROM L071F ON A HARD RESET
;
L0830       RMB   3             ;CONVERT HL TO DISPLAY CODE  (L01D5)
L0833       RMB   3             ;CONVERT A TO DISPLAY CODE   (L01DA)
L0836       RMB   3             ;LED SCAN ROUTINE    (L01BA)
L0839       RMB   3             ;SET LED DOTS    (L01EE)
L083C       RMB   3             ;RESET TONES   (L0224) 
L083F       RMB   3             ;TONE   (L0227)
L0842       RMB   3             ;SCAN/KEY/LCD/PATCH ROUTINE   (L0181)
L0845       RMB   3             ;SOFT JMON ENTRY  (L00B2)
L0848       RMB   3             ;LCD ROUTINE  (L023C)

L084B       RMB   3
L084E       RMB   3
L0851       RMB   7
L0858       RMB   2             ;"NEXT PC" BUFFER   
L085A       RMB   6

L0860       RMB   8
L0868       RMB   2
L086A       RMB   4
L086E       RMB   2
;
; STEPPER ROUTINE
;
L0870       RMB   14             ; STEPPER SAVED REGISTERS - HL REG

L087E       RMB   2
L0880       RMB   2
L0882       RMB   2
L0884       RMB   2
L0886       RMB   1
L0887       RMB   1
L0888       RMB   2
L088A       RMB   2
L088C       RMB   3
L088F       RMB   2

L0891       RMB   2
L0893       RMB   2
L0895       RMB   2
L0897       RMB   1
L0898       RMB   2
L089A       RMB   2
L089C       RMB   2
L089E       RMB   6

L08A4       RMB   2
L08A6       RMB   2
L08A8       RMB   2
L08AA       RMB   6

L08B0       RMB   1 
L08B1       RMB   2
L08B3       RMB   2
L08B5       RMB   1
L08B6       RMB   2
            RMB   6
L08BE       RMB   2        

;L08FF   EQU  08FFH
L08FF       EQU  28FFH
;L0900   EQU  0900H
L0900       EQU  2900H
;L3800   EQU  3800H                      ;LCD ROUTINES   JMON UTILITIES ROM
L3800       EQU  4000H
;
; IO ASSIGNMENTS
;
KEYBOARD    EQU 0x86            ;KEYBOARD ENCODER
DSCAN       EQU 0x85            ;DISPLAY CATHODE DRIVER LATCH
DSEGMENT    EQU 0x84            ;DISPLAY SEGMENT DRIVER LATCH
DATLATCH    EQU 0x87            ;DAT BOARD LATCH ( NOT PRESENT ON SC )
LCDINST     EQU 0x80            ;LCD INSTRUCTION REGISTER
LCDDATA     EQU 0x81            ;LCD DATA REGISTER
;
; FUNCTION KEY KEYCODES
;  
; LEAVE THE KEY CODES AS TEC-1 FOR COMPATABILITY WITH TEC-1 SOFTWARE
;
; TEC-1
AD_KEY      EQU  0x13
GO_KEY      EQU  0x12
MINUS_KEY   EQU  0x11
PLUS_KEY    EQU  0x10
;
; SC
;AD_KEY      EQU  0x10
;GO_KEY      EQU  0x11
;PLUS_KEY    EQU  0x12
;MINUS_KEY   EQU  0x13

; SHIFT KEY IS CONNECTED TO KEYBOARD ENCODE BIT 6

;AT THE START OF JMON, HL IS SAVED IN ITS SINGLE STEPPER BUFFER AND THE SOFT RESET DISPLAY 
;VALUE IS PLACED IN THE CURRENT EDIT LOCATION BUFFER. THE ROUTINE THEN IS CONTINUED AT 
;0068.
            ORG  0000H
            LD (L086E),HL       ;SAVE HL PART OF REGISTER SAVE
            LD HL,(L0828)       ;GET SOFT RESET INITIAL EDIT
            JR L006B            ;LOCATION AND CONTINUE AT 006B

;RST 08 AND RST 10 (CF AND D7)
;THESE TWO COMBINE TOGETHER TO SIMULATE A HALT INSTRUCTION. THIS IS DONE BY LOOPING UNTIL 
;THE CURRENT (IF ANY) KEY PRESS IS RELEASED (RST 08), AND THEN LOOPING UNTIL A NEW KEY
;PRESS IS DETECTED (RST 10).
L0008       RST 20H             ;TEST FOR KEY PRESS
            JR Z,L0008          ;LOOP IF KEY PRESSED
            NOP                 ;ELSE
            NOP                 ;MOVE
            NOP                 ;TO
            NOP                 ;NEXT
            NOP                 ;RST 
;RST 10H            
L0010       RST 20H             ;TEST FOR KEY AGAIN
            JR NZ,L0010         ;LOOP IF KEY NOT PRESSED
            AND 0x1F            ;MASK OF JUNK BITS
            LD I,A              ;STORE IN INTERRUPT REGISTER
            RET                 ;DONE

;RST 18  (DF)AND RST (20)
;RST 18 CALLS THE LED SCAN ROUTINE ONCE THEN MOVES ON INTO RST 20 THAT THEN CALLS A KEYBOARD
;READ ROUTINE.
;THE KEYBOARD MUST BE READ CONTINUOUSLY OVER A PERIOD OF TIME, AS THE DATA  AVAILABLE SIGNAL 
;(BIT 6, PORT 3) (USUALLY) PULSES, WHEN A KEY IS PRESSED, IN TIME WITH THE KEY ENCODER 
;CHIP'S SCANNING. IF THE KEY BOARD IS READ ONLY ONCE EVERY SECOND, THEN THE SOFTWARE MAY
;AND PROBABLY) WILL TAKE SEVERAL SECONDS TO DETECT THE KEY. 
;THE NUMBER OF READ CYCLES FOR THE KEYBOARD IS LOADED INTO B.

            PUSH HL             ;SAVE HL
            PUSH DE             ;AND DE
            CALL L0836          ;CALL SCAN ROUTINE
            POP DE              ;RECOVER DE
            POP HL              ;AND HL
            NOP                 ;NEXT RST
;RST 20H
            PUSH BC             ;SAVE BC
            LD B,0x20           ;B = NUMBER OF KEYBOARD SCAN LOOPS
            CALL L06AD          ;CALL KEY READER/VALIDATER
            POP BC              ;RECOVER BC
            RET                 ;DONE

;RST 28 (EF)
;START STEPPING FROM THE INSTRUCTION FOLLOWING THE RST 28

            EX (SP),HL          ;GET RETURN ADDRESS FROM THE STACK 
            LD (L0858),HL       ;PUT IN "NEXT PC" BUFFER
            EX (SP),HL          ;FIX UP STACK
            EI                  ;ENABLE INTERRUPTS
            RET                 ;STEPPING WILL OCCUR AFTER RETURN 
            RST 38H             ;SPARE

;RST 30 (F7)
;TEST THE BUSY STATE OF THE LCD AND LOOP WHILE BUSY

            ORG   0030H
L0030       IN A,(LCDINST)      ;READ STATUS BIT FROM LCD 
            RLCA                ;PUT IN CARRY
            JR C,L0030          ;LOOP IF LCD BUSY
            RET                 ;DONE
            RST 38H
            RST 38H

;RST 38 (FF) 
;INTERRUPT HANDLER  FOR STEPPER AND BREAK-POINTS
            ORG  0038H
            JP L0312            ;JUMP TO STEPPER ROUTINE 
            RST 38H             ;UNUSED
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "

;JUMP TABLE FOR EXTERNAL SOFTWARE TO USE JMON ROUTINES

            JP L03DD            ;MENU GATE
            JP L0479            ;PERIMETER HANDLER ENTRY
L0047       JP L03ED            ;SOFT MENU ENTRY
L004A       JP L069F            ;ERR-IN ENTRY
            JP L05B7            ;PASS/FAIL/MENU
L0050       JP L04A3            ;SOFT PERIMETER HANDLER ENTRY
            RST 38H             ;RESERVED
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "
            RST 38H             ;"   "

;SHIFT-2 ROUTINE
;THIS STORES THE CURRENT EDIT LOCATION IN THE "NEXT PC" BUFFER. THE INTERRUPTS ARE THEN 
;ENABLED AND THE PROGRAM JUMPS TO THE USER ROUTINE TO BE STEPPED. STEPPING OCCURS AT THE 
;CURRENT EDIT LOCATION (CEL).

L005E       LD HL,(L082E)       ;PUT CURRENT EDIT LOCATION IN
            LD (L0858),HL       ;"NEXT PC" BUFFER
            EI                  ;ENABLE INTERRUPTS
            JP (HL)             ;START STEPPING

;NMI HANDLER (IMMEDIATE RETURN)

            RETN                ;IGNORE NMI
            RST 38H             ;RESERVED
            RST 38H             ;FOR
            RST 38H             ;A JUMP

;CONTINUATION OF MONITOR

L006B       IM 1                ;SET INTERRUPT MODE 1 FOR STEPPER
            LD (L082E),HL       ;STORE SOFT RESET INITIAL CEL
            LD HL,L0076         ;LOAD HL WITH RE-ENTRY ADDRESS
            JP L0318            ;JUMP TO SAVE REGISTERS


;RE-ENTRY POINT AFTER SAVING REGISTERS

L0076       LD SP,L0820         ;SET STACK
            CALL L02F7          ;CALL RESET PATCH HANDLER 
            RST 20H             ;LOOK FOR FORCED HARD RESET
            JR Z,L0086          ;JUMP KEY PRESSED TO HARD RESET 
            LD A,(L08FF)        ;CHECK HARD/RESET FLAG
            CP 0xAA             ;FOR AA
            JR Z,L00A2          ;JUMP TO SOFT RESET IF AA

;HARD RESET
;MONITOR DEFAULT VARIABLES ARE RE-BOOTED AND USER PATCHES MASKED OFF.

L0086       LD HL,L070F         ;LOAD HL WITH START OF JMON DEFAULT
            LD DE,L0820         ;VARIABLES ROM TABLE
            LD BC,0x002B        ;DE IS THE RAM DE(stination)
            LDIR                ;AND BC THE COUNT: MOVE TABLE
            LD B,0x03           ;MASK OF THE THREE USER PATCHES
            LD A,0xC9           ;BY PUTTING A RETurn AT THE FIRST
L0095       LD  (DE),A          ;LOCATION OF EACH
            INC DE              ;
            INC DE              ;
            INC DE              ;
            DJNZ L0095          ;
            CALL L06D5          ;INITIALIZE/TEST FOR THE LCD
            XOR A               ;CLEAR HARD/SOFT
            LD  (L08FF),A       ;RESET FLAG

;THIS SECTION IS THE SOFT RESET SECTION. IT IS ALSO PART OF THE HARD RESET SECTION.

L00A2       LD HL,L3800         ;TEST FOR JMON UTILITIES ROM
            LD A, (HL) 
            CP 0xC3             ;AND CALL ITS RESET ROUTINE
            CALL Z,L3800        ;IF REQUIRED
            CALL L083C          ;CALL RESET TONE ROUTINE
L00AE       XOR A               ;CLEAR MONITOR CONTROL BYTE
            LD (L082B),A        ;0 = DATA MODE, NO NIBBLES ENTERED

;EACH TIME A KEYBOARD INPUT OR USER PATCH "PLANT", IS PROCESSED, THE PROGRAM JUMPS BACK 
;TO HERE SO THE DISPLAYS MAY BE UP-DATED.

L00B2       LD HL, (L082E)      ;GET CURRENT EDIT LOCATION (CEL) 
            LD BC,(L082C)       ;AND DISPLAY BUFFER ADDRESS
            CALL L0830          ;AND CONVERT CEL TO DISPLAY CODE 
            LD A, (HL)          ;AND THEN CONVERT CONTENTS OF 
            CALL L0833          ;CEL TO DISPLAY CODE
            CALL L0839          ;CALL THE SET DOTS ROUTINE
            CALL L0842          ;CALL SCAN/KEY/LCD/PATCH ROUTINE

;THE SECTION BELOW IS EXECUTED WHEN EITHER A KEY OR KEY "PLANT" IS DETECTED IN THE 
;SCAN/KEY/LCD/PATCH ROUTINE ROUTINE

            LD HL,(L082E)       ;POINT HL TO CURRENT EDIT LOCATION 
            LD C,A              ;PRESERVE INPUT KEY IN C
            LD A,(L082B)        ;GET MONITOR CONTROL BYTE (MCB) 
            BIT 4,A             ;TEST FOR ADDRESS OR FUNCTION MODE 
            LD B,A              ;STORE MCB IN B
            LD A,C              ;GET INPUT KEY BACK IN A
            JR NZ,L0102         ;JUMP IF ADDRESS OR FUNCTION MODE 
            CP PLUS_KEY         ;***TEST FOR "+"
            JR NZ,L00E3         ;JUMP IF NOT TO TEST FOR "-"

;"+" KEY HANDLER-(WHEN IN DATA MODE ONLY)

            INC HL              ;ADD 1 TO CURRENT EDIT LOCATION

;COMMON CEL AND MCB UP-DATER
;SEVERAL SECTIONS JUMP HERE TO STORE AN UP-DATED CEL AND CLEAR THE NIBBLE COUNTER.

L00D8       LD (L082E),HL       ;STORE CEL
            LD A,B              ;GET MCB

;COMMON MCB UP-DATER
;SOME KEY HANDLER SECTION THAT DON'T REQUIRE.A NEW CEL (OR HAVE ALREADY STORED IT) JUMP 
;HERE.

L00DC       AND 0xFC            ;CLEAR NIBBLE COUNTER
            LD (L082B),A        ;STORE MCB
L00E1       JR L00B2            ;JUMP BACK TO UPDATE DISPLAY 
L00E3       CP MINUS_KEY        ;***TEST FOR "-"
            JR NZ,L00EA         ;JUMP IF NOT TO TEST FOR "GO"

;"-" KEY HANDLER (WHEN IN DATA MODE ONLY)

            DEC HL              ;DECREASE CEL ADDRESS BY ONE
            JR L00D8            ;JUMP TO COMMON CEL AND MCB UP-DATER
L00EA       CP GO_KEY           ;***TEST FOR GO
            JR NZ,L0102         ;JUMP IF NOT TO TEST FOR "AD"

;"GO" HANDLER (WHEN IN DATA MODE ONLY)

            LD A,(L0823)        ;TEST FOR ALTERNATE GO ADDRESS 
            CP 0xAA             ;IF (0823)=AA
            JR Z,L00FA          ;JUMP IF SET FOR ALTERNATE GO ADDR 
            LD HL,(L082E)       ;ELSE GET CURRENT EDIT LOCATION 
            JR L00FD            ;SKIP ALTERNATE JUMP ADDRESS FETCH 
L00FA       LD HL,(L0828)       ;GET ALTERNATE GO ADDRESS
L00FD       LD DE,L0845         ;BUT RETURN ADDRESS ON STACK
            PUSH DE
            JP (HL)             ;START USER EXECUTION

;TEST HERE FOR ADDRESS KEY. IF THE KEY PRESSED IS NOT THE ADDRESS KEY, THEN A JUMP IS 
;PERFORMED. OTHERWISE THE ADDRESS KEY IS PROCESSED.

L0102       CP AD_KEY            ;***TEST FOR ADDRESS KEY
            JR NZ,L0111         ;0= IF NOT TO DATA KEY HANDLER
            LD A,B              ;GET MONITOR CONTROL BYTE (MCB)
            BIT 5,B             ;TEST FOR FUNCTION MODE AND JUMP TO
            JR NZ,L010D         ;CLEAR FUNCTION MODE BITS IF SO
            XOR 0x10            ;ELSE TOGGLE ADDRESS MODE BIT
L010D       AND 0xD3            ;CLEAR ALL FUNCTION MODE BITS
            JR L00DC            ;LOOP BACK TO COMMON MCB UP-DATER

;A TEST FOR ADDRESS/FUNCTION MODE IS DONE. IF IN ADDRESS OR FUNCTION MODE A JUMP IS 
;PERFORMED.

L0111       LD A,B              ;GET MCB
            BIT 4,A             ;TEST FOR ADDRESS OR FUNCTION MODE
            JR NZ,L013B         ;JUMP IF EITHER MODE

;A TEST FOR SHIFT IS DONE AND A JUMP IS PERFORMED IF IN THE SHIFT MODE TO THE FUNCTION/SHIFT 
;HANDLER.

            IN A,(KEYBOARD)     ;TEST FOR THE SHIFT KEY
            BIT 6,A             ;***AND JUMP IF SHIFT IS PRESSED
            JR Z,L0150          ;TO THE FUNCTION HANDLER

;ANY TIME A DATA KEY IS PRESSED WHILE IN THE DATA MODE, IT IS PROCESSED STARTING HERE.

            LD A,B              ;GET MCB
            AND 0x03            ;MASK IT DOWN TO BYTE COUNTER 
            CP 0x02             ;AND TEST FOR TWO NIBBLES ENTERED
            LD A,B              ;INPUT KEY VALUE BACK IN A
            JR NZ,L0132         ;JUMP IF NOT READY FOR AUTO INC
            PUSH AF             ;SAVE MCB
            LD A,(L0827)        ;TEST AUTO INC MASK
            OR A                ;IF NOT ZERO THEN JUMP AS USER
            JR NZ,L012F         ;HAS SWITCHED OFF AUTO INC MODE
            INC HL              ;ELSE INCREMENT CEL BEFORE ENTERING
            LD (L082E),HL       ;NEW NIBBLE AND STORE NEW CEL
L012F       POP AF              ;RECOVER MON CONTROL BYTE IN A
            AND 0xFC            ;CLEAR BYTE COUNTER (BITS 0 AND 1)
L0132       INC A               ;ADD ONE TO NIBBLE COUNTER
            LD  (L082B),A       ;STORE IT
            LD A, (L0820)       ;GET INPUT KEY FROM INPUT BUFFER
            JR L014C            ;JUMP TO ENTER IT

;TEST HERE FOR A CONTROL KEY WHILE IN EITHER THE ADDRESS OR FUNCTION MODE AND JUMP TO 
;ENCODE THE FUNCTION NUMBER BITS (2 AND 3 OF MCB). IF NOT A CONTROL KEY, THEN TEST FOR 
;THE FUNCTION MODE AND JUMP TO FUNCTION JUMP CONTROL IF SO, ELSE SERVICE DATA KEY FOR 
;ADDRESS MODE.

L013B       LD A,(L0820)        ;GET INPUT KEY FROM INPUT BUFFER 
            BIT 4,A             ;TEST FOR CONTROL KEY (+,- OR GO) 
            JR NZ,L0171         ;JUMP IF CONTROL TO FUNCTION ENCODER 
            BIT 5,B             ;TEST FUNCTION MODE
            JR NZ,L0150         ;JUMP IF SO TO FUNCTION JUMP CONTROL

;DATA KEY PRESS WHILE IN THE ADDRESS MODE

            LD HL,L082E         ;POINT HL TO CEL BUFFER
            RLD                 ;AND SHIFT IN THE NEW NIBBLE
            INC HL              ;AND MOVE THE OTHERS ACROSS
L014C       RLD                 ;THIS RLD USED BY DATA MODE ALSO
L014E       JR L00E1            ;JUMP (VIA A JUMP) TO UP-DATE DISPLAYS

;FUNCTION AND SHIFT JUMP CONTROL
;BITS 2 AND 3 OF THE MONITOR CONTROL BYTE (MCB) ARE THE FUNCTION IDENTIFIER BITS.
;IF BOTH ARE ZERO THEN EITHER FUNCTION 1 IS SELECTED OR NO FUNCTION IS SELECTED. BECAUSE 
;THIS IS THE ALSO THE NO FUNCTION MODE ENABLED STATE, THE SHIFT KEY, WHICH DOES NOT AFFECT 
;THE MONITOR CONTROL BYTE, WILL ALSO WILL INVOKE FUNCTION 1. (THEREFORE THIS ROUTINE DOES 
;NOT NEED TO TEST FOR THE SHIFT KEY).
;IF BIT 2 IS HIGH THEN FUNCTION 2 IS SELECTED AND IF BIT 3 IS HIGH THEN FUNCTION 3 IS 
;SELECTED.
;DURING THIS ROUTINE, HL IS LOADED TO THE BASE OF THE REQUIRED JUMP TABLE MINUS TWO BYTES 
; (ONE ENTRY). THIS IS BECAUSE THE OFFSET PROVIDED FROM THE KEYBOARD HAS BEEN INCREMENTED 
;BY ONE. THIS SAVES TESTING FOR ZERO INPUT WHICH WOULD NOT ALLOW THE TABLE ACCESSING TO 
;WORK CORRECTLY. THE REQUIRED BASE IS FOUND BY EXAMINING THE STATE OF THE BITS 2 AND 3 OF 
;THE MONITOR CONTROL BYTE (MCB) AND LOADING HL, ACCORDINGLY.
;AS EACH ENTRY IS TWO BYTES LONG, THE TABLE POINTER (THE VALUE INSIDE HL), IS INCREMENTED 
;TWICE FOR EACH DECREMENT OF THE INPUT VALUE (FROM THE KEYBOARD). WHEN THE REQUIRED TABLE
;ENTRY IS FOUND, 17 IS PUT' INSIDE EL (VIA_ DE) AND THE ROUTINE JUMPS TO PART OF THE "GO"
;KEY ROUTINE TO CREATE A RETURN ADDRESS ON THE STACK AND EXECUTE THE SELECTED ROUTINE.

L0150       LD A,B              ;PUT MONITOR CONTROL BYTE IN A
            AND 0x0C            ;MASK IT DOWN TO FUNCTION BITS
            LD HL,07DEH         ;JMON FUNCTION JUMP TABLE BASE -2
            JR Z,L0162          ;JUMP IF FUNCTION 1 OR SHIFT
            LD HL,L08BE         ;LOAD HL WITH USER TABLE -2
            CP 0x04             ;TEST FOR FUNCTION 2
            JR Z,L0162          ;JUMP IF FUNCTION 2 (USER FUNCTION)
            LD HL,0x381E        ;OTHERWISE MUST BE FUNCTION 3
L0162       LD A,(L0820)        ;GET INPUT KEY FROM INPUT BUFFER
            INC A               ;ADD ONE IN CASE IT WAS ZERO
            LD B,A              ;PUT IN B TO USE AS A LOOP COUNTER
L0167       INC HL              ;LOOK THROUGH TABLE
            INC HL              ;FOR RIGHT JUMP VECTOR
            DJNZ L0167
            LD E,(HL)           ;PUT IT IN HL
            INC HL              ;VIA DE
            LD D,(HL)
            EX DE,HL            ;JUMP TO CREATE RETURN ADDRESS AND
            JR L00FD            ;EXECUTE SELECTED ROUTINE

;FUNCTION NUMBER ENCODER
;THIS SECTION ENCODES THE FUNCTION IDENTIFIER BITS (BITS 2 AND 3) IN THE MONITOR CONTROL 
;BYTE (BITS 2 AND 3) THEN SETS THE FUNCTION ENABLE BIT (BIT 5).
;THE FUNCTION IDENTIFIER BITS ARE DERIVED FROM THE LEAST TWO SIGNIFICANT BITS OF THE INPUT 
;CONTROL KEY (+, AND GO). THESE ARE SHIFTED LEFT TWICE TO ALIGN THEM TO THE FUNCTION 
;SELECT BITS (BITS 2 AND 3) IN THE MCB. THE INPUT CONTROL KEY IS IN THE ACCUMULATOR ON 
;ENTRY AND THE MONITOR CONTROL BYTE (MCB) IN B.

L0171       AND 0x03            ;MASK DOWN CONTROL KEY
            RLCA                ;SHIFT IT LEFT TWICE TO ALIGN BITS 0
            RLCA                ;AND 1 TO FUNCTION IDENTITY BITS IN MCB
            OR 0x20             ;SET FUNCTION MODE ENABLED FLAG
            LD C,A              ;SAVE IN C
            LD A,B              ;GET CURRENT MCB
            AND 0xD3            ;CLEAR ANY PREVIOUS FUNCTION BITS
            OR C                ;MERGE TOGETHER
            LD (L082B),A        ;STORE MCB
            JR L014E            ;JUMP VIA JUMPS TO UP-DATE DISPLAYS

;THIS IS THE SCAN/KEY/LCD/PATCH ROUTINE. THIS ROUTINE LOOPS SCANNING THE LED DISPLAY AND 
;SERVICING THE "DURING LOOP" USER PATCH UNTIL A KEY PRESS IS VALIDATED BY THE AUTO-KEY 
;REPEAT SECTION. THE INPUT KEY IS RETURNED IN THE ACCUMULATOR AND IN THE INPUT BUFFER AT 
;0820 WITH THE ZERO FLAG SET AND CARRY CLEARED.
;THREE PATCHES ARE SUPPORTED IN THIS ROUTINE. THEY ARE A PATCH BEFORE LOOP, A PATCH DURING 
;THE LOOP AND A PATCH AFTER A VALID KEY PRESS.
;THE "PLANT" IS A VALUE INSERTED INTO THE INPUT BUFFER (0820) BY THE DURING LOOP PATCH. 
;THE "PLANT" VALUE IS IDENTIFIED BY BIT 7 OF THE INPUT BUFFER BEING SET. BIT 7 IS RESET 
;BEFORE RETURNING TO SERVICE THE PLANT.
;THIS ROUTINE USES A BYTE AT 082A, CALLED THE AUTO KEY STATUS BYTE AS A FLAG AND TIMER 
;TO GENERATE THE AUTO REPEAT DELAY.

L0181       CALL L0848          ;CALL LCD ROUTINES
            CALL L084B          ;CALL PRE-SCAN USER PATCH
L0187       CALL L0836          ;CALL SCAN
            CALL L084E          ;CALL USER "DURING LOOP" PATCH
            LD HL,L0820         ;TEST KEY INPUT BUFFER BIT 7 FOR A
            BIT 7,(HL)          ;"PLANT" INSERTED BY USER DURING
            RES 7,(HL)          ;PATCH: RESET BIT 7 RETURN TO
            RET NZ              ;SERVICE "PLANT" IF BIT 7 NOT ZERO
            RST 20H             ;TEST FOR KEY PRESS VIA RST 20
            LD HL,L082A         ;SET HL TO POINT TO AUTO KEY STATUS
            JR C,L019F          ;JUMP IF A KEY IS PRESSED
            LD (HL),0x0080      ;ELSE SET AUTO KEY STATUS TO
            JR L0187            ;NO KEY STATE AND CONTINUE LOOP
L019F       CALL L06CA          ;CALL UNIVERSAL KEY INPUTTER
            BIT 7, (HL)         ;TEST AUTO KEY STATUS FOR FIRST KEY
            JR NZ,L01B6         ;JUMP IF SO TO SET LONG KEY DELAY
            DEC (HL)            ;ELSE COUNT DOWN KEY DELAY
            JR NZ,L0187         ;LOOP IF NOT READY FOR KEY REPEAT
            LD (HL),0x0C        ;ELSE SET SHORT TIME DELAY BETWEEN
L01AB       CALL L0851          ;KEYS: CALL USER "AFTER KEY" PATCH
            CALL L083F          ;CALL KEY TONE
            XOR A               ;SET ZERO FLAG AND CLEAR CARRY
            LD A, (L0820)       ;PUT INPUT KEY IN A
            RET                 ;AND RETURN FOR KEY SERVICE
L01B6       LD  (HL),0x0070     ;SET KEY TIMER FOR LONG DELAY 
            JR L01AB            ;JUMP TO SERVICE PATCH, TONE ETC.

;THIS IS THE LED SCAN ROUTINE.

L01BA       LD B,20H            ;B IS THE SCAN BIT
            LD HL,(L082C)       ;GET ADDRESS OF DISPLAY BUFFER
L01BF       LD A,(HL)           ;GET FIRST BYTE
            OUT  (DSEGMENT),A   ;AND OUTPUT IT TO SEGMENTS
            LD A,B              ;GET SCAN BIT
            OUT  (DSCAN),A      ;OUTPUT IT TO COMMONS
            LD B,40H            ;CREATE SHORT
L01C7       DJNZ L01C7          ;DELAY IN B
            INC HL              ;INCREASE HL TO NEXT DISPLAY BYTE
            LD  B,A             ;GET SCAN BIT BACK IN B
            XOR A               ;CLEAR THE LAST PORT OUTPUTTED TO
            OUT (DSCAN),A       ;TO PREVENT "GHOSTING"
            RRC B               ;SHIFT SCAN BIT ACROSS TO NEXT 
            JR NC,L01BF         ;COMMON: WHEN SCAN BIT FALLS INTO 
            OUT (DSEGMENT),A    ;CARRY SCAN IS TERMINATED: CLEAR 
            RET                 ;PORT 2 AND RETURN

;THIS ROUTINE CONVERTS HL TO DISPLAY CODE AND STORE THE DISPLAY CODE IN A BUFFER POINTED 
;TO BY BC.

L01D5       LD A,H              ;PUT H IN A
            CALL L0833          ;CONVERT A TO DISPLAY CODE 
            LD A,L              ;NOW DO FOR L

;THIS SECTION CONVERTS THE BYTE IN A TO TWO DISPLAY BYTES.

L01DA       PUSH AF             ;SAVE A
            RLCA                ;SHIFT MSN TO LSN PLACE
            RLCA                ;FOR NIBBLE AT A TIME CONVERSION
            RLCA
            RLCA
            CALL L01E3          ;CONVERT FIRST NIBBLE
            POP AF              ;RECOVER A TO CONVERT SECOND NIBBLE
L01E3       AND 0x0F            ;MASK OF HIGH NIBBLE
            LD DE,07D0H         ;SET DE TO BASE OF CONVERSION
            ADD A,E             ;TABLE: ADD A TO BASE
            LD E,A              ;UPDATE POINTER
            LD A,(DE)           ;GET DISPLAY CODE
            LD (BC),A           ;STORE IN DISPLAY BUFFER
            INC BC              ;INCREMENT DISPLAY BUFFER POINTER
            RET                 ;NIBBLE CONVERSION DONE

;SET DOTS
;THIS ROUTINE SETS THE DOTS IN THE DISPLAY BUFFER. IF IN ADDRESS MODE THEN 4 DOTS ARE SET 
;IN THE ADDRESS DISPLAY BUFFER, IF IN A FUNCTION MODE, THEN ONE DOT IN THE ADDRESS DISPLAY 
;- RIGHT MOST FOR FUNCTION 1 SECOND RIGHT FOR FUNCTION 2 AND THIRD RIGHT FOR FUNCTION 3.
;IF IN THE DATA MODE THEN 2 DOTS IN THE DATA DISPLAY BUFFER OR ONE DOT, ON THE RIGHTMOST 
;DISPLAY, IF TWO NIBBLES HAVE BEEN ENTERED AND IN THE AUTO-INCREMENT MODE.

L01EE       LD B,0x02           ;SET B FOR 2 DOTS
            LD HL,(L082C)       ;PUT DISPLAY BUFFER IN HL
            LD A, (L082B)       ;GET MONITOR CONTROL BYTE (MCB)
            BIT 4,A             ;TEST FOR ADDRESS OR FUNCTION MODE
            JR Z,L0214          ;JUMP IF NOT TO DO DATA DOTS
            BIT 5,A             ;TEST ONLY FOR FUNCTION MODE
            JR NZ,L0206         ;JUMP IF FUNCTION MODE
            LD B,4              ;ADDRESS MODE SO SET B FOR 4 DOTS
L0200       SET 7,(HL)          ;SET DOT IN DISPLAY BUFFER
            INC HL              ;NEXT LOCATION
            DJNZ L0200          ;DO 4 TIMES
            RET                 ;DONE
L0206       DEC B               ;FUNCTION MODE: SET B FOR ONE DOT
            BIT 3,A             ;TEST FOR FUNCTION 3
            JR NZ,L0211         ;JUMP IF FUNCTION 3 TO ADD HL+1
            BIT 2,A             ;TEST FOR FUNCTION 2
            JR NZ,L0210         ;JUMP IF FUNCTION 2 TO ADD HL+2
L020F       INC HL              ;INCREMENT HL TO POINT TO THE
L0210       INC HL              ;REQUIRED DISPLAY BYTE
L0211       INC HL              ;
            JR  L0200           ;JUMP TO SET DOT
L0214       INC   HL            ;DATA MODE: HL NOW POINTS TO SECOND 
            LD  C,A             ;LEFT MOST DISPLAY BUFFER: SAVE MCB 
            LD  A,(L0827)       ;IN C: TEST AUTO INCREMENT ENABLE 
            OR  A               ;FLAG
            JR  NZ,L020F        ;JUMP IF NO AUTO INCREMENT TO SET BOTH 
            BIT 1,C             ;DATA DOTS: TEST BYTE COUNTER FOR 2 
            JR  Z,L020F         ;NIBBLES: JUMP IF NOT TO SET BOTH DATA 
            INC   HL            ;DOTS: ELSE SKIP DOT ON ONE DISPLAY 
            DEC   B             ;AND DECREASE DOT COUNT FROM 2 TO 1 
            JR  L020F           ;JUMP TO ADJUST HL AND SET DOTS

;MASKABLE RESET TONE ROUTINE
;IF 0822 IS NOT ZERO THEN NO TONE

L0224       CALL L083F          ;CALL TONE

;MASKABLE TONE ROUTINE

L0227       LD A, (L0822)       ;TEST SOUND MASK
            OR A
            RET NZ              ;NO TONE IF NOT ZERO
            LD C,0x40           ;LOAD C WITH PERIOD
            LD L,0x31           ;LOAD L WITH NUMBER OF CYCLES 
            XOR A               ;CLEAR A
L0231       OUT (DSCAN),A       ;OUT TO SPEAKER
            LD B,C
L0234       DJNZ L0234          ;DELAY FOR PERIOD
            XOR 0x80            ;TOGGLE SPEAKER BIT 
            DEC L               ;DECREMENT CYCLE COUNT 
            JR NZ,L0231         ;LOOP UNTIL ZERO
            RET                 ;DONE

;LCD ROUTINE
;IF 0821 IS NOT ZERO, THEN LCD HAS BEEN MASKED OFF BY EITHER THE USER OR THE LCD 
;INTIALIZER/TESTER ROUTINE AND NO ACTION IS TAKEN ON THE LCD. THE RST 30 (F7) IS USED 
;EXTENSIVELY TO TEST AND WAIT FOR THE LCD BUSY FLAG. THROUGHOUT THESE NOTES, THE INVISIBLE
;INTERNAL CURSOR ON THE LCD IS REFERRED TO AS THE CURSOR, WHILE THE ">" ON THE LCD IS
;REFERRED TO AS THE PROMPT.

L023C       LD A,(L0821)        ;TEST LCD MASK
            OR A
            RET NZ              ;NOT ZERO = LCD NOT REQUIRED OR FITTED
            LD A,0x80           ;SET LCD CURSOR TO HOME
            OUT (LCDINST),A
            RST 30H             ;WAIT UNTIL LCD READY
            CALL L0253          ;CALL SET-UP AND OUTPUT FIRST LINE
            LD A,0xC0           ;SET CURSOR TO BOTTOM LINE
            OUT (LCDINST),A
            RST 30H             ;WAIT
            CALL L025A          ;CALL ROUTINE TO OUTPUT BOTTOM LINE
            JR L0286            ;JUMP TO PROMPT ROUTINE

;SET-UP
;MODIFY CURRENT EDIT LOCATION ADDRESS IN HL SO THAT IT POINTS TO A BYTE AT AN ADDRESS 
;ENDING IN EITHER 0 OR 8.

L0253       LD HL,(L082E)       ;GET CEL AND PUT LOW BYTE IN A
            LD A,L              ;THEN MASK OFF THE 3 LOWEST BITS
            AND 0xF8            ;AS THE ADDR OF THE FIRST BYTE ON
            LD L,A              ;THE LCD WILL END WITH 0 OR 8

;OUTPUT A LINE

L025A       CALL  L026C         ;CALL "HI TO ASCII OUTPUT"
            LD    B,04          ;SET B FOR 4 BYTES ON A LINE
L025F       LD    A,0x20        ;LOAD A WITH ASCII SPACE
            OUT   (LCDDATA),A   ;CHARATER AND OUTPUT IT
            RST   30H           ;WAIT
            LD    A,(HL)        ;GET BYTE TO DISPLAY
            CALL  L0271         ;CONVERT AND OUTPUT IT
            INC HL              ;POINT TO NEXT BYTE
            DJNZ L025F          ;DO FOR 4 BYTES
            RET                 ;DONE

;CONVERT HL TO ASCII (VIA CONVERT A) AND OUTPUT IT

L026C       LD A,H              ;CONVERT AND
            CALL L0271          ;OUTPUT H
            LD A,L              ;THEN L

;CONVERT A TO ASCII AND OUTPUT IT

L0271       PUSH AF             ;SAVE A FOR SECOND NIBBLE 
            RRCA                ;SHIFT HIGH NIBBLE ACROSS
            RRCA                ;
            RRCA                ;
            RRCA                ;
            CALL L027A          ;CALL NIBBLE CONVERTER 
            POP AF              ;RECOVER LOW NIBBLE
L027A       AND 0x0F            ;MASK OFF HIGH NIBBLE 
            ADD A,0x90          ;CONVERT TO
            DAA                 ;ASCII
            ADC A,0x40          ;USING THIS 
            DAA                 ;AMAZING ROUTINE
L0282       OUT (LCDDATA),A     ;OUTPUT IT 
            RST 30H             ;WAIT
            RET                 ;DONE

;LCD PROMPT AND MODE WORD OUTPUT
;THE 3 LOWEST BITS OF THE CURRENT EDIT LOCATION (CEL) ARE USED AS A DISPLACEMENT WHICH IS 
;ADDED TO A TABLE BASE. THE TABLE ENTRIES ARE THE LCD ADDRESSES OF THE PROMPT LOCATIONS. 
;IF THE AUTO INCREMENT MODE IS ON AND 2 NIBBLES HAVE BEEN ENTERED, THE DISPLACEMENT IS 
;INCREMENTED SO THAT THE NEXT PROMPT ADDRESS TABLE ENTRY WILL BE ACCESSED TO MOVE THE 
;PROMPT TO ITS NEXT SCREEN LOCATION. THE TABLE IS 9 ENTRIES LONG. 8 ARE FOR THE SPACES 
;BETWEEN THE DATA BYTES AND THE NINTH IS TO PARK THE PROMPT AT THE TOP LEFT-HAND CORNER 
;WHEN A SCREEN CHANGE IS DUE

L0286       LD A,(L082E)        ;GET LOW BYTE OF CEL
            AND 0x07            ;MASK IT DOWN TO THE 3 LOWEST BITS
            LD C,A              ;SAVE IN C
            LD A,(L0827)        ;TEST FOR AUTO INCREMENT MODE
            OR A                ;O=ON
            LD A,(L082B)        ;GET MCB
            LD D,A              ;PUT MCB IN D
            JR NZ,L029B         ;JUMP IF AUTO INCREMENT MODE OFF
            BIT 1,A             ;TEST FOR 2 NIBBLES ENTERED: JUMP
            JR Z,L029B          ;IF NOT: ELSE INCREMENT
            INC C               ;DISPLACEMENT TO ADVANCE TO
L029B       LD  A,C             ;NEXT PROMPT LOCATION ADDRESS
            LD HL,0x07BD        ;LOAD HL WITH BASE OF PROMPT
            ADD A,L             ;TABLE AND ADD DISPLACEMENT
            LD L,A              ;PUT LOW BYTE OF TABLE ADDRESS
            LD A,(HL)           ;IN L AND GET PROMPT ADDRESS IN A
            OUT (LCDINST),A     ;AND OUTPUT PROMPT ADDRESS TO LCD
            RST 30H             ;WAIT
            LD A,0x3E           ;LOAD A WITH ASCII FOR ">"
            OUT (LCDDATA),A     ;OUTPUT PROMPT
            RST 30H             ;WAIT

;OUTPUT MODE WORD TO BOTTOM LEFT CORNER OF THE LCD.
;IF THE MODE IS EITHER DATA OR ADDR, THEN THE FOUR ASCII BYTES ARE OUTPUTTED. IF IN THE 
;FUNCTION MODE, THEN ONLY THREE BYTES FROM THE TABLE ARE OUTPUTTED AND THEN THE FUNCTION 
;NUMBER IS CALCULATED AND OUTPUTTED.
;NOTICE THAT FROM THE TABLE BASE THE FIRST ENTRY (DATA) HAS A ZERO DISPLACEMENT WHILE THE 
;SECOND (ADDR) HAS A DISPLACEMENT OF 4 AND THE THIRD (Fs-) HAS A DISPLACEMENT OF 12.
;IF YOU LOOK AT THE TABLE AT 07AD, YOU WILL SEE THAT IT IS STAGGERED WITH THE THIRD ENTRY 
;12 BYTES AWAY FROM THE BASE.

            LD A,0xC0           ;SET CURSOR TO BOTTOM LINE
            OUT (LCDINST),A     ;OUTPUT
            RST 30H             ;AND WAIT
            LD A,D              ;PUT MONITOR CONTROL BYTE (MCB) IN A 
            RRCA                ;SHIFT MODE BITS TO BITS 2 AND 3
            RRCA                ;TO USE AS TABLE DISPLACEMENT 
            LD D,A              ;SAVE IN D AND MASK OFF ALL BITS
            AND 0x0C            ;EXCEPT THE 2 THAT FLAG BETWEEN DATA, 
            LD HL,L07AD         ;ADDR AND FUNCTION: A=0 IF DATA, 4 IF 
            ADD A,L             ;ADDR, 12 IF FUNCTION, NOTE THAT TABLE 
            LD L,A              ;IS STAGGERED (SEE 07AD): ADD A TO BASE 
            CP 0xB9             ;IF A=B9 THEN MODE IS FUNCTION MODE 
            LD  BC,0x0400+LCDDATA   ;LOAD C WITH PORT, B WITH BYTE COUNT
            JR Z,L02C7          ;JUMP IF FUNCTION MDDE TO OUT 3 BYTES 
L02C1       OUTI                ;OUT (HL) TO (C) B=B-1
            RST 30H             ;HL=HL+1: WAIT FOR LCD BUSY FLAG 
            JR NZ,L02C1         ;LOOP UNTIL B=0
            RET                 ;DONE
L02C7       LD B,0x03           ;ONLY THREE BYTES FOR FUNCTION MODE 
            CALL L02C1          ;CALL THE OUTPUT ROUTINE ABOVE
            LD A,D              ;PUT MCB (SHIFTED RIGHT TWICE) IN A 
            AND 0x03            ;MASK IT DOWN TO GET JUST THE FUNCTION 
            ADD A,0x31          ;NUMBER BITS: ADD ASCII "1"
            JR L0282            ;JUMP TO OUTPUT FUNCTION NUMBER

;-END OF MONITOR ROUTINES- (EXCEPT KEYBOARD READER AT 06AD)

;LCD PROMPT MOVING ROUTINES. (SHIFT AND FUNCTION 1)
;THESE ROUTINES ALTER THE CURRENT EDIT LOCATION ADDRESS AND STORE IT IN ITS BUFFER. WHEN 
;THE RETURN IS DONE, JMON IS RE-ENTERED AT 00132 (VIA THE SOFT RE-ENTRY JUMP AT 0845, THE 
;ADDRESS OF WHICH HAS BEEN PLACED ON THE STACK BY PART OF THE "GO" ROUTINE).

L02D3       LD DE,0x0004        ;DE= +4
L02D6       LD HL,(L082E)       ;PUT CEL IN HL
            ADD HL,DE           ;ADD TO GET NEW CEL
            LD (L082E),HL       ;STORE IN CEL BUFFER
            RET                 ;DONE
L02DE       LD DE,0xFFFC        ;DE= -4
            JR L02D6            ;JUMP TO ADD
L02E3       LD DE,0xFFFF        ;DE= -1
            JR L02D6            ;JUMP TO ADD
L02E8       LD DE,0x0001        ;DE= +1
            JR L02D6            ;JUMP TO ADD
L02ED       LD DE,0x0008        ;DE++8
            JR L02D6            ;JUMP TO ADD
L02F2       LD DE,0xFFF8        ;DE= -8
            JR L02D6            ;JUMP TO ADD

;RESET PATCH CHECKER.
;TESTS FOR PATCH REQUIREMENT AND UP TO THE FIRST 256 BYTES OF THE PATCH ROUTINE. THE 
;CHECKSUM FEATURE ENSURES A WAY TO CHECK THAT THE PATCH OR PATCH VARIABLES HAVE NOT BEEN 
;CORRUPTED BY A SYSTEM CRASH, OTHERWISE YOU MAY NEVER REGAIN CONTROL OF THE COMPUTER UNLESS 
;YOU TURN IT OFF, (AND LOSE THE CONTENTS OF YOUR MEMORY - YOU CANNOT RECOVER IT BY A FORCED 
;HARD RESET AS THE USER PATCH IS EXECUTED BEFORE THE FORCED HARD RESET TEST). (A FORCED 
;HARD RESET IS WHEN A KEY IS HELD DOWN WHEN THE RESET KEY IS RELEASED).
;IF YOU HAVE A NON VOLATILE MEMORY AT 0800 THE SITUATION WOULD BE ABSOLUTELY HOPELESS 
;WITHOUT THIS CHECKER ROUTINE.
;A VARIABLE CAN BE PASSED TO YOUR PATCH ROUTINE IN THE "C" REGISTER. TO DO THIS THE VARIABLE 
;IS PLACED AT ADDRESS LOCATION 08B3.

L02F7       LD A,(L08B0)        ;TEST FOR RESET PATCH REQUIRED
            CP 0xAA
            RET NZ              ;RETURN IF NOT
            LD BC,(L08B3)       ;PUT NO OF BYTES IN B VARIABLE IN C 
            LD HL, (L08B1)      ;START IN HL
            XOR A               ;CLEAR A
L0305       ADD A, (HL)         ;ADD CHECKSUM
            INC HL 
            DJNZ L0305          ;UNTIL B=0
            LD HL,L08B5         ;POINT TO REQUIRED CHECKSUM 
            CP (HL)             ;TEST FOR EQUAL
            RET NZ              ;ABORT IF NOT
            LD HL,(L08B6)       ;ELSE GET START ADDR
            JP (HL)             ;AND DO RESET PATCH

;STEPPER ROUTINE
;THE STEPPER ROUTINE IS BROKEN UP INTO SEVERAL SECTIONS. THE FIRST IS THE REGISTER SAVE, 
;WHERE ALL THE Z80 USER REGISTERS ARE STORED IN MEMORY.

L0312       LD (L0870),HL       ;STORE HL IN ITS REGISTER STACK SPOT
            LD HL,L0344         ;LOAD HL WITH RETURN ADDRESS

;MONITOR JUMPS TO HERE ON RESET TO PRESERVE USER REGISTERS.

L0318       LD (L0860),HL       ;STORE RE-ENTRY ADDRESS IN BUFFER 
            LD HL,(L0858)       ;GET ADDRESS OF INSTRUCTION JUST 
            LD (L0868),HL       ;STEPPED AND PUT IT IN "NEXT PC" 
            LD (L087E),SP       ;BUFFER: SAVE STACK POINTER VALUE 
            POP HL              ;GET RETURN ADDR, THIS IS THE ADDRESS
            LD (L0858),HL       ;OF NEXT BYTE TO STEP: STORE IN
            LD SP,L087E         ;"NEXT PC" BUFFER: LOAD REGISTER DUMP
            EX AF,AF'          ;STACK: PUSH ALTERNATE REGISTERS
            EXX                 ;FIRST
            PUSH HL             ;SAVE ALL REGISTERS
            PUSH DE
            PUSH BC
            PUSH AF
            PUSH IY
            PUSH IX
            EX AF,AF'
            EXX
            DEC SP
            DEC SP
            PUSH DE
            PUSH BC
            PUSH AF
            LD HL,(L0860)       ;RE-ENTER CALLING ROUTINE VIA
            JP (HL)             ;THE ADDRESS IT SUPPLIED AT 0860
L0341       LD SP,L086A         ;SHIFT 7 ROUTINE START (REG DISPLAY)

;THE REGISTERS HAVE BEEN SAVED. NOW THE DISPLAY AND KEYBOARD HANDLER IS SET UP. THE STACK 
;IS DECREMENTED BY TWO TO POINT TO THE "PC" BUFFER. THE ADDRESS IN THE "PC" BUFFER IS THE 
;ADDRESS OF THE INSTRUCTION JUST STEPPED.
;THE NUMBER OF THE FIRST REGISTER (1 FOR "PC") IS PUT INTO THE CURRENT REGISTER NUMBER 
;BUFFER.

L0344       LD HL,L0806         ;CREATE NEW DISPLAY BUFFER
            LD (L082C),HL       ;
            DEC SP              ;DECREASE SP BY 2 TO POINT TO THE
            DEC SP              ;"PC" BUFFER

;WHEN UP-DATING THE DISPLAY, THE ROUTINE MAY JUMP BACK TO HERE IF THE FIRST DISPLAY IS 
;REQUIRED.

L034C       LD A,0x01           ;SET UP FOR THE FIRST REGISTER (PC)
            LD (L085A),A        ;DISPLAY

;OR HERE IF IT HAS ALTERED THE CURRENT REGISTER NUMBER IN ITS STORAGE LOCATION (085A). 

L0351       LD A,(L085A)        ;DISPLAY LOOP STARTS HERE

;HL IS LOADED WITH THE STACK POINTER VALUE, (WHICH POINTS TO THE "PC" BUFFER), MINUS TWO. 
;THE TWO IS SUBTRACTED BECAUSE AN EXTRA TWO WILL BE ADDED TO HL DURING THE REGISTER BUFFER 
;CALCULATOR (IMMEDIATELY BELOW) AS THE NUMBER OF THE FIRST REGISTER IS 1 AND NOT ZERO.

            LD HL,0xFFFE        ;HL=-2
            ADD HL, SP          ;HL=SP-2
L0358       INC HL              ;INCREMENT HL TO POINT TO THE
            INC HL              ;CURRENT REGISTER BUFFER
            DEC A               ;INDICATED BY THE NUMBER IN A
            JR NZ,L0358

;HL NOW POINTS TO THE CURRENT REGISTER BUFFER. THIS SECTION PUTS THE REGISTER(S) CONTENT(S) 
;INTO HL AND CONVERTS IT TO DISPLAY CODE AND STORE THE DISPLAY CODE IN THE DISPLAY BUFFER.

            LD A,(HL)           ;GET 16 BIT VALUE
            INC HL              ;AND PUT IT
            LD H,(HL)           ;BACK INTO
            LD L,A              ;HL
            LD BC,(L082C)       ;PUT DISPLAY BUFFER ADDRESS IN BC 
            CALL L0830          ;CALL HL TO DISPLAY CODE ROUTINE

;THIS SECTION CALCULATES THE ADDRESS OF THE REGISTER NAME FOR THE DATA DISPLAYS. THESE 
;ARE STORED IN A TABLE. THE REQUIRED REGISTER NAME IS THEN TRANSFERRED TO THE DISPLAY
;BUFFER.

            LD A,(L085A)        ;GET REGISTER NUMBER
            PUSH BC             ;PUT NEXT DISPLAY BUFFER
            POP DE              ;LOCATION INTO DE(stination)
            LD BC,0x0002        ;BC IS THE NUMBER OF DATA DISPLAYS
;       LD HL,0x0792    ;HL=THE BASE OF THE NAME TABLE
            LD HL,L0794-2
L0373       ADD HL,BC           ;ADD TO HL 2 FOR EACH
            DEC A               ;REGISTER NUMBER TO ACCESS THE
            JR NZ,L0373         ;CURRENT REGISTER NAME
            LDIR                ;MOVE REGISTER NAEL INTO LAM
;THE SCAN AND KEYBOARD ROUTINE ARE NOW CALLED (VIA THE RST 18). IF A VALID KEY IS PRESSED, 
;THEN THE ZERO FLAG IS SET WHEN THE RST RETURNS.

L0379       RST 18H             ;SCAN/KEY READ RST
            LD HL,L0824         ;(HL)=AUTO STEP CONTROL/TIMER BYTE
            JR Z,L038A          ;JUMP IF VALID KEY PRESSED

;NO KEY IS PRESSED SO THE ROUTINE CHECKS FOR THE AUTO REPEAT MODE ENABLED FLAG (BIT 7 AUTO 
;STEP CONTROL/TIMER BYTE, ZERO IS AUTO STEP ENABLED) AND DECREMENTS THE COUNTER IF IT IS. 
;IF THE COUNTER REACHES ZERO, THEN IT IS RELOADED AND THE ROUTINE JUMPS TO RECOVER THE 
;REGISTERS AND STEP THE NEXT INSTRUCTION. IF NOT IN THE AUTO MODE OR THE COUNTER DOES NOT 
;REACH ZERO, THEN THE ROUTINE LOOPS BACK TO SCAN THE DISPLAY AND WAIT FOR EITHER A KEY 
;PRESS OR FOR THE COUNTER TO REACH ZERO.

            BIT 7,(HL)          ;TEST FOR AUTO INCREMENT JUMP IF NOT
            JR NZ,L0379         ;ENABLED TO SCAN/KEY READ LOOP
            DEC (HL)            ;DECREMENT COUNTER: LOOP TO
            JR NZ,L0379         ;SCAN/KEY READ UNTIL COUNT=0

;AT THIS POINT THE AUTO-STEP DELAY HAS REACHED ZERO AND IS RELOADED WITH THE DELAY VALUE. 
;A JUMP IS THEN DONE TO RECOVER THE REGISTERS AND STEP THE NEXT INSTRUCTION.
            LD (HL),0x0030      ;RESET AUTO STEP DELAY, JUMP TO RECOVER
            JR L03AC            ;REGISTERS AND STEP NEXT INSTRUCTION

;KEY PROCESSING STARTS HERE
;THE AUTO-STEP IS DISABLED AND THEN THE KEY IS IDENTIFIED AND HANDLED. 
;THE AUTO-STEP WILL BE RE-ENABLED IF THE KEY PRESSED IS A DATA KEY.

L038A       LD B,A              ;SAVE KEY
            LD (HL),0x00FF      ;SET AUTO STEP CONTROL/TIMER BIT 7
            LD HL,L085A         ;THUS DISABLING THE AUTO REPEAT MODE
            LD A,B              ;POINT HI, TO CURRENT REG No. BUFFER
            CP PLUS_KEY         ;***PUT INPUT IN A,TEST IT FOR "+"
            JR NZ,L039D         ;JUMP IF NOT TO TEST FOR "-"

;"+" KEY HANDLER
;THE CURRENT REGISTER NUMBER IS INCREMENTED AND THEN CHECK TO SEE THAT IT HAS NOT EXCEEDED 
;THE HIGHEST REGISTER NUMBER (OC). IF IT HAS, THE ROUTINE JUMPS TO RESET THE CURRENT 
;REGISTER NUMBER WITH 1, OTHERWISE IT JUMPS TO THE DISPLAY LOOP.

            INC (HL)            ;INCREMENT REGISTER NUMBER
            LD A,(HL)           ;AND CHECK TO SEE IF IT LARGER
            CP 0x0D             ;THAN HIGHEST REG No. (0C): IF LOWER
            JR C,L0351          ;THAN OD JUMP TO DISPLAY LOOP ELSE
            JR L034C            ;JUMP TO SET REGISTER NUMBER TO 1
L039D       CP MINUS_KEY        ;***TEST FOR "-"
            JR NZ,L03A8         ;JUMP IF NOT

;"-" HANDLER
;ONE IS TAKEN FROM THE CURRENT REGISTER NUMBER AND THEN IT IS CHECKED FOR ZERO. IF IT 
;BECOMES ZERO, THEN THE CURRENT REGISTER NUMBER IS SET TO THE HIGHEST REGISTER NUMBER (OC) 
;TO WRAP-AROUND TO DISPLAY THE LAST REGISTER.
            DEC (HL)            ;SUBTRACT 1 FROM REGISTER NUMBER
            JR NZ,L0351         ;JUMP IF NOT 0 TO UP-DATE DISPLAY
            LD (HL),0x0C        ;ELSE SET TO LAST REGISTER
            JR L0351            ;AND UP-DATE

;TEST FOR "GO"

L03A8       CP GO_KEY           ;***TEST FOR "GO" AND JUMP IF NOT 
            JR NZ,L03C6         ;TO TEST FOR "AD" OR DATA KEY

;"GO" KEY
;THE GO KEY CAUSES STEPPING EXECUTION TO CONTINUE.
;BEFORE STEPPING IS CONTINUED THOUGH, THE KEYBOARD IS READ AND THE PROGRAM LOOPS UNTIL 
;ALL KEYS ARE RELEASED. THIS IS TO SEPARATE KEY PRESSES MEANT FOR THE STEPPER AND THOSE 
;FOR THE ROUTINE BEING STEPPED. ONCE ALL KEYS ARE RELEASED, ALL THE REGISTERS ARE POPPED 
;OF THE REGISTER DISPLAY STACK, THE STACK IS RESTORED TO ITS "REAL" POSITION AND THE 
;INTERRUPTS RE-ENABLED. THE RETURN ADDRESS FOR THE ROUTINE BEING STEPPED, STILL THERE ON 
;THE TOP OF THE REAL STACK, IS USED AS THE RETURN ADDRESS.

L03AC       RST 20H             ;WAIT UNTIL AIL KEYS ARE RELEASED
            JR Z,L03AC          ;BEFORE RESTARTING
            POP HL              ;RECOVER ALL
            POP AF              ;REGISTERS
            POP BC              ;IN
            POP DE              ;THE 
            POP HL              ;REVERSE
            POP IX              ;ORDER
            POP IY              ;TO
            EX AF,AF'          ;HOW 
            EXX                 ;THEY
            POP AF              ;STORED
            POP BC 
            POP DE 
            POP HL 
            EX AF,AF' 
            EXX
            LD SP,(L087E)       ;AND STACK POINTER
            EI                  ;RE-ENABLE THE INTERRUPTS 
            RET                 ;RET TO STEP NEXT INSTRUCTION

;TEST FOR "AD" KEY  (RETURN TO JMON)

L03C6       CP AD_KEY           ;***TEST FOR "ADDR" KEY
            JR NZ,L03CB         ;JUMP IF NOT TO ASSUME DATA KEY
            RST 00H             ;RETURN TO MONITOR

;DATA KEY HANDLER (ENABLE AUTO STEP)

L03CB       LD A,0x20           ;SET AND ENABLE AUTO STEP IN THE
            LD (L0824),A        ;CONTROL/TIMER BYTE (BIT 7 LOW, 20
            JR L0379            ;CYCLES): JUMP TO DISPLAY LOOP

;-END OF STEPPER-

;START OF MENU
;MENU IS SET-UP FOR TAPE ROUTINE HERE
;THE VARIABLES ARE MOVED FROM ROM TO RAM AND THE DISPLAY BUFFER IS SET TO 0800.

L03D2       LD HL,077CH         ;LOAD HL WITH START OF TAPE 
            LD DE,L0880         ;VARIABLES: DE IS RAM DE(stination)
            LD BC,0018H         ;BC IS THE COUNT
            LDIR                ;SHIFT VARIABLES
L03DD       LD HL,L0800         ;PUT DISPLAY BUFFER AT 0800
            LD (L082C),HL

;MENU DISPLAY LOOP STARTS HERE
;THE MENU ENTRY NUMBER (MEN), HOLDS THE NUMBER OF THE CURRENT MENU ENTRY ON THE DISPLAY. 
;ALL ACTIONS OF THE MENU DRIVER CENTRE AROUND THIS BYTE.
;THE DISPLAY ON THE TEC LED DISPLAY IS GENERATED BY SHIFTING BOTH THE DATA AND ADDRESS 
;DISPLAY CODES INTO THE RAM DISPLAY BUFFER.
;ALL THE POSSIBLE DATA AND ADDRESS DISPLAY CODES ARE STORED IN SEPARATE TABLES IN ROM, 
;THE BASE OF EACH IS ADDRESSED BY THE CONTENTS OF MEMORY LOCATIONS 0895 (DATA TABLE), AND 
;0893 (ADDRESS TABLE).
;THE FIRST MENU ENTRY IS DENOTED BY A ZERO VALUE IN THE MENU ENTRY NUMBER (MEN). THIS 
;MEANS THAT THE POSSIBLE ZERO CONDITION MUST BY DETECTED AND THE TABLE ENTRY CALCULATOR 
;SECTION SKIPPED OVER. WHEN ACCESSING THE DISPLAY TABLES, THE MENU ENTRY NUMBER IS 
;DECREMENTED UNTIL ZERO AND EACH TIME AN OFFSET EQUAL TO THE LENGTH OF EACH TABLE ENTRY 
;(4 FOR ADDR AND 2 FOR DATA TABLES) IS ADDED TO THE POINTERS.
;AFTER THE REQUIRED ENTRIES ARE FOUND, THEY ARE MOVED INTO THE RAM DISPLAY BUFFER.

L03E3       LD A,(L088F)        ;GET MENU ENTRY NUMBER (MEN)
L03E6       LD DE,(L0895)       ;DE POINTS TO DATA DISPLAY TABLE 
            LD HL,(L0893)       ;HL POINTS TO ADDR DISPLAY TABLE 
L03ED       LD BC,0004H         ;BC IS BOTH AN INDEX OFFSET AND 
            OR A                ;BYTE COUNTER (USED BELOW): TEST 
            JR Z,L03F9          ;A AND SKIP CALCULATOR IF ZERO 
L03F3       ADD HL, BC          ;ADD 4 TO HL TO POINT TO NEXT ADDR 
            INC DE              ;DISPLAY AND 2 TO DE FOR NEXT DATA 
            INC DE              ;DISPLAY
            DEC A               ;DO UNTIL A=0
            JR NZ,L03F3
L03F9       PUSH HL             ;SAVE ADDR POINTER (not required) 
            PUSH DE             ;AND DATA POINTER
            LD DE,L0800         ;SHIFT ACROSS ADDR DISPLAY
            LDIR                ;TO 0800 (LC-0004 FROM ABOVE) 
            POP HL              ;POP DATA DISPLAY ADDR INTO HL
            LD C,0x02           ;SET PC TO SHIFT DATA DISPLAY BYTES
            LDIR                ;SHIFT THE BYTES TO DISPLAY RAM
            POP HL              ;CLEAN UP STACK

;THIS SECTION CALLS THE SCAN/KEY/LCD/PATCH ROUTINE.
;WHEN A KEY IS DETECTED A KEY HANDLER ROUTINE IS CALLED. THIS KEY HANDLER IS COMMON TO 
;BOTH THE MENU DRIVER AND THE PERIMETER HANDLER AND IS DOCUMENTED ON FURTHER.
;IF THE "GO" KEY WAS PRESSED, THE ZERO FLAG WILL BE SET WHEN THE COMMON KEY HANDLER RETURNS 
;AND THE ROUTINE JUMPS TO THE GO HANDLER. IF NOT, THEN A (UNUSED BY JMON) ROUTINE (AT 
;0897) IS CALLED AND FINDS AN IMMEDIATE RETURN.
;THE RETURN INSTRUCTION WAS PLACED AT 0897 WHEN THE TAPE'S MENU VARIABLES WERE SHIFTED 
;FROM ROM TO RAM (SEE 0793).
;A JUMP THEN LOOPS BACK TO THE MAIN DISPLAY LOOP TO UP-DATE THE DISPLAYS IN CASE OF A NEW 
;MENU ENTRY NUMBER (MEN) BEING PROVIDED BY THE KEY HANDLER.
;THE GO HANDLER IS A SIMPLE TABLE ENTRY CALCULATOR THAT USES THE MENU ENTRY NUMBER TO 
;INDEX THROUGH A TABLE OF THREE BYTE JUMPS. LIKE THE DISPLAY CALCULATOR, THE ZERO POSSIBILITY 
;IS TESTED FOR AND THE CALCULATOR SECTION IS SKIPPED OVER IF ZERO. WHEN THE REQUIRED TABLE 
;ENTRY IS POINTED TO BY HL, IT IS THEN JUMPED TO VIA JP (HL), AND THE TABLE ENTRY,,,ITSELF 
;BEING A 3 BYTE JUMP THEN JUMPS TO THE SELECTED MENU ENTRY'S ROUTINE.

            CALL  L0842         ;CALL SCAN/KEY/LCD/PATCH ROUTINE
            LD HL,L088F         ;POINT HL TO MENU ENTRY NUMBER
            CALL L04B2          ;CALL COMMON KEY HANDLER
            JR Z,L0416          ;JUMP IF KEY WAS "GO" ELSE CALL TO
            CALL L0897          ;RETURN INSTRUCTION (UNUSED BY JMON)
            JR L03E3            ;LOOP TO MAIN DISPLAY LOOP

;MENU "GO" KEYHANDLER

L0416       LD HL,(L0891)       ;POINT HL TO BASE OF JUMP TABLE 
            LD A,(L088F)        ;GET MENU ENTRY NUMBER
            OR A                ;TEST FOR ZERO
            JR Z,L0425          ;SKIP CALCULATOR IF ZERO
L041F       INC HL              ;FIND JUMP VECTOR FOR THE CURRENT
            INC HL              ;MENU HEADING
            INC HL
            DEC A
            JR NZ,L041F
L0425       JP (HL)             ;AND JUMP TO THE REQUIRED ROUTINE

;PERIMETER HANDLER SET-UP ROUTINES FOR THE TAPE SOFTWARE
;WHEN GO IS PRESSED IN THE MENU HANDLER, ONE OF THE IMMEDIATE FOLLOWING ROUTINES IS EXECUTED 
;(WHEN THE MENU IS WORKING WITH THE TAPE SOFTWARE). THESE ROUTINES SET-UP THE VARIABLES 
;FOR THE MAIN TAPE FUNCTIONS (SAVE, TEST CS, TEST BL AND LOAD). THE TWO TESTS AND THE LOAD 
;ROUTINE IS BASICALLY THE ONE ROUTINE, EXCEPT THAT EACH HAS ITS OWN PRIVATE SIGN-ON BYTE. 
;LATER YOU WILL SEE THE THE ROUTINE TO LOAD OR TEST IS BASICALLY THE SAME AND THIS "SIGN-ON 
;BYTE" SEPARATES THE DIFFERENT FUNCTIONS AT THE CRITICAL STAGE.
;THE COMMON SECTION FOR THE LOAD AND TESTS, SETS THE PERIMETER HANDLER TO HAVE TWO WINDOWS, 
;ONE FOR THE FILE NUMBER AND ONE FOR THE OPTIONAL START ADDRESS. IT ALSO SETS THE OPTIONAL 
;START WINDOW TO FFFF (NO OPTIONAL START ADDRESS BY DEFAULT) AND PUTS THE EXECUTING ADDRESS 
;OP THE LOAD/TESTS ROUTINE IN THE PERIMETER "GO" JUMP ADDRESS BUFFER.
;THE SAVE SET-UP SETS THE NUMBER OF WINDOWS TO 4 AND STORES THE EXECUTING ADDRESS OF THE 
;SAVE PREAMBLE ROUTINE IN THE PERIMETER "GO" JUMP ADDRESS BUFFER (0888).
;THE 4 TAPE SAVE WINDOWS ARE: THE FILE NUMBER, THE START, THE END AND THE OPTIONAL AUTO 
;GO ADDRESS.
;ALL THE ABOVE ROUTINES HAVE A COMMON SET-UP AREA. THIS COMMON AREA STORES THE ROUTINE'S 
;JUMP ADDRESS, IN HL, AND THE NUMBER OF WINDOWS, IN A, BOTH PROVIDED FROM THEIR OWN 
;DEDICATED SECTION. THE COMMON AREA ALSO CLEARS THE "ACTIVE WINDOW NUMBER" TO ZERO SO THAT 
;THE PERIMETER HANDLER WILL BE ENTERED WITH THE FIRST WINDOW (FILE NUMBER) SHOWING.

;"LOAD" SET-UP

L0426       XOR A               ;CLEAR A FOR LOAD SIGN-ON BYTE 

;COMMON AREA FOR LOAD AND TESTS

L0427       LD (L088A),A        ;SAVE SIGN-ON BYTE IN BUFFER
            LD A,0x01           ;LOAD A WITH NUMBER OF WANTED
            LD HL,0xFFFF        ;WINDOWS -1 (2 WINDOWS): SET
            LD (L089A),HL       ;OPTIONAL START WINDOW TO FFFF
            LD HL,L0531         ;LOAD HL WITH "GO" ADDR OF LOAD/TEST
            JR L0444            ;ROUTINE: JUMP TO STORE HL AND A

;"TEST BLOCK" SET-UP

L0437       LD A,0x02           ;2=TEST BLOCK SIGN-ON BYTE
L0439       JR L0427            ;JUMP TO TEST/LOAD COMMON AREA

;"TEST CHECKSUM" SET-UP

L043B       LD A,0x03           ;3=TEST CHECKSUM SIGN-ON BYTE 
            JR L0439            ;JUMP TO TEST/LOAD COMMON AREA

;SAVE SET-UP

L043F       LD HL,L0450         ;POINT HL TO START OF SAVE PRE-AMBLE 
            LD A,0x03           ;SET UP FOR 4 WINDOWS

;COMMON AREA FOR ALL SET-UPS

L0444       LD (L0888),HL       ;STORE HL AND A
            LD (L0887),A
            XOR A               ;SET MEN TO FIRST WINDOW (FILE NUMBER)
            LD (L0886),A
            JR L0473            ;JUMP TO PERIMETER HANDLER

;SAVE ROUTINE PRE-AMBLE
;THE SAVE PREAMBLE FITS IN BETWEEN THE PERIMETER HANDLER AND THE ACTUAL SAVE ROUTINE. THE 
;PURPOSE OF IT IS TO SHIFT ACROSS THE FILE NUMBER, THE START ADDRESS AND THE OPTIONAL GO 
;ADDRESS. IT ALSO CALCULATES THE LENGTH OF THE BLOCK AND TRANSFERS IT ACROSS TO THE TAPE 
;FILE INFORMATION BLOCK WHICH IS OUTPUTTED TO THE TAPE.
;IF THE END IS LOWER THAN THE START THE ROUTINE WILL JUMP TO DISPLAY "Err -In".

L0450       LD HL,(L089E)       ;SHIFT OPTIONAL GO TO OUTPUT BUFFER
            LD (L08AA),HL
            LD HL,(L089A)       ;SHIFT START ADDRESS OF BLOCK
            LD (L08A6),HL       ;TO TAPE FILE OUTPUT BUFFER
            EX DE,HL            ;PUT START OF BLOCK IN DE
            LD HL,(L089C)       ;GET END OF BLOCK IN HL
            OR A                ;CLEAR CARRY
            SBC HL,DE           ;CALCULATE NUMBER OF BYTES IN
            INC HL              ;BLOCK (DIFFERENCE +1)
            JP  C,L004A         ;JUMP IF CARRY TO "Err-In"
            LD (L08A8),HL       ;STORE COUNT IN FILE INFO OUTPUT
            LD HL,(L0898)       ;SHIFT FILE NUMBER TO
            LD (L08A4),HL       ;TAPE FILE INFO OUTPUT BUFFER
            JP  L04F0           ;JUMP TO SAVE OUTPUT ROUTINE

;FINAL TAPE SET-UP BEFORE THE PERIMETER HANDLER. THIS PLACES FFFF IN THE OPTIONAL GO WINDOW 
;BEFORE ENTERING THE PERIMETER HANDLER.

L0473       LD HL,0xFFFF        ;PUT FFFF IN OPTIONAL GO WINDOW
            LD (L089E),HL       ;

;PERIMETER HANDLER
;THE PERIMETER HANDLER ROUTINE IS SIMILAR TO THE MENU DRIVER. THE MAJOR DIFFERENCES ARE 
;LISTED BELOW:
;THE PERIMETER HANDLER CREATES ITS OWN ADDRESS DISPLAY CODES BY CONVERTING THE CONTENTS 
;OF THE ACTIVE WINDOW TO DISPLAY CODE AND THEREFORE DOES NOT REQUIRE A TABLE OF ADDRESS 
;DISPLAY CODES.
;ANOTHER DIFFERENCE IS THE ADDRESS OF THE ROUTINE TO BE EXECUTED ON A "GO" PRESS IS SUPPLIED 
;BY THE CALLING ROUTINE. THEREFORE THE PERIMETER HANDLER DOESN'T REQUIRE A JUMP TABLE AND 
;ASSOCIATED CALCULATOR.
;THE ONLY OTHER MAJOR DIFFERENCE IS THAT THE PERIMETER HANDLER HAS ITS OWN BUILT IN DATA 
;KEY HANDLER WHILE THE MENU DOES NOT.
;THE FRONT SECTION BELOW CALCULATES THE ADDRESS OF THE ACTIVE WINDOW AND THE ADDRESS OF 
;THE DATA DISPLAY FROM THE DISPLAY TABLE.
;THE MENU ENTRY NUMBER FROM THE MENU DRIVER HAS AN EQUIVALENT HERE. IT IS THE ACTIVE WINDOW
;NUMBER AND IS USED IN IDENTICAL FASHION.

L0479       LD A,(L0886)        ;GET NUMBER OF ACTIVE WINDOW
            LD HL,(L0884)       ;GET ADDRESS OF FIRST (FILE) WINDOW+1
            LD DE,(L0882)       ;GET BASE OF DATA DISPLAY TABLE
            OR A                ;TEST ACTIVE WINDOW NUMBER FOR ZERO
            JR Z,L048D          ;SKIP CALCULATOR IF ZERO
L0486       INC DE              ;FINE CURRENT DATA DISPLAY
            INC DE              ;AND WINDOW
            INC HL 
            INC HL 
            DEC A
            JR NZ,L0486

;AFTER THE ADDRESS+1 OF THE ACTIVE WINDOW IS CALCULATED, IT IS STORED IN A BUFFER (AT
;088C). EACH TIME A DATA KEY 1S PRESSED, HL IS LOADED FROM THIS BUFFER AND THEREFORE POINTS 
;TO THE ACTIVE WINDOW. THE DATA CAN THEN BE SHIFTED INTO THE ACTIVE WINDOW IMMEDIATELY. 

L048D       LD (L088C),HL       ;STORE ACTIVE WINDOW ADDRESS+l

;BELOW THE DATA DISPLAY BYTES ARE PUT INTO THE DATA SECTION OF THE DISPLAY BUFFER VIA HL.

            EX DE,HL            ;PUT DATA DISPLAY ADDRESS IN HL 
            LD A,(HL)           ;GET RIGHT-HAND DISPLAY BYTE IN A 
            INC HL              ;AND LEFT-HAND IN H
            LD H,(HL)           ;PUT RIGHT-HAND BYTE IN L
            LD L,A              ;HL HOLDS THE DATA DISPLAY BYTES 
            LD (L0804),HL       ;STORE DATA DISPLAY IN BUFFER

;BELOW THE 16 BIT CONTENTS OF THE ACTIVE WINDOW ARE CONVERTED TO DISPLAY CODE ARE PLACED 
;IN THE ADDRESS SECTION OF THE DISPLAY BUFFER.

            EX DE,HL            ;GET ACTIVE WINDOW ADDRESS FROM DE 
            LD A,(HL)           ;AND TRANSFER
            DEC HL              ;THE 16 BIT CONTENTS OF THE ACTIVE 
            LD L,(HL)           ;WINDOW INTO HL
            LD H,A              ;READY TO COVERT TO DISPLAY CODE 
            LD BC,L0800         ;BC=DISPLAY BUFFER START
            CALL L0830          ;CALL CONVERSION HL TO DISPLAY CODE

;THE DISPLAY BUFFER IS NOW SET-UP AND THE SCAN/KEY LOOP IS CALLED. WHEN A KEY IS PRESSED, 
;A COMMON KEY HANDLER IS CALLED.
;THE COMMON KEY HANDLER DOES ALL THE REQUIRED PROCESSING FOR THE "+", "- " AND "AD" KEYS. 
;IF EITHER THE "GO" AR A DATA KEY IS PRESSED, THEN THE HANDLER RETURNS WITH THE FLAGS SET 
;TO SIGNIFY THESE KEYS.
;IF "GO" IS PRESSED THEN THE ZERO FLAG IS SET AND THE "GO" HANDLER BELOW IS EXECUTED. IF 
;A DATA KEY IS PRESSED THEN THE ZERO FLAG IS CLEAR (NOT ZERO) AND CARRY FLAG IS CLEAR THE 
;DATA KEY HANDLER IS EXECUTED IF THESE CONDITIONS ARE MET.

L04A3       CALL L0842          ;CALL SCAN/KEY/LCD/PATCH ROUTINE 
            LD HL,L0886         ;POINT HL TO ACTIVE WINDOW NUMBER 
            CALL L04B2          ;CALL COMMON KEY HANDLER
            JR NZ,L04C4         ;JUMP IF NOT GO KEY TO TEST FOR DATA 
            LD HL,(L0888)       ;OR CONTROL KEY: ELSE GET JUMP ADDRESS 
            JP (HL)             ;STORED BY SET-UP AND GO

;COMMON KEY HANDLER
;BECAUSE THE PERIMETER HANDLER AND THE MENU DRIVER ARE VERY SIMILAR, THEY ARE ABLE TO 
;SHARE A COMMON KEY HANDLER.
;THE ACTION OF THE KEY HANDLER IS AS FOLLOWS:
;IF THE "AD" KEY IS PRESSED, THEN THE RETURN ADDRESS IS POPPED OFF THE STACK AND A RETURN 
;IS DONE TO THE CALLING ROUTINE (USUALLY JMON). IF THE "GO" KEY IS PRESSED, THEN THE ZERO 
;FLAG WILL BE SET AND A RETURN DONE. IT IS THEN UP TO THE CALLING ROUTINE TO SERVICE THE 
;"GO" KEY.
;A DATA KEY WILL BE FLAGGED BY SETTING THE CARRY FLAG AND CLEARING THE ZERO FLAG. LIKE 
;THE "GO" KEY, THE CALLING ROUTINE MUST DECIDE WHAT IT IS TO DO WITH THE DATA KEY (THERE 
;IS A BUILT IN DATA KEY HANDLER FOR THE PERIMETER HANDLER).
;IF EITHER THE "+" OR "-" KEYS ARE PRESSED THEN A SPECIAL ROUTINE IS CALLED. THIS ROUTINE 
;WILL ALTER THE CURRENT NUMBER OF THE ACTIVE WINDOW OR MENU ENTRY. THE RESULT IS THAT WHEN 
;THE DISPLAY IS UP-DATED, THE DISPLAYS WILL BE SHIFTED TO EITHER THE NEXT DISPLAY FOR "+" 
;OR TO THE PREVIOUS ONE FOR "- " AND WRAP-AROUND IF REQUIRED.

L04B2       CP  PLUS_KEY        ;***IS THE "+" KEY
            JR  Z,L04D1         ;JUMP IF SO TO "+" HANDLER 
            CP  MINUS_KEY       ;***IS IT "-"
            JR  Z,L04D1         ;JUMP IF SO TO "-" HANDLER 
            CP  AD_KEY          ;***IS IT "AD"
            JR NZ,L04C0         ;JUMP IF NOT TO TEST FOR "GO"
            POP HL              ;CLEAN UP STACK
            RET                 ;RETURN TO JMON (OR CALLING ROUTINE)
L04C0       CP  GO_KEY          ;***IS IT "GO"
            CCF                 ;CLEAR CARRY IF NOT IF GO C=1 Z=1
            RET                 ;IF DATA SET Z=0 C=0: RETURN

;BELOW IS THE PERIMETER HANDLER DATA KEY HANDLER/DISCRIMINATOR
;IF THE KEY WAS "+" OR "-" THEN IT HAS ALREADY BEEN HANDLED AND THIS CONDITION IS FLAGGED 
;BY THE CARRY BEING SET. IN THIS CASE, A JUMP IS DONE BACK TO THE MAIN BODY TO UP-DATE 
;THE DISPLAY OTHERWISE THE DATA KEY VALUE IS SHIFTED INTO THE ACTIVE WINDOW.

L04C4       JR C,L0479          ;JUMP IF KEY WAS "+" OR "-‚Äù
            LD HL,(L088C)       ;POINT HL TO ACTIVE WINDOW+1
            DEC HL              ;POINT TO LOW ORDER BYTE
            RLD                 ;SHIFT IN DATA KEY VALUE
            INC HL              ;AND SHIFT OTHER NIBBLES
            RLD                 ;ACROSS
            JR L0479            ;JUMP BACK TO UP-DATE DISPLAY

;THIS ROUTINE IS CALLED FROM THE COMMON KEY HANDLER IF EITHER "+" OR "-" HAVE BEEN 
;PUSHED.
;THIS ROUTINE WILL EITHER INCREMENT OR DECREMENT THE MEMORY LOCATION ADDRESSED BY HL FOR 
;THE "+" AND "-" KEY RESPECTIVELY. HL WAS LOADED BY THE CALLING ROUTINE TO POINT TO ITS 
;MAIN CONTROLLING BYTE. THIS IS EITHER THE CURRENT MENU ENTRY NUMBER (MENU DRIVER), OR 
;THE ACTIVE WINDOW NUMBER (PERIMETER HANDLER) , BOTH OF WHICH HAVE BEEN DESCRIBED PREVIOUSLY. 
;AFTER INCREMENTING OR DECREMENTING (HL), THIS ROUTINE THEN CHECKS THAT THE VALUE IN (HL) 
;IS NOT GREATER THAT THE BYTE AT HL+1 (WHICH IS THE MAXIMUM NUMBER OF DISPLAYS LESS 1). 
;KEEP IN MIND, IF IT UNDERFLOWED FROM ZERO IT WILL BECOME FF AND BE HIGHER THAN (HL). THIS 
;SECOND BYTE (AT HL+1) IS THE NUMBER OF ALLOWABLE DISPLAYS-1 AND WAS PROVIDED BY THE ROM 
;TABLE FOR THE (TAPE) MENU DRIVER, AND PROVIDED BY THE PERIMETER HANDLER SET-UP ROUTINES 
;(REFER TO 042A AND 0442).
;IF THE FIRST BYTE BECOMES HIGHER THAN THE SECOND., THEN THE ROUTINE CHECKS TO SEE WHICH 
;KEY WAS PRESSED. IF THE "+" KEY WAS, THEN (HL) IS CLEARED. THIS WILL CAUSE MENU OR 
;PERIMETER HANDLER TO SHOW ITS FIRST DISPLAY WHEN RE-ENTERED.
;IF THE KEY WAS "-", THEN THE MAXIMUM NUMBER OF DISPLAYS-1 (WHICH IS THE SAME AS THE NUMBER 
;OF THE FINAL DISPLAY) IS TRANSFERRED INTO (HL) (THE NUMBER OF THE CURRENT DISPLAY). THIS 
;WILL CAUSE THE LAST DISPLAY TO BE SHOWN WHEN THE MENU DRIVER OR PERIMETER HANDLER IS 
;RE-ENTERED.
;IF THERE IS NO UNDERFLOW OR OVERFLOW THEN THE ROUTINE RETURNS JUST AFTER IT HAS EITHER 
;INCREMENTED OR DECREMENTED THE CURRENT NUMBER OF THE MENU ENTRY NUMBER OR ACTIVE WINDOW 
;NUMBER.
;WHEN THE MENU DRIVER OR PERIMETER HANDLER ARE RE-ENTERED, THEY WILL SHOW THE NEXT DISPLAY 
;FOR "+" OR THE PREVIOUS FOR "-" AND WRAP-AROUND AUTOMATICALLY IF REQUIRED.

L04D1       LD C,A              ;SAVE INPUT KEY VALUE IN C
            INC HL              ;PUT MAX NUMBER OF DISPLAYS-1
            LD B, (HL)          ;IN B
            DEC HL              ;RESET HL TO POINT TO CURRENT NUMBER
            RRCA                ;WAS KEY "+" OR "-"? BIT 0 WILL TELL
            LD A,(HL)           ;PUT CURRENT NUMBER IN A
            JR C,L04DB          ;***JUMP IF KEY WAS "-"
            INC A               ;INCREASE A BY 2
            INC A               ;
L04DB       DEC A               ;DECREASE A BY ONE
            INC B               ;ADD 1 TO MAX NUMBER-1: IS CURRENT
            CP B                ;NUMBER EQUAL OR GREATER THAN MAX?
            JR NC,L04E5         ;JUMP IF SO TO UNDER/OVERFLOW HANDLER
L04E0       LD (HL),A           ;ELSE STORE UPDATED CURRENT NUMBER
            XOR A               ;SET ZERO FLAG
            DEC A               ;CHANGE ZERO FLAG TO 0
            SCF                 ;AND SET CARRY
            RET                 ;DONE
L04E5       BIT 0,C             ;TEST FOR "+" OR "-"
            JR NZ,L04EC         ;***JUMP IF "-" TO SET CURRENT NUMBER
            XOR A               ;TO LAST DISPLAY: ELSE SET FIRST
            JR L04E0            ;DISPLAY: JUMP TO STORE NEW NUMBER
L04EC       DEC B               ;CORRECT MAX NUMBER-1
            LD A,B              ;SET A TO LAST DISPLAY NUMBER
            JR L04E0            ;JUMP TO STORE LAST DISPLAY NUMBER

;THIS IS THE TAPE OUTPUT ROUTINE
;THE ACTION IS AS FOLLOWS:
;A LEADER OF LOW FREQUENCY TONE IS OUTPUTTED FOLLOWED BY THE FILE INFORMATION BLOCK. 
;AFTER THE FILE INFORMATION BLOCK IS OUTPUTTED, SEVERAL SECONDS OF HIGH FREQUENCY MIDDLE 
;SYNC IS OUTPUTTED, THE TIME IT TAKES TO OUTPUT THE MIDDLE SYNC IS USED BY THE TAPE INPUT 
;ROUTINE TO DISPLAY THE FILE NUMBER.
;THE DATA TO BE SAVED ON TAPE IS BROKEN UP INTO BLOCKS OF 256 BYTES AND OUTPUTTED WITH A 
;CHECKSUM AT THE END OF EACH BLOCK. A COUNTER IS SHOWN ON THE TEC LED DISPLAY THAT SHOWS 
;HOW MANY COMPLETE BLOCKS LEFT (UP TO 16 BLOCKS).
;IF THERE IS AN ODD SIZE BLOCK, IT IS OUTPUTTED AS THE LAST BLOCK.
;AFTER ALL THE BLOCKS HAVE BEEN OUTPUTTED, AN END OF FILE HIGH FREQUENCY TONE IS OUTPUTTED.

L04F0       LD HL,0x3000        ;HL HAS NUMBER OF LEADER CYCLES 
            CALL L0680          ;CALL LOW TONE
            LD HL,L08A4         ;HL IS START OF FILE INFORMATION BLOCK 
            LD B,0x0C           ;LOAD B WITH NUMBER OF BYTES TO BE 
            XOR A               ;OUTPUTTED: ZERO A FOR CHECKSUM
            CALL L064B          ;CALL OUT BLOCK
            LD HL,0x5000        ;LD HL WITH MID SYNC CYCLE COUNT
            CALL L0684          ;CALL HIGH TONE
            LD HL,(L08A6)       ;LOAD HL, WITH START OF OUTPUT BLOCK

;OUTPUT LOOP STARTS HERE
;THE DISCUSSION BELOW ON THE BYTE COUNTER AND BLOCK FORMATION APPLIES TO THE TAPE INPUT 
;LOOP ALSO. THE TAPE INPUT LOOP DESCRIPTION WILL REFER YOU BACK TO THESE NOTES.
;THE BYTE COUNT IS PUT INTO BC AND THEN A ROUTINE TO CONVERT B (THE TOTAL NUMBER OF FULL 
;BLOCKS TO BE OUTPUTTED) TO DISPLAY FORMAT AND OUTPUT IT IS CALLED.
;THE CONVERSION ROUTINE ALSO TESTS B FOR ZERO. IF B IS NOT ZERO, THE ROUTINE RETURNS WITH 
;THE ZERO FLAG CLEAR (NOT ZERO) AND THE HIGH ORDER BYTE OF THE BYTE COUNT IN B IS DECREMENTED 
;BY ONE AND STORED IN ITS BUFFER. THIS COUNTS DOWN THE BLOCKS. B IS THEN ZEROED SO THAT 
;A FULL BLOCK (256 BYTES) WILL BE OUTPUTTED ON RETURNING.
;IF THE HIGH ORDER BYTE OF THE BYTE COUNT (IN B) IS ZERO (NO FULL BLOCK OF 256 BYTES) THEN 
;C (THE LOW ORDER BYTE OF THE COUNT) IS TRANSFERRED INTO B AND THE ZERO FLAG IS SET.
;THE CONVERSION THEN RETURNS WITH THE NUMBER (IF ANY) OF REMAINING BYTES IN B.
;AFTER THE CONVERSION ROUTINE HAS RETURNED, A JUMP IS DONE IF THE ZERO FLAG IS CLEAR 
;(DENOTING A NOT ZERO STATE). THIS JUMP SKIPS AHEAD TO SAVE THE FLAGS AND OUTPUT ONE FULL 
;BLOCK
;IF THE ZERO FLAG IS SET, THEN THE ROUTINE BELOW CHECKS TO SEE IF THE LOW ORDER BYTE (FROM 
;C) THAT HAS BEEN PLACED IN B, IS ZERO. IF THE LOW ORDER BYTE IS ZERO, THEN ALL THE BYTES 
;HAVE BEEN OUTPUTTED. THE ROUTINE THEN JUMPS TO DISPLAY " -END -S".
;IF THE LOW ORDER BYTE OF THE COUNT IS NOT ZERO THEN THE ZERO FLAG IS SET AND SAVED ON 
;THE STACK BEFORE WHAT ARE NOW KNOWN TO BE THE LAST IS OUTPUTTED.
;BEFORE THE DATA IS SENT TO THE TAPE, A SHORT HIGH TONE SYNC IS OUTPUTTED TO COVER THE 
;SOFTWARE OVERHEAD OF THE TAPE INPUT ROUTINE, AND A IS ZEROED TO BE USED AS THE CHECK-SUM.

L0508       LD BC,(L08A8)       ;LOAD BC WITH NUMBER OF BYTES
            CALL L05C9          ;CALL ROUTINE TO DISPLAY BLOCK COUNT 
            JR NZ,L0516         ;AND TEST LENGTH: JUMP IF FULL BLOCK 
            LD A,B              ;TO OUTPUT: TEST LOW BYTE OF COUNT 
            OR A                ;IN B IS ZERO AND JUMP TO DISPLAY 
            JR Z,L0526          ;"-END-S" IF SO

;THE XOR A INSTRUCTION BELOW SETS THE ZERO FLAG TO SIGNIFY THAT THE BLOCK ABOUT TO BE 
;OUTPUTTED IS THE FINAL BLOCK. THE ROUTINE WILL THEN DISPLAY "-END-S" (AFTER A SHORT END 
;SYNC TONE).

            XOR A               ;SET ZERO FLAG
L0516       PUSH AF             ;AND SAVE ON STACK

;AT THIS POINT IF THE ZERO FLAG ON THE STACK IS CLEAR (NOT ZERO STATE), THEN AFTER THE 
;CURRENT BLOCK IS OUTPUTTED, THE ROUTINE WILL LOOP BACK TO START OF THE OUTPUT LOOP TO 
;SEE IF THERE IS ANY MORE BYTES TO BE OUTPUTTED.
            EXX                 ;SWAP REGISTERS
            LD HL,0x0214        ;LOAD HL FOR SHORT BURST OF
            CALL L0684          ;HIGH TONE
            EXX                 ;SWAP BACK REGISTERS
            XOR A               ;ZERO A FOR CHECKSUM
            CALL L064B          ;CALL OUTBLOCK
            POP AF              ;RECOVER FLAGS AND JUMP IF
            JR NZ,L0508         ;THERE MIGHT BE MORE TO OUTPUT

;ALL BLOCKS HAVE BEEN OUTPUTTED SO FINISH WITH A SHORT END TONE AND SET-UP END DISPLAY 
;"-END-S".
L0526       LD HL,0x1000        ;LOAD HL WITH SHORT END TONE
            CALL L0684          ;CALL HIGH TONE
            LD A,0x05           ;LD A TO INDEX "END-S DISPLAY
            JP L03E6            ;JUMP BACK TO MENU

;THIS IS THE START OF THE TAPE INPUT SECTION.
;THE ACTION HERE IS TO DETECT A VALID LEADER BY COUNTING 1000H CYCLES OF LOW FREQUENCY 
;TONE. AFTER THIS HAS BEEN DETECTED, THE ROUTINE WAITS UNTIL IT DETECTS THE START BIT OF 
;THE FILE INFORMATION BLOCK. THE BLOCK IS THEN LOADED IN AND A CHECK-SUM COMPARE IS DONE. 
;IF AN ERROR IS DETECTED, THE ROUTINE JUMPS TO DISPLAY "FAIL -XX", OTHERWISE THE FILE 
;NUMBER IS CONVERTED TO DISPLAY FORMAT AND DISPLAYED FOR A FEW SECONDS.

L0531       LD BC,0x1000        ;LOAD BC TO COUNT 0x1000 CYCLES 
L0534       CALL L0630          ;CALL PERIOD
            JR C,L0531          ;LOOP UNTIL LOW TONE IS DETECTED 
            DEC BC              ;COUNT LONG
            LD A,B              ;PERIODS
            OR C                ;IF BC REACHES ZERO THEN IT IS 
            JR NZ,L0534         ;ACCEPTED THAT A VALID FILE FOLLOWS 
            LD B,0x0C           ;LOAD B TO INPUT 12 BYTES AND
            LD HL,L08A4         ;POINT HL TO FILE INFO BLOCK INPUT 
L0543       CALL L0630          ;BUFFER: CALL PERIOD
            JR NC,L0543         ;AND WAIT FOR LOW TONE TO END
            CALL L05E7          ;CALL INBLOCK TO GET FILE INFO BLOCK 
            JR NZ,L05A1         ;JUMP NOT ZERO TO FAIL LOAD ROUTINE 
            LD BC,L0800         ;LOAD BC TO POINT TO DISPLAY BUFFER 
            LD HL,(L08A4)       ;PUT FILE NUMBER INTO EL
            CALL L0830          ;CONVERT HL TO DISPLAY CODE            
            LD A,0x71           ;PUT "F" IN DISPLAY BUFFER
            LD  (L0805),A       ;FOR "FILE"
            LD BC,0x01F2        ;LD BC WITH THE DISPLAY ON TIME
L055E       PUSH BC             ;SAVE ON STACK
            CALL L0836          ;CALL SCAN
            POP BC              ;RECOVER BC
            DEC BC              ;DECREMENT
            LD A,B              ;AND LOOP UNTIL
            OR C                ;BC IS ZERO
            JR NZ,L055E

;AFTER A FILE INFORMATION BLOCK IS LOADED AND THE FILE NUMBER DISPLAYED, A TEST IS DONE 
;ON THE REQUIRED FILE NUMBER WINDOW. FIRST IT IS TESTED FOR FFFF (LOAD/TEST NEXT FOUND 
;FILE). IF FFFF, THE ROUTINE SKIPS AHEAD TO LOAD/TEST THE FILE. OTHERWISE THE REQUIRED 
;FILE NUMBER IS SUBTRACTED FROM THE JUST LOADED FILE NUMBER, IF THE RESULT IS ZERO THEN 
;THE FILE IS THE ONE SELECTED AND IS LOADED/TESTED.
;THE OPTIONAL START WINDOW IS THEN TESTED FOR FFFF. IF IT IS, THE START ADDRESS FROM THE 
;TAPE IS USED. IF THE OPTIONAL START BUFFER HAS SOMETHING OTHER THAT FFFF, THEN THE ADDRESS 
;HERE IS USED AS THE START ADDRESS TO LOAD/TEST THE TAPE.

            LD HL,(L0898)       ;TEST FOR FFFF IN FILE NAME WINDOW
            INC HL
            LD A,H
            OR L
            DEC HL              ;JUMP IF FILE WINDOW IS FFFF
            JR Z,L057A          ;TO INPUT FILE REGARDLESS OF ITS NUMBER 
            LD DE,(L08A4)       ;ELSE TEST THAT INPUT FILE NAME
            OR A                ;IS THE SAME AS THE ONE IN THE FILE 
            SBC HL,DE           ;NUMBER WINDOW AND JUMP IF NOT
            JR NZ,L0531         ;SELECTED FILE TO LOOK FOR NEXT FILE 
L057A       LD HL, (L089A)      ;TEST THAT OPTIONAL START ADDRESS 
            INC HL              ;IS FFFF
            LD A,H
            OR L
            DEC HL
            JR NZ,L0586         ;JUMP IF NOT, ELSE USE START ADDRESS 
            LD HL,(L08A6)       ;PROVIDED FROM THE TAPE

;THE MAIN LOAD/TEST ROUTINE STARTS HERE.
;REFER TO THE DESCRIPTION OF THE BYTE COUNT AND BLOCK FORMATION AT THE OUTPUT SECTION 
;ROUTINE  (SEE 508).
;WHEN ALL THE BLOCKS HAVE BEEN INPUTTED AND THE ROUTINE JUMPS TO DISPLAY PASS/FAIL -Ld ON 
;THE LED DISPLAY.
;HL IS POINTING TO THE PLACE IN MEMORY WHERE THE FILE WILL BE LOADED/TESTED.

L0586       LD BC,(L08A8)       ;PUT NUMBER OF BYTES INTO BC 
            CALL L05C9          ;CALL B CONVERT AND TEST
            JR NZ,L0594         ;JUMP IF NOT ZERO AS THERE IS AT 
            LD A,B              ;LEAST ONE FULL BLOCK TO LOAD/TEST 
            OR A                ;CHECK THAT B (FORMALLY C)=0
            JR Z,L059D          ;JUMP IF SO AS ALL BYTES DONE 
            XOR A               ;ELSE SET ZERO FLAG TO REMEMBER 
L0594       PUSH AF             ;SAVE FLAGS ON STACK
            CALL L05E3          ;CALL INBLOCK
            JR NZ,L05A0         ;JUMP IF LOAD/TEST FAILED 
            POP AF              ;RECOVER FLAGS
            JR NZ,L0586         ;LOOP IF THERE MIGHT BE MORE 
L059D       XOR A               ;SET ZERO (SUCCESS) FLAG 
            JR L05A1            ;JUMP TO END HANDLER
L05A0       POP DE              ;CLEAN UP STACK
L05A1       JR NZ,L05B4         ;JUMP IF FAILED LOAD/TEST

;THE LOAD/TEST HAS PASSED. TEST HERE FOR OPTIONAL AUTO-GO AND FOR LOAD OPERATION (NO 
;AUTO-GO FOR TEST OPERATIONS). START EXECUTION AT AUTO-GO ADDRESS IF REQUIRED.

            LD HL,(L08AA)       ;PUT OPTIONAL GO ADDRESS IN HL
            INC HL              ;TEST FOR FFFF
            LD A,H              ;AND JUMP
            OR L                ;IF FFFF
            DEC HL              ;AS THERE
            JR Z,L05B3          ;IS NO AUTO-GO
            LD A,(L088A)        ;TEST THAT A LOAD OPERATION WAS 
            OR A                ;DONE
            JR NZ,L05B3         ;SKIP JUMP IF IT WAS A TEST 
            JP (HL)             ;ELSE AUTO START THE PROGRAM 
L05B3       XOR A
;THE POST LOAD/TEST MENU DISPLAYS ARE SET UP HERE. IF THE LOAD/TEST FAILED THE ZERO FLAG 
;IS CLEAR THE ROUTINE WILL POINT TO THE "FAIL" DISPLAY. OTHERWISE IT IS SET TO POINT TO 
;THE "PASS" DISPLAY. THE DATA DISPLAY IS CALCULATED BY ADDING THE MENU ENTRY NUMBER OF 
;THE JUST PERFORMED OPERATION X2, TO THE TABLE BASE OF POST LOAD/TEST DATA DISPLAYS.
;(THE MENU ENTRY NUMBER IS STILL THE SAME AS IT WAS WHEN "GO" WAS PRESS FROM THE MENU).

L05B4       LD DE,L0768         ;LOAD DE TO BASE OF DATA DISPLAY 
L05B7       LD HL,L075C         ;TABLE AND HL "FAIL" DISPLAY 
            JR NZ,L05BE         ;TABLE:
            LD L,0x58           ;ADJUST HL TO PASS IF ZERO      
L05BE       LD A, (L088F)       ;FIND WHAT OPERATION WAS PERFORMED 
            RLCA                ;AND DOUBLE VALUE AND ADD TO HL TO 
            ADD A,E             ;POINT DE AT POST TAPE OPERATION 
            LD E,A              ;DATA DISPLAY ENTRY (SEE 0768-0771) 
            NOP                 ;(FROM FIXED ERROR)
            XOR A               ;ZERO A
            JP L0047            ;JUMP TO SOFT MENU ENTRY

;THIS IS THE CONVERT/TEST B ROUTINE.
;THE VALUE IN B IS CONVERTED AND OUTPUTTED TO PORT 2.
;THEN B IS TESTED AND ONE OF THE FOLLOWING OPERATIONS IS PERFORMED. IF B=0 THEN C IS 
;TRANSFERRED INTO B AND THE ZERO FLAG IS SET. IF B IS NOT 0 THEN B IS DECREMENTED, THE 
;COUNT IS UP-DATED IN ITS BUFFER AND THE ZERO FLAG AND B IS CLEARED.

L05C9       LD A,B              ;PUT HIGH BYTE OF COUNT IN A 
            AND 0x0F            ;MASK TO ONE DIGIT
            LD DE,07D0H         ;POINT DE TO DISPLAY CODE TABLE 
            ADD A,E             ;ADD A
            LD E,A 
            LD A, (DE)          ;GET DISPLAY VALUE
            OUT (DSEGMENT),A    ;OUTPUT IT TO DISPLAY
            LD A,B              ;TEST HIGH BYTE
            OR A                ;FOR ZERO
            JR Z,L05E1          ;JUMP IF ZERO
            DEC B               ;ELSE DECREASE COUNT BY ONE BLOCK 
            LD (L08A8),BC       ;STORE COUNT
            LD B,0x00           ;LOAD B FOR 256 BYTE OUTPUT BLOCK 
            OR A                ;CLEAR ZERO FLAG
            RET                 ;DONE
L05E1       LD B,C              ;PUT LAST BLOCK SIZE IN B
            RET                 ;DONE

;THIS BLOCK LOADS/TESTS THE BYTES IN FROM THE TAPE. THE NUMBER OF BYTES IS HELD IN B ON 
;INPUT. AFTER THE SUB-ROUTINE THAT INPUTS A BYTE IS CALLED, A TEST AND JUMP IS DONE. THE 
;TEST AND JUMP SELECT THE REQUIRED CODE TO PERFORM A LOAD OR TEST AS SELECTED FROM THE 
;MENU BY THE USER. THE CHECK-SUM LOADED FROM THE TAPE HAS HAD ONE ADDED TO IT BY THE TAPE 
;OUTPUT ROUTINE. THIS ADDED ONE IS REMOVED IN THIS ROUTINE BEFORE THE CHECK-SUM COMPARE 
;IS DONE.

L05E3       LD A, (L088A)       ;GET CURRENT OPERATION
            LD C,A              ;SAVE IN C
L05E7       XOR A               ;CLEAR A FOR CHECKSUM
L05E8       PUSH AF             ;SAVE CHECKSUM 
            CALL L060B          ;CALL GET BYTE 
            BIT 1,C             ;TEST FOR CURRENT OPERATION
            JR NZ,L05FE         ;JUMP IF A EITHER TEST
            LD (HL),E           ;ELSE STORE INPUTTED BYTE IN MEMORY 
            INC HL              ;POINT TO NEXT LOCATION
L05F2       POP AF              ;GET CHECKSUM 
L05F3       ADD A,E             ;ADD TO NEW BYTE
            DJNZ L05E8          ;DO UNTIL BLOCK DONE
            PUSH AF             ;SAVE CHECKSUM 
            CALL L060B          ;GET TAPE CHECKSUM
            POP AF              ;GET MEMORY CHECKSUM
            DEC E               ;CORRECT TAPE CHECKSUM
            CP E                ;TEST CHECKSUMS TO SET FLAGS
            RET                 ;BLOCK DONE
L05FE       BIT 0,C             ;TEST FOR WHICH TEST
            JR Z,L05F2          ;JUMP IF CHECKSUM ONLY TEST
            POP  AF             ;GET CHECKSUM
            LD D,A              ;SAVE IN D
            LD A,E              ;GET INPUT BYTE
            CP (HL)             ;TEST TO MEMORY
            INC  HL             ;POINT TO NEXT LOCATION
            LD A,D              ;PUT CHECKSUM BACK IN A
            JR Z,L05F3          ;JUMP TO MAIN LOOP IF ALL OK
            RET                 ;RETURN IF ERROR

;THIS ROUTINE INPUTS A SINGLE BYTE.

L060B       CALL L0618          ;GET START BIT
            LD D,0x08           ;LOAD D FOR 8 BITS 
L0610       CALL L0618          ;GET BIT
            RR E                ;PUT IT IN E
            DEC D
            JR NZ,L0610         ;DO FOR EIGHT BITS,

;THIS ROUTINE INPUTS A SINGLE BIT
;THE STRUCTURE OF EACH BIT IS IMPORTANT TO UNDERSTAND AT THIS POINT. A LOGIC 0 IS REPRESENTED 
;BY 4 SHORT PERIODS FOLLOWED BY 1 LONG PERIOD AND A LOGIC 1 BY 2 SHORT PERIODS AND 2 LONG 
;PERIODS. THESE ARE HIGH SPEED FIGURES. FOR LOW SPEED THE ABOVE COUNTS ARE DOUBLED.
;THE BITS ARE DECODED BY COUNTING THE RATIO OF SHORT PERIODS TO LONG PERIODS. A COMPLICATED 
;METHOD OF COUNTING IS USED TO RESULT IN THE BIT VALUE BEING REFLECTED IN BIT 7 OF L. THE 
;ROUTINE IS TERMINATED WHEN A SHORT PERIOD THAT FOLLOWED A LONG PERIOD IS DETECTED. THE 
;LONG PERIOD IS FLAGGED WITH BIT 0 OF H. THE "SHORT AFTER LONG" PERIOD USED FOR TERMINATION
;IS ACTUALLY THE FIRST CELL OF THE NEXT BIT.
;THE VALUE OF THE BIT INPUTTED IS THEN POT INTO THE CARRY FLAG.

L0618       EXX                 ;SWAP REGISTERS
            LD HL,0x0000        ;ZERO HL
L061C       CALL L0630          ;CALL TO MEASURE PERIOD
            JR C, L0627         ;JUMP IF SHORT PERIOD
            DEC L               ;SET HIGH ORDER BIT OF L TO ONES
            DEC L
            SET 0,H             ;REMEMBER THAT THE LONG PERIOD
            JR L061C            ;HAS BEEN DETECTED: LOOP BACK
L0627       INC L               ;SHORT PERIOD SO ADD ONE TO L
            BIT 0,H             ;TEST FOR SHORT AFTER LONG PERIOD
            JR Z,L061C          ;JUMP IF NOT
            RL L                ;END OF BIT: PUT BIT 7,L INTO
            EXX                 ;CARRY: SWAP REGISTERS
            RET                 ;INPUT BIT IN CARRY

;THIS ROUTINE INPUTS AND MEASURES THE PERIOD OF EACH TAPE CELL AND COMPARES IT TO THE 
;THRESHOLD BETWEEN A SHORT AND LONG PERIOD. THE  CELL IS ALSO ECHOED ON THE TEC SPEAKER.

L0630       LD DE,0x0000        ;ZERO DE FOR PERIOD MEASUREMENT
L0633       IN A,(DATLATCH)     ;TEST TAPE LEVEL
            INC DE              ;TIME PERIOD
            RLA                 ;PUT TAPE LEVEL INTO CARRY
            JR NC,L0633         ;LOOP UNTIL IT GOES HIGH
            XOR A               ;ECHO IT ON
            OUT (DSCAN),A       ;THE TEC SPEAKER
L063C       IN A,(DATLATCH)     ;MEASURE SECOND HALF OF CYCLE
            INC DE              ;IN THE SAME FASHION AS ABOVE
            RLA
            JR C,L063C          ;THIS TIME LOOP UNTIL TAPE LEVEL
            LD A,0x84           ;GOES LOW: ECHO IT ON TEC SPEAKER
            OUT  (DSCAN),A
            LD A,E              ;GET PERIOD MEASUREMENT
            CP 0x1A             ;COMPARE IT TO THRESHOLD
            RET                 ;TO SET FLAGS: DONE

;THIS ROUTINE OUTPUTS A BLOCK TO THE TAPE. THE NUMBER OF BYTES IS HELD IN B AND THE BLOCK 
;IS ADDRESS BY HL. AFTER ALL THE BYTES HAVE BEEN OUTPUTTED, THE CHECKSUM +1, WHICH WAS 
;ADDED OF AS EACH BYTE WAS OUTPUTTED, IS SENT TO THE TAPE.

L064A       EX  AF,AF'         ;GET CHECKSUM IN A
L064B       LD E,(HL)           ;PUT BYTE TO BE OUTPUTTED IN E 
            ADD A,E             ;ADD FOR CHECKSUM
            EX  AF,AF'          ;SAVE IN ALTERNATE AF
            CALL L0657          ;CALL OUT BYTE
            INC HL              ;POINT TO NEXT BYTE
            DJNZ  L064A
            EX AF,AF'          ;GET CHECKSUM
            INC A               ;INCREASE IT BY ONE
            LD E,A              ;PUT IT IN E

;THIS ROUTINE OUTPUTS A SINGLE BYTE IN E TO THE TAPE. THE FORMAT IS 1 START BIT, EIGHT 
;DATA BITS AND 1 STOP BIT.

L0657       LD D,0x08           ;SET D FOR 8 BITS
            OR A                ;CLEAR CARRY AND CALL OUTBIT
            CALL L0666          ;TO OUTPUT BINARY ZERO FOR START BIT 
L065D       RR E                ;PUT FIRST BIT IN CARRY
            CALL L0666          ;CALL OUT BIT
            DEC D
            JR NZ,L065D         ;DO FOR 8 BITS
            SCF                 ;SET CARRY TO OUTPUT STOP BIT (1)

;THIS ROUTINE OUTPUTS A SINGLE BIT. IF THE CARRY IS SET, THEN A LOGIC 1 IS OUTPUTTED 
;OTHERWISE A LOGIC O.
;A 1 IS REPRESENTED BY 2 SHORT AND 2 LONG PERIODS.
;A 0 IS REPRESENTED BY 4 SHORT PERIODS AND 1 LONG PERIOD.
;L IS LOADED WITH DOUBLE THE LOW SPEED CYCLE COUNT AS IT IS USED TO COUNT THE HALF CYCLES 
;IN THE TONE ROUTINE. IF THE HIGH SPEED SAVE IS SELECTED, THEN THE CYCLE COUNT WILL BE
;HALVED IN THE TONE ROUTINE.

L0666       EXX                 ;SWAP REGISTERS
            LD H,0x00           ;ZERO H
            JR C,L0674          ;JUMP IF BINARY 1 IS TO BE OUTPUTTED
            LD L,0x10           ;LOAD L WITH HIGH TONE CYCLE COUNT
            CALL L0684          ;CALL HIGH TONE
            LD L,0x04           ;LOAD L WITH LOW TONE CYCLE COUNT
            JR L067B            ;JUMP TO LOW TONE
L0674       LD L,0x08           ;LOAD L FOR HIGH TONE CYCLE COUNT
            CALL L0684          ;FOR BINARY ONE: CALL HIGH TONE
            LD L,0x08           ;LOAD L FOR LOW TONE CYCLE COUNT
L067B       CALL L0680          ;CALL LOW TONE
            EXX                 ;SWAP BACK REGISTERS
            RET                 ;DONE

;SET-UP FOR LOW TONE (LONG PERIOD)

L0680       LD C,0x29           ;LOAD C FOR LOW TONE
            JR L0686            ;JUMP TO TONE ROUTINE

;SET-UP FOR HIGH TONE (SHORT PERIOD)

L0684       LD C,11H            ;LOAD C FOR HIGH TONE

;TONE ROUTINE 
;TESTS FOR LOWSPEED SAVE. IF SO THEN IT HALVES THE CYCLE COUNT IN L.

L0686       LD A,(L088F)        ;FIND WHICH SPEED
            OR A                ;ZERO = HIGH SPEED
            JR NZ,L068E         ;JUMP IF LOW SPEED
            SRL L               ;ELSE HALVE CYCLE COUNT
L068E       LD DE,0001H         ;
            LD A,0x84           ;TURN ON SPEAKER AND MIDDLE DISPLAY
L0693       OUT (DSCAN),A       ;
            LD B,C              ;
L0696       DJNZ L0696          ;PERIOD DELAY
            XOR 0x80            ;TOGGLE SPEAKER BIT
            SBC HL,DE           ;DECREASE CYCLE COUNT
            JR NZ,L0693         ;JUMP IF NOT ALL CYCLES DONE
            RET                 ;ELSE RETURN

;THIS ROUTINE SETS UP THE "ERR-IN DISPLAY ON THE PERIMETER HANDLER.

L069F       LD HL,L0752         ;POINT HL TO "Err-In" DISPLAY
            LD DE,L0800         ;CODE AND DE TO RAM DEstination
            LD BC,0x0006        ;BC(ount)
            LDIR                ;MOVE BLOCK
            JP L0050            ;JUNE TO SOFT PERIMETER ENTRY

;----END OF TAPE ROUTINES----
;THIS ROUTINE IS THE KEYBOARD READER/VALIDATER
;THE ACTION IS AS FOLLOWS:
;A SHORT LOOP LOOKS FOR A KEY PRESS. IF NO KEY IS PRESSED, THEN THE KEY PRESS BUFFER (0825) 
;IS CLEARED THE ZERO AND THE CARRY FLAG CLEARED AND THE ROUTINE RETURNS.
;IF A KEY IS FOUND, THEN THE REMAINING LOOP COUNTS ARE WORKED OFF IN A DUMMY LOOP TO ENSURE 
;EQUAL TIME IN EXECUTING THE ROUTINE.
;IF IT IS THE FIRST TIME.THAT THE KEY HAS BEEN DETECTED, THEN THE KEY PRESS FLAG WILL BE 
;CLEAR. (IT WAS CLEARED BY THE MONITOR VARIABLES ON RESET). THE ROUTINE TESTS FOR THIS 
;CONDITION AND IF TRUE THEN THE KEY IS ACCEPTED AS "VALID" AND FLAGGED BY A SET CARRY AND 
;SET ZERO FLAG AND THE KEY PRESS FLAG IS SET TO INDICATE THE A KEY HAS BEEN DETECTED. THE
;INPUT IS THEN PLACED IN BOTH THE "I" REGISTER AND THE ACCUMULATOR. IF A KEY IS DETECTED 
;BUT FOUND NOT TO BE VALID, I.E. IT HAS ALREADY BEEN DETECTED AND PROCESSED, THEN THE 
;CARRY WILL BE SET BUT THE ZERO CLEARED. THIS ALLOWS THE AUTO KEY REPEAT SECTION TO KNOW 
;THAT A KEY IS STILL BEING HELD DOWN. THE AUTO KEY REPEAT SECTION MAKE UP ITS OWN MIND 
;WHETHER IT IS VALID OR NOT.

L06AD       IN A,(KEYBOARD)     ;TEST FOR KEY PRESSED
            BIT 5,A             ;SC USES D5 AS THE DA INPUT
            JR NZ,L06BB         ;DA IS HIGH = KEYPRESS
            DJNZ L06AD          ;LOOP LOOKING FOR KEY UNTIL B=0
L06B5       XOR A               ;CLEAR KEY PRESS FLAG
            LD (L0825),A
            DEC A               ;SET A TO FF AND CLEAR ZERO FLAG
L06BA       RET                 ;DONE
L06BB       LD A,(L0825)        ;GET KEY PRESS FLAG
            OR A                ;TEST FOR ZERO
            JR NZ,L06C1         ;DUMMY JUMP TO EQUALIZE TIME
L06C1       DJNZ L06BB          ;FINISH LOOP
            SCF                 ;SET CARRY
            JR NZ,L06BA         ;DUMMY JUMP TO RETURN
            DEC A               ;SET KEY PRESS FLAG TO FF
            LD (L0825),A
L06CA       IN A,(KEYBOARD)     ;GET INPUT KEY FROM ENCODER CHIP
            AND 0x1F            ;MASK OFF UNUSED BITS
            BIT 7,A             ;SET ZERO FLAG (THINK ABOUT IT!)
            SCF                 ;SET CARRY
            LD (L0820) ,A       ;STORE INPUT KEY
            RET                 ;DONE
;
; INITIALISE AND TEST FOR THE LCD
;
L06D5       LD   B,110
            CALL DELAE                   ;MORE THAN 100MS POWER UP DELAY
            
            LD   HL,INTLCD               ;POINT TO INITIALISATION TABLE
            LD   BC,0x1000+LCDINST       ; B = NUMBER OF BYTES IN TABLE = 16, C = IO PORT
ISTEP       OUTI                         ;OUTPUT COMMAND TO LCD, INC HL, DEC B
            PUSH  BC
            LD   B,(HL)                  ;GET COMMAND DELAY TIME FROM TABLE
            INC  HL
            CALL DELAE
            POP  BC
            DJNZ ISTEP
;
; NOW SEE IF IT IS INITIALISED, READ THE INSTRUCTION REGISTER INSTEAD OF THE CGRAM
;
            IN  A,(C)    ;THE BUSY FLAG SHOULD BE LOW AND THE CGRAM ADDRESS SHOULD BE 0x00                    
            JP  L07B5    ; 3 BYTES
;
;  RAN OUT OF SPACE! SO MOVED FOLLOWING CODE TO L0B75 BELOW
;        
;            LD (L0821),A  ;3 BYTES
;            RET           ;1 BYTE

;           
; LCD INITIALISATION AND DELAY TABLE           
; <LCD COMMAND>,<MILLISECOND DELAY TIME FOR COMMAND TO COMPLETE>
;
            ORG   0x06F0
INTLCD      .DB   0x30,5            ;SPECIAL CASE OF 'FUNCTION SET', 5MS DELAY
            .DB   0x30,2            ;SPECIAL CASE OF 'FUNCTION SET', 2MS DELAY
            .DB   0x30,2            ;SPECIAL CASE OF 'FUNCTION SET', 2MS DELAY
            .DB   0x3C,2            ;FUNCTION SET 8 BIT INTERFACE, DUAL LINE, 2 MS DELAY
            .DB   0x08,2            ;DISPLAY OFF, NO CURSOR, NO BLINK, 2 MS DELAY
            .DB   0x01,10           ;CLEAR DISPLAY, 10MS DELAY
            .DB   0x06,2            ;ENTRY MODE SET  INCREMENT CG ADDRESS COUNTER, NO DISPLAY SHIFT, 2MS DELAY
            .DB   0x0C,2            ;DISPLAY ON,NO CURSOR, NO BLINK, 2 MS DELAY

            ORG    0x0700       ;AT 0700 IS THE TAPE'S MENU JUMP TABLE.
            JP    L043F         ;HIGH SPEED SAVE
            JP    L043F         ;LOW SPEED SAVE
            JP    L043B         ;TEST BLOCK
            JP    L0437         ;TEST CHECKSUM
            JP    L0426         ;LOAD TAPE

;BELOW ARE THE JMON DEFAULT RESET VARIABLES (A ZERO IS THE ACTIVE                           RAM 
;STATE UNLESS OTHERWISE STATED).                                                           LOCATION

L070F       .DB     0x00         ;KEY BUFFER                                                0820
            .DB     0x00         ;LCD ON/OFF FLAG                                           0821*
            .DB     0x00         ;SOUND ON/OFF                                              0822*
            .DB     0xFF         ;GO AT ALTERNATE GO ADDRESS IF AA                          0823*
            .DB     0xFF         ;STEPPER KEY CONTROL/TIMER                                 0824 
            .DB     0x00         ;KEY PRESSED FLAG                                          0825
            .DB     0xFF         ;UNUSED                                                    0826
            .DB     0x00         ;AUTO INCREMENT ON/OFF                                     0827*
            .DB     0x00,0x0A    ;ALT GO ADDR/SOFT RESET EDIT LOCATION                      0828*
            .DB     0x70         ;AUTO KEY REPEAT TIMER                                     082A
            .DB     0x00         ;MONITOR CONTROL BYTE                                      082B
            .DW     L0800        ;DISPLAY BUFFER ADDRESS                                    082C*
            .DW     L0900        ;INITIAL EDITING LOCATION (CEL)                            082E
;           
;BELOW ARE THE JMON INDIRECT JUMP ADDRESSES. THIS TABLE IS SHIFTED
;DOWN TO 0830 ON A HARD RESET.

L071F       JP    L01D5         ;CONVERT HL TO DISPLAY CODE                               0830
            JP    L01DA         ;CONVERT A TO DISPLAY CODE                                0833
            JP    L01BA         ;LED SCAN ROUTINE                                         0836
            JP    L01EE         ;SET LED DOTS                                             0839
            JP    L0224         ;RESET TONES                                              083C
            JP    L0227         ;TONE                                                     083F
            JP    L0181         ;SCAN/KEY/LCD/PATCH LOOP                                  0842
            JP    L00B2         ;SOFT JMON ENTRY                                          0845
            JP    L023C         ;LCD ROUTINE                                              0848

;BELOW ARE THE DISPLAY TABLES FOR THE TAPE'S MENU ADDRESS DISPLAYS AND 
;THE "ERR-IN" DISPLAY THAT IS SUPERIMPOSED OVER THE PERIMETER HANDLER.

L073A       .DB   0x6D,0x77,0x3E,0x79 ;"SAVE" 
            .DB   0x6D,0x77,0x3E,0x79 ;"SAVE" 
            .DB   0x78,0x79,0x6D,0x78 ;"TEST" 
            .DB   0x78,0x79,0x6D,0x78 ;"TEST" 
            .DB   0x38,0x3F,0x77,0x5E ;"LOAD" 
            .DB   0x40,0x79,0x54,0x5E ;"-End" 
L0752       .DB   0x40,0x79,0x50,0x50,0x06,0x54 ;"-Err In"
            .DB   0x73,0x77,0x6D,0x6D ;"PASS' 
L075C       .DB   0x71,0x77,0x06,0x38 ;"FAIL

;BELOW ARE THE TAPE'S MENU DATA DISPLAYS.

L0760       .DB  0x40,0x76      ;"-H"
            .DB  0x40,0x38      ;"-L"
            .DB  0x7C,0x38      ;"bL"
            .DB  0x39,0x6D      ;"CS"
L0768       .DB  0x40,0x78      ;"-t"
            .DB  0x40,0x6D      ;"-S"
            .DB  0x78,0x7C      ;"tb"
            .DB  0x39,0x6D      ;"CS"
            .DB  0x38,0x5E      ;"Ld"
;-------------------------
; APPROX. 1mS DELAY @ 4MHz
;-------------------------
            ORG  0x0772       
DELAE       PUSH   BC           ;11T
            LD    B,233         ;7T
DELAE2      NOP                 ;4T
            DJNZ  DELAE2        ;NZ=13T,Z=8T
            POP   BC            ;10T
            DJNZ  DELAE         ;NZ=13T,Z=8T
            RET                 ;10T
            
;       .DB  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;(UNUSED)

; * DENOTES CONTROL BYTES DESIGNED TO BE USER ALTERED (IN RAM).

;BELOW IS THE PERIMETER HANDLER COMMAND STRING FOR THE TAPE SOFTWARE.
            ORG 0x77C
L077C       .DB 0x00,0xFF,0xC6,0x07,0x99,0x08,0x00,0x03;(FF FF; THE JUMP ADDRESS FOR THE TAPE 
            ;ROUTINES IS SUPPLIED BY THE POST MENU SET-UP ROUTINES, SEE 0426-044E).

L0786       .DB  0xFF,0xFF,0xFF,0xFF,0xFF ;(RESERVED FOR COMMAND STRING EXPANSION). 

;BELOW IS THE TAPE'S MENU DRIVER COMMAND STRING.
L0789       .DB  0xFF,0xFF,0x00,0x04,0x00,0x07,0x3A,0x07,0x60,0x07

;TAPE'S SOFTWARE MENU DATA KEY HANDLER ROUTINE JUMP VECTOR 
;(A RETURN INSTRUCTION).
L0793       .DB  0xC9

;BELOW IS THE STEPPERS DATA DISPLAY CODES.
L0794       .DB  0x73,0x39      ;"PC"
            .DB  0x77,0x71      ;"AF"
            .DB  0x7C,0x39      ;"BC"
            .DB  0x5E,0x79      ;"DE"
            .DB  0x74,0x38      ;"HL"
            .DB  0x06,0x76      ;"IX"
            .DB  0x06,0x6E      ;"IY"
            .DB  0xF7,0xF1      ;"AF'"
            .DB  0xFC,0xB9      ;"BC'"
            .DB  0xDE,0xF9      ;"DE'"
            .DB  0xF4,0xB8      ;"HL'"
            .DB  0x6D,0x73      ;"SP"
            .DB  0xFF           ;(UNUSED)

;START OF STAGGERED TABLE OF JMON MODE WORDS FOR LCD
L07AD       .DB 0x44,0x61,0x74,0x61 ;"Data"   
L07B1       .DB 0x41,0x64,0x64,0x72 ;"Addr"

;LCD INITIALIZATION CODES
;L07B5  .DB  0x38,0x01,0x06,0x0C
;
; THE REST OF THE LCD INITIALISATION!
L07B5    LD (L0821),A
         RET

;THE REST OF THE JMON MODE WORD TABLE FOR LCD 
L07B9       .DB 0x46,0x73,0x2D  ;"Fs-"
            .DB 0xFF            ;(UNUSED)
            
;ADDRESS TABLE OF THE LCD PROMPT LOCATIONS. 
L07BD       .DB  0x84,0x87,0x8A,0x8D,0xC4,0xC7,0xCA,0xCD,0x80

;TAPE'S PERIMETER HANDLER DATA DISPLAYS
L07C6       .DB 0x40,0x71       ;"-F"
            .DB 0x40,0x6D       ;"-S"
            .DB 0x40,0x79       ;"-E"
            .DB 0x40,0x3D       ;"-G"
            .DB 0xFF,0xFF       ;(UNUSED)
            
;BELOW ARE THE DISPLAY CODE EQUIVALENTS OF THE HEX DIGITS 
;0 TO F LISTED IN ASCENDING ORDER.
L07D0       .DB 3FH,06H,5BH,4FH ;0,1,2,3
            .DB 66H,6DH,7DH,07H ;4,5,6,7
            .DB 7FH,6FH,77H,7CH ;8,9,A,B
            .DB 39H,5EH,79H,71H ;C,D,E,F

;FINALLY AT 07E0 IS THE FUNCTION-1 AND SHIFT JUMP ADDRESSES.
L07E0       .DW   L03D2
            .DW   L02E3
            .DW   L005E
            .DW   0xFFFF
            .DW   L02D3
            .DW   L00AE
            .DW   L02DE
            .DW   L0341
            .DW   L02ED
            .DW   L02E8
            .DW   L02F2
            .DW   0xFFFF
            .DW   0xFFFF
            .DW   0xFFFF
            .DW   0xFFFF
            .DW   0xFFFF
            END
