;___ROM_MONITOR_PROGRAM_______________________________________________________ ;___ROM_MONITOR_PROGRAM_______________________________________________________ ; ; ORIGINAL CODE BY: ANDREW LYNCH (LYNCHAJ@YAHOO COM) 13 FEB 2007 ; ; MODIFIED BY : DAN WERNER 03 09.2009 ; ;__REFERENCES_________________________________________________________________ ; THOMAS SCHERRER BASIC HAR.DWARE TEST ASSEMBLER SOURCES FROM THE Z80 INFO PAGE ; INCLUDING ORIGINAL SCHEMATIC CONCEPT ; HTTP://Z80 INFO/Z80SOURC.TXT ; CODE SAMPLES FROM BRUCE JONES PUBLIC DOMAIN ROM MONITOR FOR THE SBC-200C ; HTTP://WWW RETROTECHNOLOGY.COM/HERBS_STUFF/SD_BRUCE_CODE.ZIP ; INSPIRATION FROM JOEL OWENS "Z-80 SPACE-TIME PRODUCTIONS SINGLE BOARD COMPUTER" ; HTTP://WWW JOELOWENS.ORG/Z80/Z80INDEX.HTML ; GREAT HELP AND TECHNICAL ADVICE FROM ALLISON AT ALPACA_DESIGNERS ; HTTP://GROUPS YAHOO.COM/GROUP/ALPACA_DESIGNERS ; INTEL SDK-85 ROM DEBUG MONITOR ;_____________________________________________________________________________ ; #INCLUDE "std.asm" ; ;__CONSTANTS__________________________________________________________________ ; CR: .EQU 0DH ; ASCII CARRIAGE RETURN CHARACTER LF: .EQU 0AH ; ASCII LINE FEED CHARACTER ESC: .EQU 1BH ; ASCII ESCAPE CHARACTER BS: .EQU 08H ; ASCII BACKSPACE CHARACTER ; ;__MAIN_PROGRAM_______________________________________________________________ ; ; ORG 00100h ; FOR DEBUG IN CP/M (AS .COM) .ORG MON_LOC ; ;__ENTRY JUMP TABLE___________________________________________________________ ; JP DSKY_ENTRY JP UART_ENTRY ; #INCLUDE "util.asm" ; ;__UART_ENTRY_________________________________________________________________ ; ; SERIAL MONITOR STARTUP ;_____________________________________________________________________________ ; UART_ENTRY: LD SP,MON_STACK ; SET THE STACK POINTER EI ; INTS OK NOW CALL INITIALIZE ; INITIALIZE SYSTEM LD HL,TXT_READY ; POINT AT TEXT CALL MSG ; SHOW WE'RE HERE ; ;__SERIAL_MONITOR_COMMANDS____________________________________________________ ; ; B - BOOT SYSTEM ; D XXXX YYYY - DUMP MEMORY FROM XXXX TO YYYY ; F XXXX YYYY ZZ - FILL MEMORY FROM XXXX TO YYYY WITH ZZ ; H - LOAD INTEL HEX FORMAT DATA ; K - ECHO KEYBOARD INPUT ; L XX - INPUT FROM PORT XX AND SHOW HEX DATA ; M XXXX YYYY ZZZZ - MOVE MEMORY BLOCK XXXX TO YYYY TO ZZZZ ; O XX YY - OUTPUT TO PORT XX HEX DATA YY ; P XXXX - PROGRAM RAM STARTING AT XXXXH, WILL PROMPT FOR SUCCESSIVE VALUES ; R XXXX - RUN A PROGRAM FROM LOCATION XXXX ; ;__COMMAND_PARSE______________________________________________________________ ; ; PROMPT USER FOR COMMANDS, THEN PARSE THEM ;_____________________________________________________________________________ ; SERIALCMDLOOP: LD SP,MON_STACK ; RESET STACK CALL CRLFA ; CR,LF,> LD HL,KEYBUF ; SET POINTER TO KEYBUF AREA CALL GETLN ; GET A LINE OF INPUT FROM THE USER LD HL,KEYBUF ; RESET POINTER TO START OF KEYBUF LD A,(HL) ; LOAD FIRST CHAR INTO A (THIS SHOULD BE THE COMMAND) INC HL ; INC POINTER CP 'B' ; IS IT "B" (Y/N) JP Z,BOOT ; IF YES BOOT CP 'R' ; IS IT "R" (Y/N) JP Z,RUN ; IF YES GO RUN ROUTINE CP 'P' ; IS IT "P" (Y/N) JP Z,PROGRM ; IF YES GO PROGRAM ROUTINE CP 'O' ; IS IT AN "O" (Y/N) JP Z,POUT ; PORT OUTPUT CP 'L' ; IS IT A "L" (Y/N) JP Z,HXLOAD ; INTEL HEX FORMAT LOAD DATA CP 'I' ; IS IT AN "I" (Y/N) JP Z,PIN ; PORT INPUT CP 'D' ; IS IT A "D" (Y/N) JP Z,DUMPMEM ; DUMP MEMORY CP 'K' JP Z,KLOP ; LOOP ON KEYBOARD CP 'M' ; IS IT A "M" (Y/N) JP Z,MOVEMEM ; MOVE MEMORY COMMAND CP 'F' ; IS IT A "F" (Y/N) JP Z,FILLMEM ; FILL MEMORY COMMAND CP 'H' ; IS IT A "H" (Y/N) JP Z,HELP ; HELP COMMAND LD HL,TXT_COMMAND ; POINT AT ERROR TEXT CALL MSG ; PRINT COMMAND LABEL JR SERIALCMDLOOP ; ;__INITIALIZE_________________________________________________________________ ; ; INITIALIZE SYSTEM ;_____________________________________________________________________________ ; INITIALIZE: ; CALL CIOCON_DISP + (CF_INIT * 3) #IF (PLATFORM == PLT_UNA) ; INSTALL UNA INVOCATION VECTOR FOR RST 08 LD A,$C3 ; JP INSTRUCTION LD (8),A ; STORE AT 0x0008 LD HL,($FFFE) ; UNA ENTRY VECTOR LD (9),HL ; STORE AT 0x0009 #ENDIF RET ; ;__BOOT_______________________________________________________________________ ; ; PERFORM BOOT ACTION ;_____________________________________________________________________________ ; BOOT: #IF (PLATFORM == PLT_UNA) LD BC,$01FB ; UNA FUNC = SET BANK LD DE,$0000 ; ROM BANK 0 CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE) JP 0000H ; JUMP TO RESTART ADDRESS #ELSE LD A,BID_BOOT ; BOOT BANK LD HL,0 ; ADDRESS ZERO CALL HB_BNKCALL ; DOES NOT RETURN #ENDIF ;__RUN________________________________________________________________________ ; ; TRANSFER OUT OF MONITOR, USER OPTION "R" ; SYNTAX: R ;_____________________________________________________________________________ ; RUN: CALL WORDPARM ; GET START ADDRESS JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE VALUE CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL POP HL ; RECOVER START ADDRESS JP (HL) ; GO ; ;__PROGRM_____________________________________________________________________ ; ; PROGRAM RAM LOCATIONS, USER OPTION "P" ;_____________________________________________________________________________ ; PROGRM: CALL WORDPARM ; GET STARTING LOCATION JP C,ERR ; HANDLE SYNTAX ERRORS PUSH DE ; SAVE VALUE CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL PROGRM1: CALL CRLF POP HL PUSH HL CALL PHL LD A,':' CALL COUT CALL SPACE CALL COUT LD HL,KEYBUF CALL GETLN LD HL,KEYBUF CALL NONBLANK CP 0 JP Z,SERIALCMDLOOP CALL BYTEPARM JR C,PROGRM2 ; SYNTAX ERROR POP DE LD (DE),A INC DE PUSH DE JR PROGRM1 PROGRM2: LD HL,TXT_BADNUM CALL MSG JR PROGRM1 ; ;__KLOP_______________________________________________________________________ ; ; READ FROM THE SERIAL PORT AND ECHO, MONITOR COMMAND "K" ;_____________________________________________________________________________ ; KLOP: CALL CRLF ; KLOP1: CALL KIN ; GET A KEY CP ESC ; IS ? JP Z,SERIALCMDLOOP ; IF SO, ALL DONE CALL COUT ; OUTPUT KEY TO SCREEN JR KLOP1 ; LOOP ; ;__HXLOAD_____________________________________________________________________ ; ; LOAD INTEL HEX FORMAT FILE FROM THE SERIAL PORT, USER OPTION "H" ; ; [INTEL HEX FORMAT IS: ; 1) COLON (FRAME 0) ; 2) RECORD LENGTH FIELD (FRAMES 1 AND 2) ; 3) LOAD ADDRESS FIELD (FRAMES 3,4,5,6) ; 4) RECORD TYPE FIELD (FRAMES 7 AND 8) ; 5) DATA FIELD (FRAMES 9 TO 9+2*(RECORD LENGTH)-1 ; 6) CHECKSUM FIELD - SUM OF ALL BYTE VALUES FROM RECORD LENGTH TO AND ; INCLUDING CHECKSUM FIELD = 0 ] ; ; EXAMPLE OF INTEL HEX FORMAT FILE ; EACH LINE CONTAINS A CARRIAGE RETURN AS THE LAST CHARACTER ; :18F900002048454C4C4F20574F524C4420FF0D0AFF0D0A3EFF0D0A54BF ; :18F918006573742050726F746F7479706520524F4D204D6F6E69746FF1 ; :18F9300072205265616479200D0AFF0D0A434F4D4D414E4420524543F2 ; :18F948004549564544203AFF0D0A434845434B53554D204552524F52CD ; :16F96000FF0A0D20202D454E442D4F462D46494C452D20200A0DA4 ; :00000001FF ;_____________________________________________________________________________ ; HXLOAD: CALL CRLF ; SHOW READY HXLOAD0: CALL KIN ; GET THE FIRST CHARACTER, EXPECTING A ':' HXLOAD1: CP 03Ah ; IS IT COLON ':'? START OF LINE OF INTEL HEX FILE JR NZ,HXLOADERR ; IF NOT, MUST BE ERROR, ABORT ROUTINE LD E,0 ; FIRST TWO CHARACTERS IS THE RECORD LENGTH FIELD CALL HEXINS ; GET US TWO CHARACTERS INTO BC, CONVERT IT TO A BYTE CALL HXCHKSUM ; UPDATE HEX CHECK SUM LD D,A ; LOAD RECORD LENGTH COUNT INTO D CALL HEXINS ; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS CALL HXCHKSUM ; UPDATE HEX CHECK SUM LD H,A ; PUT VALUE IN H REGISTER CALL HEXINS ; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS CALL HXCHKSUM ; UPDATE HEX CHECK SUM LD L,A ; PUT VALUE IN L REGISTER CALL HEXINS ; GET NEXT TWO CHARACTERS, RECORD FIELD TYPE CALL HXCHKSUM ; UPDATE HEX CHECK SUM CP 001h ; RECORD FIELD TYPE 00 IS DATA, 01 IS END OF FILE JR NZ,HXLOAD2 ; MUST BE THE END OF THAT FILE CALL HEXINS ; GET NEXT TWO CHARACTERS, ASSEMBLE INTO BYTE CALL HXCHKSUM ; UPDATE HEX CHECK SUM LD A,E ; RECALL THE CHECKSUM BYTE AND A ; IS IT ZERO? JP Z,HXLOADEXIT ; MUST BE O K., GO BACK FOR SOME MORE, ELSE JR HXLOADERR ; CHECKSUMS DON'T ADD UP, ERROR OUT HXLOAD2: LD A,D ; RETRIEVE LINE CHARACTER COUNTER AND A ; ARE WE DONE WITH THIS LINE? JR Z,HXLOAD3 ; GET TWO MORE ASCII CHARACTERS, BUILD A BYTE AND CHECKSUM CALL HEXINS ; GET NEXT TWO CHARS, CONVERT TO BYTE IN A, CHECKSUM IT CALL HXCHKSUM ; UPDATE HEX CHECK SUM LD (HL),A ; CHECKSUM OK, MOVE CONVERTED BYTE IN A TO MEMORY LOCATION INC HL ; INCREMENT POINTER TO NEXT MEMORY LOCATION DEC D ; DECREMENT LINE CHARACTER COUNTER JR HXLOAD2 ; AND KEEP LOADING INTO MEMORY UNTIL LINE IS COMPLETE HXLOAD3: CALL HEXINS ; GET TWO CHARS, BUILD BYTE AND CHECKSUM CALL HXCHKSUM ; UPDATE HEX CHECK SUM LD A,E ; CHECK THE CHECKSUM VALUE AND A ; IS IT ZERO? JR Z,HXLOADAGAIN ; IF THE CHECKSUM IS STILL OK, CONTINUE ON, ELSE HXLOADERR: LD HL,TXT_CKSUMERR ; GET "CHECKSUM ERROR" MESSAGE CALL MSG ; PRINT MESSAGE FROM (HL) AND TERMINATE THE LOAD JP HXLOADEXIT ; RETURN TO PROMPT HXCHKSUM: LD C,A ; BUILD THE CHECKSUM LD A,E ; SUB C ; THE CHECKSUM SHOULD ALWAYS .EQUAL ZERO WHEN CHECKED LD E,A ; SAVE THE CHECKSUM BACK WHERE IT CAME FROM LD A,C ; RETRIEVE THE BYTE AND GO BACK RET ; BACK TO CALLER HXLOADAGAIN: CALL KIN ; CATCH THE TRAILING CARRIAGE RETURN JP HXLOAD0 ; LOAD ANOTHER LINE OF DATA HXLOADEXIT: CALL KIN ; CATCH ANY STRAY TRAILING CHARACTERS JP SERIALCMDLOOP ; RETURN TO PROMPT ; ;__POUT_______________________________________________________________________ ; ; OUTPUT TO AN I/O PORT, MONITOR COMMAND "O" ; SYNTAX: O ; NOTE: A WORD VALUE IS USED FOR THE PORT NUMBER BECAUSE THE ; Z80 WILL ACTUALLY PLACE 16 BITS ON THE BUS USING ; THE B AND C REGISTERS IN AN "OUT (C),A" ;_____________________________________________________________________________ ; POUT: CALL WORDPARM ; GET PORT NUMBER JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT FOR NOW CALL BYTEPARM ; GET VALUE TO WRITE JP C,ERR ; HANDLE ERRORS POP BC ; RESTORE PORT NUMBER TO BC OUT (C),A ; SEND VALUE TO PORT JP SERIALCMDLOOP ; DONE, BACK TO COMMAND LOOP ; ;__PIN________________________________________________________________________ ; ; INPUT FROM AN I/O PORT, MONITOR COMMAND "I" ; SYNTAX: I ; NOTE: A WORD VALUE IS USED FOR THE PORT NUMBER BECAUSE THE ; Z80 WILL ACTUALLY PLACE 16 BITS ON THE BUS USING ; THE B AND C REGISTERS IN AN "INC A,(C)" ;_____________________________________________________________________________ ; PIN: CALL WORDPARM ; GET PORT NUMBER JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT CALL CRLF ; POP BC ; RESTORE TO BC IN A,(C) ; GET PORT VALUE CALL HXOUT ; PRINT HEX VALUE JP SERIALCMDLOOP ; DONE, BACK TO COMMAND LOOP ; ;__DUMPMEM____________________________________________________________________ ; ; PRINT A MEMORY DUMP, USER OPTION "D" ; SYNTAX: D ;_____________________________________________________________________________ ; DUMPMEM: CALL WORDPARM ; GET START ADDRESS JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT CALL WORDPARM ; GET END ADDRESS JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT POP DE ; DE := END ADDRESS POP HL ; HL := START ADDRESS GDATA: INC DE ; BUMP DE FOR LATER COMPARE CALL CRLF ; BLKRD: CALL PHL ; PRINT START LOCATION LD A,':' CALL COUT CALL SPACE CALL COUT LD C,16 ; SET FOR 16 LOCS PUSH HL ; SAVE STARTING HL NXTONE: EXX ; LD C,E ; IN A,(C) ; EXX ; AND 7FH ; CP ESC ; JP Z,SERIALCMDLOOP ; CP 19 ; JR Z,NXTONE ; LD A,(HL) ; GET BYTE CALL HXOUT ; PRINT IT CALL SPACE ; UPDH: INC HL ; POINT NEXT DEC C ; DEC LOC COUNT JR NZ,NXTONE ; IF LINE NOT DONE ; NOW PRINT 'DECODED' DATA TO RIGHT OF DUMP PCRLF: CALL SPACE ; SPACE IT LD C,16 ; SET FOR 16 CHARS POP HL ; GET BACK START PCRLF0: LD A,(HL) ; GET BYTE AND 060H ; SEE IF A 'DOT' LD A,(HL) ; O K. TO GET JR NZ,PDOT ; DOT: LD A,2EH ; LOAD A DOT PDOT: CALL COUT ; PRINT IT INC HL ; LD A,D ; CP H ; JR NZ,UPDH1 ; LD A,E ; CP L ; JP Z,SERIALCMDLOOP ; ; ;IF BLOCK NOT DUMPED, DO NEXT CHARACTER OR LINE UPDH1: DEC C ; DEC CHAR COUNT JR NZ,PCRLF0 ; DO NEXT CONTD: CALL CRLF ; JP BLKRD ; ; ;__MOVEMEM____________________________________________________________________ ; ; MOVE MEMORY, USER OPTION "M" ; SYNTAX: M ;_____________________________________________________________________________ ; MOVEMEM: CALL WORDPARM ; GET WORD VALUE INTO DE (MOVE SRC START ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL WORDPARM ; GET WORD VALUE INTO DE (MOVE SRC END ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL WORDPARM ; GET WORD VALUE INTO DE (MOVE TGT ADR) JP C,ERR ; SYNTAX ERROR IF HEXBYTE FAILED PUSH DE ; SAVE IT CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL POP DE ; TGT ADR TO DE POP BC ; SRC END ADR TO BC POP HL ; SRC START ADR TO HL DEC HL ; PRE-DECREMENT DEC DE ; PRE-DECREMENT MOVEMEM1: INC HL ; BUMP CUR SRC ADR INC DE ; BUMP CUR TGT ADR LD A,(HL) ; GET SOURCE VAUEE LD (DE),A ; WRITE TO TARGET LOC LD A,H ; CHECK MSB OF END ADR CP B ; JR NZ,MOVEMEM1 ; NO MATCH, LOOP LD A,L ; CHECK LSB OF END ADR CP C ; JR NZ,MOVEMEM1 ; NO MATCH, LOOP JP SERIALCMDLOOP ; LSB AND MSB MATCH, ALL DONE ; ;__FILLMEM____________________________________________________________________ ; ; FILL MEMORY, USER OPTION "M" ; SYNTAX: F ;_____________________________________________________________________________ ; FILLMEM: CALL WORDPARM ; GET WORD VALUE INTO DE (FILL START ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL WORDPARM ; GET WORD VALUE INTO DE (FILL END ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL BYTEPARM ; GET BYTE VALUE (FILL VALUE) INTO A JP C,ERR ; SYNTAX ERROR IF HEXBYTE FAILED LD C,A ; FILL VALUE TO C CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL POP DE ; END ADR TO DE POP HL ; START ADR TO HL DEC HL ; PRE-DECREMENT FILLMEM1: INC HL ; BUMP CUR ADR LD A,C ; FILL VALUE TO A LD (HL),A ; WRITE FILL VALUE TO CUR ADR (HL) LD A,H ; CHECK MSB OF END ADR CP D ; JR NZ,FILLMEM1 ; NO MATCH, LOOP LD A,L ; CHECK LSB OF END ADR CP E ; JR NZ,FILLMEM1 ; NO MATCH, LOOP JP SERIALCMDLOOP ; LSB AND MSB MATCH, ALL DONE ; ;__HELP_______________________________________________________________________ ; ; SYNTAX HELP, USER OPTION "H" ;_____________________________________________________________________________ ; HELP: LD HL,TXT_HELP ; POINT AT SYNTAX HELP TEXT CALL MSG ; DISPLAY IT JP SERIALCMDLOOP ; AND BACK TO COMMAND LOOP ; ;__ERR________________________________________________________________________ ; ; SYNTAX ERROR ;_____________________________________________________________________________ ; ERR: LD HL,TXT_ERR ; POINT AT ERROR TEXT CALL MSG ; DISPLAY IT JP SERIALCMDLOOP ; AND BACK TO COMMAND LOOP ; ;__BYTEPARM___________________________________________________________________ ; ; ATTEMPT TO GET A BYTE PARM, VALUE RETURNED IN A ; CF SET ON ERROR ;_____________________________________________________________________________ ; BYTEPARM: CALL NONBLANK ; SKIP LEADING BLANKS JP Z,ERR ; SYNTAX ERROR IF PARM NOT FOUND CALL ISHEX ; HEX CHAR? JP NZ,BYTEPARM1 ; IF NOT, ERR JP HEXBYTE ; RETURN VIA HEXBYTE BYTEPARM1: SCF ; SIGNAL ERROR RET ; RETURN ; ;__WORDPARM___________________________________________________________________ ; ; ATTEMPT TO GET A WORD PARM, VALUE RETURNED IN DE ; CF SET ON ERROR ;_____________________________________________________________________________ ; WORDPARM: CALL NONBLANK ; SKIP LEADING BLANKS JP Z,ERR ; SYNTAX ERROR IF PARM NOT FOUND CALL ISHEX ; HEX CHAR? JP NZ,WORDPARM1 ; IF NOT, ERR JP HEXWORD ; RETURN VIA HEXWORD WORDPARM1: SCF ; SIGNAL ERROR RET ; RETURN ; ;__GETLN______________________________________________________________________ ; ; READ A LINE(80) OF TEXT FROM THE SERIAL PORT, HANDLE , TERM ON ; EXIT IF TOO MANY CHARS STORE RESULT IN HL. CHAR COUNT IN C. ;_____________________________________________________________________________ ; GETLN: LD C,00H ; ZERO CHAR COUNTER PUSH DE ; STORE DE GETLNLOP: CALL KIN ; GET A KEY CP CR ; IS ? JR Z,GETLNDONE ; YES, EXIT CALL COUT ; OUTPUT KEY TO SCREEN CP BS ; IS ? JR NZ,GETLNSTORE ; NO, STORE CHAR LD A,C ; A=C CP 0 ; JR Z,GETLNLOP ; NOTHING TO BACKSPACE, IGNORE & GET NEXT KEY DEC HL ; PERFORM BACKSPACE DEC C ; LOWER CHAR COUNTER LD A,0 ; LD (HL),A ; STORE NULL IN BUFFER LD A,20H ; BLANK OUT CHAR ON TERM CALL COUT ; LD A,BS ; CALL COUT ; JR GETLNLOP ; GET NEXT KEY GETLNSTORE: LD (HL),A ; STORE CHAR IN BUFFER INC HL ; INC POINTER INC C ; INC CHAR COUNTER LD A,C ; A=C CP 4DH ; OUT OF BUFFER SPACE? JR NZ,GETLNLOP ; NOPE, GET NEXT CHAR GETLNDONE: LD (HL),00H ; STORE NULL IN BUFFER POP DE ; RESTORE DE RET ; ; ;__KIN________________________________________________________________________ ; ; READ FROM THE SERIAL PORT AND ECHO & CONVERT INPUT TO UCASE ;_____________________________________________________________________________ ; KIN: CALL CIN AND 7FH ; STRIP HI BIT CP 'A' ; KEEP NUMBERS, CONTROLS RET C ; AND UPPER CASE CP 7BH ; SEE IF NOT LOWER CASE RET NC AND 5FH ; MAKE UPPER CASE RET ; ;__CRLFA______________________________________________________________________ ; ; PRINT COMMAND PROMPT TO THE SERIAL PORT ;_____________________________________________________________________________ ; CRLFA: PUSH HL ; PROTECT HL FROM OVERWRITE LD HL,PROMPT ; CALL MSG ; POP HL ; PROTECT HL FROM OVERWRITE RET ; DONE ; ;__CRLF_______________________________________________________________________ ; ; SEND CR & LF TO THE SERIAL PORT ;_____________________________________________________________________________ ; CRLF: PUSH HL ; PROTECT HL FROM OVERWRITE LD HL,TCRLF ; LOAD MESSAGE POINTER CALL MSG ; SEBD MESSAGE TO SERIAL PORT POP HL ; PROTECT HL FROM OVERWRITE RET ; ; ;__NONBLANK___________________________________________________________________ ; ; FIND NEXT NONBLANK CHARACTER IN BUFFER AT (HL) ;_____________________________________________________________________________ ; NONBLANK: LD A,(HL) ; GET NEXT CHAR CP ' ' ; COMPARE TO BLANK RET NZ ; DONE IF NOT BLANK INC HL ; BUMP TO NEXT CHAR JR NONBLANK ; AND LOOP ; ;__ISHEX______________________________________________________________________ ; ; CHECK BYTE AT (HL) FOR HEX CHAR, RET Z IF SO, ELSE NZ ;_____________________________________________________________________________ ; ISHEX: LD A,(HL) ; CHAR TO AS CP '0' ; < '0'? JR C,ISHEX1 ; YES, NOT 0-9, CHECK A-F CP '9' + 1 ; > '9' JR NC,ISHEX1 ; YES, NOT 0-9, CHECK A-F XOR A ; MUST BE 0-9, SET ZF RET ; AND DONE ISHEX1: CP 'A' ; < 'A'? JR C,ISHEX2 ; YES, NOT A-F, FAIL CP 'F' + 1 ; > 'F' JR NC,ISHEX2 ; YES, NOT A-F, FAIL XOR A ; MUST BE 0-9, SET ZF RET ; AND DONE ISHEX2: OR $FF ; CLEAR ZF RET ; AND DONE ; ;__HEXBYTE____________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A ;_____________________________________________________________________________ ; HEXBYTE: LD C,0 ; INIT WORKING VALUE HEXBYTE1: CALL ISHEX ; DO WE HAVE A HEX CHAR? JR NZ,HEXBYTE3 ; IF NOT, WE ARE DONE LD B,4 ; SHIFT WORKING VALUE (C := C * 16) HEXBYTE2: SLA C ; SHIFT ONE BIT RET C ; RETURN W/ CF SET INDICATING OVERFLOW ERROR DJNZ HEXBYTE2 ; LOOP FOR 4 BITS CALL NIBL ; CONVERT HEX CHAR TO BINARY VALUE IN A & INC HL OR C ; COMBINE WITH WORKING VALUE LD C,A ; AND PUT BACK IN WORKING VALUE JR HEXBYTE1 ; DO ANOTHER CHARACTER HEXBYTE3: LD A,C ; WORKING VALUE TO A OR A ; CLEAR CARRY RET ; AND DONE ; ;__HEXWORD____________________________________________________________________ ; ; GET ONE WORD OF HEX DATA FROM BUFFER IN HL, RETURN IN DE ;_____________________________________________________________________________ ; HEXWORD: LD DE,0 ; INIT WORKING VALUE HEXWORD1: CALL ISHEX ; DO WE HAVE A HEX CHAR? JR NZ,HEXWORD3 ; IF NOT, WE ARE DONE LD B,4 ; SHIFT WORKING VALUE (DE := DE * 16) HEXWORD2: SLA E ; SHIFT LSB ONE BIT RL D ; SHIFT MSB ONE BIT RET C ; RETURN W/ CF SET INDICATING OVERFLOW ERROR DJNZ HEXWORD2 ; LOOP FOR 4 BITS CALL NIBL ; CONVERT HEX CHAR TO BINARY VALUE IN A & INC HL OR E ; COMBINE WITH LSB LD E,A ; AND PUT BACK IN WROKING VALUE JR HEXWORD1 ; DO ANOTHER CHARACTER HEXWORD3: OR A ; CLEAR CARRY RET ; AND DONE ; ;__NIBL_______________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A ;_____________________________________________________________________________ ; NIBL: LD A,(HL) ; GET K B. DATA INC HL ; INC KB POINTER CP 40H ; TEST FOR ALPHA JR NC,ALPH ; AND 0FH ; GET THE BITS RET ; ALPH: AND 0FH ; GET THE BITS ADD A,09H ; MAKE IT HEX A-F RET ; ; ;__HEXINS_____________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM SERIAL PORT, RETURN IN A ;_____________________________________________________________________________ ; HEXINS: PUSH BC ;SAVE BC REGS CALL NIBLS ;DO A NIBBLE RLC A ;MOVE FIRST BYTE UPPER NIBBLE RLC A ; RLC A ; RLC A ; LD B,A ; SAVE ROTATED BYTE CALL NIBLS ; DO NEXT NIBBLE ADD A,B ; COMBINE NIBBLES IN ACC POP BC ; RESTORE BC RET ; DONE NIBLS: CALL KIN ; GET K B. DATA CP 40H ; TEST FOR ALPHA JR NC,ALPH ; AND 0FH ; GET THE BITS RET ; ; ;__PHL________________________________________________________________________ ; ; PRINT THE HL REG ON THE SERIAL PORT ;_____________________________________________________________________________ ; PHL: LD A,H ; GET HI BYTE CALL HXOUT ; DO HEX OUT ROUTINE LD A,L ; GET LOW BYTE CALL HXOUT ; HEX IT RET ; DONE ; ;__HXOUT______________________________________________________________________ ; ; PRINT THE ACCUMULATOR CONTENTS AS HEX DATA ON THE SERIAL PORT ;_____________________________________________________________________________ ; HXOUT: PUSH BC ; SAVE BC LD B,A ; RLC A ; DO HIGH NIBBLE FIRST RLC A ; RLC A ; RLC A ; AND 0FH ; ONLY THIS NOW ADD A,30H ; TRY A NUMBER CP 3AH ; TEST IT JR C,OUT1 ; IF CY SET PRINT 'NUMBER' ADD A,07H ; MAKE IT AN ALPHA OUT1: CALL COUT ; SCREEN IT LD A,B ; NEXT NIBBLE AND 0FH ; JUST THIS ADD A,30H ; TRY A NUMBER CP 3AH ; TEST IT JR C,OUT2 ; PRINT 'NUMBER' ADD A,07H ; MAKE IT ALPHA OUT2: CALL COUT ; SCREEN IT POP BC ; RESTORE BC RET ; ; ;__SPACE______________________________________________________________________ ; ; PRINT A SPACE CHARACTER ON THE SERIAL PORT ;_____________________________________________________________________________ ; SPACE: PUSH AF ; STORE AF LD A,20H ; LOAD A "SPACE" CALL COUT ; SCREEN IT POP AF ; RESTORE AF RET ; DONE ; ;__MSG________________________________________________________________________ ; ; PRINT A STRING TO THE SERIAL PORT ;_____________________________________________________________________________ ; MSG: LD A,(HL) ; GET CHARACTER TO A OR A ; SET FLAGS RET Z ; DONE IF NULL CALL COUT ; PRINT CHARACTER INC HL ; INC POINTER, TO NEXT CHAR JR MSG ; LOOP ; #IF (PLATFORM == PLT_UNA) ; ;__COUT_______________________________________________________________________ ; ; OUTPUT CHARACTER FROM A ;_____________________________________________________________________________ ; COUT: ; SAVE ALL INCOMING REGISTERS PUSH AF PUSH BC PUSH DE PUSH HL ; ; OUTPUT CHARACTER TO CONSOLE VIA UBIOS LD E,A LD BC,$12 RST 08 ; ; RESTORE ALL REGISTERS POP HL POP DE POP BC POP AF RET ; ;__CIN________________________________________________________________________ ; ; INPUT CHARACTER TO A ;_____________________________________________________________________________ ; CIN: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; INPUT CHARACTER FROM CONSOLE VIA UBIOS LD BC,$11 RST 08 LD A,E ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; ;__CST________________________________________________________________________ ; ; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) ;_____________________________________________________________________________ ; CST: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; GET CONSOLE INPUT STATUS VIA UBIOS LD BC,$13 RST 08 LD A,E ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; #ELSE ; ;__COUT_______________________________________________________________________ ; ; OUTPUT CHARACTER FROM A ;_____________________________________________________________________________ ; COUT: ; SAVE ALL INCOMING REGISTERS PUSH AF PUSH BC PUSH DE PUSH HL ; ; OUTPUT CHARACTER TO CONSOLE VIA HBIOS LD E,A ; OUTPUT CHAR TO E LD C,CIODEV_CONSOLE ; CONSOLE UNIT TO C LD B,BF_CIOOUT ; HBIOS FUNC: OUTPUT CHAR RST 08 ; HBIOS OUTPUTS CHARACTDR ; ; RESTORE ALL REGISTERS POP HL POP DE POP BC POP AF RET ; ;__CIN________________________________________________________________________ ; ; INPUT CHARACTER TO A ;_____________________________________________________________________________ ; CIN: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; INPUT CHARACTER FROM CONSOLE VIA HBIOS LD C,CIODEV_CONSOLE ; CONSOLE UNIT TO C LD B,BF_CIOIN ; HBIOS FUNC: INPUT CHAR RST 08 ; HBIOS READS CHARACTDR LD A,E ; MOVE CHARACTER TO A FOR RETURN ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; ;__CST________________________________________________________________________ ; ; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) ;_____________________________________________________________________________ ; CST: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; GET CONSOLE INPUT STATUS VIA HBIOS LD C,CIODEV_CONSOLE ; CONSOLE UNIT TO C LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS RST 08 ; HBIOS RETURNS STATUS IN A ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; #ENDIF ; ;__WORK_AREA__________________________________________________________________ ; ; RESERVED RAM FOR MONITOR WORKING AREA ;_____________________________________________________________________________ ; KEYBUF: .FILL 80,' ' ; ;__TEXT_STRINGS_______________________________________________________________ ; ; SYSTEM TEXT STRINGS ;_____________________________________________________________________________ ; TCRLF: .DB CR,LF,0 PROMPT: .DB CR,LF,'>',0 TXT_READY: .DB CR,LF .TEXT "MONITOR READY ('H' FOR HELP)" .DB 0 TXT_COMMAND: .DB CR,LF .TEXT "UNKNOWN COMMAND ('H' FOR HELP)" .DB 0 TXT_ERR: .DB CR,LF .TEXT "SYNTAX ERROR ('H' FOR HELP)" .DB 0 TXT_CKSUMERR: .DB CR,LF .TEXT "CHECKSUM ERROR" .DB 0 TXT_BADNUM: .TEXT " *INVALID VALUE*" .DB 0 TXT_HELP: .DB CR,LF .TEXT "MONITOR COMMANDS (ALL VALUES IN HEX):\r\n" .TEXT "B - BOOT SYSTEM\r\n" .TEXT "D XXXX YYYY - DUMP MEMORY FROM XXXX TO YYYY\r\n" .TEXT "F XXXX YYYY ZZ - FILL MEMORY FROM XXXX TO YYYY WITH ZZ\r\n" .TEXT "I XX - SHOW VALUE FROM PORT XX\r\n" .TEXT "K - ECHO KEYBOARD INPUT\r\n" .TEXT "L - LOAD INTEL HEX FORMAT DATA\r\n" .TEXT "M XXXX YYYY ZZZZ - MOVE MEMORY BLOCK XXXX-YYYY TO ZZZZ\r\n" .TEXT "O XX YY - WRITE VALUE YY TO PORT XX\r\n" .TEXT "P XXXX - PROGRAM RAM STARTING AT XXXX\r\n" .TEXT "R XXXX - RUN A PROGRAM AT ADDRESS XXXX" .DB 0 ; #IF DSKYENABLE ; #INCLUDE "dsky.asm" ; ; ;__DSKY_ENTRY_________________________________________________________________ ; ; DSKY FRONT PANEL STARTUP ;_____________________________________________________________________________ ; DSKY_ENTRY: LD SP,MON_STACK ; SET THE STACK POINTER EI ; INTS OK NOW CALL INITIALIZE ; INITIALIZE SYSTEM ; ;__FRONT_PANEL_STARTUP________________________________________________________ ; ; START UP THE SYSTEM WITH THE FRONT PANEL INTERFACE ;_____________________________________________________________________________ ; CALL MTERM_INIT ; INIT 8255 FOR MTERM LD HL,CPUUP ; SET POINTER TO DATA BUFFER CALL SEGDISPLAY ; DISPLAY ; ;__COMMAND_PARSE______________________________________________________________ ; ; PROMPT USER FOR COMMANDS, THEN PARSE THEM ;_____________________________________________________________________________ ; FRONTPANELLOOP: CALL KB_GET ; GET KEY FROM KB CP 10H ; IS PORT READ? JP Z,DOPORTREAD ; YES, JUMP CP 11H ; IS PORT WRITE? JP Z,DOPORTWRITE ; YES, JUMP CP 14H ; IS DEPOSIT? JP Z,DODEPOSIT ; YES, JUMP CP 15H ; IS EXAMINE? JP Z,DOEXAMINE ; YES, JUMP CP 16H ; IS GO? JP Z,DOGO ; YES, JUMP CP 17H ; IS BO? JP Z,DOBOOT ; YES, JUMP JR FRONTPANELLOOP ; LOOP EXIT: RET ; ;__DOBOOT_____________________________________________________________________ ; ; PERFORM BOOT FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOBOOT: JP BOOT ; ;__DOPORTREAD_________________________________________________________________ ; ; PERFORM PORT READ FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOPORTREAD: CALL GETPORT ; GET PORT INTO A PORTREADLOOP: LD C,A ; STORE PORT IN "C" SRL A ; ROTATE HIGH NIB TO LOW SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+5),A ; SHOW HIGH NIB IN DISP 5 LD A,C ; RESTORE PORT VALUE INTO "A" AND 0FH ; CLEAR HIGH NIB, LEAVING LOW LD (DISPLAYBUF+4),A ; SHOW LOW NIB IN DISP 4 IN A,(C) ; GET PORT VALUE FROM PORT IN "C" LD C,A ; STORE VALUE IN "C" SRL A ; ROTATE HIGH NIB TO LOW SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+1),A ; SHOW HIGH NIB IN DISP 1 LD A,C ; RESTORE VALUE TO "A" AND 0FH ; CLEAR HIGH NIB, LEAVING LOW LD (DISPLAYBUF),A ; DISPLAY LOW NIB IN DISP 0 LD A,10H ; CLEAR OTHER DISPLAYS LD (DISPLAYBUF+2),A ; LD (DISPLAYBUF+3),A ; LD A,13H ; "P" LD (DISPLAYBUF+7),A ; STORE IN DISP 7 LD A,14H ; "O" LD (DISPLAYBUF+6),A ; STORE IN DISP 6 LD HL,DISPLAYBUF ; SET POINTER TO DISPLAY BUFFER CALL HEXDISPLAY ; DISPLAY BUFFER CONTENTS PORTREADGETKEY: CALL KB_GET ; GET KEY FROM KB CP 12H ; [CL] PRESSED, EXIT JP Z,PORTREADEXIT ; CP 10H ; [PR] PRESSED, PROMPT FOR NEW PORT JR Z,DOPORTREAD ; JR PORTREADGETKEY ; NO VALID KEY, LOOP PORTREADEXIT: LD HL,CPUUP ; SET POINTER TO DATA BUFFER CALL SEGDISPLAY ; DISPLAY JP FRONTPANELLOOP ; ; ;__DOPORTWRITE________________________________________________________________ ; ; PERFORM PORT WRITE FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOPORTWRITE: CALL GETPORT ; GET PORT INTO A PORTWRITELOOP: LD C,A ; STORE PORT IN "C" SRL A ; ROTATE HIGH NIB INTO LOW SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+5),A ; DISPLAY HIGH NIB IN DISPLAY 5 LD A,C ; RESTORE PORT VALUE INTO "A" AND 0FH ; CLEAR OUT HIGH NIB LD (DISPLAYBUF+4),A ; DISPLAY LOW NIB IN DISPLAY 4 LD A,10H ; CLEAR OUT DISPLAYS 2 AND 3 LD (DISPLAYBUF+2),A ; LD (DISPLAYBUF+3),A ; LD A,13H ; DISPLAY "P" IN DISP 7 LD (DISPLAYBUF+7),A ; LD A,14H ; DISPLAY "O" IN DISP 6 LD (DISPLAYBUF+6),A ; LD HL,DISPLAYBUF ; POINT TO DISPLAY BUFFER CALL GETVALUE ; INPUT A BYTE VALUE, RETURN IN "A" OUT (C),A ; OUTPUT VALUE TO PORT STORED IN "C" LD HL,CPUUP ; SET POINTER TO DATA BUFFER CALL SEGDISPLAY ; DISPLAY JP FRONTPANELLOOP ; ; ;__DOGO_______________________________________________________________________ ; ; PERFORM GO FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOGO: CALL GETADDR ; GET ADDRESS INTO HL JP (HL) ; GO THERE! ; ;__DODEPOSIT__________________________________________________________________ ; ; PERFORM DEPOSIT FRONT PANEL ACTION ;_____________________________________________________________________________ ; DODEPOSIT: CALL GETADDR ; GET ADDRESS INTO HL PUSH HL DEPOSITLOOP: LD A,H ; SRL A ; SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+7),A ; LD A,H ; AND 0FH ; LD (DISPLAYBUF+6),A ; LD A,L ; SRL A ; SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+5),A ; LD A,L ; AND 0FH ; LD (DISPLAYBUF+4),A ; LD A,10H ; LD (DISPLAYBUF+3),A ; LD HL,DISPLAYBUF ; CALL GETVALUE ; POP HL ; LD (HL),A ; DEPOSITGETKEY: CALL KB_GET ; GET KEY FROM KB CP 12H ; [CL] PRESSED, EXIT JP Z,DEPOSITEXIT ; CP 13H ; [EN] PRESSED, INC ADDRESS AND LOOP JR Z,DEPOSITFW ; CP 14H ; [DE] PRESSED, PROMPT FOR NEW ADDRESS JR Z,DODEPOSIT ; JR DEPOSITGETKEY ; NO VALID KEY, LOOP DEPOSITFW: INC HL ; PUSH HL ; STORE HL JR DEPOSITLOOP ; DEPOSITEXIT: LD HL,CPUUP ; SET POINTER TO DATA BUFFER CALL SEGDISPLAY ; DISPLAY JP FRONTPANELLOOP ; ; ;__DOEXAMINE__________________________________________________________________ ; ; PERFORM EXAMINE FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOEXAMINE: CALL GETADDR ; GET ADDRESS INTO HL PUSH HL ; STORE HL EXAMINELOOP: LD A,H ; MOVE HIGH BYTE IN "A" SRL A ; SHOW HIGH NIBBLE IN DISP 7 SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+7),A ; LD A,H ; RESTORE HIGH BYTE AND 0FH ; CLEAR HIGH NIBBLE LD (DISPLAYBUF+6),A ; DISPLAY LOW NIBBLE IN DISP 6 LD A,L ; PUT LOW BYTE IN "A" SRL A ; SHOW HIGH NIBBLE IN DISP 5 SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+5),A ; LD A,L ; RESTORE LOW BYTE IN "A" AND 0FH ; CLEAR OUT HIGH NIBBLE LD (DISPLAYBUF+4),A ; DISPLAY LOW NIBBLE IN DISP 4 LD A,10H ; CLEAR OUT DISP 3 LD (DISPLAYBUF+3),A ; LD A,(HL) ; GET VALUE FROM ADDRESS IN HL SRL A ; DISPLAY HIGH NIB IN DISPLAY 1 SRL A ; SRL A ; SRL A ; LD (DISPLAYBUF+1),A ; LD A,(HL) ; GET VALUE FROM ADDRESS IN HL AND 0FH ; CLEAR OUT HIGH NIBBLE LD (DISPLAYBUF),A ; DISPLAY LOW NIBBLE IN DISPLAY 0 LD HL,DISPLAYBUF ; POINT TO DISPLAY BUFFER CALL HEXDISPLAY ; DISPLAY BUFFER ON DISPLAYS POP HL ; RESTORE HL EXAMINEGETKEY: CALL KB_GET ; GET KEY FROM KB CP 12H ; [CL] PRESSED, EXIT JP Z,EXAMINEEXIT ; CP 13H ; [EN] PRESSED, INC ADDRESS AND LOOP JR Z,EXAMINEFW ; CP 15H ; [DE] PRESSED, PROMPT FOR NEW ADDRESS JR Z,DOEXAMINE ; JR EXAMINEGETKEY ; NO VALID KEY, LOOP EXAMINEFW: INC HL ; HL++ PUSH HL ; STORE HL JR EXAMINELOOP ; EXAMINEEXIT: LD HL,CPUUP ; SET POINTER TO DATA BUFFER CALL SEGDISPLAY ; DISPLAY JP FRONTPANELLOOP ; ; ;__GETADDR____________________________________________________________________ ; ; GET ADDRESS FROM FRONT PANEL ;_____________________________________________________________________________ ; GETADDR: PUSH BC ; STORE BC JR GETADDRCLEAR ; GETADDR1: LD HL,ADDR ; DISPLAY PROMPT CALL SEGDISPLAY ; GETADDRLOOP: CALL KB_GET ; CP 10H ; JP M,GETADDRNUM ; NUMBER PRESSED, STORE IT CP 13H ; EN PRESSED, DONE JR Z,GETADDRDONE ; CP 12H ; CLEAR PRESSED, CLEAR JR Z,GETADDRCLEAR ; JR GETADDRLOOP ; INVALID KEY, LOOP GETADDRDONE: LD HL,00H ; HL=0 LD A,(DISPLAYBUF+1) ; GET DIGIT IN DISPLAY 1 SLA A ; ROTATE IT TO HIGH NIBBLE SLA A ; SLA A ; SLA A ; LD C,A ; STORE IT IN "C" LD A,(DISPLAYBUF) ; GET DIGIT IN DISPLAY 0 AND 0FH ; CLEAR HIGH NIBBLE OR C ; ADD IN NIBBLE STORED IN C LD L,A ; STORE IT IN LOW BYTE OF ADDRESS POINTER LD A,(DISPLAYBUF+3) ; GET DIGIT IN DISPLAY 3 SLA A ; ROTATE IT TO HIGH NIBBLE SLA A ; SLA A ; SLA A ; LD C,A ; STORE IT IN "C" LD A,(DISPLAYBUF+2) ; GET DIGIT IN DISPLAY 2 AND 0FH ; CLEAR HIGH NIBBLE OR C ; ADD IN NIBBLE STORED IN "C" LD H,A ; STORE BYTE IN HIGH BYTE OF ADDRESS POINTER LD A,10H ; CLEAR OUT DISPLAYS 0,1,2 & 3 LD (DISPLAYBUF),A ; LD (DISPLAYBUF+1),A ; LD (DISPLAYBUF+2),A ; LD (DISPLAYBUF+3),A ; POP BC ; RESTORE BC RET GETADDRNUM: LD C,A ; LD A,(DISPLAYBUF+2) ; SHIFT BYTES IN DISPLAY BUF TO THE LEFT LD (DISPLAYBUF+3),A ; LD A,(DISPLAYBUF+1) ; LD (DISPLAYBUF+2),A ; LD A,(DISPLAYBUF) ; LD (DISPLAYBUF+1),A ; LD A,C ; DISPLAY KEYSTROKE IN RIGHT MOST DISPLAY (0) LD (DISPLAYBUF+0),A ; JR GETADDRDISP ; GETADDRCLEAR: LD A,12H ; CLEAR OUT DISPLAYS 0,1,2 & 3 LD (DISPLAYBUF),A ; LD (DISPLAYBUF+1),A ; LD (DISPLAYBUF+2),A ; LD (DISPLAYBUF+3),A ; GETADDRDISP: LD A,(DISPLAYBUF) ; ENCODE DIGITS IN DISPLAY BUFFER TO DISPLAY CALL DECODEDISPLAY ; LD (ADDR),A ; LD A,(DISPLAYBUF+1) ; CALL DECODEDISPLAY ; LD (ADDR+1),A ; LD A,(DISPLAYBUF+2) ; CALL DECODEDISPLAY ; LD (ADDR+2),A ; LD A,(DISPLAYBUF+3) ; CALL DECODEDISPLAY ; LD (ADDR+3),A ; JP GETADDR1 ; ; ;__DSPSECTOR__________________________________________________________________ ; ; DISPLAY SECTOR IN HL ON FRONT PANEL ;_____________________________________________________________________________ ; DSPSECTOR: PUSH BC ; STORE BC PUSH HL ; STORE HL LD A,H ; DISPLAY HIGH BYTE, HIGH NIBBLE SRL A ; SRL A ; SRL A ; SRL A ; AND 0FH ; CALL DECODEDISPLAY ; LD (SEC+3),A ; LD A,H ; DISPLAY HIGH BYTE, LOW NIBBLE AND 0FH ; CALL DECODEDISPLAY ; LD (SEC+2),A ; LD A,L ; DISPLAY LOW BYTE, HIGH NIBBLE AND 0F0H ; SRL A ; SRL A ; SRL A ; SRL A ; AND 0FH ; CALL DECODEDISPLAY ; LD (SEC+1),A ; DISPLAY LOW BYTE, LOW NIBBLE LD A,L ; AND 0FH ; CALL DECODEDISPLAY ; LD (SEC),A ; LD HL,SEC ; DISPLAY PROMPT CALL SEGDISPLAY ; POP HL ; RESTORE HL POP BC ; RESTORE BC RET ; ;__GETPORT____________________________________________________________________ ; ; GET PORT FROM FRONT PANEL ;_____________________________________________________________________________ ; GETPORT: PUSH BC ; STORE BC JR GETPORTCLEAR ; GETPORT1: LD HL,PORT ; DISPLAY PROMPT CALL SEGDISPLAY ; GETPORTLOOP: CALL KB_GET ; CP 10H ; JP M,GETPORTNUM ; NUMBER PRESSED, STORE IT CP 13H ; EN PRESSED, DONE JR Z,GETPORTDONE ; CP 12H ; CLEAR PRESSED, CLEAR JR Z,GETPORTCLEAR ; JR GETPORTLOOP ; INVALID KEY, LOOP GETPORTDONE: LD A,(DISPLAYBUF+1) ; SLA A ; SLA A ; SLA A ; SLA A ; LD C,A ; LD A,(DISPLAYBUF) ; AND 0FH ; OR C ; LD C,A ; LD A,10H ; LD (DISPLAYBUF),A ; LD (DISPLAYBUF+1),A ; LD A,C ; POP BC ; RESTORE BC RET GETPORTNUM: LD C,A ; LD A,(DISPLAYBUF) ; LD (DISPLAYBUF+1),A ; LD A,C ; LD (DISPLAYBUF+0),A ; JR GETPORTDISP ; GETPORTCLEAR: LD A,12H ; LD (DISPLAYBUF),A ; LD (DISPLAYBUF+1),A ; GETPORTDISP: LD A,(DISPLAYBUF) ; CALL DECODEDISPLAY ; LD (PORT),A ; LD A,(DISPLAYBUF+1) ; CALL DECODEDISPLAY ; LD (PORT+1),A ; JP GETPORT1 ; ; ;__GETVALUE___________________________________________________________________ ; ; GET VALUE FROM FRONT PANEL ;_____________________________________________________________________________ ; GETVALUE: PUSH BC ; STORE BC JR GETVALUECLEAR ; GETVALUE1: CALL HEXDISPLAY ; GETVALUELOOP: CALL KB_GET ; CP 10H ; JP M,GETVALUENUM ; NUMBER PRESSED, STORE IT CP 13H ; EN PRESSED, DONE JR Z,GETVALUEDONE ; CP 12H ; CLEAR PRESSED, CLEAR JR Z,GETVALUECLEAR ; JR GETVALUELOOP ; INVALID KEY, LOOP GETVALUEDONE: LD A,(DISPLAYBUF+1) ; SLA A ; SLA A ; SLA A ; SLA A ; LD C,A ; LD A,(DISPLAYBUF) ; AND 0FH ; OR C ; LD C,A ; LD A,10H ; LD (DISPLAYBUF),A ; LD (DISPLAYBUF+1),A ; LD A,C ; POP BC ; RESTORE BC RET GETVALUENUM: LD C,A ; LD A,(DISPLAYBUF) ; LD (DISPLAYBUF+1),A ; LD A,C ; LD (DISPLAYBUF+0),A ; JR GETVALUE1 ; GETVALUECLEAR: LD A,12H ; LD (DISPLAYBUF),A ; LD (DISPLAYBUF+1),A ; JP GETVALUE1 ; ; ;__MTERM_INIT_________________________________________________________________ ; ; SETUP 8255, MODE 0, PORT A=OUT, PORT B=IN, PORT C=OUT/OUT ;_____________________________________________________________________________ ; MTERM_INIT: LD A, 82H OUT (PPIX),A LD A, 30H ;set PC4,5 to disable PPISD (if used) OUT (PPIC),A ;won't affect DSKY RET ; ;__KB_GET_____________________________________________________________________ ; ; GET A SINGLE KEY AND DECODE ; ;_____________________________________________________________________________ ; KB_GET: PUSH HL ; STORE HL KB_GET_LOOP: ; WAIT FOR KEY CALL KB_SCAN ; SCAN KB ONCE CP 00H ; NULL? JR Z,KB_GET_LOOP ; LOOP WHILE NOT ZERO LD D,A ; STORE A LD A,4FH | 30H ; SCAN ALL COL LINES OUT (PPIC),A ; SEND TO COLUMN LINES CALL KB_SCAN_DELAY ; DELAY TO ALLOW LINES TO STABILIZE KB_CLEAR_LOOP: ; WAIT FOR KEY TO CLEAR IN A,(PPIB) ; GET ROWS AND 7FH ;ignore PB7 for PPISD CP 00H ; ANYTHING PRESSED? JR NZ,KB_CLEAR_LOOP ; YES, EXIT LD A,D ; RESTORE A LD D,00H ; LD HL,KB_DECODE ; POINT TO BEGINNING OF TABLE KB_GET_LLOOP: CP (HL) ; MATCH? JR Z,KB_GET_DONE ; FOUND, DONE INC HL INC D ; D + 1 JP NZ,KB_GET_LLOOP ; NOT FOUND, LOOP UNTIL EOT KB_GET_DONE: LD A,D ; RESULT INTO A POP HL ; RESTORE HL RET ; ;__KB_SCAN____________________________________________________________________ ; ; SCAN KEYBOARD MATRIX FOR AN INPUT ; ;_____________________________________________________________________________ ; KB_SCAN: LD C,0000H LD A,41H | 30H ; SCAN COL ONE OUT (PPIC),A ; SEND TO COLUMN LINES CALL KB_SCAN_DELAY ; DELAY TO ALLOW LINES TO STABILIZE IN A,(PPIB) ; GET ROWS AND 7FH ;ignore PB7 for PPISD CP 00H ; ANYTHING PRESSED? JR NZ,KB_SCAN_FOUND ; YES, EXIT LD C,0040H LD A,42H | 30H ; SCAN COL TWO OUT (PPIC),A ; SEND TO COLUMN LINES CALL KB_SCAN_DELAY ; DELAY TO ALLOW LINES TO STABILIZE IN A,(PPIB) ; GET ROWS AND 7FH ;ignore PB7 for PPISD CP 00H ; ANYTHING PRESSED? JR NZ,KB_SCAN_FOUND ; YES, EXIT LD C,0080H LD A,44H | 30H ; SCAN COL THREE OUT (PPIC),A ; SEND TO COLUMN LINES CALL KB_SCAN_DELAY ; DELAY TO ALLOW LINES TO STABILIZE IN A,(PPIB) ; GET ROWS AND 7FH ;ignore PB7 for PPISD CP 00H ; ANYTHING PRESSED? JR NZ,KB_SCAN_FOUND ; YES, EXIT LD C,00C0H ; LD A,48H | 30H ; SCAN COL FOUR OUT (PPIC),A ; SEND TO COLUMN LINES CALL KB_SCAN_DELAY ; DELAY TO ALLOW LINES TO STABILIZE IN A,(PPIB) ; GET ROWS AND 7FH ;ignore PB7 for PPISD CP 00H ; ANYTHING PRESSED? JR NZ,KB_SCAN_FOUND ; YES, EXIT LD A, 40H | 30H ; TURN OFF ALL COLUMNS OUT (PPIC),A ; SEND TO COLUMN LINES LD A, 00H ; RETURN NULL RET ; EXIT KB_SCAN_FOUND: AND 3FH ; CLEAR TOP TWO BITS OR C ; ADD IN ROW BITS LD C,A ; STORE VALUE LD A, 00H | 30H ; TURN OFF ALL COLUMNS OUT (PPIC),A ; SEND TO COLUMN LINES LD A,C ; RESTORE VALUE RET PAUSE: KB_SCAN_DELAY: NOP NOP NOP NOP NOP NOP NOP NOP NOP RET ; ;__HEXDISPLAY_________________________________________________________________ ; ; DISPLAY CONTENTS OF DISPLAYBUF IN DECODED HEX BITS 0-3 ARE DISPLAYED DIG, BIT 7 IS DP ; ;_____________________________________________________________________________ ; HEXDISPLAY: PUSH HL ; STORE HL PUSH AF ; STORE AF PUSH BC ; STORE BC LD BC,0007H ADD HL,BC LD B,08H ; SET DIGIT COUNT LD A,40H | 30H ; SET CONTROL PORT 7218 TO OFF OUT (PPIC),A ; OUTPUT CALL PAUSE ; WAIT LD A,0F0H ; SET CONTROL TO 1111 (DATA COMING, HEX DECODE,NO DECODE, NORMAL) OUT (PPIA),A ; OUTPUT TO PORT LD A,80H | 30H ; STROBE WRITE PULSE WITH CONTROL=1 OUT (PPIC),A ; OUTPUT TO PORT CALL PAUSE ; WAIT LD A,40H | 30H ; SET CONTROL PORT 7218 TO OFF OUT (PPIC),A ; OUTPUT HEXDISPLAY_LP: LD A,(HL) ; GET DISPLAY DIGIT CALL DECODEDISPLAY ; DECODE DISPLAY OUT (PPIA),A ; OUT TO PPIA LD A,00H | 30H ; SET WRITE STROBE OUT (PPIC),A ; OUT TO PPIC CALL PAUSE ; DELAY LD A,40H | 30H ; SET CONTROL PORT OFF OUT (PPIC),A ; OUT TO PPIC CALL PAUSE ; WAIT DEC HL ; INC POINTER DJNZ HEXDISPLAY_LP ; LOOP FOR NEXT DIGIT POP BC ; RESTORE BC POP AF ; RESTORE AF POP HL ; RESTORE HL RET ; ;__DECODEDISPLAY______________________________________________________________ ; ; DISPLAY CONTENTS OF DISPLAYBUF IN DECODED HEX BITS 0-3 ARE DISPLAYED DIG, BIT 7 IS DP ; ;_____________________________________________________________________________ ; DECODEDISPLAY: PUSH BC ; STORE BC PUSH HL ; STORE HL LD HL,SEGDECODE ; POINT HL TO DECODE TABLE LD B,00H ; RESET HIGH BYTE LD C,A ; CHAR INTO LOW BYTE ADD HL,BC ; SET TABLE POINTER LD A,(HL) ; GET VALUE POP HL ; RESTORE HL POP BC ; RESTORE BC RET ; ;__SEGDISPLAY_________________________________________________________________ ; ; DISPLAY CONTENTS OF DISPLAYBUF IN DECODED HEX BITS 0-3 ARE DISPLAYED DIG, BIT 7 IS DP ; ;_____________________________________________________________________________ ; SEGDISPLAY: PUSH AF ; STORE AF PUSH BC ; STORE BC LD BC,0007H ADD HL,BC LD B,08H ; SET DIGIT COUNT LD A,40H | 30H ; SET CONTROL PORT 7218 TO OFF OUT (PPIC),A ; OUTPUT CALL PAUSE ; WAIT LD A,0F0H ; SET CONTROL TO 1111 (DATA COMING, HEX DECODE,NO DECODE, NORMAL) OUT (PPIA),A ; OUTPUT TO PORT LD A,80H | 30H ; STROBE WRITE PULSE WITH CONTROL=1 OUT (PPIC),A ; OUTPUT TO PORT CALL PAUSE ; WAIT LD A,40H | 30H ; SET CONTROL PORT 7218 TO OFF OUT (PPIC),A ; OUTPUT SEGDISPLAY_LP: LD A,(HL) ; GET DISPLAY DIGIT OUT (PPIA),A ; OUT TO PPIA LD A,00H | 30H ; SET WRITE STROBE OUT (PPIC),A ; OUT TO PPIC CALL PAUSE ; DELAY LD A,40H | 30H ; SET CONTROL PORT OFF OUT (PPIC),A ; OUT TO PPIC CALL PAUSE ; WAIT DEC HL ; INC POINTER DJNZ SEGDISPLAY_LP ; LOOP FOR NEXT DIGIT POP BC ; RESTORE BC POP AF ; RESTORE AF RET ; CPUUP .DB $84,$EE,$BB,$80,$BB,$EE,$CB,$84 ADDR .DB $00,$00,$00,$00,$8C,$BD,$BD,$FE PORT .DB $00,$00,$80,$80,$94,$8C,$9D,$EE SEC .DB $80,$80,$80,$80,$80,$CB,$CF,$D7 ;_KB DECODE TABLE_____________________________________________________________ ; ; KB_DECODE: ; 0 1 2 3 4 5 6 7 8 9 A B C D E F .DB $41,$02,$42,$82,$04,$44,$84,$08,$48,$88,$10,$50,$90,$20,$60,$A0 ; FW BK CL EN DP EX GO BO .DB $01,$81,$C1,$C2,$C4,$C8,$D0,$E0 ; ; F-KEYS, ; FW = FORWARD ; BK = BACKWARD ; CL = CLEAR ; EN = ENTER ; DP = DEPOSIT (INTO MEM) ; EX = EXAMINE (MEM) ; GO = GO ; BO = BOOT ;_____________________________________________________________________________ ; ;_HEX 7_SEG_DECODE_TABLE______________________________________________________ ; ; 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, ,- ; AND WITH 7FH TO TURN ON DP ;_____________________________________________________________________________ SEGDECODE: .DB $FB,$B0,$ED,$F5,$B6,$D7,$DF,$F0,$FF,$F7,$FE,$9F .DB $CB,$BD,$CF,$CE,$80,$84,$00,$EE,$9D ; DISPLAYBUF: .FILL 8,0 ; #ELSE ; DSKY_ENTRY: CALL PANIC ; #ENDIF ;********************* END OF PROGRAM *********************************** ; SLACK .EQU (MON_END - $) .FILL SLACK,00H ; MON_STACK .EQU $ ; .ECHO "DBGMON space remaining: " .ECHO SLACK .ECHO " bytes.\n" .END