;NEWMON.MAC: ROM monitor program. Uses no RAM !! ;BEGUN 01/09/88 RONALD E. JACOBS ;latest work done 10/11/88 LF EQU 00Ah ;ASCII line feed character CR EQU 00Dh ;ASCII carriage return character TRUE EQU 001h FALSE EQU 000h .Z80 ;USE Z80 NMEMONICS ;************************************************************************ ;* * ;* USER SETTABLE EQUATES: * ;* CONSOLE PORT INFORMATION: Only one may be true * ;* PROMPT SELECTION: A printing character of your choice * ;* * ;************************************************************************ MD3 EQU true ;MORROW MD2 OR MD3 MICRODECISION WB14 EQU false ;MORROW WUNDERBUS OR MULT/IO BOARD MDHD EQU false ;MORROW HARD DISK MICRODECISION PROMPT EQU ']' ;SELECT THE CHARACTER TO BE THE PROMPT MONITOR EQU true ;INCLUDE MONITOR PORTION OF PROGRAM? ALIGNMENT EQU TRUE ;INCLUDE FSTEP PORTION OF PROGRAM? ;************************************************************************ ;* END OF USER SETTABLE EQUATES * ;************************************************************************ ONCRT MACRO DUM1,DUM2 ;FOR SHOWING INFO ON CRT AT ASSEMBLY .PRINTX DUM1=DUM2 ;DUM1='TEXT', DUM2=VARIABLE ENDM IF WB14 ;MORROW WUNDERBUS OR MULT/IO BOARD STATUS EQU 04Dh ;PORT STATUS REGISTER RDREG EQU 048h ;port input register (read) WRREG EQU 048h ;port output register (write) RDBIT EQU 001h ;port data ready to read (1 if ready) WRBIT EQU 020h ;port ready to output data (1 if ready) ENDIF IF MD3 ;MORROW MD2 OR MD3 MICRODECISION STATUS EQU 0FDh ;PORT STATUS REGISTER RDREG EQU 0FCh ;port input register (read) WRREG EQU 0FCh ;port output register (write) RDBIT EQU 002h ;port data ready to read (1 if ready) WRBIT EQU 001h ;port ready to output data (1 if ready) S1STAT EQU 0FDh ;for initialization of status port 1 S2STAT EQU 0FFh ;for initialization of status port 2 ENDIF IF MDHD ;MORROW HARD DISK MICRODECISION STATUS EQU 061h ;PORT STATUS REGISTER RDREG EQU 060h ;port input register (read) WRREG EQU 060h ;port output register (write) RDBIT EQU 001h ;port data ready to read (1 if ready) WRBIT EQU 004h ;port ready to output data (1 if ready) ; I/O Registers - Serial Ports ;MORROW HARD DISK MICRODECISION ;----------------------------- ; s1data equ 60h ;serial port 1 data (dart1 = console port) s1stat equ 61h ;serial port 1 status s2data equ 62h ;serial port 2 data (dart2 = printer port) s2stat equ 63h ;serial port 2 status s3data equ 70h ;serial port 3 data (sio) s3stat equ 71h ;serial port 3 status (sio) $TxRdy equ 00000100b ;Uart Transmitter Ready Bit $RcvRdy equ 00000001b ;Uart Reciever Ready Bit ; I/O Registers - Counter Timer Chip ;----------------------------------- ; 1) The labels baud0, baud1 and baud2 correspond to the schematic labels ; for the signals carrying the baud rate clocks to the dart/sio. baud0 ; is the clock for serial port 1. ; baudset equ 53h ;ctc channel select/mode port baud0 equ 52h ;baud rate control for serial port 1 (consol) baud1 equ 51h ;baud rate control for serial port 2 baud2 equ 50h ;baud rate control for serial port 3 $JBAUD equ 00100000b ;Console Baud Rate Jumper (1=19200,0=9600) DrvSts equ 0C0h ;Drive Status ;*Baud Rate Definitions for CTC initialization (see IntCtc)* B300 equ 342h ;300 Baud B1200 equ 0D0h ;1200 Baud B9600 equ 01Ah ;9600 Baud B19200 equ 00Dh ;19200 Baud ENDIF ;End of hard disk MicroDecision equates ;************************************************************************ ;* * ;* BEGIN PROGRAM CODE * ;* * ;************************************************************************ BYTE0: ;label for addressing first byte (for Relocate) ;---------------------------------------------------------------------- ; routine: INITUART (INITIALIZE MICRODECISION MD2, MD3 UARTS) ;--------------------- ; ; Function: This routine initializes both UARTS and the CTC (Clock Control ; Chip). The UARTS are set for 8 bits, no parity, x1 clock rate, ; and 2 stop bits. In addition, DTR and RTS are programmed to be on. ; The CTC is set for 9600 on the console UART, 1200 baud on the printer ; UART, and maximum delay on the drive time out counter. ; IF MD3 inituart: ld hl,init_tab ;pointer to init data table ld b,init_len ;init data table length init_loop: ld c,(hl) ;port address inc hl ld a,(hl) ;data inc hl out (c),a ;output data to port djnz init_loop ;loop until done ENDIF ;end of MD2/MD3 port initialization code ;INTURT - Initialize the Serial I/O Devices(12_Nov_83)(HARD DISK MICRODECISION) ;------------------------------------------------------- ; function: this routine initializes both channels of the darts. ; they are set for 8 bits, no parity, x16 clock rate, and ; 2 stop bits. in addition, dtr, and rts, are programmed ; to be on. ; IF MDHD inturt: ld a,18h ; send channel reset commands out (s1stat),a out (s2stat),a out (s3stat),a ld a,10h ;reset ext/status interrupts out (s1stat),a out (s2stat),a out (s3stat),a ;end of reset sequence ld a,04h ;select register 4 out (s1stat),a out (s2stat),a out (s3stat),a ld a,04ch ;no par, x16, 2 stops out (s1stat),a out (s2stat),a out (s3stat),a ld a,03h ;select register 3 out (s1stat),a out (s2stat),a out (s3stat),a ld a,0c1h ;rx 8 bits, auto off, rx enabled out (s1stat),a out (s2stat),a out (s3stat),a ld a,05h ;select register 5 out (s1stat),a out (s2stat),a out (s3stat),a ld a,0EAh ;tx 8 bits, dtr/rts on tx enabled out (s1stat),a out (s2stat),a out (s3stat),a ld a,10h ;reset ext/status interupts again out (s1stat),a out (s2stat),a out (s3stat),a ld a,01h ;select register 1 out (s1stat),a out (s2stat),a out (s3stat),a ld a,0h ;disable all interrupts here out (s1stat),a out (s2stat),a out (s3stat),a ;---------------------------------------------------------------------- ; For the hard disk MicroDecision (MDHD): ; INTCTC - Initialize the Counter Timer Chip Baud Rates (12_Jan_84) ;------------------------------------------------------------------ ; 1) This routine intializes the counter timer chip that serves as ; a baud rate generator for the serial ports. ; 2) Notice that the Console Device (channel_2) has its baud rate ; set as a function of a jumper (bit_5 of drvsts). If the jumper ; IS NOT present then the console will be set to 9600 baud. If the ; jumper IS present then the console will be set to 19200 baud. ; 3) Baud rate definitions (B...) are defined in the Local Equates ; section at the beginning of this module (following the index). ; ; Device Baud Rate CTC Channel ; Con 9600/19200 2 ; Lst 1200 1 ; Aux 1200 0 ; IntCTC: ld a,0BEh ;Console:= Mode 3 (Channel 2) out (baudset),a in a,(drvsts) ;If (Baud Rate Jumper is IN) and $JBAUD jr z,IcSk1 ld a,LOW B19200 out (baud0),a ld a,HIGH B19200 out (baud0),a ; Console_Baud_Rate:= 19200 Baud jr IcSk2 IcSk1: ld a,LOW B9600 ;Else out (baud0),a ld a,HIGH B9600 out (baud0),a ; Console_Baud_Rate:= 9600 Baud IcSk2: ld a,7Eh ;List:= Mode 3 (Channel 1) out (baudset),a ld a,LOW B1200 out (baud1),a ld a,HIGH B1200 out (baud1),a ;List_Baud_Rate:= 1200 Baud ld a,3Eh ;Aux:= Mode 3 (Channel 0) out (baudset),a ld a,LOW B1200 out (baud2),a ld a,HIGH B1200 out (baud2),a ;Aux_Baud_Rate:= 1200 Baud ENDIF ;End of hard disk MicroDecision port init. code START: IF MONITOR LD IX,CONOUT3 JP CRLF ;SEND A CARRIAGE RETURN/LINE FEED ;** SEND A PROMPT ** CONOUT3:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUT3 ;loop if not ready LD A,PROMPT ;monitor prompt character OUT (WRREG),A ;Output to transmitter buffer LD IX,FIND JP GETCHR ;Get character from console, echo it back find: LD C,2 ;INITIALIZE TO GET 2 PARAMETERS ;** TEST IF CHARACTER IS A VALID COMMAND ** IF ALIGNMENT CP 'A' ;enter ALIGNment tool and paint the screen JP Z,align ; display cp 03h ;03h is ^C enter ALIGNMENT tool without jp z,comand ; destroying screen display ENDIF CP 'C' JP Z,CURR ;display CURRent location CP 'D' JP Z,DUMP CP 'F' JP Z,FILL CP 'G' JP Z,GO CP 'H' JP Z,HEX CP 'I' JP Z,IN CP 'L' JP Z,LOOP CP 'M' JP Z,MOVE CP 'O' JP Z,OUT CP 'R' JP Z,RELOC ;RELOCate ROM code to RAM CP 'S' JP Z,SET CP 'T' JP Z,TEST CP 'V' JP Z,VERIFY ;** SEND A question mark ** ERROR: IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,ERROR ;loop if not ready LD A,'?' OUT (WRREG),A ;Output to transmitter buffer JP START ;INVALID CHARACTER, LOOP BACK TO GET ANOTHER ;************************************************************************ ;* C * ;* COMMAND C: CURRENT. LIST CURRENT LOCATION OF MONITOR PROGRAM * ;* C * ;************************************************************************ ;** SEND A space ** CURR: IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CURR ;loop if not ready LD A,' ' OUT (WRREG),A ;Output to transmitter buffer ld a,high byte0 ;high byte of first memory location of this mon LD IX,curr1 jp lbyte ;list the first byte to the console curr1: ld a,low byte0 ;low byte of first memory location of this mon. ld ix,start ;no need to return to this routine jp lbyte ;************************************************************************ ;* D * ;* COMMAND D: DUMP. DISPLAY MEMORY FROM XXXX TO XXXX * ;* D * ;************************************************************************ DUMP: ld ix,dumpr jp expr ;get start address (D'E') and end addr (H'L') dumpr: exx ;start addr=DE, end addr=HL ld b,d ;save a copy of start address for ASCII dump ld c,e ; BC<--DE dump1: ld ix,dump7 jp crlf ;print a carriage return and line feed dump7: ld ix,dump2 jp abort ;test to see if ^C has been typed, abort if so dump2: ld a,d ;send high byte of start address to console ld ix,dump3 jp lbyte dump3: ld a,e ;send low byte of start address to console ld ix,dmemhex jp lbyte ;******************************** ;* PRINT IN HEX * ;******************************** ;** PRINT A SPACE ** dmemhex:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,dmemhex ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer ld a,e ;low byte of memory pointer and 7 ;low nybble of memory pointer jr z,conout5 ;insert space if 8 bytes printed cp 4 ;insert space if 4 or 12 bytes printed jr nz,dump4 ;don't insert space if not 4 or 12 ;** PRINT A SPACE ** CONOUT5:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUT5 ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer dump4: ld a,(de) ;get contents of the current memory location ld ix,dump5 ;convert the a register to ascii and print jp lbyte dump5: inc de ;next successive memory location ld a,e and 0Fh jr nz,dmemhex ;loop ;******************************** ;* PRINT IN ASCII * ;******************************** ;** PRINT A SPACE ** CONOUT9:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUT9 ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer nop ;delay for Morrow Microdecision hardware ;** PRINT A SPACE ** CONOUTE:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTE ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer nop ;delay for Morrow Microdecision hardware ;** PRINT AN ASTERIX ** CONOUTH:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTH ;loop if not ready LD A,'*' ;space OUT (WRREG),A ;Output to transmitter buffer ;** DETERMINE IF A GROUP OF 4 CHARACTERS HAS BEEN PRINTED YET ** DMEMASC:ld a,c ;low byte of memory pointer and 0Fh jr z,dump6 and 07h ;low nybble of memory pointer jr z,conoutf cp 4 jr nz,dump6 ;** PRINT A '|' to seperate groups of 4 ASCII characters ** CONOUTF:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTF ;loop if not ready LD A,'|' ;space OUT (WRREG),A ;Output to transmitter buffer ;** TURN THE CHARACTER INTO ASCII AND PRINT IT ** nop ;delay for Morrow Microdecision hardware dump6: in a,(status) ;Get communications port status and wrbit ;test if ready to send a character jr z,dump6 ;loop if not ready ld a,(bc) ;Get contents of memory location cp ' ' jð c,mkspace ;Iæ lesó thaî á spacå (i.e® nonprintinç char) cp 07Fh jp c,charok ;If a printing character mkspace:ld a,' ' ;prepare to print a space charok: out (wrreg),a ;Output to transmitter buffer inc bc ;next successive memory location ld a,c ;low byte of current address and 0Fh ;16 bytes per line of display jr nz,dmemasc ;loop to print out next memory location content ;** PRINT AN ASTERIX because 16 bytes have been printed ** CONOUTG:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTG ;loop if not ready LD A,'*' ;asterix OUT (WRREG),A ;Output to transmitter buffer ;** SEE IF END OF DUMP REACHED ** ld a,b or c jp z,start ld a,l sub c ld a,h sbc a,b jp nc,dump1 jp start ;************************************************************************ ;* F * ;* COMMAND F: FILL. FILL MEMORY FROM XXXX TO XXXX WITH XX * ;* F * ;************************************************************************ FILL: ld ix,fill1 jp expr3 ;get start address, end address, and fill byte fill1: exx ;after exx: BC=start adr,DE=end adr,L=fill byte ld a,l ;register A has fill byte ld h,b ;HL<--BC (start addr ends up in HL) ld l,c ld c,a ;Register C has fill byte fill2: ld (hl),c ;store fill byte to memory ld a,l ;compare a byte of end addr with current addr sub e jp nz,bump ;if different ld a,h ;compare 2nd byte of end addr with current addr sub d bump: inc hl ;increment start addr toward end address jp nz,fill2 jp start ;finished filling, go get another command ;************************************************************************ ;* G * ;* COMMAND G: GO. GOTO (EXECUTE) XXXX * ;* G * ;************************************************************************ GO: LD IX,GO1 JP EXPR1 go1: jp (hl) ;************************************************************************ ;* H * ;* COMMAND H: HEX. HEXIDECIMAL ARITHMETIC * ;* H * ;************************************************************************ HEX: LD IX,HEX1 JP EXPR ;Get first number in D'E', 2nd number in H'L' hex1: exx ;first number in DE, second number in HL ld ix,hex2 jp crlf ;print a carriage return and line feed hex2: ld b,h ;BC<--HL ld c,l ;save a copy of HL in BC add hl,de ;SUM ld a,h ;prepare to print the high byte of the sum ld ix,hex3 jp lbyte ;print the high byte hex3: ld a,l ;prepare to print the low byte of the sum ld ix,conoutp jp lbyte ;** PRINT A SPACE to separate the sum from the difference ** CONOUTP:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTP ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer ld h,b ;HL<--BC ld l,c ;Get a fresh copy of the second parameter ex de,hl or a sbc hl,de ld a,h ;prepare to print the high byte of difference ld ix,hex4 jp lbyte ;print the high byte hex4: ld a,l ;prepare to print the low byte of the sum ld ix,start ;finished after print difference, get next cmd jp lbyte ;************************************************************************ ;* I * ;* COMMAND I: INPUT. INPUT DATA FROM I/O PORT * ;* I * ;************************************************************************ IN: LD IX,IN1 JP EXPR1 ;get the 1 parameter (the port number) in1: ld c,l ;PORT TO INPUT FROM IS IN REGISTER L ld ix,conoutj jp crlf ;** PRINT A SPACE to separate port number from hexidecimal data ** CONOUTJ:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTJ ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer in e,(c) ;get data from port in a,(c) ;get data from port for use with lbyte ld ix,in2 jp lbyte ;print port data in hexidecimal in2: ld b,08 ;count=8 bits to display ;** PRINT A SPACE to separate hexidecimal from binary display ** CONOUTK:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTK ;loop if not ready LD A,' ' ;space OUT (WRREG),A ;Output to transmitter buffer in3: NOP ;delay for Morrow Microdecision hardware CONOUTL:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTL ;loop if not ready sla e ;shift port data high bit into carry bit ld a,018h ;(18h)x2='0' adc a,a ;(18h)x2+carry bit --> '0' or '1' OUT (WRREG),A ;Output '0' or '1' to transmitter buffer djnz in3 ;decrement count, go print next bit jp start ;finished with I command, go get another commnd ;************************************************************************ ;* L PERFORM A VERY TIGHT LOOP FOR SIGNAL TRACING * ;* COMMAND L: LOOP. WITH AN OSCILLOSCOPE. THERE IS NO EXIT FROM * ;* L THESE LOOPS EXCEPT BY RESET. * ;************************************************************************ ;** GET A CHARACTER FROM THE CONSOLE ** LOOP: ld ix,loop1 jp getchr ;get a character from the console, echo back loop1: LD C,2 ;INITIALIZE TO GET 2 PARAMETERS cp 'O' jp z,loopo cp 'W' jp z,loopw cp 'I' jp z,loopi cp 'R' jp nz,error ;if not O, W, I, R then error ;**************************** ;* Read a memory location * ;**************************** loopr: ld ix,loopr1 jp expr1 loopr1: ld a,(hl) ;read from a memory address jr loopr1 ;************************* ;* Input a port address * ;************************* loopi: ld ix,loopi1 jp expr1 loopi1: ld c,l loopi2: in a,(c) ;input from a port jr loopi2 ;******************** ;* Write to memory * ;******************** loopw: ld ix,loopw1 jp expr loopw1: exx ;DE=address, L=data ld a,l ;a <-- data loopw2: ld (de),a jr loopw2 ;********************* ;* Output to a port * ;********************* loopo: ld ix,loopo1 jp expr loopo1: exx ;E=port, L=data ld a,l ;A=data ld c,e ;C=port loopo2: out (c),a ;output data to port jr loopo2 ;************************************************************************ ;* M * ;* COMMAND M: MOVE. MOVE DATA STARTING XXXX AND ENDING XXXX, TO XXXX * ;* M * ;************************************************************************ MOVE: LD IX,MOVE1 JP EXPR3 move1: EXX ;START=BC, END=DE, DESTINATION=HL move2: ld a,(bc) ;Get a byte from the source ld (hl),a ;Put the byte into the destination ld a,c ;low byte of current source cp e ;low byte of end source jr nz,minc ;if not equal, go prepare to move next byte ld a,b ;high byte of current source cp d ;high byte of end source jr nz,minc ;if not equal, go prepare to move next byte jp start ;end of move reached, go get another command minc: inc bc ;increment source location inc hl ;increment destination location jp move2 ;go move next byte ;************************************************************************ ;* O * ;* COMMAND O: OUTPUT. OUTPUT TO PORT XX THE DATA XX * ;* O * ;************************************************************************ OUT: LD IX,OUT1 JP EXPR ;get port (register E') and data (register L') out1: exx ;port is in register E, data is in register L ld c,e ;port is in register c out (c),l ;output data to port jp start ;finished outputing, go get another command ;************************************************************************ ;* R * ;* COMMAND R: RELOCATE. RELOCATE ROM CODE TO ANY PAGE BOUNDARY XXXX * ;* R * ;************************************************************************ RELOC: LD IX,RELOC1 JP EXPR1 ;returns destination address XXXX in HL & H'L' reloc1: xor a ;zero A or l ;L must be zero: XXXX must be a page boundary P jp nz,error ;if not zero (meaning not a page boundary) P ; P ld de,byte0 ;initial address of block of ROM to move P ex de,hl ;DE=destination, HL=source P ld bc,mvlen ;BC=count: length of RELOCATING code to move P ld a,d ;high byte of destination address P sub h ;high byte of source address--->offset P exx ld e,h ; E=high byte of initial destination address S ld d,a ;D=offset S ld c,08 ; C=initial bit count S ld hl,bitmap ;HL=initial address byte of bit map S ld b,(hl) ;get byte from bit map S ifoff: srl b ;prepare next byte from bit map S ld a,d ;put the offset into the D register S exx jr c,addoff ;if this byte gets an offset P xor a ;no offset, so zero register A P addoff: add a,(hl) ;add source byte to offset if any P ld (de),a ;store byte in destination P exx dec c ;bit count <-- bit count-1 S jr nz,reloc2 ;if 8 bits from this byte are not done yet S set 3,c ;set bit count to eight again S inc hl ;(hl)=byte of bit map S ld b,(hl) ;get another byte from bit map S reloc2: exx inc hl ;source <-- source + 1 P inc de ;destination <-- destination + 1 P dec bc ;length of code count <-- len of code count-1 P ld a,b ; P or c ;if bc=0, done relocating code P exx jr nz,ifoff ; S exx ld c,low bitlen ;B already was 0: C=length of bitmap P ldir ;move the bit map (it need not be relocated) P exx ld l,low start ; S ld h,e ;high byte of initial destination address S jp (hl) ;jump to START: in new location ;************************************************************************ ;* S * ;* COMMAND S: SET. EXAMINE AND (OPTIONALLY) CHANGE MEMORY DATA * ;* S * ;************************************************************************ SET: LD IX,SET1 JP EXPR1 set1: CP CR ;was a carriage return typed following the addr jp z,start ;if a carriage return, exit this set command ld a,(hl) ld ix,conouti jp lbyte ;convert register A to ASCII and print it ;** PRINT A '-' ** CONOUTI:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTI ;loop if not ready LD A,'-' ;seperate and prompt for optional memory change OUT (WRREG),A ;Output to transmitter buffer ;** GET A CHARACTER FROM THE CONSOLE ** CONIN3: IN A,(STATUS) ;Read status register AND RDBIT JR Z,CONIN3 ;No character ready, loop IN A,(RDREG) ;Read character and 07Fh ;strip parity ;************************************************************************ ;* * ;* CHARACTER CHECK: check for space or comma or carriage return. * ;* Return with carry set if a carriage return, clear if anything * ;* else. Return with zero set if a space or comma. * ;* * ;************************************************************************ CP ' ' ;is it a space jR z,eval1 ;return zero set, carry cleared if ' ' CP ',' ;is it a comma jR z,eval1 ;return zero set, carry cleared if ',' CP 00DH ;is it a carriage return SCF jR z,eval1 ;return carry and zero set if a carriage return CCF ;ret carry and zero cleared if not cr, ',', ' ' ;RET EVAL1: jp c,start ;exit from set routine if a CR typed jr z,su1 ;if it was space or comma ld d,h ;save memory location in de ld e,l ; DE<--HL ld hl,0 ;initialize ld c,001h ;count of bytes to get ld ix,change jp get1 ;returns new value for memory location in reg L change: ex de,hl ;HL=memory location E=new value in hexidecimal ld (hl),e ;change value of memory location ;ex1 also returns a next character in reg. A cp CR ;was it a carriage return? jp z,start ;exit from set routine if a CR typed su1: inc hl ld ix,sendh jp crlf SENDH: lä a,è ;senä thå È bytå tï thå console ld ix,lbyte1 jp lbyte ;CALL LBYTE lbyte1: ld a,l ;send the L byte to the console ld ix,conoutb jp lbyte ;CALL LBYTE ;*ª SENÄ Á SPACÅ ** CONOUTB:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTB ;loop if not ready LD A,' ' ;ASCII space OUT (WRREG),A ;Output to transmitter buffer JR SET1 ;LOOP (print new location value, etc.) ;************************************************************************ ;* T * ;* COMMAND T: TEST. TEST MEMORY FROM XXXX TO XXXX * ;* T * ;************************************************************************ TEST: ld ix,test1 jp expr ;get two parameters, return them in aux. regs. test1: exx ; HL=start addr, DE=end addr ex de,hl ; DE=end addr, HL=start addr t1: ld ix,t3 jp abort ;see if ^S (stop scrolling) or ^C typed (abort) t3: ld a,(hl) ;get contents of memory location ld b,a ;temporarily save contents of memory location cpl ;compliment value of memory location ld (hl),a ;store complimented value in memory location xor (hl) ;make a bit display of bad bits (1=bad) ld (hl),b ;restore originally read contents of memory jò z,t² ;iæ nï error ld c,a ;register C=bit display ld a,h ;send the H byte to the console ld ix,tbyte jp lbyte ;CALL LBYTE tbyte: ld a,l ;send the L byte to the console ld ix,conoutc jp lbyte ;CALL LBYTE ;*ª SENÄ Á SPACÅ ** CONOUTC:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTC ;loop if not ready LD A,' ' ;ASCII space OUT (WRREG),A ;Output to transmitter buffer ld b,008h ;count 8 bits ;*ª SENÄ Á "bit" ** CONOUTD:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTD ;loop if not ready sla c ;move bit 7 to carry ld a,018h ;2 times 18h=30h=ASCII 0 adc a,a ;reg. A='0'if no carry, '1' if carry OUT (WRREG),A ;Output to transmitter buffer djnz conoutd ;if all 8 bits not printed yet LD IX,T2 JP CRLF ;SEND A CARRIAGE RETURN/LINE FEED T2: ld a,l ;compare a byte of end addr with current addr sub e jp nz,bump1 ;if different ld a,h ;compare 2nd byte of end addr with current addr sub d bump1: inc hl ;increment start addr toward end address jp nz,t1 jp start ;finished testing, go get another command ;************************************************************************ ;* V * ;* COMMAND V: VERIFY. VERIFY MEMORY XXXX TO XXXX WITH XXXX * ;* V * ;************************************************************************ VERIFY: LD IX,VER1 JP EXPR3 ver1: exx ;from=BC, to=DE, with=HL vertst: ld ix,ver2 jp abort ;see if ^S (stop scrolling) or ^C typed (abort) ver2: ld a,(bc) ;get a byte from the "from" block cp (hl) ;compare with a byte from the "with" block jr z,vadcmp ;if the bytes are the same ld ix,vererr jp crlf ;print a carriage return-line feed vererr: ld a,b ;high byte of "from" byte address ld ix,ver3 ;CALL LBYTE jp lbyte ver3: ld a,c ;low byte of "from" byte address ld ix,conoutn ;CALL LBYTE JP LBYTE ;*ª SENÄ Á SPACÅ ** CONOUTN:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTN ;loop if not ready LD A,' ' ;ASCII space OUT (WRREG),A ;Output to transmitter buffer ld a,(bc) ;data byte of "from" block ld ix,conouto ;CALL LBYTE jp lbyte ;*ª SENÄ Á space ** CONOUTO:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTO ;loop if not ready LD A,' ' ;ASCII space OUT (WRREG),A ;Output to transmitter buffer ld a,h ;high byte of "with" byte address ld ix,ver4 ;CALL LBYTE jp lbyte ver4: ld a,l ;low byte of "with" byte address ld ix,conoutm ;CALL LBYTE JP LBYTE ;*ª SENÄ Á SPACÅ separating "with" address and "with" byte ** CONOUTM:IN A,(STATUS) ;Get communications port status AND WRBIT ;test if ready to send a character JR Z,CONOUTM ;loop if not ready LD A,' ' ;ASCII space OUT (WRREG),A ;Output to transmitter buffer ld a,(hl) ;data byte of "with" block ld ix,vadcmp ;CALL LBYTE jp lbyte vadcmp: ld a,e ;low byte of finish address cp c ;low byte of current "from" address jp nz,verinc ;if current address not equal final address ld a,d ;high byte of finish address cp b ;high byte of current "from" address jp z,start ;if current address equal final address, done verinc: inc bc ;next address to get a byte from inc hl ;next address to compare a byte to JP vertst ;go compare the next two bytes ;************************************************************************ ;* * ;* GET PARAMETERS 1,2,OR 3 * ;* These parameters are returned in the alternate registers as * ;* follows: * ;* Most recently received parameter goes to H'L'. * ;* Second most recently received parameter goes to D'E'. * ;* Third most recently received parameter goes to B'C'. * ;* Additionally, the most recently received parameter is also * ;* returned in the primary HL register. This routine expects * ;* parameters to be seperated by a comma or a space and the * ;* final parameter to be followed by a carriage return. * ;* Parameters are checked to see if each character of the * ;* parameter is a valid hex digit. If an invalid character is * ;* typed this routine jumps to the "?" error printing routine. * ;* * ;************************************************************************ EXPR3: INC C ;on entry c was 2, this makes it 3 parameters JP EXPR EXPR1: LD C,001H ;on entry c was 2, this makes it one parameter EXPR: LD HL,0 ;initialize the HL register;if entered here get 2 parms EX0: ;** GET A CHARACTER FROM THE CONSOLE ** CONIN2: IN A,(STATUS) ;Read status register AND RDBIT JR Z,CONIN2 ;No character ready, LOOP IN A,(RDREG) ;Read character and 07Fh ;strip parity get1: LD I,A ;TEMPORARILY SAVE THE CHARACTER<<< 'z' jp c,inst5 ;ret c sub ' ' ;convert to upper case nibok: SUB 030H ;'0' jp c,inst5 ;RET C ;RETURN IF LESS THAN '0' cp 017h ;WAS IT GREATER THAN 'F' (BEFORE CONVERSION) ? ccf jp c,inst5 ;RET C CP 00AH ;IS IT 0-9? CCF jp nc,inst5 ;RET NC ;RETURN IF 0-9 SUB 007H ;CONVERT TO Ah to Fh CP 00AH inst5: JR C,EX2 ;returns carry set if not a valid digit (0-Fh) ; jump if a valid digit not returned ADD HL,HL ;on first pass HL is 0 as initialized above ADD HL,HL ;on successive passes each nybble is shifted ADD HL,HL ; into next higher nybble ADD HL,HL OR L ;add nybble from register A to register L LD L,A ;save in register L JR EX0 ;go get another character (nybble) from console ;************************************************************************ ;* * ;* received parameters are saved by "pushing" them into the * ;* alternate secondary registers. * ;* * ;* Most recently received parameter goes to H'L'. * ;* Second most recently received parameter goes to D'E'. * ;* Third most recently received parameter goes to B'C'. * ;* * ;************************************************************************ EX2: EXX LD C,E ;B'C'<--D'E' C'<--E' LD B,D ; B'<--D' LD E,L ;D'E'<--H'L' E'<--L' LD D,H ; D'<--H' EXX ;H'L'<--HL LD A,H ; GET H EXX LD H,A ; H'<--H EXX LD A,L ; GET L EXX LD L,A ; L'<--L EXX ;************************************************************************ ;* * ;* CHARACTER CHECK: check for space or comma or carriage return. * ;* Return with carry set if a carriage return, clear if anything * ;* else. Return with zero set if a space or comma. * ;* * ;************************************************************************ LD A,I ;get the original unconverted character CP ' ' ;is it a space jR z,CALL39 ;zero set, carry cleared if ' ' CP ',' ;is it a comma jR z,CALL39 ;zero set, carry cleared if ',' CP CR ;is it a carriage return SCF jR z,CALL39 ;carry and zero set if a carriage return CCF ;carry and zero cleared if not cr, ',', ' ' call39: JR NC,EX3 ;if not a carriage return DEC C ;decrement count of parameters <<