.Z80 .SFCOND PAGE 64 FALSE EQU 0 TRUE EQU 0FFH T2732 EQU FALSE T2716 EQU TRUE ; IF T2732 TITLE PROGRAMMER, 2732 ENDIF IF T2716 TITLE PROGRAMMER, 2716 ENDIF ; ; This routine reads a CP/M .COM file of maximum size 4k bytes ; and burns it in a 2732 installed in U80 of BIGBOARD II. ; Or into a 2716 installed in U81. ; The 2732/2716 is 1st checked against the code to be burned in ; to be sure no '0' levels are to be programmed to '1'. ; Note that the 2732/2716 need not be blank. ; To achieve maximum speed, only those locations needing to be ; programmed actually receive the 50 ms programming pulse. ; Following programming, the 2732/2716 is verified, ; and any errors reported. The program can possibly be modified ; to burn other PROMS, but the reader should proceed with caution. ; Programming requirements vary considerably. ; ; jumpering for U-80 (2732) is as follows: ; ; pin 18 to REC5 ; pin 20 to /OE/VPP5 ; pin 21 TO RA11 ; ; ; D. H. DURLAND ; 663 Georgia Ave. ; Palo Alto, CA 94306 ; ; edit 12-8-82 remove phone #. You are welcome to write. Include ; stamped, self addressed envelope. ; edit 11-1-82 to remove reference to 2716's ; edit 10-21-82 to include jumper information ; ; the program is intended to be assembled using MACRO-80 ; .phase/.dephase commands work well to get code to 100h for .com file ; ; Instructions for use: ; Your code should be stored in a CP/M .COM file. ; To program, for example, EXAMPROG.COM ; ; Turn on your programming power supply. ; Insert the PROM to be programmed in U-80 or U81 ; Boot up CP/M to access PROGRAM.COM and EXAMPROG.COM ; (the usual drive access rules apply) ; Type 'PROGRAM EXAMPROG.COM'(the .COM is optional) ; (The program will bounce if it doesn't find a .com file) ; ; The rest is automatic ; ; ;******************************************************** ; * ; 2716 Entry's included 26/06/83 * ; * ; by L.Koopman * ; Waarbekenplein 13 * ; 7553 KK Hengelo (o) * ; Tel. 074-913022 * ; Holland * ; * ; jumpering for U-81 (2716) is as follows: * ; * ; pin 18 to PGM * ; pin 20 to RECX * ; pin 21 to /OE/VPP4 * ; * ; pin 2 of U44 must be lifted for programming and * ; verify of a 2716 eprom. * ; * ;******************************************************** BOOT EQU 0 FCB EQU 5CH BDOS EQU 5 CR EQU 0DH LF EQU 0AH R2 EQU 7FH SYS1 EQU 0C8H PROG EQU 0C0H CTCB3 EQU 08BH SRCMEM EQU 9000H ; park source here STACK EQU SRCMEM ON EQU 00001000B OFF EQU 00000000B IF T2732 ROMSIZ EQU 4096 ; size of a 2732 ENDIF IF T2716 ROMSIZ EQU 2048 ; size of a 2716 ENDIF MAXREC EQU ROMSIZ/128 PRAM EQU 8000H ; where some of this will run IF T2716 ROMLOC EQU 4000H ; ROM LOCATION ENDIF IF T2732 ROMLOC EQU 5000H ; ROM LOCATION ENDIF ROMCPY EQU 0A000H ; PROM copied here ENDCK EQU HIGH (SRCMEM+ROMSIZ) ; ASEG org 100h ; ; PROGRM: LD SP,STACK ; Underneath code to be burned ; ; 1st check to be sure a name has been entered. ; LD HL,FCB+1 ; 1 past drive LD A,(HL) CP ' ' ; is there a letter? JP Z,BUMFIL ; if not, go report no file ; ; now check for no type spec or .COM ; LD DE,65H ; 1st type in FCB LD HL,COMTBL LD BC,3 ; COM0: LD A,(DE) ; get type CP ' ' JR Z,COM1 ; space OK ; CP (HL) ; ck letter JP NZ,BUMFIL ; insist on space or correct letter ; COM1: LDI ; move a letter JP PE,COM0 ; until COM moved in ; JR OPNFIL ; go open it ; COMTBL: DEFM 'COM' ; OPNFIL: LD C,15 ; open file LD DE,FCB CALL BDOS OR A ; set flags JP M,BUMFIL ; if can't find it ; LD C,35 ; compute file size LD DE,FCB CALL BDOS LD HL,R2 ; point to high virtual size byte LD A,(HL) DEC HL OR (HL) ; middle byte JP NZ,TOOBIG ; both high bytes must be 0 ; DEC HL LD A,MAXREC CP (HL) ; least significant byte JP C,TOOBIG ; MAXREC records maximum ; ; fill with FF 1st ; LD HL,SRCMEM LD DE,SRCMEM+1 LD (HL),0FFH LD BC,ROMSIZ ; byte count LDIR ; do it ; ; now the actual read ; LD DE,SRCMEM-128 RDLP: LD HL,128 ADD HL,DE ; update DMA ADDR EX DE,HL PUSH DE ; save DMA ADDR LD C,26 ; set DMA ADDR CALL BDOS ; LD C,20 ; read sequential LD DE,FCB CALL BDOS ; read a record POP DE ; recover DMA ADDR OR A ; successful? JR Z,RDLP ; if not past end of file ; CP 1 ; end of file? JP NZ,BUMRD ; anything else is an error ; ; now we move the next section up to 8000 and jump to it, ; as we are going to bank switch in the PROMS and can't operate ; from CP/M ; LD DE,BURNIT LD HL,BURNLO LD BC,BRNEND-BURNIT LDIR ; move code up JP BURNIT ; and go to it ; BURNLO EQU $ ; .PHASE PRAM ; out of bank switched area ; BURNIT: DI LD A,0 OUT (SYS1),A ; switch in the PROMS EI ; ; 1st we check the PROM for 0-1 transitions ; LD HL,SRCMEM ; source code LD DE,ROMLOC ; PROM address LD A,TRUE LD (BITSOK),A ; initialize assuming OK ; CKLOOP: LD A,(DE) ; get a PROM byte OR (HL) LD B,A ; save with (possibly) extra bits LD A,(DE) ; get PROM again CP B JR NC,CKADUP ; if no bits went up ; LD A,FALSE LD (BITSOK),A ; flag for message at end JP ROMOUT ; go back to CP/M ; CKADUP: INC HL INC DE LD A,H CP ENDCK ; 1 past end JR C,CKLOOP ; for 2k or 4k bytes ; ; at this point we know that the PROM is at least theoretically ; programmable. Copy it into ROMCPY for reference. ; LD HL,ROMLOC ; PROM LD DE,ROMCPY ; copy destination LD BC,ROMSIZ ; byte count LDIR ; move it ; ; here is the actual burn ; LD B,3 LD C,PROG LD HL,BRNTBL ; table of output words OTIR ; get set ; LD HL,SRCMEM ; source code LD DE,ROMLOC ; PROM address LD BC,ROMCPY ; copy address JR BURNLP ; and do it BRNTBL: DEFB 00000000B+ON ; to disable PROM outs, enable U-57 outs DEFB 00000001B+ON ; to disable PROM /CS lines DEFB 00000100B+ON ; to turn on program voltage ; BURNLP: LD A,(BC) ; PROM copy CP (HL) ; same as source? JR Z,BURN9 ; skip burn if so (save time) ; LD A,(HL) ; get source LD (DE),A ; latch it to PROM for burn ; IF T2732 LD A,00000001B+OFF OUT (PROG),A ; /DECODE low thus /CS low ENDIF IF T2716 LD A,00000011B+ON ; pgm on OUT (PROG),A ; PROGRAM PULSE ON ENDIF ; PUSH BC ; save copy address LD B,50 ; millisecond count CNTMS: IN A,(CTCB3) ; get current count LD C,A ; it becomes reference MSCHG: IN A,(CTCB3) CP C ; change? JR Z,MSCHG ; until a change ; DJNZ CNTMS ; do 50x 1 millisec POP BC ; retrieve copy address ; IF T2732 LD A,00000001B+ON OUT (PROG),A ; /DECODE high thus /CS high ENDIF IF T2716 LD A,00000011B+OFF OUT (PROG),A ; pgm off ENDIF ; BURN9: ; can get here if PROM=source ; (see BURNLP+2) ; INC HL INC DE INC BC LD A,H CP ENDCK ; 1 past end JR C,BURNLP ; for 4k bytes ; ; PROM is now burned. Time to verify it. ; LD B,3 LD C,PROG LD HL,NRMTBL ; table to go back to normal OTIR ; go back ; JR VERIF1 ; and verify NRMTBL: DEFB 00000100B+OFF ; to turn off program voltage DEFB 00000001B+OFF ; to enable chip set decoder DEFB 00000000B+OFF ; to turn off out buff and enable PROM ; VERIF1: ; ; 1st we copy the burned PROM into ROMCPY ; LD HL,ROMLOC ; PROM LD DE,ROMCPY ; copy destination LD BC,ROMSIZ ; byte count LDIR ; move it ; ; Now switch out the PROMS and go back to CP/M for verification. ; ROMOUT: DI LD A,8 OUT (SYS1),A ; switch out the PROMS EI JP VERIFY ; go do the verification ; BRNEND EQU $ ; BITSOK: DEFS 1 ; goes false on 0 to 1 transition request ROMOK: DEFS 1 ; goes false on bad verify ; .DEPHASE ; VERIFY: LD A,(BITSOK) OR A JP Z,BITNG ; go report no try ; LD DE,CRLF ; else do the verification CALL PMSG ; put crlf ; LD A,TRUE LD (ROMOK),A ; assume ok LD HL,SRCMEM ; source start LD DE,ROMCPY ; PROM copy ; VLP: LD A,(DE) ; get a PROM byte CP (HL) ; match? CALL NZ,REPORT ; if not INC HL INC DE LD A,H CP ENDCK ; 1 past end JR C,VLP ; catch all bytes ; LD A,(ROMOK) OR A JP Z,FINIS ; if not ok, no reporting to be done ; LD DE,VERMSG ; else report success, and quit CALL PMSG JP FINIS ; ; Report receives DE pointing to the bad PROM byte and HL pointing ; to the source byte. HL is a relative address. ; REPORT: PUSH DE PUSH HL CALL MOVE4 ; move address into message LD A,(DE) ; get bad PROM byte LD DE,ERRMS4 CALL MOVE2 ; move bad PROM byte to message LD A,(HL) ; get source byte LD DE,ERRMS6 CALL MOVE2 ; move to message LD DE,ERRMS1 CALL PMSG ; print the error message POP HL POP DE LD A,FALSE LD (ROMOK),A ; if we get here at all, we have a problem RET ; ; MOVE4 converts the address to ASCII and moves it to the message area ; MOVE4: PUSH DE LD DE,ERRMS2 LD A,H RES 7,A ; modulo 4k CALL MOVE2 ; move H to message area LD A,L CALL MOVE2 ; and L POP DE RET ; ; MOVE2 converts a HEX byte to two ASCII characters and moves ; them into the message area ; MOVE2: PUSH AF RRA RRA RRA RRA ; get high nibble into low CALL MOVNIB ; and move it POP AF ; restore entire byte MOVNIB: AND 0FH ; only low part of interest ADD A,90H DAA ADC A,40H DAA ; convert to ASCII LD (DE),A ; put it in the message area INC DE ; advance to next slot RET ; ; this area contains abort routines and messages ; BITNG: LD DE,BITMSG CALL PMSG JP FINIS BITMSG: DEFM CR,LF,'Bits not all blank. Not programmable.' DEFM ' Aborting',CR,LF,'$' ; BUMFIL: LD DE,FILMSG CALL PMSG JP FINIS FILMSG: DEFM CR,LF,'Improper file specification',CR,LF,'$' ; TOOBIG: LD DE,BIGMSG CALL PMSG JP FINIS BIGMSG: DEFM CR,LF,'Too big for PROM',CR,LF,'$' ; BUMRD: LD DE,RDMSG CALL PMSG JP FINIS RDMSG: DEFM CR,LF,'Bad read, aborting',CR,LF,'$' ; PMSG: LD C,9 CALL BDOS RET ; ERRMS1: DEFM 'Relative ' ERRMS2: DEFS 4 ; will hold address ERRMS3: DEFM '=' ERRMS4: DEFS 2 ; will hold bad PROM byte ERRMS5: DEFM ' should=' ERRMS6: DEFS 2 ; will hold source byte CRLF: DEFM CR,LF,'$' VERMSG: DEFM 'PROM verifies OK',CR,LF,'$' ; FINIS: JP BOOT ; END ;