ROM EQU 0Q
RAM EQU 01100Q
RV10 EQU RAM + 010Q
RV20 EQU RAM + 020Q
RV30 EQU RAM + 030Q
RV40 EQU RAM + 040Q
RV50 EQU RAM + 050Q
RV60 EQU RAM + 060Q
TOS EQU 02000Q
P0 EQU 0
P1 EQU 1
P2 EQU 2
DELAY EQU 0446Q
; The following jumps vector into RAM to enable
; user programs to use the restart instructions
; and/or hardware interrupts.
.org ROM + 000Q
JMP START
.org ROM + 010Q
JMP RV10
.org ROM + 020Q
JMP RV20
.org ROM + 030Q
JMP RV30
.org ROM + 040Q
JMP RV40
.org ROM + 050Q
JMP RV50
.org ROM + 060Q
JMP RV60
; Start of main program.
.org ROM + 070Q
START:
LXI SP,TOS ; Set the stack pointer to the top of
; RAM (actually, one byte higher because
; the stack pointer is automaticcaly
; decremented before use.
LXI H,RAM ; The initial value for HL is the start
; of RAM.
POINTA:
MOV C,M ; Load the memory data into a temporary
; data buffer (register C).
MOV A,H ; Output the high byte of the memory
OUT P1 ; address to the diagnostic LEDs.
MOV A,L ; Output the low byte of the memory
OUT P0 ; address to the diagnostic LEDs.
POINTB:
MOV A,C ; Output the temporary data buffer
OUT P2 ; to the diagnostic LEDs.
POINTC:
CALL KBRD ; Wait and input next key closure.
CPI 010Q ; Is the value numerical (0..7)?
JNC POINTD ; Jump if a command.
; The detected keypress was numerical (0-7).
MOV B,A ; Save the keycode into reister B.
MOV A,C ; Get the 'old' data value.
RAL ; Rotate 1 bit to the left.
RAL ; Rotate a total of 2 bits to the left.
RAL ; Rotate a total of 3 bits to the left.
ANI 0370Q ; Mask out the least significant octal digit (11 111 000).
ORA B ; 'OR' in the new octal digit.
MOV C,A ; Put the new data value back into the buffer.
JMP POINTB ; Take action (output the new data value to the LEDs).
POINTD:
CPI 011Q ; Is the keypress the "L" command?
JNZ POINTE ; Jump if not.
MOV L,C ; Store buffer data into the low byte of the address (register L).
JMP POINTA ; Take action (output the new address and data value to the LEDs).
POINTE:
CPI 010Q ; Is the keypress the "H" command?
JNZ POINTF ; Jump if not.
MOV H,C ; Store buffer data into the hgh byte of the address (register H).
JMP POINTA ; Take action (output the new address and data value to the LEDs).
POINTF:
CPI 013Q ; Is the keypress the "S" command?
JNZ POINTG ; Jump if not.
MOV M,C ; Store the data buffer into memory.
INX H ; Increment the memory pointer.
JMP POINTA ; Take action (output the new address and data value to the LEDs).
POINTG:
CPI 012Q ; Is the keypress the "G" command?
JNZ POINTC ; Jump if not. Basically, ignore the command.
PCHL ; Go and execute the program specified by the address register HL.
; We should never get here!
.org ROM + 0277Q
; This 10 millisecond delay does not corrupt any registers or the flags.
TIMOUT:
PUSH PSW ; Save CPU flags.
PUSH D ; Save the registers that are used within the subroutine.
LXI D,DELAY ; Load DE with the desired delay count for 10 milliseconds.
MORE:
DCX D ; Decrement the DE register pair.
MOV A,D ; Check to see if registers D and E are zero (0).
ORA E ; Ditto.
JNZ MORE ; If DE is none zero, keep looping until it is.
POP D ; Restore DE from the stack.
POP PSW ; Restore the CPU flags from the stack.
RET ; Return from the TIMOUT subroutine back to the caller.
; The KBRD subroutine debounces key closures and translates key codes.
KBRD:
IN P0 ; Input from the keyboard.
ORA A ; Set CPU flags appropriately.
JM KBRD ; Loop if key still pressed.
CALL TIMOUT ; Wait for 10 milliseconds.
FLAGCK:
IN P0 ; Input from the keyboard.
ORA A ; Set CPU flags appropriately.
JP FLAGCK ; Loop if no key press.
CALL TIMOUT ; Wait for 10 milliseconds (debounce).
IN P0 ; Input from the keyboard.
ORA A ; Set CPU flags appropriately.
JP FLAGCK ; Loop if key not pressed (false alarm).
ANI 017Q ; Mask out everything except the keycode itself (00 001 111).
PUSH H ; Save HL onto the stack.
MVI H,0 ; Zero into the H register.
ADI 0360Q ; Add the address of the beginning of the table to the keycode.
MOV L,A ; Store into the L register.
MOV A,M ; Indexed byte from table into A.
POP H ; Recover HL from the stack.
RET ; Return from the KBRD subroutine.
TABLE:
DB 000Q ; '0'.
DB 001Q ; '1'.
DB 002Q ; '2'.
DB 003Q ; '3'.
DB 004Q ; '4'.
DB 005Q ; '5'.
DB 006Q ; '6'.
DB 007Q ; '7'.
DB 013Q ; 'S'. Store/See...
DB 000Q ; Never generated. No button!
DB 017Q ; 'C'. Unused.
DB 012Q ; 'G'. Go...
DB 010Q ; 'H'. High byte of address...
DB 011Q ; 'L'. Low byte of address...
DB 015Q ; 'A'. Unused.
DB 016Q ; 'B'. Unused.
.end