; PPD:  MITS 88-PPG PROM Programmer Driver
;
; The MITS 88-PPG is a 1702A EPROM programming system for the Altair BUS and consists 
; of 88-PPG PROM Programmer Interface Card, an 88-PMC PROM card (which contains this
; driver), and the PROM Programmer unit.
;
; This code is assembled to run from a PROM installed on an 88-PMC card (B socket). 
; The 88-PMC should have a BASE address of 0F800H.  The Altair PROM code makes use
; of the 88-PMC as follows:
; 	Socket A:  PROM to check
;	Socket B:  PROM Programmer Driver (PPD)
;	Socket C:  PROM Programmer Checker (PPC)
;	Socket D:  PROM to be copied

; 1702A Programming information:
;
; Initially, all 2048 bits of the ROM are in the "0" state (output low). Information
; is introduced by selectively programming "1"s (output high) in the proper bit locations.
;
; Word address selection is done by the same decoding circuitry used in READ mode (see
; table for logic levels).  All 8 address bits must be in the binary complement state
; when pulsed Vdd and Vgg move to their negative levels.  The addresses must be held in
; their binary complement state for a minimum of 25us after Vdd and Vgg have moved to their 
; negative levels.  The addresses must then make the transition to thier true state a 
; minimum of 10us before the program pulse is applied.  The addresses should be programmed
; in the sequence 0-255 for a minimum or 32 times.  The eight output terminals are used
; as data inputs to determine the information pattern in the eight bits of each word. A
; low data input level (-48V) will program a "1" and a high data input level (ground)
; will leave a "0" (see table on page 4-4). All eight bits of one word are programmed
; simultaneously by setting the desired bit information patterns on the data input
; terminals.
;
; During the programming, Vgg, Vdd and the Program Pulse are pulsed signals.


; Altair PROM Programmer Interface Card notes
;
; The Altair PROM Programmer Interface Card has two I/O Ports the even port
; All data written to these ports is inverted as it is latched from the Altair bus.

; Altair ports
SENSE				EQU	0FFH

; PROM Programmer I/O ports
CONTROL				EQU	40H
ADDR_DATA			EQU	41H

; Control Latch Bits
CL_PVGG				EQU	01H								; Enable pulsed Vgg
CL_PVDD				EQU	02H								; Enable pulsed Vdd
CL_PPRG				EQU	04H								; Enable the program pulse
CL_SD				EQU	08H								; Select the data latch
CL_I1				EQU	10H								; Programmer front panel LED selection
CL_I2				EQU	20H
CL_I3				EQU	40H
CL_READ				EQU	80H


                    ORG	0F900H

; Mode 1 entry point.  This mode transfers the 256-byte block contained in the 88-PMC
; (D socket) to the Programmer.  This mode is useful for making a number of copies of
; a previously programmed PROM.

					LD	C,20H							; Number of programming passes
					JP	MODE1_INIT						; Go finish mode 1 specific initialization

; Mode 2 entry point.  This mode transfers the 256-byte block identified by the current
; setting of the sense switches to the Programmer.  The sense switches are used to form
; the upper 8 bits of the pointer address for the starting location of the block to be
; programmed.  Thus, the starting locations that can be selected are restricted to 
; integral 256-byte locations,

					LD	C,20H							; Number of programming passes
					LD	E,80H							; Set mode 2 flag.

MODE2_REINIT:
					LD	B,00H							; B -> Current address to program
					LD	L,00H							; Read the sense switches to determine the starting
					IN	A,(SENSE)						;   address of the image to program.
					LD	H,A								; HL -> image to program.
					JP	BURNBYTE							; Go execute common programming code

MODE1_INIT:
					LD	E,00H							; Set mode 1 flag.
MODE1_REINIT:
					LD	B,00H							; B -> Current address to program
					LD	HL,0FB00H						; HL -> 88-PMC socket D which is the image to program.

; Common code for programming a PROM
;
; HL -> Byte to be programmed
; B  -> PROM address to program
; C  =  Number of programming passes remaining 

BURNBYTE:
					LD	A,CL_SD							; A = Select Data Latch Flag.
					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag.
					OUT	(CONTROL),A						; Select the data latch.
					XOR	A								; A = 00H
					OUT	(041H),A						; Clear the data latch
					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag.
					OUT	(CONTROL),A						; Select the address latch.
					XOR	A								; A = 00H
					OUT	(041H),A						; Clear the address latch.

					LD	D,11H							; Delay 13450.5 us
BURNDELAY:			LD	A,68H
BURNDELAY1:			DEC	A
					JP	NZ,BURNDELAY1
					DEC	D
					JP	NZ,BURNDELAY

					LD	A,B								; Get PROM address to program.
					OUT	(041H),A						; Write the address to program to the address latch.
                                                        ;   Note that since the PROM Programmer Interface card 
                                                        ;   inverts the data from the Altair Bus the address
                                                        ;   will be inverted as it is presented to the PROM socket.

					LD	A,CL_SD							; A = Select Data Latch Flag.
					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag.
					OUT	(CONTROL),A						; Select the data latch.
        
					LD	A,(HL)							; Get data byte to program.
					OUT	(041H),A						; Write the data byte to the data latch.
                                                        ;   Note that since the PROM Programmer Interface card 
                                                        ;   inverts the data from the Altair Bus the data
                                                        ;   will be inverted as it is presented to the Programmer,
                                                        ;   however, the programmer will uninvert the data prior
                                                        ;   to presenting it to the PROM socket.


					LD	A,10H							; Delay 123.5 us.  This delay covers PROM address complement Set-Up time.
ADDRSETUP:			DEC	A
					JP	NZ,ADDRSETUP

					LD	A,CL_PVGG | CL_PVDD				; Enable pulsed Vgg (-35V) and Pulsed Vdd (-48V).
					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag.
					OUT	(CONTROL),A

					LD	A,14H							; Delay 153.5 us
DELAY1:				DEC	A
					JP	NZ,DELAY1

; Output the PROM address to program

					LD	A,B								; A -> PROM address to program.
					CPL									; Complement the address bits.
					OUT	(041H),A						; Output address to program to the address latch.

					LD	A,13H							; Delay 146 us
DELAY2:				DEC	A
					JP	NZ, DELAY2

					LD	A,CL_PVGG | CL_PVDD | CL_PPRG	; Apply the Program Pulse
					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag.
					OUT	(CONTROL),A

					LD	A,0D0H							; Delay 1563.5 us
DELAY3:				DEC	A
					JP	NZ,DELAY3

					LD	A,CL_PVGG | CL_PVDD
					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag
					OUT	(CONTROL),A

					LD	A,03H							; Delay 26 us
DELAY4:				DEC	A 
					JP	NZ,DELAY4

					OR	E								; Mask in the current programming LED state.
					AND	07FH							; Mask off programming mode flag.
					OUT	(CONTROL),A

					LD	A,B								; Get the address to program
					AND	08H								; Toggle the Programming LED after every 8 bytes
					JP	Z,PROG_LED_OFF					; Go if LED should be off
					LD	A,E								; Get control latch image
					OR	CL_I1							; Set the CL_I1 flag
					LD	E,A								; Save updated control latch image
					JP	NEXTBYTE						; Go burn the next byte

PROG_LED_OFF:
					LD	A,E								; Get the control latch image
					AND	080H							; Clear the CL_I1 flag
					LD	E,A								; Save the updated control latch image
					JP	NEXTBYTE						; Go burn the next byte
					NOP
					NOP
					NOP

NEXTBYTE:
					INC	B								; Bump PROM address to program
					JP	Z, NEXTPASS						; Go if we have programmed all 256 bytes
					INC	HL								; Move to next image address
					JP	BURNBYTE

NEXTPASS:
					DEC	C								; More programming passes needed?
					JP	Z,BURNDONE						; Nope, Signal that programming is done
					LD	A,80H							; Programming mode 2?
					AND	E
					JP	Z,MODE1_REINIT					; Nope, start next pass as mode 1
					JP	MODE2_REINIT					; Yes, start next pass as mode 2

BURNDONE:
					LD	A,08H							; Select data latch.
					OUT	(CONTROL),A
					XOR	A								; Zero accumulator.
					OUT	(041H),A						; Clear the data latch.
					OUT	(CONTROL),A						; Select the address latch.
					OUT	(041H),A						; Clear the address latch.
					JP	BURN_COMPLETE					; Done.

					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
					NOP
BURN_COMPLETE:		JP	BURN_COMPLETE					; Loop forever

                    END
