;___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 hardware 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 ; ;__Hardware_Interfaces________________________________________________________________________________________________________________ ; ; PIO 82C55 I/O IS DECODED TO PORT 60-67 ; PORTA .EQU 60H PORTB .EQU 61H PORTC .EQU 62H PIOCONT .EQU 63H ; ; UART 16C450 SERIAL IS DECODED TO 68-6F ; UART0: .EQU 68H ; DATA IN/OUT UART1: .EQU 69H ; CHECK RX UART2: .EQU 6AH ; INTERRUPTS UART3: .EQU 6BH ; LINE CONTROL UART4: .EQU 6CH ; MODEM CONTROL UART5: .EQU 6DH ; LINE STATUS UART6: .EQU 6EH ; MODEM STATUS UART7: .EQU 6FH ; SCRATCH REG. ; ; MEMORY PAGE CONFIGURATION LATCH IS DECODED TO 78 ; MPCL: .EQU 78H ; CONTROL PORT, SHOULD ONLY BE CHANGED WHILE ; IN UPPER MEMORY PAGE $8000-$FFFF OR LIKELY ; LOSS OF CPU MEMORY CONTEXT. ; ; MEMORY PAGE CONFIGURATION LATCH CONTROL PORT ( IO_Y3 ) INFORMATION ; ; 7 6 5 4 3 2 1 0 ONLY APPLICABLE TO THE LOWER MEMORY PAGE $0000-$7FFF ; ^ ^ ^ ^ ^ ^ ^ ^ ; : : : : : : : :--0 = A15 RAM/ROM ADDRESS LINE DEFAULT IS 0 ; : : : : : : :----0 = A16 RAM/ROM ADDRESS LINE DEFAULT IS 0 ; : : : : : :------0 = A17 RAM/ROM ADDRESS LINE DEFAULT IS 0 ; : : : : :--------0 = A18 RAM/ROM ADDRESS LINE DEFAULT IS 0 ; : : : :-----------0 = A19 ROM ONLY ADDRESS LINE DEFAULT IS 0 ; : : :-------------0 = ; : :---------------0 = ; :-----------------0 = ROM SELECT (0=ROM, 1=RAM) DEFAULT IS 0 ; ; ;IDE REGISTER IO PORT ; FUNCTION IDELO .EQU $20 ; DATA PORT (LOW BYTE) IDEERR .EQU $21 ; READ: ERROR REGISTER; WRITE: PRECOMP IDESECTC .EQU $22 ; SECTOR COUNT IDESECTN .EQU $23 ; SECTOR NUMBER IDECYLLO .EQU $24 ; CYLINDER LOW IDECYLHI .EQU $25 ; CYLINDER HIGH IDEHEAD .EQU $26 ; DRIVE/HEAD IDESTTS .EQU $27 ; READ: STATUS; WRITE: COMMAND IDEHI .EQU $28 ; DATA PORT (HIGH BYTE) IDECTRL .EQU $2E ; READ: ALTERNATIVE STATUS; WRITE; DEVICE CONTROL IDEADDR .EQU $2F ; DRIVE ADDRESS (READ ONLY) ; ; ;__Constants_________________________________________________________________________________________________________________________ ; ROMSTART_CPM: .EQU $0900 ; Where the CCP+BDOS+BIOS is stored in ROM RAMTARG_CPM: .EQU $D400 ; Where the CCP+BDOS+BIOS starts in RAM (entry point) MOVSIZ_CPM: .EQU $1EFF ; CCP, BDOS, + BIOS is 6-7KB in length RAMTOP: .EQU $FFFF ; HIGHEST ADDRESSABLE MEMORY LOCATION STACKSTART: .EQU $D3FF ; sTART OF STACK RAMBOTTOM: .EQU $8000 ; START OF FIXED UPPER 32K PAGE OF 512KB x 8 RAM 8000H-FFFFH MONSTARTCOLD: .EQU $F800 ; COLD START MONITOR IN HIGH RAM END: .EQU $FF ; Mark END OF TEXT 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 $0100 ; For Debug in CP/M (AS .COM) .ORG 0000H ; Normal Op LD SP,STACKSTART ; Set the Stack Pointer to STACKSTART CALL INITIALIZE ; Initialize System ; REMOVE THIS TO USE THE DSKY BOARD ; JP MONSTARTWARM ; ; ;__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 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 BOOT? JP Z,DoBoot ; YES, JUMP JR FRONTPANELLoop ; LOOP Exit: RET ;__DoBoot________________________________________________________________________________________________________________________ ; ; PERFORM BOOT FRONT PANEL ACTION ;________________________________________________________________________________________________________________________________ ; DoBoot: LD HL,BOOT ; POINT TO BOOT MESSAGE CALL SEGDISPLAY ; DISPLAY MESSAGE BOOTGETKEY: CALL KB_GET ; Get Key from KB INTO A LD HL,BOOT ; POINT TO BOOT MESSAGE PUSH AF ; STORE AF CALL DECODEDISPLAY ; DECODE "A" TO 7 SEG LD (HL),A ; STORE VALUE IN A TO DISPLAY BUF CALL SEGDISPLAY ; DISPLAY BUFFER ON 7 SEG POP AF ; RESTORE AF CP 12H ; [CL] PRESSED, EXIT JP Z,BootExit ; CP 00H ; [0] PRESSED, BOOT SERIAL MONITOR JP Z,MONSTARTWARM ; CP 01H ; [1] PRESSED, BOOT ROM CP/M JP Z,GOCPM ; CP 02H ; [2] PRESSED, BOOT ATAPI PRIMARY JP Z,BOOTATAPIPRI ; CP 03H ; [3] PRESSED, BOOT ATAPI SECONDARY JP Z,BOOTATAPISEC ; LD HL,BOOT ; POINT TO BOOT MESSAGE LD A,00H ; BLANK OUT SELECTION,IT WAS INVALID LD (HL),A ; STORE IT IN DISPLAY BUFFER CALL SEGDISPLAY ; DISPLAY THE BUFFER JR BOOTGETKEY ; NO VALID KEY, LOOP BootExit: LD HL,CPUUP ; SET POINTER TO DATA BUFFER CALL SEGDISPLAY ; DISPLAY JP FRONTPANELLoop ; BOOTATAPIPRI: LD A,00H LD (IDEDEVICE),A ; SET PRIMARY DEVICE JR BOOTATAPI ; BOOTATAPISEC: LD A,10H ; LD (IDEDEVICE),A ; SET SECONDARY DEVICE BOOTATAPI: CALL IDE_SOFT_RESET ; LD HL,SEC ; DISPLAY PROMPT CALL SEGDISPLAY ; LD DE,0000H ; SET SECTOR HIGH WORD TO 00H LD HL,0000H ; SET SECTOR LOW WORD TO 00H LD IX,0D400H ; SET TOP OF CP/M LD B,19 ; SET NUMBER OF SECTORS TO LOAD BOOTATAPILOOP: CALL DSPSECTOR ; CALL ATAPI_READ_SECTOR ; READ A SECTOR INC HL ; POINT TO NEXT SECTOR DJNZ BOOTATAPILOOP ; LOOP JP 0EA00H ; GO TO CP/M ;__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 ; ;__MONSTARTWARM___________________________________________________________________________________________________________________ ; ; Serial Monitor Startup ;________________________________________________________________________________________________________________________________ ; MONSTARTWARM: ; CALL HERE FOR SERIAL MONITOR WARM START XOR A ;ZERO OUT ACCUMULATOR (added) PUSH HL ;protect HL from overwrite LD HL,TXT_READY ;POINT AT TEXT CALL MSG ;SHOW WE'RE HERE POP HL ;protect HL from overwrite ; ;__SERIAL_Monitor_Commands_________________________________________________________________________________________________________ ; ; B Xx BOOT CPM FROM DRIVE Xx ; D XXXXH YYYYH DUMP MEMORY FROM XXXX TO YYYY ; F XXXXH YYYYH ZZH FILL MEMORY FROM XXXX TO YYYY WITH ZZ ; H LOAD INTEL HEX FORMAT DATA ; I INPUT FROM PORT AND SHOW HEX DATA ; K ECHO KEYBOARD INPUT ; M XXXXH YYYYH ZZZZH MOVE MEMORY BLOCK XXXX TO YYYY TO ZZZZ ; O OUTPUT TO PORT HEX DATA ; P XXXXH YYH PROGRAM RAM FROM XXXXH WITH VALUE IN YYH, WILL PROMPT FOR NEXT LINES FOLLOWING UNTIL CR ; R RUN A PROGRAM FROM CURRENT LOCATION ;__Command_Parse_________________________________________________________________________________________________________________ ; ; Prompt User for commands, then parse them ;________________________________________________________________________________________________________________________________ ; SERIALCMDLOOP: 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,CONDOBOOT ; IF YES DO 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 'H' ; IS IT A "H" (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,DUMP ; DUMP MEMORY CP 'K' JP Z,KLOP ; LOOP ON KEYBOARD CP 'M' ; IS IT A "M" (y/n) JP Z,MOVE ; MOVE MEMORY COMMAND CP 'F' ; IS IT A "F" (y/n) JP Z,FILL ; FILL MEMORY COMMAND LD HL,TXT_COMMAND ; POINT AT ERROR TEXT CALL MSG ; print command label JR SERIALCMDLOOP ;__KLOP__________________________________________________________________________________________________________________________ ; ; Read from the Serial Port and Echo, Monitor Command "K" ;________________________________________________________________________________________________________________________________ ; KLOP: CALL KIN ; GET A KEY CALL COUT ; OUTPUT KEY TO SCREEN CP ESC ; IS ? JR NZ,KLOP ; NO, LOOP JP SERIALCMDLOOP ; ;__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 CALL COUT ; OUTPUT KEY TO SCREEN CP CR ; IS ? JR Z,GETLNDONE ; YES, EXIT 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: IN A,(UART5) ; READ Line Status Register BIT 0,A ; TEST IF DATA IN RECEIVE BUFFER JP Z,KIN ; LOOP UNTIL DATA IS READY IN A,(UART0) ; THEN READ THE CHAR FROM THE UART 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 ;__COUT__________________________________________________________________________________________________________________________ ; ; Write the Value in "A" to the Serial Port ;________________________________________________________________________________________________________________________________ ; COUT: PUSH AF ; Store AF TX_BUSYLP: IN A,(UART5) ; READ Line Status Register BIT 5,A ; TEST IF UART IS READY TO SEND JP Z,TX_BUSYLP ; IF NOT REPEAT POP AF ; Restore AF OUT (UART0),A ; THEN WRITE THE CHAR TO UART 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 ; ;__LDHL__________________________________________________________________________________________________________________________ ; ; GET ONE WORD OF HEX DATA FROM BUFFER POINTED TO BY HL SERIAL PORT, RETURN IN HL ;________________________________________________________________________________________________________________________________ ; LDHL: PUSH DE ; STORE DE CALL HEXIN ; GET K.B. AND MAKE HEX LD D,A ; THATS THE HI BYTE CALL HEXIN ; DO HEX AGAIN LD L,A ; THATS THE LOW BYTE LD H,D ; MOVE TO HL POP DE ; RESTORE BC RET ; GO BACK WITH ADDRESS ;__HEXIN__________________________________________________________________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A ;________________________________________________________________________________________________________________________________ ; HEXIN: PUSH BC ;SAVE BC REGS. CALL NIBL ;DO A NIBBLE RLC A ;MOVE FIRST BYTE UPPER NIBBLE RLC A ; RLC A ; RLC A ; LD B,A ; SAVE ROTATED BYTE CALL NIBL ; DO NEXT NIBBLE ADD A,B ; COMBINE NIBBLES IN ACC. POP BC ; RESTORE BC RET ; DONE 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 INC HL ; INC KB POINTER CP 40H ; TEST FOR ALPHA JR NC,ALPH ; AND 0FH ; GET THE BITS RET ; ;__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 ;__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 CALL SPACE ; RET ; DONE ;__POUT__________________________________________________________________________________________________________________________ ; ; Output to an I/O Port, Monitor Command "O" ;________________________________________________________________________________________________________________________________ ; POUT: POUT1: INC HL ; CALL HEXIN ; GET PORT LD C,A ; SAVE PORT POINTER INC HL ; CALL HEXIN ; GET DATA OUTIT: OUT (C),A ; JP SERIALCMDLOOP ; ;__PIN___________________________________________________________________________________________________________________________ ; ; Input From an I/O Port, Monitor Command "I" ;________________________________________________________________________________________________________________________________ ; PIN: INC HL ; CALL HEXIN ; GET PORT LD C,A ; SAVE PORT POINTER CALL CRLF ; IN A,(C) ; GET DATA CALL HXOUT ; SHOW IT JP SERIALCMDLOOP ; ;__cONDoBoot_____________________________________________________________________________________________________________________ ; ; PERFORM BOOT ACTION ;________________________________________________________________________________________________________________________________ ; CONDOBOOT: INC HL ; CALL HEXIN ; GET BOOT SEQ LD C,A ; SAVE PORT POINTER CALL CRLF ; LD A,C ; CP 01H ; [1] PRESSED, BOOT ROM CP/M JP Z,GOCPM ; CP 02H ; [2] PRESSED, BOOT ATAPI PRIMARY JP Z,CONBOOTATAPIPRI ; CP 03H ; [3] PRESSED, BOOT ATAPI SECONDARY JP Z,CONBOOTATAPISEC ; JP SERIALCMDLOOP ; CONBOOTATAPIPRI: LD A,00H LD (IDEDEVICE),A ; SET PRIMARY DEVICE JR CONBOOTATAPI ; CONBOOTATAPISEC: LD A,10H ; LD (IDEDEVICE),A ; SET SECONDARY DEVICE CONBOOTATAPI: CALL IDE_SOFT_RESET ; LD DE,0000H ; SET SECTOR HIGH WORD TO 00H LD HL,0000H ; SET SECTOR LOW WORD TO 00H LD IX,0D400H ; SET TOP OF CP/M LD B,19 ; SET NUMBER OF SECTORS TO LOAD CONBOOTATAPILOOP: CALL ATAPI_READ_SECTOR ; READ A SECTOR INC HL ; POINT TO NEXT SECTOR DJNZ CONBOOTATAPILOOP ; LOOP JP 0EA00H ; GO TO CP/M ;__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 ;__MSG___________________________________________________________________________________________________________________________ ; ; Print a String to the serial port ;________________________________________________________________________________________________________________________________ ; MSG: TX_SERLP: LD A,(HL) ; GET CHARACTER TO A CP END ; TEST FOR END BYTE JP Z,TX_END ; JUMP IF END BYTE IS FOUND CALL COUT ; INC HL ; INC POINTER, TO NEXT CHAR JP TX_SERLP ; TRANSMIT LOOP TX_END: RET ;ELSE DONE ;__RUN___________________________________________________________________________________________________________________________ ; ; TRANSFER OUT OF MONITOR, User option "R" ;________________________________________________________________________________________________________________________________ ; RUN: INC HL ; SHOW READY CALL LDHL ; GET START ADDRESS JP (HL) ; ;__PROGRM________________________________________________________________________________________________________________________ ; ; Program RAM locations, User option "P" ;________________________________________________________________________________________________________________________________ ; PROGRM: INC HL ; SHOW READY PUSH HL ; STORE HL CALL LDHL ; GET START ADDRESS LD D,H ; LD E,L ; DE POINTS TO ADDRESS TO PROGRAM POP HL ; INC HL ; INC HL ; INC HL ; INC HL ; INC HL ; PROGRMLP: CALL HEXIN ; GET NEXT HEX NUMBER LD (DE),A ; STORE IT INC DE ; NEXT ADDRESS; CALL CRLFA ; CR,LF,> LD A,'P' ; CALL COUT ; CALL SPACE ; LD H,D ; LD L,E ; CALL PHL ; 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 CP 00H ; END OF LINE? JP Z,PROGRMEXIT ; YES, EXIT JP PROGRMLP ; NO, LOOP PROGRMEXIT: JP SERIALCMDLOOP ;__DUMP__________________________________________________________________________________________________________________________ ; ; Print a Memory Dump, User option "D" ;________________________________________________________________________________________________________________________________ ; DUMP: INC HL ; SHOW READY PUSH HL ; STORE HL CALL LDHL ; GET START ADDRESS LD D,H ; LD E,L ; POP HL ; PUSH DE ; SAVE START INC HL ; INC HL ; INC HL ; INC HL ; INC HL ; CALL LDHL ; GET END ADDRESS INC HL ; ADD ONE MORE FOR LATER COMPARE EX DE,HL ; PUT END ADDRESS IN DE POP HL ; GET BACK START GDATA: CALL CRLF ; BLKRD: CALL PHL ; PRINT START LOCATION 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 ; ;__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 $3A ; 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 $01 ; 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 ;__MOVE__________________________________________________________________________________________________________________________ ; ; Move Memory, User option "M" ;________________________________________________________________________________________________________________________________ ; MOVE: LD C,03 ; start GETNM replacement ; get source starting memory location INC HL ; SHOW EXAMINE READY PUSH HL ; CALL LDHL ; LOAD IN HL REGS. LD D,H ; LD E,L ; POP HL ; PUSH DE ; push memory address on stack INC HL ; INC HL ; INC HL ; INC HL ; INC HL ; print space separator PUSH HL ; CALL LDHL ; LOAD IN HL REGS. LD D,H ; LD E,L ; POP HL ; PUSH DE ; push memory address on stack INC HL ; INC HL ; INC HL ; INC HL ; INC HL ; print space separator CALL LDHL ; LOAD IN HL REGS. PUSH HL ; push memory address on stack ; end GETNM replacement POP DE ; DEST POP BC ; SOURCE END POP HL ; SOURCE PUSH HL ; LD A,L ; CPL ; LD L,A ; LD A,H ; CPL ; LD H,A ; INC HL ; ADD HL,BC ; LD C,L ; LD B,H ; POP HL ; CALL MOVE_LOOP ; JP SERIALCMDLOOP ; EXIT MOVE COMMAND ROUTINE MOVE_LOOP: LD A,(HL) ; FETCH LD (DE),A ; DEPOSIT INC HL ; BUMP SOURCE INC DE ; BUMP DEST DEC BC ; DEC COUNT LD A,C ; OR B ; JP NZ,MOVE_LOOP ; TIL COUNT=0 RET ; ;__FILL__________________________________________________________________________________________________________________________ ; ; Fill Memory, User option "M" ;________________________________________________________________________________________________________________________________ ; FILL: LD C,03 ; ; start GETNM replacement ; get fill starting memory location INC HL ; SHOW EXAMINE READY PUSH HL ; CALL LDHL ; LOAD IN HL REGS. LD D,H ; LD E,L ; POP HL ; PUSH DE ; push memory address on stack INC HL ; INC HL ; INC HL ; INC HL ; INC HL ; print space separator ; get fill ending memory location PUSH HL ; CALL LDHL ; LOAD IN HL REGS. LD D,H ; LD E,L ; POP HL ; PUSH DE ; push memory address on stack INC HL ; INC HL ; INC HL ; INC HL ; INC HL ; print space separator ; get target starting memory location CALL HEXIN ; GET K.B. AND MAKE HEX LD C,A ; put fill value in F so it is saved for later PUSH BC ; push fill value byte on stack ; end GETNM replacement POP BC ; BYTE POP DE ; END POP HL ; START LD (HL),C ; FILL_LOOP: LD (HL),C ; INC HL ; LD A,E ; SUB L ; LD B,A ; LD A,D ; SUB H ; OR B ; JP NZ,FILL_LOOP ; JP SERIALCMDLOOP ; ;__GOCPM_________________________________________________________________________________________________________________________ ; ; BOOT CP/M From ROM Drive, User option "C" ;________________________________________________________________________________________________________________________________ ; GOCPM: ;___________________________ ; REMOVE COMMENTS WHEN BURNED IN ROM ;___________________________ ; LD A,%00000000 ; RESET MPCL latch to default ROM ; OUT (MPCL),A ; ; LD HL,ROMSTART_CPM ; where in rom CP/M is stored (first byte) ; LD DE,RAMTARG_CPM ; where in ram to move Monitor to (first byte) ; LD BC,MOVSIZ_CPM ; number of bytes to move from ROM to RAM ; LDIR ; Perform Block Copy of CP/M to Upper RAM page ; LD A,%10000000 ; RESET MPCL latch to default CP/M with 64K setting ; OUT (MPCL),A ; JP $EA00 ; CP/M COLD BOOT ENTRY POINT ; ;__Init_UART_____________________________________________________________________________________________________________________ ; ; Initialize UART ; Params: SER_BAUD Needs to be set to Baud Rate ; 1200: 96 = 1,843,200 / ( 16 x 1200 ) ; 2400: 48 = 1,843,200 / ( 16 x 2400 ) ; 4800: 24 = 1,843,200 / ( 16 x 4800 ) ; 9600: 12 = 1,843,200 / ( 16 x 9600 ) ; 19K2: 06 = 1,843,200 / ( 16 x 19,200 ) ; 38K4: 03 ; 57K6: 02 ; 115K2: 01 ; ;_________________________________________________________________________________________________________________________________ ; INIT_UART: LD A,80H ; OUT (UART3),A ; SET DLAB FLAG LD A,(SER_BAUD) ; OUT (UART0),A ; LD A,00H ; OUT (UART1),A ; LD A,03H ; OUT (UART3),A ; Set 8 bit data, 1 stopbit RET ; ;__FILL_MEM_______________________________________________________________________________________________________________________ ; ; Function : fill memory with a value ; Input : HL = start address block ; : BC = length of block ; : A = value to fill with ; Uses : DE, BC ; Output : ; calls : ; tested : 13 Feb 2007 ;_________________________________________________________________________________________________________________________________ ; FILL_MEM: ld e,l ; ld d,h ; inc de ; ld (hl),A ; initialise first byte of block with data byte in A ldir ; fill memory RET ; return to caller ; ;__Initialize_____________________________________________________________________________________________________________________ ; ; Initialize System ;_________________________________________________________________________________________________________________________________ ; INITIALIZE: LD A,12 ; specify baud rate 9600 bps (9600,8,None,1) LD (SER_BAUD),A ; CALL INIT_UART ; INIT the UART RET ; ADDED FOR TESTING (as .COM) ; ;__mTerm_Init________________________________________________________________________________________ ; ; Setup 8255, Mode 0, Port A=Out, Port B=In, Port C=Out/Out ; ;____________________________________________________________________________________________________ mTerm_Init: LD A, 82H OUT (PIOCONT),A 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 ; Scan All Col Lines OUT (PORTC),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,(PORTB) ; Get Rows 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 ; Scan Col One OUT (PORTC),A ; Send to Column Lines CALL KB_Scan_Delay ; Delay to allow lines to stabilize IN A,(PORTB) ; Get Rows CP 00H ; Anything Pressed? JR NZ,KB_Scan_Found ; Yes, Exit. LD C,0040H LD A,42H ; Scan Col Two OUT (PORTC),A ; Send to Column Lines CALL KB_Scan_Delay ; Delay to allow lines to stabilize IN A,(PORTB) ; Get Rows CP 00H ; Anything Pressed? JR NZ,KB_Scan_Found ; Yes, Exit. LD C,0080H LD A,44H ; Scan Col Three OUT (PORTC),A ; Send to Column Lines CALL KB_Scan_Delay ; Delay to allow lines to stabilize IN A,(PORTB) ; Get Rows CP 00H ; Anything Pressed? JR NZ,KB_Scan_Found ; Yes, Exit. LD C,00C0H ; LD A,48H ; Scan Col Four OUT (PORTC),A ; Send to Column Lines CALL KB_Scan_Delay ; Delay to allow lines to stabilize IN A,(PORTB) ; Get Rows CP 00H ; Anything Pressed? JR NZ,KB_Scan_Found ; Yes, Exit. LD A, 40H ; Turn off All Columns OUT (PORTC),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 ; Turn off All Columns OUT (PORTC),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 ; set Control port 7218 to off OUT (PORTC),A ; output CALL PAUSE ; wait LD A,0F0H ; set control to 1111 (Data Coming, Hex Decode,NO Decode, Normal) OUT (PORTA),A ; output to port LD A,80H ; Strobe write pulse with Control=1 OUT (PORTC),A ; output to port CALL PAUSE ; wait LD A,40H ; set Control port 7218 to off OUT (PORTC),A ; output HEXDISPLAY_LP: LD A,(HL) ; GET DISPLAY DIGIT CALL DECODEDISPLAY ; DECODE DISPLAY OUT (PORTA),A ; OUT TO PORTA LD A,00H ; SET WRITE STROBE OUT (PORTC),A ; OUT TO PORTC CALL PAUSE ; DELAY LD A,40H ; SET CONTROL PORT OFF OUT (PORTC),A ; OUT TO PORTC 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 ; set Control port 7218 to off OUT (PORTC),A ; output CALL PAUSE ; wait LD A,0F0H ; set control to 1111 (Data Coming, Hex Decode,NO Decode, Normal) OUT (PORTA),A ; output to port LD A,80H ; Strobe write pulse with Control=1 OUT (PORTC),A ; output to port CALL PAUSE ; wait LD A,40H ; set Control port 7218 to off OUT (PORTC),A ; output SEGDISPLAY_LP: LD A,(HL) ; GET DISPLAY DIGIT OUT (PORTA),A ; OUT TO PORTA LD A,00H ; SET WRITE STROBE OUT (PORTC),A ; OUT TO PORTC CALL PAUSE ; DELAY LD A,40H ; SET CONTROL PORT OFF OUT (PORTC),A ; OUT TO PORTC CALL PAUSE ; WAIT DEC HL ; INC POINTER DJNZ SEGDISPLAY_LP ; LOOP FOR NEXT DIGIT POP BC ; RESTORE BC POP AF ; RESTORE AF RET ;________________________________________________________________________________________________________________________________ ; ; ATAPI Code ;________________________________________________________________________________________________________________________________ ;__ATAPI_READ_SECTOR_____________________________________________________________________________________________________________ ; READ ATAPI SECTOR ; ; D E H L = SECTOR (DOUBLE WORD) TO READ ; IX = READ TO ADDRESS ; ; ON RETURN IX WILL BE POINTED TO NEXT BYTE AFTER READ OPERATION ;________________________________________________________________________________________________________________________________ ATAPI_READ_SECTOR: PUSH BC ; STORE BC PUSH DE ; STORE DE PUSH HL ; STORE HL LD A,D ; STORE SECTOR ADDRESS TO PACKET LD (READ_DISK_PACKET+2),A ; LD A,E ; LD (READ_DISK_PACKET+3),A ; LD A,H ; LD (READ_DISK_PACKET+4),A ; LD A,L ; LD (READ_DISK_PACKET+5),A ; CALL REQUEST_SENSE_LOOP ; GET ATAPI SENSE CODES TO CLEAR ERRORS LD HL,READ_DISK_PACKET ; SET POINTER TO READ SECTOR PACKET CALL ATAPI_SEND_PACKET ; SEND PACKET COMMAND CALL ATAPI_READ_DATA ; POP HL ; RESTORE HL POP DE ; RESTORE DE POP BC ; RESTORE BC RET ; ;__ATAPI_SEND_PACKET_____________________________________________________________________________________________________________ ; SEND PACKET POINTED TO BY HL TO ATAPI DRIVE ; ;________________________________________________________________________________________________________________________________ ATAPI_SEND_PACKET: CALL IDE_WAIT_BUSY_READY ; MAKE SURE DRIVE IS READY TO PROCEED CALL IDE_WAIT_DRQ_ZERO ; ; LD A,0AH ; OUT (IDECTRL),A ; Disable INT LD A,00H ; OUT (IDEERR),A ; LD A,00H ; OUT (IDESECTC),A ; LD A,00H ; OUT (IDESECTN),A ; LD A,00H ; OUT (IDECYLLO),A ; LD A,60H ; OUT (IDECYLHI),A ; LD A,(IDEDEVICE) ; OUT (IDEHEAD),A ; Bit 4 selects device LD A,0A0H ; OUT (IDESTTS),A ; ; CALL IDE_WAIT_DRQ_READY ; MAKE SURE DRIVE IS READY TO PROCEED ; LD B,6 ; SEND 12 BYTES (6 WORDS) ; ATAPI_SEND_PACKET_LOOP: LD A,(HL) ; GET BYTE LD D,A ; STORE LOW BYTE IN D INC HL ; INC POINTER LD A,(HL) ; GET HIGH BYTE OUT (IDEHI),A ; STORE HIGH BYTE LD A,D ; MOVE LOW BYTE INTO A OUT (IDELO),A ; STORE LOW BYTE INC HL ; INC POINTER IN A,(IDECTRL) ; GET STATUS DJNZ ATAPI_SEND_PACKET_LOOP ; LOOP ; CALL IDE_WAIT_BUSY_READY ; MAKE SURE DRIVE IS READY TO PROCEED IN A,(IDECTRL) ; READ STATUS (FOR DELAY) ; RET ; ;__ATAPI_READ_DATA__________________________________________________________________________________________________________ ; READ DATA BLOCK INTO IDE_SECTOR_BUFFER ; ; IX = POINTER TO BUFFER ; ;___________________________________________________________________________________________________________________________ ATAPI_READ_DATA: LD B,0 ; 256 WORDS (512 BYTES PER SECTOR) CALL IDE_WAIT_BUSY_READY ; MAKE SURE DRIVE IS READY TO PROCEED IN A,(IDESTTS) ; READ REG AND %00001000 ; MASK OFF BIT CP 08H ; IS DATA WAITING? JR NZ,ATAPI_READ_DATA_EXIT ; NO, EXIT ATAPI_READ_DATA_LOOP: IN A,(IDELO) ; LD (IX),A ; INC IX ; IN A,(IDEHI) ; LD (IX),A ; INC IX ; DJNZ ATAPI_READ_DATA_LOOP ; ATAPI_READ_DATA_EXIT: RET ; ;__IDE_SOFT_RESET__________________________________________________________________________________________________________ ; RESET IDE DEVICE ;___________________________________________________________________________________________________________________________ IDE_SOFT_RESET: LD A,%00001110 ;NO INTERRUPTS, RESET DRIVE = 1 OUT (IDECTRL),A ; CALL DELAY ; LD A,%00001010 ;NO INTERRUPTS, RESET DRIVE = 0 OUT (IDECTRL),A ; CALL IDE_WAIT_BUSY_READY ; CALL ATAPI_DEVICE_SELECTION ; CALL DELAY ; CALL REQUEST_SENSE_LOOP ; RET ;__REQUEST_SENSE_LOOP_______________________________________________________________________________________________________ ; REQUEST SENSE DATA FROM DEVICE ;___________________________________________________________________________________________________________________________ REQUEST_SENSE_LOOP: PUSH HL ; STORE HL PUSH IX ; STORE IX PUSH AF ; STORE AF LD HL,ATAPI_REQUEST_SENSE ; CALL ATAPI_SEND_PACKET ; LD IX,IDE_SECTOR_BUFFER ; SET SECTOR BUFFER CALL ATAPI_READ_DATA ; CALL DELAY ; IN A,(IDESTTS) ;READ ERROR REG AND %00000001 ;MASK OFF BIT JR NZ,REQUEST_SENSE_LOOP ; POP AF ; RESTORE AF POP IX ; RESTORE IX POP HL ; RESTORE HL RET ;__ATAPI_DEVICE_SELECTION___________________________________________________________________________________________________ ; IDE SELECT DEVICE ;___________________________________________________________________________________________________________________________ ATAPI_DEVICE_SELECTION: CALL IDE_WAIT_BUSY_READY ; LD A,(IDEDEVICE) ; Selects Device OR 0A0H ; OUT (IDEHEAD),A ; CALL IDE_WAIT_BUSY_READY ; RET ; ;__DELAY____________________________________________________________________________________________________________________ ; DELAY ;___________________________________________________________________________________________________________________________ DELAY: NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; RET ;__IDE_WAIT_BUSY_READY______________________________________________________________________________________________________ ; WAIT FOR BUSY TO BE READY ;___________________________________________________________________________________________________________________________ IDE_WAIT_BUSY_READY: PUSH DE ; PUSH BC ; LD DE,0 ; IDE_WBSY: LD B,5 ; IDE_DLP: DJNZ IDE_DLP ; INC DE ; LD A,D ; OR E ; JR Z,IDE_TO ; IN A,(IDESTTS) ; READ ERROR REG AND %10000000 ; MASK OFF BUSY BIT JR NZ,IDE_WBSY ; WE WANT BUSY(7) TO BE 0 SCF ; CARRY 1 = OK POP BC ; POP DE ; RET ; IDE_TO: POP BC ; POP DE ; XOR A ; CARRY 0 = TIMED OUT RET ; ;__IDE_WAIT_DRDY_READY______________________________________________________________________________________________________ ; WAIT FOR DRDY ;___________________________________________________________________________________________________________________________ IDE_WAIT_DRDY_READY: IN A,(IDESTTS) ; READ ERROR REG AND %01000000 ; MASK OFF RDY BIT JR Z,IDE_WAIT_DRDY_READY ; WE WANT RDY(6) TO BE 1 RET ;__IDE_WAIT_DRQ_READY_______________________________________________________________________________________________________ ; WAIT FOR DRQ ;___________________________________________________________________________________________________________________________ IDE_WAIT_DRQ_READY: IN A,(IDESTTS) ; READ ERROR REG AND %00001000 ; MASK OFF RDY BIT JR Z,IDE_WAIT_DRQ_READY ; WE WANT DRQ(3) TO BE 1 RET ;__IDE_WAIT_DRQ_ZERO________________________________________________________________________________________________________ ; WAIT FOR DRQ = 0 ;___________________________________________________________________________________________________________________________ IDE_WAIT_DRQ_ZERO: IN A,(IDESTTS) ; READ ERROR REG AND %00001000 ; MASK OFF RDY BIT JR NZ,IDE_WAIT_DRQ_ZERO ; WE WANT DRQ(3) TO BE 0 RET ; ;__Work_Area___________________________________________________________________________________________________________________ ; ; Reserved Ram For Monitor working area ;_____________________________________________________________________________________________________________________________ ; SER_BAUD: .DS 1 ; specify desired UART com rate in bps KEYBUF: .TEXT " " DISPLAYBUF: .DB 00,00,00,00,00,00,00,00 IDEDEVICE: .DB 1 ; IDE DRIVE SELECT FLAG (00H=PRIAMRY, 10H = SECONDARY) IDE_SECTOR_BUFFER: .DS $0200 ; ;__Text_Strings_________________________________________________________________________________________________________________ ; ; System Text Strings ;_____________________________________________________________________________________________________________________________ ; TCRLF: .BYTE CR,LF,END PROMPT: .BYTE CR,LF,'>',END TXT_READY: .BYTE CR,LF .TEXT " NN NN 8888 VV VV EEEEEEEEEE MM MM" .BYTE CR,LF .TEXT " NNNN NN 88 88 VV VV EE MMMM MMMM" .BYTE CR,LF .TEXT " NN NN NN 88 88 VV VV EE MM MM MM MM" .BYTE CR,LF .TEXT " NN NNNN 88 88 VV VV EE MM MM MM" .BYTE CR,LF .TEXT " NN NN 8888 VV VV EEEEEEE MM MM" .BYTE CR,LF .TEXT " NN NN 88 88 VV VV EE MM MM" .BYTE CR,LF .TEXT " NN NN 88 88 VV VV EE MM MM" .BYTE CR,LF .TEXT " NN NN 88 88 VVV EE MM MM" .BYTE CR,LF .TEXT " NN NN 8888 V EEEEEEEEEE MM MM S B C" .BYTE CR,LF .BYTE CR,LF .TEXT " ****************************************************************************" .BYTE CR,LF .TEXT "Monitor Ready " .BYTE CR,LF,END TXT_COMMAND: .BYTE CR,LF .TEXT "UNKNOWN COMMAND." .BYTE END TXT_CKSUMERR: .BYTE CR,LF .TEXT "CHECKSUM ERROR." .BYTE END CPUUP: .DB 084H,0EEH,0BBH,080H,0BBH,0EEH,0CBH,084H ADDR: .DB 00H,00H,00H,00H,08CH,0BDH,0BDH,0FEH BOOT: .DB 00H,00H,80H,80H,094H,09DH,09DH,09FH PORT: .DB 00H,00H,80H,80H,094H,08CH,09DH,0EEH SEC: .DB 80H,80H,80H,80H,80H,0CBH,0CFH,0D7H ;_ATAPI COMMAND PACKETS______________________________________________________________________________________________________ ; ; READ_DISK_PACKET .DB 0A8H,00H,00H,00H,00H,01H,00H,00H,00H,01H,00H,00H ATAPI_REQUEST_SENSE .DB 03H,00H,00H,00H,011H,00H,00H,00H,00H,00H,00H,00H ;_KB Decode Table__________________________________________________________________________________________________________ ; ; KB_Decode: ; 0 1 2 3 4 5 6 7 8 9 A B C D E F .DB 41H,02H,42H,82H,04H,44H,84H,08H,48H,88H,10H,50H,90H,20H,60H,0A0H ; FW BK CL EN DP EX GO BO .DB 01H,81H,0c1H,0c2H,0c4H,0c8H,0D0H,0E0H ; ; 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 0FBH,0B0H,0EDH,0F5H,0B6H,0D7H,0DFH,0F0H,0FFH,0F7H,0FEH,09FH,0CBH,0BDH,0CFH,0CEH,080H,084H,00H,0EEH,09DH ;********************* END OF PROGRAM *********************************** ;.ORG $FFFF ;.BYTE $FF .END