TITLE JIM MONESMITH'S EPROM PROGRAMMER ; DATE NOVEMBER 6,1981 ; 4 MHZ. CPU BIGBOARD VERSION ; ; EXTENSIONS BY DAVID THOMPSON ; DATE MAY 4, 1982 ; 1. ADDED CRC CALCULATION AND DISPLAY ; 2. REMOVED MOST 2708 RELATED CODE ; 3. ADDED JUMP TO PFM ; 4. ADDED CHECK TO SEE IF ROM HAS BEEN ERASED ; 5. FIXED BUG WHICH PREVENTED USER FROM READING SECOND ; FILE OFF THE DISK INTO PROGRAMMING SPACE. ; .Z80 ;ASSEMBLE Z80 MNEMONICS PAGE 60 ASEG ;ABSOLUTE CODE ORG 0100H ;TPA AREA BOOT EQU 0000H ;SYSTEM RETURN BDOS EQU 0005H ;SYSTEM INTERFACE ADDRESS FCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK PROMIN EQU 08H ;DATA INPUT PORT WHEN SO PROGRAMMED PROMOT EQU 08H ;DATA OUTPUT PORT WHEN SO PROGRAMMED CONTRL EQU 0AH ;CONTROL OUTPUT PORT MDATA EQU 4000H ;BEGINNING OF DATA FOR EPROM PDATA EQU 3000H ;COMPARISON AREA FOR PROM DATA CNT08 EQU 0400H ;2708 BYTE COUNT CNT16 EQU 0800H ;2716 BYTE COUNT CNT32 EQU 1000H ;2732 BYTE COUNT PFM EQU 0F003H ;MONITOR WARM ENTRY POINT ; START: LD SP,START ;SET STACK BELOW PROGRAM XOR A ;RESET STATUS FLAG LD (STATUS),A LD A,8CH ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0ACH ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0ADH ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;INITIALIZE I/O PORTS CALL INIT ;RESET ADDRESS COUNTERS AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD C,9 ;PRINT STRING FUNCTION LD DE,MESS ;PRINT OUT MENU CALL BDOS ;SEND MENU LD C,1 ;CONSOLE INPUT FUNCTION CALL BDOS ;GET A CHARACTER FROM CONSOLE CP 03H ;CHECK FOR CONTROL C CODE JP Z,EXBOOT ;EXIT IF CONTROL C CP 3BH ;CHECK FOR A TO LARGE SELECTION JP NC,ERROR ;JUMP IF INVALID SELECTION CP 30H ;CHECK FOR A TO SMALL SELECTION JP C,ERROR ;JUMP IF INVALID SELECTION SUB 30H ;REMOVE ASCII BIAS ADD A,A ;COMPENSATE FOR 2 BYTE TABLE ENTRIES LD D,0 ;SET D TO ZERO LD E,A ;DE NOW CONTAINS INDEX INTO TABLE LD HL,TABLE ;SET POINTER TO START OF JUMP TABLE ADD HL,DE ;INDEX INTO TABLE LD E,(HL) ;GET LOW BYTE OF JUMP ADDRESS INC HL ;POINT TO HIGH BYTE OF JUMP ADDRESS LD D,(HL) ;GET HIGH BYTE OF JUMP ADDRESS EX DE,HL ;PUT JUMP ADDRESS IN HL JP (HL) ;JUMP TO THE ADDRESS IN HL EXBOOT: EI ;ENABLE INTERRUPTS JP BOOT ;RE-BOOT SYSTEM ; ERROR: LD C,9 ;PRINT STRING FUNCTION LD DE,MESS4 ;BAD INPUT MESSAGE CALL BDOS ;SEND MESSAGE JP START ;TRY AGAIN ; ; ROUTINE TO READ A 2716 EPROM INTO MEMORY AT MDATA ; I2716: LD DE,MESS15 ;SEND INSTRUCTIONS CALL SWMESS LD A,0FFH ;SET PORT A DIRECTION TO INPUT LD (DIR),A LD A,8CH ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0ACH ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0ADH ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;INITIALIZE I/O PORTS CALL INIT ;RESET ADDRESS COUNTER AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD HL,MDATA ;BEGINNING OF DATA AREA LD BC,CNT16 ;2716 BYTE COUNT CALL INPUT ;READ DATA INTO ADDRESS 4000H LD C,9 ;PRINT STRING FUNCTION LD DE,MESS1 ;DATA READ MESSAGE CALL BDOS ;SEND MESSAGE JP START ;DISPLAY MENU ; ; ROUTINE TO COMPARE A 2716 EPROM WITH MEMORY DATA AT MDATA ; C2716: LD DE,MESS15 ;SEND INSTRUCTIONS CALL SWMESS LD A,0FFH ;SET PORT A DIRECTION TO INPUT LD (DIR),A LD A,8CH ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0ACH ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0ADH ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;INITIALIZE I/O PORTS CALL INIT ;RESET ADDRESS COUNTER AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD HL,PDATA ;SET DATA INPUT POINTER LD BC,CNT16 ;SET DATA INPUT COUNTER CALL INPUT ;BRING IN PROM DATA TO ADDRESS PDATA LD HL,PDATA ;PROGRAMMED PROM DATA POINTER LD DE,MDATA ;MEMORY DATA POINTER LD BC,CNT16 ;BYTE COUNT CALL COMPR ;MAKE COMPARISON, SEND APPROPIATE MESSAGE JP START ;DISPLAY MENU ; ; ; ROUTINE TO VERIFY THAT ROM HAS BEEN ERASED ; GETS 2K OR 4K COUNT IN DE ; CHKROM: PUSH AF PUSH BC PUSH HL LD A,0FFH ;SET PORT A DIRECTION TO INPUT LD (DIR),A LD A,8CH ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0ACH ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0ADH ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;INITIALIZE I/O PORTS CALL INIT ;RESET ADDRESS COUNTER AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE UNERLP: IN A,(PROMIN) ;GET A BYTE CP 0FFH ;CHECK IF IT'S FF JP NZ,UNERA ;ROM NOT ERASED LD A,(INC) ;0EDH INCREMENT ADDRESS COUNTERS OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP DEC A ;REMOVE CLOCK STROBE OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP DEC DE ;DECREMENT BYTE COUNT REGISTER LD A,E ;CHECK FOR LAST BYTE OR D JP NZ,UNERLP ;GET NEXT BYTE,IF NOT LAST JP UNER1 ;ROM IS ALL 0FFH SO PREPAIR TO GO BACK UNERA: POP HL ;ARRIVE HERE IF ROM IS NOT ALL 0FFH POP BC POP AF LD DE,MESS17 ;REPORT ROM NOT ALL FF CALL SWMESS ;PRINT AND GET OPERATOR SELECTION JR UNER2 UNER1: POP HL ;RESTORE POP BC POP AF UNER2: RET ; ; ; ROUTINE TO PROGRAM A 2716 EPROM WITH MEMORY DATA AT MDATA ; P2716: LD DE,MESS15 ;SEND 2716 MODULE MESSAGE CALL SWMESS LD DE,CNT16 ;SEND COUNT FOR 2K ROM CALL CHKROM ;MAKE SURE ERASED AND INSERTED CORRECTLY LD A,00H ;SET PORT A DIRECTION TO OUTPUT LD (DIR),A CALL INITDEV ;INITIALIZE I/O PORTS LD C,9 ;PRINT STRING FUNCTION LD DE,MESS5 ;PROGRAMMING MESSAGE CALL BDOS LD A,14H ;RESET ADDRESS COUNTER AND ENTER PROGRAM MODE OUT (CONTRL),A ;ALSO SET BUFFERS TO OUTPUT MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD A,34H ;REMOVE RESET BIT OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP LD HL,MDATA ;SET DATA POINTER TO BEGINNING BEG16: LD A,(HL) ;GET DATA OUT (PROMOT),A ;STORE IT CALL PUL50 ;PRODUCE 50 MS. PULSE LD A,35H ;INCREMENT THE COUNTER OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP DEC A OUT (CONTRL),A ;REMOVE CLOCK PULSE NOP ;SMALL DELAY NOP NOP INC HL ;INCREMENT DATA POINTER LD A,L ;CHECK FOR END OF DATA, LOW BYTE OR A JP NZ,BEG16 ;LOOP UNTIL L=0 LD A,H ;CHECK FOR END OF DATA, HIGH BYTE CP 48H ;END OF PROM DATA, HIGH BYTE JP NZ,BEG16 ;GO DO NEXT BYTE UNTIL DONE LD A,0FFH ;SET PORT A DIRECTION TO INPUT LD (DIR),A LD A,8CH ;SETUP PATTERN 1 LD (PAT1),A LD A,0ACH ;SETUP PATTERN 2 LD (PAT2),A LD A,0ADH ;SETUP INCREMENT PATTERN LD (INC),A CALL INITDEV ;INITIALIZE I/O PORTS CALL INIT ;RESET ADDRESS COUNTER AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD HL,PDATA ;SET DATA INPUT POINTER LD BC,CNT16 ;SET DATA INPUT COUNTER CALL INPUT ;READ DATA INTO ADDRESS 5000H LD HL,PDATA ;PROGRAMMED PROM DATA POINTER LD DE,MDATA ;MEMORY DATA POINTER LD BC,CNT16 ;BYTE COUNT CALL COMPR ;MAKE COMPARISON, SEND APPROPIATE MESSAGE JP START ;DISPLAY MENU ; ; ROUTINE TO READ 2732 EPROM DATA INTO MEMORY AT MDATA ; I2732: LD DE,MESS14 ;SEND INSTRUCTIONS CALL SWMESS LD A,0FFH ;SET BUFFERS TO INPUT LD (DIR),A LD A,88H ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0A8H ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0A9H ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;PROGRAM PORTS CALL INIT ;RESET ADDRESS COUNTER ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD HL,MDATA ;SET DATA POINTER TO BEGINNING LD BC,CNT32 ;SET BYTE COUNTER CALL INPUT ;READ DATA INTO ADDRESS MDATA LD C,9 ;PRINT STRING FUNCTION LD DE,MESS1 ;DATA READ MESSAGE CALL BDOS ;SEND MESSAGE JP START ;DISPLAY MENU ; ; ROUTINE TO COMPARE 2732 EPROM DATA AT PDATA WITH MEMORY DATA AT MDATA ; C2732: LD DE,MESS14 ;SEND INSTRUCTIONS CALL SWMESS C2732A: LD A,0FFH ;SET BUFFERS TO INPUT LD (DIR),A LD A,88H ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0A8H ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0A9H ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;PROGRAM PORTS CALL INIT ;RESET ADDRESS COUNTER AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD HL,PDATA ;SET DATA INPUT POINTER LD BC,CNT32 ;SET DATA INPUT COUNTER CALL INPUT ;READ PROM DATA INTO MEMORY LD HL,PDATA ;PROGRAMMED PROM DATA POINTER LD DE,MDATA ;MEMORY DATA POINTER LD BC,CNT32 ;BYTE COUNT CALL COMPR ;MAKE COMPARISION, SEND APPROPIATE MESSAGE JP START ;DISPLAY MENU ; ; ROUTINE TO PROGRAM A 2732 EPROM WITH DATA AT MDATA ; P2732: LD DE,MESS14 ;SEND INSTRUCTINS CALL SWMESS LD DE,CNT32 ;4K ROM CALL CHKROM ;SEE IF IT IS ALL 0FFH LD A,00H ;SET BUFFERS TO OUTPUT LD (DIR),A CALL INITDEV ;PROGRAM PORTS LD DE,MESS16 ;TURN ON VOLTAGE MESSAGE CALL SWMESS LD C,9 ;PRINT STRING FUNCTION LD DE,MESS12 ;PROGRAMMING MESSAGE CALL BDOS ;SEND MESSAGE LD A,14H ;RESET COUNTER AND OUT (CONTRL),A ;ENTER PROGRAM MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD A,34H ;REMOVE RESET PULSE OUT (CONTRL),A LD HL,MDATA ;SET DATA POINTER TO BEGINNING BEG32: LD A,(HL) ;GET DATA OUT (PROMOT),A ;STORE IT CALL PUL50 ;PRODUCE 50 MS. PULSE LD A,35H ;INCREMENT THE ADDRESS COUNTER OUT (CONTRL),A NOP ;SHORT DELAY NOP NOP DEC A OUT (CONTRL),A ;REMOVE CLOCK PULSE INC HL ;INCREMENT DATA POINTER LD A,L ;CHECK FOR END OF DATA, LOW BYTE OR A JP NZ,BEG32 ;LOOP UNTIL L=0 LD A,H ;CHECK FOR END OF DATA, HIGH BYTE CP 50H ;END OF PROM DATA, HIGH BYTE JP NZ,BEG32 ;GO DO NEXT BYTE UNTIL DONE LD A,8CH ;SETUP FIRST BIT PATTERN LD (PAT1),A LD A,0ACH ;SETUP SECOND BIT PATTERN LD (PAT2),A LD A,0ADH ;SETUP BIT PATTERN TO INCREMENT COUNTER LD (INC),A CALL INITDEV ;INITIALIZE I/O PORTS CALL INIT ;RESET ADDRESS COUNTERS AND ENTER VERIFY MODE CALL SETTLE ;ALLOW THINGS TO SETTLE LD DE,MESS13 ;SEND INSTRUCTIONS CALL SWMESS JP C2732A ;GO READ DATA AND DO THE COMPARE ; ; ROUTINE TO PRODUCE A 1 MS. PULSE ; PUL01: DI ;PRODUCE A 1 MS. PROGRAMMING LD A,30H ;PULSE FOR 2708 PROM OUT (CONTRL),A DELAY1: LD A,8AH ; 1 MS. DELAY LP1: DEC A ; AT 4 MHZ CLOCK JP NZ,LP1 LD A,8AH ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK LP2: DEC A ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK JP NZ,LP2 ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK LD A,34H ;REMOVE PULSE OUT (CONTRL),A EI ;ENABLE INTERRUPTS RET ; ; ROUTINE TO PRODUCE A 50 MS. PULSE ; PUL50: DI ;PRODUCE PULSE LD A,30H OUT (CONTRL),A ; ; USE ONLY ONE OF THE FOLLOWING TWO LINES. COMMENT THE UNUSED LINE OUT. ; ;DELAY2: LD B,3DH ;USE THIS LINE FOR A 2.5 MHZ. CPU CLOCK DELAY2: LD B,6AH ;USE THIS LINE FOR A 4 MHZ. CPU CLOCK LP3: LD A,85H LP4: DEC A JP NZ,LP4 DEC B JP NZ,LP3 LD A,34H ;REMOVE PULSE OUT (CONTRL),A EI RET ; ; ROUTINE TO ALLOW THINGS TO SETTLE AFTER REPROGRAMMING ; PORTS FOR INPUT OR OUTPUT ; SETTLE: LD BC,0 ;SETUP INITIAL COUNT SETL1: DEC BC ;DO THE LOOP LD A,B ;CHECK FOR 0 OR C JP NZ,SETL1 LD BC,0 ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK SETL2: DEC BC ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK LD A,B ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK OR C ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK JP NZ,SETL2 ;REMOVE THIS LINE FOR A 2.5 MHZ. CPU CLOCK RET ; ; ROUTINE TO READ EPROM DATA INTO ADDRESS POINTED TO BY HL, ; FOR BYTE COUNT CONTAINED IN BC. ; USES BIT PATTERN STORED IN (INC) TO INCREMENT ADDRESS COUNTER ; INPUT: PUSH HL LD HL,0 LD (CRCWRD),HL ;INITIALIZE CRC COUNT TO 0 POP HL INPUT1: IN A,(PROMIN) ;GET A BYTE LD (HL),A ;STORE IT IN MEMORY CALL CRC ;CALCULATE CRC LD A,(INC) ;0EDH INCREMENT ADDRESS COUNTERS OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP DEC A ;REMOVE CLOCK STROBE OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP INC HL ;INCREMENT DATA POINTER DEC BC ;DECREMENT BYTE COUNT REGISTER LD A,C ;CHECK FOR LAST BYTE OR B JP NZ,INPUT1 ;GET NEXT BYTE,IF NOT LAST CALL PRTCRC ;PRINT CRC CHARACTERS RET ;PRINT MENU ; ; ; ROUTINE TO GET A BLOCK OF RAM FOR CRC ; AND THEN PRINT RESULTS ; CRC16: LD BC,CNT16 ;CHECK ONLY 2K JR CRCA ;JUMP AROUND 4K COUNT CRC32: LD BC,CNT32 ;CHECK 4K CRCA: LD HL,0 LD (CRCWRD),HL ;INITIALIZE CRC COUNT TO 0 LD HL,MDATA ;POINT TO 4000H CRCB: LD A,(HL) CALL CRC ;GENERATE CRC INC HL DEC BC LD A,B OR C JR NZ,CRCB CALL MEMCRC ;PRINT MEMORY CRC CHARACTERS JP START ; ; ; ROUTINE TO CALCULATE CRC ; EXPECTS TO RECEIVE BYTE IN THE A REGISTER ; STORES CRC IN CRCWRD ; STORES RECEIVED BYTE IN CRCBYT ; CRC: LD (CRCBYT),A PUSH HL PUSH BC PUSH DE LD HL,(CRCWRD) BIT 7,H ; TEST BIT SEVEN PUSH AF ; STORE ZERO FLAG ADD HL,HL ; MULTIPLY BY 2 LD A,(CRCBYT) ADD A,L LD L,A POP AF JR Z,CRC2 ; JUMP AROUND CALC IF BIT 7 WAS ZERO LD A,H XOR 0A0H LD H,A LD A,L XOR 97H LD L,A CRC2: LD (CRCWRD),HL POP DE POP BC POP HL RET ; ; ; PRINT PROM CRC CHARACTERS ON THE SCREEN ; PRTCRC: PUSH HL ; SAVE REGISTERS PUSH BC PUSH DE LD A,(CRCWRD+1) ; GET HIGH ORDER BYTE LD HL,CRCNUM ; NAME THE MESSAGE LOCATION FOR IT CALL HEXASC ; CONVERT TO ASCII AND STICK IT IN MESSAGE LD A,(CRCWRD) ; GET LOW ORDER BYTE CALL HEXASC ; CONVERT TO ASCII AND STICK IT IN MESSAGE LD DE,MESS2B ; DE POINTS TO START OF MESSAGE LD C,9 ; PRINT ROUTINE CALL BDOS ; LET CP/M DO IT POP DE ; PREPAIR TO RETURN POP BC POP HL RET ; ; ; ; PRINT MEMORY CRC CHARACTERS ON THE SCREEN ; MEMCRC: PUSH HL ; SAVE REGISTERS PUSH BC PUSH DE LD A,(CRCWRD+1) ; GET HIGH ORDER BYTE LD HL,MEMNUM ; NAME THE MESSAGE LOCATION FOR IT CALL HEXASC ; CONVERT TO ASCII AND STICK IT IN MESSAGE LD A,(CRCWRD) ; GET LOW ORDER BYTE CALL HEXASC ; CONVERT TO ASCII AND STICK IT IN MESSAGE LD DE,MESS2C ; DE POINTS TO START OF MESSAGE LD C,9 ; PRINT ROUTINE CALL BDOS ; LET CP/M DO IT POP DE ; PREPAIR TO RETURN POP BC POP HL RET ; ; ROUTINE TO COMPARE EPROM DATA POINTED TO BY HL ; WITH MEMORY DATA POINTED TO BY DE FOR BYTE COUNT ; CONTAINED IN BC, AND SEND THE APPROPRIATE MESSAGE. ; COMPR: LD A,(DE) ;GET GOOD MEMORY DATA XOR (HL) ;COMPARE IT WITH PROM DATA CALL NZ,BAD ;SEND MESSAGE IF NOT THE SAME INC HL ;INCREMENT POINTERS INC DE DEC BC ;DECREMENT BYTE COUNT LD A,C ;CHECK FOR LAST BYTE OR B JP NZ,COMPR ;CHECK NEXT BYTE IF NOT LAST LD A,(STATUS) ;GET STATUS FLAG OR A ;TO SET FLAGS RET NZ ;SEND NO DATA MESSAGE IF FLAG SET LD DE,MESS3 ;SEND GOOD DATA MESSAGE LD C,9 ;PRINT STRING FUNCTION JP BDOS ;GO SEND MESSAGE AND RETURN DIRECTLY TO CALLER BAD: PUSH HL ;SAVE REGISTERS PUSH BC PUSH DE LD A,0FFH ;SET STATUS FLAG LD (STATUS),A LD A,(HL) ;GET PROM DATA BYTE LD HL,PROM ;HL POINTS TO BUFFER FOR ASCII CALL HEXASC ;CONVERT TO ASCII LD A,(DE) ;GET MEMORY DATA BYTE LD HL,MEM ;HL POINTS TO BUFFER FOR ASCII CALL HEXASC ;CONVERT TO ASCII LD A,D ;CONVERT HIGH BYTE AND 0FH ;MASK OUT HIGH NIBBLE LD HL,ADDR ;HL CONTAINS BUFFER ADDRESS FOR ASCII CALL HEXASC ;CONVERT TO ASCII LD A,E ;CONVERT LOW BYTE CALL HEXASC ;CONVERT TO ASCII LD DE,MESS2 ;DE POINTS TO MESSAGE LD C,9 ;PRINT STRING FUNCTION CALL BDOS ;SEND MESSAGE LD C,11 ;RETURN CONSOLE STATUS FUNCTION CALL BDOS ;GET THE STATUS AND 0FFH ;CHECK FOR CONSOLE ABORT JP Z,BADEX ;ZERO MEANS NO CHARACTER READY LD C,1 ;CONSOLE INPUT FUNCTION CALL BDOS ;GET CHARACTER CP ' ' ;SPACE IS ABORT CHARACTER JP Z,START ;ABORT IF SPACE BADEX: POP DE ;RESTORE REGISTERS POP BC POP HL RET ; ; ROUTINE TO RESET ADDRESS COUNTER, ENTER VERIFY MODE ; AND SET BUFFERS TO INPUT MODE. SEE BIGBOARD SCHEMATICS ; OF THE GENERAL PURPOSE PIO FOR ADDITIONAL DETAILS. ; INIT: LD A,(PAT1) ;RESET ADDRESS ADDR. COUNTER, ENTER VERIFY MODE OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP LD A,(PAT2) ;REMOVE RESET BIT OUT (CONTRL),A NOP ;SMALL DELAY NOP NOP RET ; ; ROUTINE TO INITIALIZE I/O PORTS ; INITDEV:LD HL,INITAB ;PROGRAM PIO DEVICE LOOP: LD B,(HL) ;GET BYTE COUNT INC HL ;POINT TO PORT ADDRESS LD C,(HL) ;GET PORT ADDRESS INC HL ;POINT TO DATA OTIR ;PROGRAM PIO LD A,24H ;CHECK FOR END OF TABLE CP (HL) JP NZ,LOOP ;DO ALL PIO PORTS RET ; ; ROUTINE TO SEND SWITCH MESSAGE AND WAIT FOR A RESPONSE ; SWMESS: LD C,9 ;PRINT STRING FUNCTION CALL BDOS WTSP: LD C,1 ;CONIN FUNCTION CALL BDOS CP 3 ;CHECK FOR ^C JP Z,START ;GO BACK TO MAIN MENU IF ^C CP ' ' ;CHECK FOR SPACE JP NZ,WTSP ;WAIT FOR A SPACE RET ; ; CONVERTS EIGHT BIT HEX TO A TWO CHARACTER ASCII STRING ; ON ENTRY HL POINTS TO A BUFFER FOR THE ASCII STRING ; A CONTAINS BINARY DATA ; ON EXIT BUFFER CONTAINS ASCII STRING ; HL POINTS TO THE ASCII BUFFER+2 ; ALL OTHER REGISTERS ARE NOT USED ; HEXASC: PUSH AF ;SAVE SECOND DIGIT AND 0F0H ;GET FIRST DIGIT RRCA ;SHIFT RIGHT FOUR RRCA RRCA RRCA CALL CVERT ;CONVERT TO ASCII LD (HL),A ;STORE IN BUFFER INC HL ;INCREMENT BUFFER POINTER POP AF ;GET SECOND DIGIT AND 0FH CALL CVERT ;CONVERT TO ASCII LD (HL),A ;STORE IN BUFFER INC HL ;BUMP FOR RETURN RET CVERT: CP 0AH ;TEST FOR 0-9 JP M,NAD ;JUMP IF 0-9 ADD A,07H ;ADJUST FOR ALPHA NAD: ADD A,30H ;ADD ASCII BIAS RET ; ; ROUTINE TO READ A FILE INTO MEMORY AT MDATA ; RFILE: PUSH BC ;save BC LD BC,MDATA ;put base of memory data into BC LD (DMA),BC ;reset DMA to base of memory data POP BC ;put back BC LD C,9 ;PRINT STRING FUNCTION LD DE,MESS6 ;ENTER FILENAME MESSAGE CALL BDOS ;SEND MESSAGE LD C,10 ;READ CONSOLE BUFFER FUNCTION LD DE,FBUF ;DE CONSOLE BUFFER ADDRESS CALL BDOS ;FILL THE BUFFER LD A,(FBUF+1) ;CHECK FOR NO INPUT DATA OR A ;SET FLAGS JP Z,START ;EXIT IF NO DATA LD A,(FBUF+3) ;CHECK FOR IMPLICIT DRIVE REQUEST CP ':' ;COLON AT FBUF+3 MEANS IMPLICIT DRIVE REQUEST JP NZ,NODRV ;JUMP IF NO DRIVE REQUEST LD A,(FBUF+2) ;GET DRIVE SELECTION CP 'E' ;CHECK FOR TOO LARGE A SELECTION JP NC,SELERR ;JUMP IF TOO LARGE A SELECTION CP 'A' ;CHECK FOR TOO SMALL A SELECTION JP C,SELERR ;JUMP IF TOO SMALL A SELECTION SUB 40H ;REMOVE ASCII BIAS LD HL,FBUF+4 ;HL POINTS TO FILENAME IF DRIVE SELECTED JP GETNAM ;GO GET NAME NODRV: LD A,00H ;DEFAULT DRIVE INDICATOR IF EXECUTED LD HL,FBUF+2 ;HL POINTS TO FILENAME IF NO DRIVE SELECTED GETNAM: LD (FCB),A ;SET DRIVE INDICATOR IN FCB LD DE,FCB+1 ;DE POINTS TO FILENAME POSITION IN FCB LD B,8 ;MAXIMUM NUMBER OF CHARACTERS IN FILENAME NAMLP: LD A,(HL) ;GET CHARACTER FROM FBUF CP '.' ;CHECK FOR SEPARATOR JP Z,PERLP ;PERIOD MEANS END OF FILENAME LD (DE),A ;PUT CHARACTER IN FCB INC HL ;BUMP FBUF POINTER INC DE ;BUMP FCB POINTER DJNZ NAMLP ;LOOP UNTIL 8 CHARACTERS INPUT OR PERIOD FOUND PERLP: LD A,B ;SEE IF FILENAME HAS 8 CHARACTERS OR A ;SET FLAGS JP Z,NAMEX ;JUMP IF 8 CHARACTERS IN FILENAME LD A,' ' ;OTHERWISE FILL NAME SLOT IN FCB WITH SPACES PERLP1: LD (DE),A INC DE DJNZ PERLP1 ;FILL WITH SPACES NAMEX: LD BC,3 ;MAXIMUM NUMBER OF CHARACTERS IN FILETYPE TYPLP: INC HL ;POINT TO FILETYPE IN FBUF LDIR ;MOVE FILETYPE FROM FBUF TO THE FCB LD B,23 ;FILL END OF FCB WITH ZEROS LD A,00H ZERLP: LD (DE),A INC DE DJNZ ZERLP LD C,15 ;OPEN FILE FUNCTION LD DE,FCB ;DE POINTS TO THE FILE CONTROL BLOCK CALL BDOS ;OPEN THE FILE INC A ;FFH BECOMES ZERO DENOTING ERROR JP Z,OPENER ;JUMP IF FILE NOT FOUND LD DE,MDATA ;DE POINTS START ADDRESS FOR EPROM DATA READLP: LD C,26 ;SET DMA FUNCTION CALL BDOS ;UPDATE DMA ADDRESS LD C,20 ;READ SEQUENTIAL FUNCTION LD DE,FCB ;DE POINTS TO DEFAULT FILE CONTROL BLOCK CALL BDOS ;READ A SECTOR LD HL,(DMA) ;UPDATE DMA POINTER LD DE,0080H ADD HL,DE LD (DMA),HL ;STORE DMA ADDRESS IN MEMORY FOR NEXT UPDATE EX DE,HL ;PUT DMA ADDRESS IN DE AND 0FFH ;CHECK FOR END OF FILE JP Z,READLP ;READ ANOTHER SECTOR IF NOT LAST LD C,9 ;PRINT STRING FUNCTION LD DE,MESS9 ;FILE READ MESSAGE CALL BDOS ;SEND MESSAGE JP START ;DISPLAY MESSAGE ; OPENER: LD C,9 ;PRINT STRING FUNCTION LD DE,MESS8 ;NO FILE MESSAGE CALL BDOS ;SEND MESSAGE JP START ;DISPLAY MENU ; SELERR: LD C,9 ;PRINT STRING FUNCTION LD DE,MESS7 ;ILLEGAL SELECTION MESSAGE CALL BDOS ;SEND MESSAGE JP RFILE ;TRY IT AGAIN ; ; ROUTINE TO MOVE NEXT BLOCK OF DATA INTO POSITION FOR PROGRAMMING ; BLKMOV: LD C,9 ;PRINT STRING FUNCTION LD DE,MESS10 ;BLOCK SELECTION MESSAGE CALL BDOS ;SEND MESSAGE LD C,1 ;READ CONSOLE FUNCTION CALL BDOS ;GET REPLY CP 3 ;CHECK FOR ABORT JP Z,START ;ABORT MOVE IF ^C CP '3' ;CHECK FOR TO LARGE A SELECTION JP NC,BLKERR ;SEND SELECTION ERROR MESSAGE IF TOO LARGE CP '1' ;CHECK FOR TO SMALL A SELECTION JP C,BLKERR ;SEND SELECTION ERROR MESSAGE IF TOO SMALL LD HL,MDATA+0800H ;ASSUME 2716 SELECTION CP '1' ;CHECK FOR 2716 SELECTION JP Z,MOVIT ;JUMP IF 2716 SELECTION LD HL,MDATA+1000H ;MUST BE A 2732 SELECTION MOVIT: LD DE,MDATA ;SETUP DESTINATION POINTER LD BC,9000H ;MOVE LARGE BLOCK OF MEMORY LDIR LD C,9 ;PRINT STRING FUNCTION LD DE,MESS11 ;BLOCK MOVED MESSAGE CALL BDOS ;SEND MESSAGE JP START ;DISPLAY MENU ; BLKERR: LD C,9 ;PRINT STRING FUNCTION LD DE,MESS4 ;ILLEGAL SELECTION MESSAGE CALL BDOS ;SEND MESSAGE JP BLKMOV ;TRY IT AGAIN ; ; ; JUMP TABLE TO THE INDIVIDUAL EPROM ROUTINES ; TABLE: DEFW I2716 ;READ A 2716 INTO MEMORY DEFW C2716 ;COMPARE A 2716 WITH MEMORY DATA DEFW P2716 ;PROGRAM A 2716 ; DEFW I2732 ;READ A 2732 INTO MEMORY DEFW C2732 ;COMPARE A 2732 WITH MEMORY DATA DEFW P2732 ;PROGRAM A 2732 ; DEFW RFILE ;READ A FILE INTO MEMORY AT MDATA DEFW BLKMOV ;BLOCK MOVE DEFW CRC16 ;CRC CHECK ON 2K OF MEMORY AT 4000 DEFW CRC32 ;CRC CHECK ON 4K OF MEMORY AT 4000 ; DEFW PFM ;JUMP TO THE PFM MONITOR ; DMA: DEFW MDATA ;DMA POINTER STORAGE STATUS: DEFB 00H ;SET INITIALLY TO GOOD DATA INC: DEFB 00H ;BIT PATTERN STORAGE FOR INCREMENTING COUNTER PAT1: DEFB 00H ;BIT PATTERN STORAGE FOR INIT ROUTINE PAT2: DEFB 00H ;BIT PATTERN STORAGE FOR INIT ROUTINE CRCWRD: DEFW 00H ;STORAGE FOR CRC WORD CRCBYT: DEFB 00H ;TEMPORARY STORAGE FOR INPUT TO CRC ; MESS: DEFB 0DH,0AH,0AH,07H ;07H SOUNDS TERMINAL BELL DEFB 'ENTER DESIRED SELECTION (OR ^C TO EXIT)',0DH,0AH,0AH DEFB ' 0 READ A 2716 INTO MEMORY AT 4000H',0DH,0AH DEFB ' 1 COMPARE A 2716 WITH MEMORY AT 4000H',0DH,0AH DEFB ' 2 PROGRAM A 2716 WITH MEMORY DATA AT 4000H',0DH,0AH,0AH DEFB ' 3 READ A 2732 INTO MEMORY AT 4000H',0DH,0AH DEFB ' 4 COMPARE A 2732 WITH MEMORY AT 4000H',0DH,0AH DEFB ' 5 PROGRAM A 2732 WITH MEMORY DATA AT 4000H',0DH,0AH,0AH DEFB ' 6 READ A .COM FILE INTO MEMORY AT 4000H',0DH,0AH DEFB ' 7 MOVE NEXT BLOCK OF DATA DOWN TO 4000H FOR PROGRAMMING' DEFB 0DH,0AH DEFB ' 8 CRC CHECK ON 2K (2716) BLOCK AT 4000H',0DH,0AH DEFB ' 9 CRC CHECK ON 4K (2732) BLOCK AT 4000H',0DH,0AH,0AH DEFB ' : JUMP TO THE PFM MONITOR (G100 RETURNS)',0DH,0AH DEFB '$' ; MESS1: DEFB 0DH,0AH,07H DEFB 'DATA READ INTO MEMORY AT LOCATION 4000H' DEFB 07H DEFB '$' ; MESS2: DEFB 0DH,0AH ADDR: DEFB 'XXXXH PROM DATA = ' PROM: DEFB 'XXH MEMORY DATA = ' MEM: DEFB 'XXH ' DEFB 07H,'$' ; MESS2B: DEFB 0DH,0AH,0AH DEFB ' ******** CRC FOR PROM = ' CRCNUM: DEFB 'XXXX ********' DEFB 0DH,0AH DEFB '$' ; MESS2C: DEFB 0DH,0AH,0AH DEFB ' ******** CRC FOR MEMORY = ' MEMNUM: DEFB 'XXXX ********' DEFB 0DH,0AH DEFB '$' ; MESS3: DEFB 0DH,0AH,07H DEFB 'DATA IN PROM COMPARES WITH DATA IN MEMORY' DEFB 07H DEFB '$' ; MESS4: DEFB 0DH,0AH,07H DEFB 'INVALID SELECTION, CHOOSE ANOTHER' DEFB 07H DEFB '$' ; MESS5: DEFB 0DH,0AH,07H DEFB 'PROGRAMMING WILL TAKE ABOUT 2 MINUTES' DEFB 07H DEFB '$' ; ; MESS6: DEFB 0DH,0AH,07H DEFB 'ENTER NAME OF .COM FILE TO BE READ: ' DEFB '$' ; MESS7: DEFB 0DH,0AH,07H DEFB 'ILLEGAL DRIVE SELECTION, DRIVE MUST BE A,B,C,OR D' DEFB 07H DEFB '$' ; MESS8: DEFB 0DH,0AH,07H DEFB 'FILE NOT FOUND ON SELECTED DISK' DEFB 07H DEFB '$' ; MESS9: DEFB 0DH,0AH,07H DEFB 'FILE READ INTO MEMORY AT 4000H, READY FOR PROGRAMMING' DEFB 07H DEFB '$' ; MESS10: DEFB 0DH,0AH,07H DEFB '-ENTER (1) FOR 2716 BLOCK - ENTER (2) FOR 2732 BLOCK-' DEFB 0DH,0AH,0AH DEFB '(^C ABORTS AND RETURNS YOU TO MAIN MENU)' DEFB 0DH,0AH,07H DEFB '$' ; MESS11: DEFB 0DH,0AH,07H DEFB 'DATA BLOCK MOVED TO 4000H, READY FOR PROGRAMMING',07H DEFB '$' ; MESS12: DEFB 0DH,0AH,07H DEFB 'PROGRAMMING WILL TAKE ABOUT 4 MINUTES' DEFB 07H,'$' ; MESS13: DEFB 0DH,0AH,07H DEFB 'TURN OFF PROGRAMMING VOLTAGE' DEFB 0DH,0AH DEFB 'TYPE SPACE WHEN READY ...' DEFB 07H,'$' ; MESS14: DEFB 0DH,0AH,07H DEFB 'PUT 2732 IN SOCKET AND TYPE SPACE WHEN READY' DEFB 0DH,0AH DEFB '(^C ABORTS AND RETURNS YOU TO MAIN MENU)' DEFB 07H,'$' ; MESS15: DEFB 0DH,0AH,07H DEFB 'PUT 2716 IN SOCKET AND TYPE SPACE WHEN READY' DEFB 0DH,0AH DEFB '(^C ABORTS AND RETURNS YOU TO MAIN MENU)' DEFB 07H,'$' ; MESS16: DEFB 0DH,0AH,07H DEFB 'TURN ON PROGRAMMING VOLTAGE, TYPE SPACE WHEN READY' DEFB 0DH,0AH DEFB '(^C ABORTS AND RETURNS YOU TO MAIN MENU)' DEFB 07H,'$' ; MESS17: DEFB 0DH,0AH,07H DEFB 'ROM ERROR, (NOT ERASED, ETC), ENTER SPACE TO PROGRAM' DEFB 0DH,0AH DEFB '(^C ABORTS AND RETURNS YOU TO MAIN MENU)' DEFB 07H,'$' ; INITAB: DEFB 4 ;BYTE COUNT DEFB 09H ;PIO PORT A CONTROL ADDRESS DEFB 1CH ;PORT A INTERRUPT VECTOR (NOT CURRENTLY USED) DEFB 0FFH ;PORT A MODE WORD (BIT MODE) DIR: DEFB 0FFH ;PORT A DIRECTION WORD (ALL INPUT) DEFB 07H ;PORT A INTERRUPT WORD (INTERRUPTS DISABLED) ; DEFB 4 ;BYTE COUNT DEFB 0BH ;PIO PORT B CONTROL ADDRESS DEFB 1EH ;PORT B INTERRUPT VECTOR (NOT CURRENTLY USED) DEFB 0FFH ;PORT B MODE WORD (BIT MODE) DEFB 00H ;PORT B DIRECTION WORD (ALL OUTPUT) DEFB 07H ;PORT B INTERRUPT WORD (INTERRUPTS DISABLED) ; DEFB '$' ;END OF TABLE INDICATOR ; FBUF: DEFB 20 ;BUFFER CAN HOLD UP TO 20 CHARACTERS DEFS 20 ; END START