You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

643 lines
12 KiB

;
;==================================================================================================
; UTILITY FUNCTIONS
;==================================================================================================
;
;
CHR_CR .EQU 0DH
CHR_LF .EQU 0AH
CHR_BS .EQU 08H
CHR_ESC .EQU 1BH
;
;__________________________________________________________________________________________________
;
; UTILITY PROCS TO PRINT SINGLE CHARACTERS WITHOUT TRASHING ANY REGISTERS
;
PC_SPACE:
PUSH AF
LD A,' '
JR PC_PRTCHR
PC_PERIOD:
PUSH AF
LD A,'.'
JR PC_PRTCHR
PC_COLON:
PUSH AF
LD A,':'
JR PC_PRTCHR
PC_COMMA:
PUSH AF
LD A,','
JR PC_PRTCHR
PC_LBKT:
PUSH AF
LD A,'['
JR PC_PRTCHR
PC_RBKT:
PUSH AF
LD A,']'
JR PC_PRTCHR
PC_LT:
PUSH AF
LD A,'<'
JR PC_PRTCHR
PC_GT:
PUSH AF
LD A,'>'
JR PC_PRTCHR
PC_LPAREN:
PUSH AF
LD A,'('
JR PC_PRTCHR
PC_RPAREN:
PUSH AF
LD A,')'
JR PC_PRTCHR
PC_ASTERISK:
PUSH AF
LD A,'*'
JR PC_PRTCHR
PC_CR:
PUSH AF
LD A,CHR_CR
JR PC_PRTCHR
PC_LF:
PUSH AF
LD A,CHR_LF
JR PC_PRTCHR
PC_PRTCHR:
CALL COUT
POP AF
RET
NEWLINE:
CALL PC_CR
CALL PC_LF
RET
;
; PRINT THE HEX BYTE VALUE IN A
;
PRTHEXBYTE:
PUSH AF
PUSH DE
LD DE,HEXSTRBUF
CALL HEXSTRBYTE
LD A,'$'
LD (DE),A
LD DE,HEXSTRBUF
CALL WRITESTR
POP DE
POP AF
RET
;
; PRINT THE HEX WORD VALUE IN BC
;
PRTHEXWORD:
PUSH AF
LD A,B
CALL PRTHEXBYTE
LD A,C
CALL PRTHEXBYTE
POP AF
RET
;
; CONVERT VALUE IN A TO A 2 CHARACTER HEX STRING AT DE
;
HEXCHR .TEXT "0123456789ABCDEF"
;
HEXSTRBYTE:
PUSH BC
PUSH HL
PUSH AF
LD BC,0
RRA
RRA
RRA
RRA
AND 0FH
LD C,A
LD HL,HEXCHR
ADD HL,BC
LD A,(HL)
LD (DE),A
INC DE
POP AF
PUSH AF
LD BC,0
AND 0FH
LD C,A
LD HL,HEXCHR
ADD HL,BC
LD A,(HL)
LD (DE),A
INC DE
POP AF
POP HL
POP BC
RET
;
; CONVERT VALUE IN BC TO A 4 CHARACTER HEX STRING AT DE
;
HEXSTRWORD:
LD A,B
CALL HEXSTRBYTE
LD A,C
CALL HEXSTRBYTE
RET
;
; PRINT A BYTE BUFFER IN HEX POINTED TO BY DE
; REGISTER A HAS SIZE OF BUFFER
;
PRTHEXBUF:
CP 0 ; EMPTY BUFFER?
JP Z,PRTHEXBUF2
LD B,A
PRTHEXBUF1:
CALL PC_SPACE
LD A,(DE)
CALL PRTHEXBYTE
INC DE
DJNZ PRTHEXBUF1
JP PRTHEXBUFX
PRTHEXBUF2:
CALL PC_SPACE
LD DE,STR_EMPTY
CALL WRITESTR
PRTHEXBUFX:
RET
;
; OUTPUT A '$' TERMINATED STRING
;
WRITESTR:
PUSH AF
WRITESTR1:
LD A,(DE)
CP '$' ; TEST FOR STRING TERMINATOR
JP Z,WRITESTR2
CALL COUT
INC DE
JP WRITESTR1
WRITESTR2:
POP AF
RET
;
; PANIC: TRY TO DUMP MACHINE STATE AND HALT
;
PANIC:
DI ; STOP ANY INTERRUPTS
PUSH HL
PUSH DE
PUSH BC
PUSH AF
LD DE,STR_PANIC
CALL WRITESTR
LD DE,STR_AF
CALL WRITESTR
POP BC
CALL PRTHEXWORD
LD DE,STR_BC
CALL WRITESTR
POP BC
CALL PRTHEXWORD
LD DE,STR_DE
CALL WRITESTR
POP BC
CALL PRTHEXWORD
LD DE,STR_HL
CALL WRITESTR
POP BC
CALL PRTHEXWORD
LD DE,STR_PC
CALL WRITESTR
POP BC
CALL PRTHEXWORD
LD DE,STR_SP
CALL WRITESTR
LD (PANIC_SP),SP
LD BC,(PANIC_SP)
CALL PRTHEXWORD
JP 0
;
;==================================================================================================
; CONSOLE CHARACTER I/O HELPER ROUTINES (REGISTERS PRESERVED)
;==================================================================================================
;
; OUTPUT CHARACTER FROM A
COUT:
PUSH AF
PUSH BC
PUSH DE
PUSH HL
#IFDEF CIOMODE_CONSOLE
#DEFINE CIOMODE_NONDOS
LD E,A
LD A,(CONDEV)
LD C,A
LD B,BF_CIOOUT
CALL BIOS_DISPATCH
#ENDIF
#IFDEF CIOMODE_CBIOS
#DEFINE CIOMODE_NONDOS
LD C,A
CALL CBIOS_CONOUT
#ENDIF
#IFNDEF CIOMODE_NONDOS
LD E,A
LD C,03H
CALL 0005H
#ENDIF
POP HL
POP DE
POP BC
POP AF
RET
;
; INPUT CHARACTER TO A
;
CIN:
PUSH BC
PUSH DE
PUSH HL
#IFDEF CIOMODE_CONSOLE
#DEFINE CIOMODE_NONDOS
LD A,(CONDEV)
LD C,A
LD B,BF_CIOIN
CALL BIOS_DISPATCH
LD A,E
#ENDIF
#IFDEF CIOMODE_CBIOS
#DEFINE CIOMODE_NONDOS
CALL CBIOS_CONIN
#ENDIF
#IFNDEF CIOMODE_NONDOS
LD C,01H
CALL 0005H
#ENDIF
POP HL
POP DE
POP BC
RET
;
; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING)
;
CST:
PUSH BC
PUSH DE
PUSH HL
#IFDEF CIOMODE_CONSOLE
#DEFINE CIOMODE_NONDOS
LD B,BF_CIOIST
LD A,(CONDEV)
LD C,A
CALL BIOS_DISPATCH
#ENDIF
#IFDEF CIOMODE_CBIOS
#DEFINE CIOMODE_NONDOS
CALL CBIOS_CONST
#ENDIF
#IFNDEF CIOMODE_NONDOS
LD C,0BH
CALL 0005H
#ENDIF
POP HL
POP DE
POP BC
RET
;
STR_PANIC .DB "\r\n\r\n>>> FATAL ERROR:$"
STR_AF .DB " AF=$"
STR_BC .DB " BC=$"
STR_DE .DB " DE=$"
STR_HL .DB " HL=$"
STR_PC .DB " PC=$"
STR_SP .DB " SP=$"
;
; INDIRECT JUMP TO ADDRESS IN HL
;
; MOSTLY USEFUL TO PERFORM AN INDIRECT CALL LIKE:
; LD HL,xxxx
; CALL JPHL
;
JPHL: JP (HL)
;
; DELAY ABOUT 25us (100 TSTATES INCLUDING CALL AND RET)
;
; TOTAL T STATES = ((B*13) + 51)
; 4MHZ CPU, B=4, 103 T STATES = 25.75us
; 8MHZ CPU, B=12, 207 TSTATES = 25.875us
; B = ((2 * FREQ) - 4)
;
DELAY: ; 17 T STATES (FOR CALL)
PUSH BC ; 11 T STATES
LD B,((CPUFREQ * 2) - 4) ; 8 T STATES
DJNZ $ ; (B*13) - 5 T STATES
POP BC ; 10 T STATES
RET ; 10 T STATES
;
; DELAY 25us * VALUE IN DE (VARIABLE DELAY)
;
VDELAY:
CALL DELAY
DEC DE
LD A,D
OR E
JP NZ,VDELAY
RET
;
; DELAY ABOUT 0.5 SECONDS = 25us * 20,000
;
LDELAY:
PUSH DE
LD DE,20000
CALL VDELAY
POP DE
RET
;
; MULTIPLY 8-BIT VALUES
; IN: MULTIPLY H WITH E
; OUT: HL = RESULT
;
MULT8:
LD D,0
LD L,D
LD B,8
MULT8_LOOP:
ADD HL,HL
JR NC,MULT8_NOADD
ADD HL,DE
MULT8_NOADD:
DJNZ MULT8_LOOP
RET
;
;==================================================================================================
; DSKY KEYBOARD ROUTINES
;==================================================================================================
;
#IF (DSKYENABLE)
;
; ____C0______C1______C2______C3__
;B5 | 20 D 60 E A0 F E0 BO
;B4 | 10 A 50 B 90 C D0 GO
;B3 | 08 7 48 8 88 9 C8 EX
;B2 | 04 4 44 5 84 6 C4 DE
;B1 | 02 1 42 2 82 3 C2 EN
;B0 | 01 FW 41 0 81 BK C1 CL
;
KY_0 .EQU 000H
KY_1 .EQU 001H
KY_2 .EQU 002H
KY_3 .EQU 003H
KY_4 .EQU 004H
KY_5 .EQU 005H
KY_6 .EQU 006H
KY_7 .EQU 007H
KY_8 .EQU 008H
KY_9 .EQU 009H
KY_A .EQU 00AH
KY_B .EQU 00BH
KY_C .EQU 00CH
KY_D .EQU 00DH
KY_E .EQU 00EH
KY_F .EQU 00FH
KY_FW .EQU 010H ; FORWARD
KY_BK .EQU 011H ; BACKWARD
KY_CL .EQU 012H ; CLEAR
KY_EN .EQU 013H ; ENTER
KY_DE .EQU 014H ; DEPOSIT
KY_EX .EQU 015H ; EXAMINE
KY_GO .EQU 016H ; GO
KY_BO .EQU 017H ; BOOT
;
;__DSKY_INIT_________________________________________________________________________________________
;
; CHECK FOR KEY PRESS, SAVE RAW VALUE, RETURN STATUS
;____________________________________________________________________________________________________
;
DSKY_INIT:
LD A,82H
OUT (PPIX),A
LD A,30H ;disable /CS on PPISD card(s)
OUT (PPIC),A
XOR A
LD (KY_BUF),A
RET
#IFDEF DSKY_KBD
;
;__KY_STAT___________________________________________________________________________________________
;
; CHECK FOR KEY PRESS, SAVE RAW VALUE, RETURN STATUS
;____________________________________________________________________________________________________
;
KY_STAT:
; IF WE ALREADY HAVE A KEY, RETURN WITH NZ
LD A,(KY_BUF)
OR A
RET NZ
; SCAN FOR A KEYPRESS, A=0 NO DATA OR A=RAW BYTE
CALL KY_SCAN ; SCAN KB ONCE
OR A ; SET FLAGS
RET Z ; NOTHING FOUND, GET OUT
LD (KY_BUF),A ; SAVE RAW KEYCODE
RET ; RETURN
;
;__KY_GET____________________________________________________________________________________________
;
; GET A SINGLE KEY (WAIT FOR ONE IF NECESSARY)
;____________________________________________________________________________________________________
;
KY_GET:
; SEE IF WE ALREADY HAVE A KEY SAVED, GO TO DECODE IF SO
LD A,(KY_BUF)
OR A
JR NZ,KY_DECODE
; NO KEY SAVED, WAIT FOR ONE
KY_STATLOOP:
CALL KY_STAT
OR A
JR Z,KY_STATLOOP
; DECODE THE RAW VALUE
KY_DECODE:
LD D,00H
LD HL,KY_KEYMAP ; POINT TO BEGINNING OF TABLE
KY_GET_LOOP:
CP (HL) ; MATCH?
JR Z,KY_GET_DONE ; FOUND, DONE
INC HL
INC D ; D + 1
JR NZ,KY_GET_LOOP ; NOT FOUND, LOOP UNTIL EOT
KY_GET_DONE:
; CLEAR OUT KEY_BUF
XOR A
LD (KY_BUF),A
; RETURN THE INDEX POSITION WHERE THE RAW VALUE WAS FOUND
LD A,D
RET
;
;__KY_SCAN____________________________________________________________________________________________
;
; SCAN KEYBOARD MATRIX FOR AN INPUT
;____________________________________________________________________________________________________
;
KY_SCAN:
LD C,0000H
LD A,41H | 30H ; SCAN COL ONE
OUT (PPIC),A ; SEND TO COLUMN LINES
CALL DELAY ; DEBOUNCE
IN A,(PPIB) ; GET ROWS
AND 7FH ;ignore PB7 for PPISD
CP 00H ; ANYTHING PRESSED?
JR NZ,KY_SCAN_FOUND ; YES, EXIT
LD C,0040H
LD A,42H | 30H ; SCAN COL TWO
OUT (PPIC),A ; SEND TO COLUMN LINES
CALL DELAY ; DEBOUNCE
IN A,(PPIB) ; GET ROWS
AND 7FH ;ignore PB7 for PPISD
CP 00H ; ANYTHING PRESSED?
JR NZ,KY_SCAN_FOUND ; YES, EXIT
LD C,0080H
LD A,44H | 30H ; SCAN COL THREE
OUT (PPIC),A ; SEND TO COLUMN LINES
CALL DELAY ; DEBOUNCE
IN A,(PPIB) ; GET ROWS
AND 7FH ;ignore PB7 for PPISD
CP 00H ; ANYTHING PRESSED?
JR NZ,KY_SCAN_FOUND ; YES, EXIT
LD C,00C0H ;
LD A,48H | 30H ; SCAN COL FOUR
OUT (PPIC),A ; SEND TO COLUMN LINES
CALL DELAY ; DEBOUNCE
IN A,(PPIB) ; GET ROWS
AND 7FH ;ignore PB7 for PPISD
CP 00H ; ANYTHING PRESSED?
JR NZ,KY_SCAN_FOUND ; YES, EXIT
LD A,040H | 30H ; TURN OFF ALL COLUMNS
OUT (PPIC),A ; SEND TO COLUMN LINES
LD A,00H ; RETURN NULL
RET ; EXIT
KY_SCAN_FOUND:
AND 3FH ; CLEAR TOP TWO BITS
OR C ; ADD IN ROW BITS
LD C,A ; STORE VALUE
; WAIT FOR KEY TO BE RELEASED
LD A,4FH | 30H ; SCAN ALL COL LINES
OUT (PPIC),A ; SEND TO COLUMN LINES
CALL DELAY ; DEBOUNCE
KY_CLEAR_LOOP: ; WAIT FOR KEY TO CLEAR
IN A,(PPIB) ; GET ROWS
AND 7FH ;ignore PB7 for PPISD
CP 00H ; ANYTHING PRESSED?
JR NZ,KY_CLEAR_LOOP ; YES, LOOP UNTIL KEY RELEASED
LD A,040H | 30H ; TURN OFF ALL COLUMNS
OUT (PPIC),A ; SEND TO COLUMN LINES
LD A,C ; RESTORE VALUE
RET
;
;_KEYMAP_TABLE_____________________________________________________________________________________________________________
;
KY_KEYMAP:
; 0 1 2 3 4 5 6 7
.DB 041H,002H,042H,082H,004H,044H,084H,008H
; 8 9 A B C D E F
.DB 048H,088H,010H,050H,090H,020H,060H,0A0H
; FW BK CL EN DE EX GO BO
.DB 001H,081H,0C1H,0C2H,0C4H,0C8H,0D0H,0E0H
#ENDIF ; DSKY_KBD
;
;==================================================================================================
; DSKY HEX DISPLAY
;==================================================================================================
;
DSKY_HEXOUT:
LD B,DSKY_HEXBUFLEN
LD HL,DSKY_BUF
LD DE,DSKY_HEXBUF
DSKY_HEXOUT1:
LD A,(DE) ; FIRST NIBBLE
SRL A
SRL A
SRL A
SRL A
LD (HL),A
INC HL
LD A,(DE) ; SECOND NIBBLE
AND 0FH
LD (HL),A
INC HL
INC DE ; NEXT BYTE
DJNZ DSKY_HEXOUT1
LD A,82H ; SETUP PPI
OUT (PPIX),A
CALL DSKY_COFF
LD A,0D0H ; 7218 -> (DATA COMING, HEXA DECODE)
OUT (PPIA),A
CALL DSKY_STROBEC
LD HL,DSKY_BUF ; POINT TO START OF BUF
LD B,DSKY_BUFLEN ; NUMBER OF DIGITS
LD C,PPIA
DSKY_HEXOUT2:
OUTI
JP Z,DSKY_STROBE ; DO FINAL STROBE AND RETURN
CALL DSKY_STROBE
JR DSKY_HEXOUT2
DSKY_STROBEC:
LD A,80H | 30H
JP DSKY_STROBE0
DSKY_STROBE:
LD A,00H | 30H ; SET WRITE STROBE
DSKY_STROBE0:
OUT (PPIC),A ; OUT TO PORTC
CALL DELAY ; DELAY
DSKY_COFF
LD A,40H | 30H ; SET CONTROL PORT OFF
OUT (PPIC),A ; OUT TO PORTC
CALL DELAY ; WAIT
RET
#ENDIF
;
;==================================================================================================
; DATA
;==================================================================================================
;
STR_EMPTY .TEXT "<EMPTY>$"
;
HEXSTRBUF .TEXT "XX$"
;
KY_BUF .DB 0
DSKY_BUF: .FILL 8,0
DSKY_BUFLEN .EQU $ - DSKY_BUF
DSKY_HEXBUF .FILL 4,0
DSKY_HEXBUFLEN .EQU $ - DSKY_HEXBUF
;
PANIC_SP .DW 0