; TITLE PROGRAMMER, 2732 ; ; 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. The ; 2732 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 ; need not be blank. To achieve maximum speed, only those loca- ; tions needing to be programmed actually receive the 50 ms prog- ; ramming pulse. Following programming, the 2732 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 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 ; (415)493-4984 ; ; 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 ; ; 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 ; 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 rest is automatic ; FALSE EQU 0 TRUE EQU 0FFH 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 ROMSIZ EQU 4096 ; size of a 2732 MAXREC EQU ROMSIZ/128 PRAM EQU 8000H ; where some of this will run ROMLOC EQU 5000H ROMCPY EQU 0A000H ; PROM copied here ENDCK EQU HIGH (SRCMEM+ROMSIZ) ; .Z80 ; 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 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 8 ; to disable PROM outs, enable U-57 outs DEFB 9 ; to disable PROM /CS lines DEFB 0CH ; 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 ; LD A,1 OUT (PROG),A ; /DECODE low thus /CS low ; 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 ; LD A,9 OUT (PROG),A ; /DECODE high thus /CS high ; 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 4 ; to turn off program voltage DEFB 1 ; to enable chip set decoder DEFB 0 ; 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 ;