JMON_SRC_01.asm
tec1group_Software/monitors/JMon/JmonSource/JMON_SRC_01.asm
;
; JMON - JIM'S MONITOR
; BY JIM ROBERTSON
;
;
; FILENAME : JMON_SRC_01.ASM
; VERSION : 1
;
; RESTORED TO SOURCE FROM PDF LISTING(S) FEBRUARY 2021
; THE PHOTOCOPIED PDF LISTING WAS CONVERTED TO A TEXT FILE VIA OCR
; THE MISSING PAGE 9 WAS TAKEN FROM ANOTHER VERSION OF THE LISTING
; PAGE NUMBERS REFER TO THE PHOTOCOPIED LISTING PDF FILE
;
;
; <PAGE 23> KEYBOARD READER/VALIDATER CONDITIONAL ASSEMBLY
; JMON USES BIT 6 OF THE LATCH ON THE DAT BOARD TO READ THE INVERTED DA 
; FROM THE KEYBOARD ENCODER 
; THE CONDITIONAL ASSEMBLY ALLOWS FOR THE ACTIVE HIGH DA SIGNAL TO 
; BE CONNECTED DIRECTLY TO D6 (VIA A TRI-STATE BUFFER) AT THE KEYBOARD I/O ADDRESS
;
; KEYBOARD ENCODER DA (DATA AVAILABLE) IS ACTIVE HIGH 
;#DEFINE DA_ACTIVE_HIGH
;KEYBOARD ENCODER DA CONNECTED TO KEYBOARD INPUT PORT DATA BIT 6
;#DEFINE DA_KEYBOARD
;
; < PAGE 1 >
;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 INFORMATION 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 THjN 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.
; <PAGE 2>
;
;
L0804   EQU  0804H
L0805   EQU  0805H
L0820   EQU  0820H                      ;KEY BUFFER 
L0821   EQU  0821H                      ;LCD ON/OFF FLAG
L0822   EQU  0822H                      ;SOUND ON/OFF   
L0823   EQU  0823H                      ;GO AT ALTERNATE GO ADDRESS IF AA  
L0824   EQU  0824H                      ;STEPPER KEY CONTROL/TIMER  
L0825   EQU  0825H                      ;KEY PRESS FLAG
L0826   EQU  0826H                      ;UNUSED 
L0827   EQU  0827H                      ;AUTO INCREMENT ON/OFF  
L0828   EQU  0828H                      ;ALT GO ADDR/SOFT RESET EDIT LOCATION 
L082A   EQU  082AH                      ;AUTO KEY STATUS BYTE
L082B   EQU  082BH                      ;MONITOR CONTROL BYTE (MCB)
L082C   EQU  082CH                      ;DISPLAY BUFFER ADDRESS

L082E   EQU  082EH                      ;CURRENT EDITING LOCATION

L0830   EQU  0830H
L0833   EQU  0833H
L0836   EQU  0836H
L0839   EQU  0839H
L083C   EQU  083CH
L083F   EQU  083FH

L0842   EQU  0842H
L0848   EQU  0848H
L084B   EQU  084BH
L084E   EQU  084EH

L0851   EQU  0851H
L0858   EQU  0858H                      ;"NEXT PC" BUFFER   
L085A   EQU  085AH

L0860   EQU  0860H
L0868   EQU  0868H
L086E   EQU  086EH

L0870   EQU  0870H
L087E   EQU  087EH
L0882   EQU  0882H
L0884   EQU  0884H
L0886   EQU  0886H
L0887   EQU  0887H
L0888   EQU  0888H
L088A   EQU  088AH
L088C   EQU  088CH
L088F   EQU  088FH

L0891   EQU  0891H
L0893   EQU  0893H
L0895   EQU  0895H
L0897   EQU  0897H
L0898   EQU  0898H
L089A   EQU  089AH
L089C   EQU  089CH
L089E   EQU  089EH

L08A4   EQU  08A4H
L08A6   EQU  08A6H
L08A8   EQU  08A8H
L08AA   EQU  08AAH

L08B0   equ  08B0H    
L08B1   EQU  08B1H
L08B3   EQU  08B3H
L08B6   EQU  08B6H

L089A   EQU  089AH
L089E   EQU  089EH

L08FF   EQU  08FFH
L3800   EQU  3800H                      ;LCD ROUTINES

;
; IO ASSIGNMENTS
;
KEYBOARD EQU 0x00      ;KEYBOARD ENCODER
DSCAN    EQU 0x01      ;DISPLAY CATHODE DRIVER LATCH
DSEGMENT EQU 0x02      ;DISPLAY SEGMENT DRIVER LATCH
;DAT BOARD
DATLATCH EQU 0x03      ;DAT BOARD LATCH
LCDDATA  EQU 0x84      ;LCD DATA REGISTER
LCDINST  EQU 0X04      ;LCD INSTRUCTION REGISTER



;
;                                  CORRECTED 2/11/1989
;
;AT THE START OF JMON, HL IS SAVED IN ITS SINGLE STEPPER BUFFER ADD 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
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 TARE 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
       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

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

       JP L0312        ;JUMP TO STEPPER ROUTINE 
       RST 38H         ;UNUSED
       RST 38H         ;"   "
       RST 38H         ;"   "
       RST 38H         ;"   "
       RST 38H         ;"   "
; <PAGE 3>
       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).

       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,0x070F    ;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.
; <PAGE 4>
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
       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 0x10         ;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 0x11         ;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 0x12         ;TEST FOR GO
       JR NZ,L0102     ;JUMP IF NOT TO TEST FOR "AD"

;"GO" HANDLER (WHEN IN DATA MODEONLY)

       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,0x0845    ;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 0x13            ;TEST FOR ADDRESS KEY
; <PAGE 5>
       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 5,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 HI, 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
; <PAGE 6>
;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,0x08BE    ;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.

       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
; <PAGE 7>
       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.

       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.

       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.

       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.

       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 4,(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          ;
; <PAGE 8>
       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

       CALL L083F      ;CALL TONE

;MASKABLE TONE ROUTINE

       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.

       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
; <PAGE 9>
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,0484H     ;LOAD C WITH PORT, B WITH BYTE COUNT

; <PAGE 10>
       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).

       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
       LD DE,0xFFFC    ;DE= -4
       JR L02D6        ;JUMP TO ADD
       LD DE,0xFFFF    ;DE= -1
       JR L02D6        ;JUMP TO ADD
       LD DE,0x0001    ;DE= +1
       JR L02D6        ;JUMP TO ADD
       LD DE,0x0008    ;DE++8
       JR L02D6        ;JUMP TO ADD
       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,0x08B5    ;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,0x0344    ;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
; <PAGE 11>
       LD (L0858),HL   ;OF NEXT BYTE TO STEP: STORE IN
       LD SP,0x087E    ;"NEXT PC" BUFFER: LOAD REGISTER DUMP
       EX AF,AF'       ;STACK: PUSH ALTERNATE REGISTERS
       EXX             ;FIRST
       PUSH HL         ;SAVE AIL 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
       LD SP,0x086A    ;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.

       LD HL,0x0806    ;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
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
 ; <PAGE 12>
;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,0x085A    ;THUS DISABLING THE AUTO REPEAT MODE
       LD A,B          ;POINT HI, TO CURRENT REG No. BUFFER
       CP 0x10         ;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 11H          ;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 0x12         ;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
; <PAGE 13>
       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 0x13          ;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.

       LD HL,077CH     ;LOAD HL WITH START OF TAPE 
       LD DE,0880H     ;VARIABLES: DE IS RAM DE(stination)
       LD BC,0018H     ;BC IS THE COUNT
       LDIR            ;SHIFT VARIABLES
L03DD  LD HL,0800H     ;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,0x0800    ;SHIFT ACROSS ADDR DISPLAY
       LDIR            ;TO 0800 (LC-0004 FROM ABOVE) 
       POP HL          ;POP DATA DISPLAY ADDR INTO HL
; <PAGE 14>
       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,0x088F    ;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

       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,0x0531   ;LOAD HL WITH "GO" ADDR OF LOAD/TEST
       JR L0444       ;ROUTINE: JUMP TO STORE HL AND A

;"TEST BLOCK" SET-UP

       LD A,0x02       ;2=TEST BLOCK SIGN-ON BYTE
;<PAGE 15>

L0439  JR L0427        ;JUMP TO TEST/LOAD COMMON AREA

;"TEST CHECKSUM" SET-UP

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

;SAVE SET-UP

       LD HL,0x0450    ;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".

       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 MAYOR 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 CALCULATER.
;THE ONLY OTHER MAYOR 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 USEDIN 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
;<PAGE 16>
;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,0x0800    ;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  0x10        ;IS THE KEY
       JR  Z,L04D1     ;JUMP IF SO TO "+" HANDLER 
       CP  0x11        ;IS IT "-"
       JR  Z,L04D1     ;JUMP IF SO TO "-" HANDLER 
       CP  0x13        ;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  0x12        ;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
;<PAGE 17>
       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,0x08A4    ;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
;<PAGE 18>
       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
;<PAGE 19>
       LD HL,0x08A4    ;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,0x0800    ;LOAD BC TO POINT TO DISPLAY BUFFER 
       LD HL,(L08A4)   ;PUT FILE NUMBER INTO EL
       CALL L0830      ;CONVERT HL TO DISPLAY CODE
       LD A,0x47       ;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
;<PAGE 20>
       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,0x0768    ;LOAD DE TO BASE OF DATA DISPLAY 
L05B7  LD HL,0x075C    ;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
;<PAGE 21>
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
;<PAGE 22>
       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,0x0752    ;POINT HL TO "Err-In" DISPLAY
       LD DE,0x0800    ;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----
;<PAGE 23>
;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.

;#IFDEF  DA_KEYBOARD
;L06AD  IN A,(KEYBOARD)      ;TEST FOR KEY PRESSED
;#ELSE
L06AD  IN A,(DATLATCH)      ;TEST FOR KEY PRESSED
;#ENDIF
       BIT 6,A
;#IFDEF DA_ACTIVE_HIGH
;       JR NZ,L06BB     ;DA IS HIGH = KEYPRESS
;#ELSE      
       JR Z,L06BB      ;DA IS LOW = KEYPRESS
;#ENDIF       
       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

;THIS ROUTINE IS CALLED ONCE ON EVERY HARD RESET. IT INITIALIZES THE LCD THEN TESTS THAT 
;IT IS THERE (IT CANNOT DO IT THE OTHER WAY AROUND AS THE LCD NEEDS TO BE INITIALIZED 
;BEFORE IT WILL RESPOND INTELLIGENTLY). IF THE LCD IS FITTED THEN THE ROUTINE WILL READ 
;IN AN ASCII SPACE CHARACTER (20H) OR IF THE LCD IS NOT, JUNK FROM THE DATA BUSS.
;20H IS SUBTRACTED FROM WHATEVER IS READ IN AND THE RESULT IS STORED IN THE LCD ENABLE 
;BUFFER. IF THE RESULT IS ZERO THEN THE LCD IS ENABLED. IT IS VITAL TO KNOW IF THE LCD IS 
;FITTED, OTHERWISE THE ROUTINE WHICH READS THE BUSY FLAG MAY LOOP FOREVER.

L06D5  LD HL,0x07B5    ;POINT HL TO LCD INITIALIZE TABLE 
       LD BC,0x0404    ;B=4 BYTES, C=PORT 4
L06DB  LD DE,0500H     ;DELAY BETWEEN
L06DE  DEC DE          ;EACH BYTE
       LD A,D          ;AS PER
       OR E            ;LCD MANUFACTER'S
       JR NZ,L06DE     ;INSTRUCTIONS
       OUTI            ;OUTPUT (HL) TO (C). HL=HL=1,B=B-1 
       JR NZ,L06DB     ;JUMP IF B NOT 0
L06E7  DJNZ L06E7      ;SHORT DELAY
       IN A,(LCDDATA)  ;INPUT FROM LCD TO SEE IF IT'S THERE 
       SUB 0x20        ;SUBTRACT ASCII SPACE, IF LCD FITTED 
       LD (L0821),A    ;RESULT WILL BE ZERO: STORE THIS IN 
       RET             ;LCD MASK: DONE
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
       RST 38H         ;
;<PAGE 24>

;AT 0700   IS THE TAPE'S MENU JUMP TABLE.
;0700  C3  3F 04             ;HIGH SPEED SAVE
;0703  C3  3F 04             ;LOW SPEED SAVE
;0706  C3  3B 04             ;TEST BLOCK
;0709  C3  37 04             ;TEST CHECKSUM
;070C  C3  26 04             ;LOAD TAPE

       ORG    0x0700
       .DB    0xC3,0x3F,0x04           ;HIGH SPEED SAVE
       .DB    0xC3,0x3F,0x04           ;LOW SPEED SAVE
       .DB    0xC3,0x3B,0x04           ;TEST BLOCK
       .DB    0xC3,0x37,0x04           ;TEST CHECKSUM
       .DB    0xC3,0x26,0x04           ;LOAD TAPE

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

;070F 00                     ;KEY BUFFER                                                0820
;0710 00                     ;LCD ON/OFF FLAG                                           0821*
;0711 00                     ;SOUND ON/OFF                                              0822*
;0712 FF                     ;GO AT ALTERNATE GO ADDRESS IF AA                          0823*
;0713 FF                     ;STEPPER KEY CONTROL/TIMER                                 0824 
;0714 00                     ;KEY PRESSED FLAG                                          0825 
;0715 FF                     ;UNUSED                                                    0826
;0716 00                     ;AUTO INCREMENT ON/OFF                                     0827*
;0717 00 OA                  ;ALT GO ADDR/SOFT RESET EDIT LOCATION                      0828*
;0719 70                     ;AUTO KEY REPEAT TIMER                                     082A
;071A 00                     ;MONITOR CONTROL BYTE                                      082B
;071B 00 08                  ;DISPLAY BUFFER ADDRESS                                    082C*
;071D 00 09                  ;INITIAL EDITING LOCATION                                  082E

        .DB     0x00
        .DB     0x00
        .DB     0x00
        .DB     0xFF
        .DB     0xFF
        .DB     0x00
        .DB     0xFF
        .DB     0x00
        .DB     0x00,0x0A
        .DB     0x70
        .DB     0x00
        .DB     0x00,0x08
        .DB     0x00,0x09
                
;BELOW ARE THE JMON INDIRECT JUMP ADDRESSES. THIS TABLE IS SHIFTED
;DOWN TO 0830 ON A HARD RESET.

;071F C3 D5 01              ;CONVERT HL TO DISPLAY CODE                               0830
;0722 C3 DA 01              ;CONVERT A TO DISPLAY CODE                                0833
;0725 C3 BA 01              ;LED SCAN ROUTINE                                         0836
;0728 C3 EE 01              ;SET LED DOTS                                             0839
;072B C3 24 02              ;RESET TONES                                              083C
;072E C3 27 02              ;TONE                                                     083F
;0731 C3 81 01              ;SCAN/KEY/LCD/PATCH LOOP                                  0842
;0734 C3 B2 00              ;SOFT JMON ENTRY                                          0845
;0737 C3 3C 02              ;LCD ROUTINE                                              0848

       .DB    0xC3,0xD5,0x01
       .DB    0xC3,0xDA,0x01
       .DB    0xC3,0xBA,0x01
       .DB    0xC3,0xEE,0x01
       .DB    0xC3,0x24,0x02
       .DB    0xC3,0x27,0x02
       .DB    0xC3,0x81,0x01
       .DB    0xC3,0xB2,0x00
       .DB    0xC3,0x3C,0x02

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

;073A   A7 6F EA C7           ;"SAVE" 
;073E   A7 6F EA C7           ;"SAVE" 
;0742   C6 C7 A7 C6           ;"TEST" 
;0746   C6 C7 A7 C6           ;"TEST" 
;074A   C2 EB  6F EC          ;"LOAD" 
;074E   04 C7  64 EC          ;"-End" 
;0752   04 C7  44 44  28 64   ;"-Err In"
;0758  4F 6F A7 A7            ;"PASS' 
;075C  47 6F  28 C2           ;"FAIL

       .DB   0xA7,0x6F,0xEA,0xC7 
       .DB   0xA7,0x6F,0xEA,0xC7
       .DB   0xC6,0xC7,0xA7,0xC6 
       .DB   0xC6,0xC7,0xA7,0xC6 
       .DB   0xC2,0xEB,0x6F,0xEC
       .DB   0x04,0xC7,0x64,0xEC  
       .DB   0x04,0xC7,0x44,0x44,0x28,0x64
       .DB   0x4F,0x6F,0xA7,0xA7
       .DB   0x47,0x6F,0x28,0xC2 

;BELOW ARE THE TAPE'S MENU DATA DISPLAYS.

;0760  04 04 6E              ;"-H"
;0762  04 C2                 ;"-L"
;0764  E6 C2                 ;"bL"
;0766  C3 A7                 ;"CS"
;0768  04 C6                 ;"-t"
;076A  04 A7
;076C  C6 E6                 ;"tb"
;076E  C3 A7                 ;"CS"
;0770  C2 EC                 ;"Ld"
;0772  - 077B  (UNUSED)

L0760  .DB  0x04,0x6E                 ;"-H"
       .DB  0x04,0xC2                 ;"-L"
       .DB  0xE6,0xC2                 ;"bL"
       .DB  0xC3,0xA7                 ;"CS"
       .DB  0x04,0xC6                 ;"-t"
       .DB  0x04,0xA7
       .DB  0xC6,0xE6                 ;"tb"
       .DB  0xC3,0xA7                 ;"CS"
       .DB  0xC2,0xEC                 ;"Ld"
       .DB  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;(UNUSED)

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

;<PAGE 25>

;BELOW IS THE PERIMETER HANDLER COMMAND STRING FOR THE TAPE SOFTWARE.
;077C 00 FF C6 07 99 08 00 03 ;(FF FF; THE JUMP ADDRESS FOR THE TAPE 

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).
                                     
;0786 - 0788 FF ;(RESERVED FOR COMMAND STRING EXPANSION). 
L0786  .DB  0xFF,0xFF,0xFF,0xFF,0xFF

;BELOW IS THE TAPE'S MENU DRIVER COMMAND STRING.
;0789 FF FF 00 04 00 07 3A 07 60 07
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).
;0793 C9
L0793  .DB  0xC9

;BELOW IS THE STEPPERS DATA DISPLAY CODES.
;0794 4F C3           ;"PC"
;0796 6F 47           ;"AF"
;0798 E6 C3           ;"BC"
;079A EC C7           ;"DE"
;079C 6E C2           ;"HL"
;079E 28 6E           ;"IX"
;07A0 28 AE           ;"IY"
;07A2 7F 57           ;“AF'"
;07A4 F6 D3           ;"BC'"
;07A6 FC D7           ;"DE'"
;07A8 7E D2           ;"HL'"
;07AA A7 4F            ;"SP"
;07AC FF              ;(UNUSED)

       .DB  0x4F,0xC3           ;"PC"
       .DB  0x6F,0x47           ;"AF"
       .DB  0xE6,0xC3           ;"BC"
       .DB  0xEC,0xC7           ;"DE"
       .DB  0x6E,0xC2           ;"HL"
       .DB  0x28,0x6E           ;"IX"
       .DB  0x28,0xAE           ;"IY"
       .DB  0x7F,0x57           ;“AF'"
       .DB  0xF6,0xD3           ;"BC'"
       .DB  0xFC,0xD7           ;"DE'"
       .DB  0x7E,0xD2           ;"HL'"
       .DB  0xA7,0x4F           ;"SP"
       .DB  0xFF               ;(UNUSED)


;START OF STAGGERED TABLE OF JMON MODE WORDS FOR LCD
;07AD 44 61 74 61    "Data"
;07B1 41 64 64 72    "Addr"
L07AD  .DB 0x44,0x61,0x74,0x61   
L07B1  .DB 0x41,0x64,0x64,0x72 

;LCD INITIALIZATION CODES
;07B5 38 01 06 OC
L07B5  .DB  0x38,0x01,0x06,0x0C

;THE REST OF THE JMON MODE WORD TABLE FOR LCD 
;07B9 46 73 2D        "Fs-"
;07BC FF (UNUSED)
L07B9  .DB 0x46,0x73,0x2D
       .DB 0xFF
         
;ADDRESS TABLE OF THE LCD PROMPT LOCATIONS. 
;07BD 84 87 8A 8D C4 C7 CA CD 80
L07BD  .DB  0x84,0x87,0x8A,0x8D,0xC4,0xC7,0xCA,0xCD,0x80

;TAPE'S PERIMETER HANDLER DATA DISPLAYS
;07C6 04 47          "-F"
;07C8 04 A7          "-S"
;07CA 04 C7          u_Ett
;07CC 04 E3
;07CD - O7CF FF (UNUSED)
L07C6  .DB 0x04,0x47   
       .DB 0x04,0xA7
       .DB 0x04,0xC7
       .DB 0x04,0xE3
       .DB 0xFF,0xFF

;BELOW ARE THE DISPLAY CODE EQUIVALENTS OF THE HEX DIGITS 
;0 TO F LISTED IN ASCENDING ORDER.
;07D0 EB 28 CD AD 2E A7 E7 29 EF 2F 6F E6 C3 EC C7 47 

L07D0  .DB 0xEB,0x28,0xCD,0xAD,0x2E,0xA7,0xE7,0x29,0xEF,0x2F,0x6F,0xE6,0xC3,0xEC,0xC7,0x47

;FINALLY AT 07E0 IS THE FUNCTION-1 AND SHIFT JUMP ADDRESSES.
;07E0 D2 03 E3 02 5E 00 FF FF D3 02 AE 00 DE 02 41 03 
;07F0 ED 02 E8 02 F2 02 FF FF FF FF FF FF FF FF FF FF

L07E0  .DB 0xD2,0x03,0xE3,0x02,0x5E,0x00,0xFF,0xFF,0xD3,0x02,0xAE,0x00,0xDE,0x02,0x41,0x03 
       .DB 0xED,0x02,0xE8,0x02,0xF2,0x02,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
       END