H	function	X,(X>>8)&0FF
L	function	X,X&0FF

	; .TITLE	TTYPGM, ´ SC/MP PROGRAMMER´

; "TTYPGM" IS A PROGRAM THAT ALLOWS THE SC/MP LCDS TO
; PROGRAM MM5204 OR MM4204 PROMS.

; THE COMMANDS AND THEIR FORMATS ARE:

;	CXXXX		COPY PROM INTO MEMORY

;	VXXXX		VERIFY PROM AGAINST MEMORY

;	PXXXX		PROGRAM PROM FROM MEMORY
;			WITH CHECK FOR ERASED

;	YXXXX		PROGRAM FROM MEMORY
;			WITHOUT CHECK FOR ERASED

; WHERE XXXX IS THE HEX STARTING ADDRESS TO BE USED.

; THE PROGRAM REQUIRES THAT THERE ARE 512 CONTINUOUS MEMORY
; LOCATIONS UPWARDS FROM XXXX.

; "TTYPGM" USES MEMORY ON THELCDS MOTHERBOARD FOR TEMPORARY
; STRORAGE.  THEREFORE, USER R/W MEMORY CAN BE ANYWHERE,
; EXCEPT AS SHOWN BELOW.

; "TTYPGM" CAN BE ASSEMBLED ANYWHERE THE USER HAS MEMORY
; SPACE EXCEPT IN THE FOLLOWING LOCATIONS:

;	X'8000 -- X'83FF	LOCATIONS OCCUPIED BY
;				PROGRAMMER HARDWARE
;	X'7000 -- X'7FFF	LOCATIONS USED BY LCDS

; A TELETYPE IS REQUIRED FOR EXECUTION

	;.PAGE	'POINTERS AND CONSTANTS'

$	=	0
P1	=	1
P2	=	2
P3	=	3

PPRGMR	=	08000		;PERIPHERAL ADDR. OF PROM
				; PROGRAMMER BOARD
VP	=	014		;ORDER CODE FOR PROG. VOLTAGE
RD	=	0C		;ORDER CODE FOR READ
VSS	=	04		;ORDER CODE FOR VSS,VBB,VDD
CS	=	01C		;ORDER CODE FOR CHIP SELECT
LOAD	=	0		;ORDER CODE TO LOAD DATA
CLK	=	1		;ORDER CODE TO CLOCK COUNTER
RDPRM	=	2		;ORDER CODE TO READ PROM
				; DATA
CLR	=	3		;ORDER CODE TO CLEAR COUNTER
ENBL	=	4		;ORDER CODE TO ENABLE CONTROL
				; LATCH
PUTC	=	07AE2		;PUT CHARACTER POINTER
GECHO	=	07A91		;GET CHARACTER W/ECHO POINTER
GHEX	=	07B50		;POINTER TO GET 4 HEX DIGITS
MESG	=	07B17		;POINTER TO MESSAGE ROUTINE
PHEX	=	07BB3		;POINTER TO PUT HEX ROUTINE
STACK	=	077D0		;STACK POINTER TO MOTHERBOARD
				; R/W MEMORY
HI	=	-17		;TEMPORARY LOCATIONS OFFSET
LO	=	-18		; FROM STACK POINTER
SAVLO	=	-19
SAVHI	=	-20
HCNT	=	-21
DPLO	=	-22
DPHI	=	-23

	;.PAGE	'COMMAND INPUT PROCESSING'

; *** COMMAND ENTRY ROUTINE ***

	NOP
ENTRY:
	LDI	H(STACK)	; INITIALIZE STACK PTR
	XPAH	P2
	LDI	L(STACK)
	XPAL	P2
PROMPT:
	JS	P3,MESG		;PROMPT FOR COMMAND
	.DBYTE	PRMPT
	JS	P3,GECHO	;GO TO GET CHAR W/ECHO
	ANI	07F		;MASK OUT PARITY, IF ANY
	XAE			;SAVE CHAR IN E. REG.
	LDI	H(CMDTBL)	;SET PTR. TO COMMAND TABLE
	XPAH	P1
	LDI	L(CMDTBL)
	XPAL	P1
	CCL
CLOOP:
	LD	@3(P1)		;GET COMMAND CHAR
	JZ	ERROR		;END OF TABLE, ERROR ON INPUT
	XRE			;CHECK FOP CORRECT COMMAND
	JNZ	CLOOP		;NOT RIGHT, TRY NEXT
	LD	@-1(P1)		;FOUND, COMMAND, GET ADDR.
	XAE			;SAVE TEMPORARILY IN E. REG
	LD	@-1(P1)
	XPAH	P1
	LDE
	XPAL	P1
	XPPC	P1		;EXECUTE COMMAND
	JMP	PROMPT
ERROR:
	LDI	L(PUTC)-1
	XPAL	P3
	LDI	'?'
	XPPC	P3
	JMP	PROMPT

	;.PAGE	'PROM ACCESS AND PROGRAMMING ROUTINES'

; *** ROUTINE TO CHECK PROM FOR ERASED CONDITION ***

; THIS SUBROUTINE IS ALSO CALLED BY "PROG:" TO VERIFY THAT
; THE PROM IS ERASED.

ERASED:
	LDI	H(PPRGMR)	;SET ADDR. OF PROGRAMMER
	XPAH	P3
	LDI	L(PPRGMR)
	XPAL	P3
	LDI	1		;SET UPPER COUNT
	ST	HI(P2)		;STACK IS EMPTY, USE AS PTR.
	ST	RD(P3)		;SET READ MODE
	ST	CS(P3)		;SELECT PROM SOCKET
	LDI	0		;SET LOWER COUNT
	ST	LO(P2)
	ST	CLR(P3)		;CLEAR PROM COUNTER
	ST	LOAD(P3)	;CLEAR DATA LATCHES FOR READ
ELOOP:
	LD	RDPRM(P3)	;READ DATA OUT OF PROM
	JNZ	NOT		;DATA NOT ZERO? NOT ERASED
	ST	CLK(P3)		;DATA OK, BUMP COUNTER
	DLD	LO(P2)		;DECREMENT LOWER COUNT
	JNZ	ELOOP		;NOT DONE YET
	DLD	HI(P2)		;DECREMENT UPPER COUNT
	JP	ELOOP		;NOT DONE YET
	XPPC	P1		;PROM IS ERASED
NOT:
	JS	P3,MESG		;GO TO MESSAGE RTN
	.DBYTE	NOTMSG		;PTR TO MESSAGE
RETN2:
	JMP	PROMPT		;RETURN TO COMMAND PROCESSING

; *** ENTRY POINT TO PROGRAM PROM W/O CHECK FOR ERASED ***

WOCHK:
	JS	P3,GHEX		;GET ADDR. TO PROG. FROM
	LDI	H(PPRGMR)
	XPAH	P3
	LDI	L(PPRGMR)
	XPAL	P3
	LD	@1(P2)		;GET UPPER BYTE OF ADDR.
	ADI	2		;ADD 512 OFFSET
	XPAH	P1
	LD	@1(P2)		;GET LOWER BYTE
	XPAL	P1
	JMP	SET

; *** ENTRY POINT TO PROGRAM PROM W/CHECK FOR ERASED ***

;     PROM IS PROGRAMMED FROM MOST SIGNIFICANT ADDRESS TO
;     LEAST SIGNIFICANT ADDRESS DUE TO INVERSION OF COUNTER

PROG:
	JS	P3,GHEX		;GET ADDR. TO PROGRAM FROM
	LD	@1(P2)		;RETRIEVE ADDR. FROM STACK
	XAE
	LD	@1(P2)
	ST	SAVLO(P2)	;SAVE IN R/W MEMORY
	LDE
	ST	SAVHI(P2)
	LDI	L(ERASED)-1	;CHECK PROM FOR ERASED
	XPAL	P1
	XPPC	P1
	LD	SAVLO(P2)
	XPAL	P1
	LD	SAVHI(P2)
	ADI	2		;ADD 512 OFFSET
	XPAH	P1
SET:	LDI	1
	ST	HI(P2)		;SET UPPER LOC COUNT
	LDI	0
	ST	LO(P2)		;SET LOWER LOC COUNT
	ST	CLR(P3)		;CLEAR PROM COUNTER
NXTLOC:
	LD	@-1(P1)		;GET DATA TO PROGRAM
	XAE			;SAVE IN EXTENSION REG.
THSLOC:
	LDI	H(PPROM)	;SET ADDR OF PROGRAMMING RTN
	XPAH	P1
	ST	SAVHI(P2)	;SAVE PTR ADDR.
	LDI	L(PPROM)-1
	XPAL	P1
	ST	SAVLO(P2)
	LDI	-2		;SET COUNT
	ST	HCNT(P2)	;SAVE HIT COUNT IN RAM
GO:
	XPPC	P1
	XRE			;CHECK PROM DATA
	JZ	OK		;PROM DATA CORRECT, DO X+5X
	DLD	HCNT(P2)	;DECREMENT HIT COUNT
	JNZ	GO
NPROG:
	JS	P3,MESG		;HIT COUNT OVER MAK. BAD PROM
	.DBYTE	BADPRM
LOC:
	LDI	L(PHEX)-1
	XPAL	P3
	LD	HI(P2)
	XPPC	P3
	LD	LO(P2)
	CCL			;CLEAR CARRY/LINK FLAG
	ADI	-1		;CORRECT COUNT
	XPPC	P3
	JMP	RETN2
OK:
	CCL
	LDI	0
	ST	DPHI(P2)	;CLEAR UPPER D. P. COUNT
	CAD	HCNT(P2)	;COMPLEMENT HIT COUNT
	ST	HCNT(P2)
	CCL			;CLEAR CARRY/LINK FLAG
	ADD	HCNT(P2)	;COMPUTE 5X
	ST	DPLO(P2)
	LDI	0
	ADD	DPHI(P2)
	ST	DPHI(P2)	;2X
	CCL
	LD	DPLO(P2)
	ADD	DPLO(P2)
	ST	DPLO(P2)
	LD	DPHI(P2)
	ADD	DPHI(P2)
	ST	DPHI(P2)	;4X
	CCL
	LD	HCNT(P2)
	ADD	DPLO(P2)
	ST	DPLO(P2)
	LDI	0
	ADD	DPHI(P2)
	ST	DPHI(P2)
PRLP:
	XPPC	P1		;PROGRAM PROM
	DLD	DPLO(P2)	;DECREMENT LOWER COUNT
	JNZ	PRLP		;NOT DONE
	DLD	DPHI(P2)	;DECREMENT UPPER COUNT
	JP	PRLP		;NOT DONE
	LD	SAVLO(P2)	;RESTORE P1
	XPAL	P1
	LD	SAVHI(P2)
	XPAH	P1
UPDATE:
	ST	CLK(P3)		;BUMP PROM COUNTER
	DLD	LO(P2)		;DECREMENT LOWER LOC COUNT
	JNZ	NXTLOC		;NOT DONE
	DLD	HI(P2)		;DECREMENT UPPER LOC COUNT
	JP	NXTLOC		;NOT DONE
	JMP	RETN1		;PROGRAMMING DONE
PPROM:
	LDI	0
	ST	RD(P3)		;TURN OFF READ MODE AND
	ST	CS(P3)		; CHIP SELECT
	LDE
	ST	LOAD(P3)	;SEND DATA TO PROGRAMMER
	LDI	1
	ST	VSS(P3)		;TURN ON VSS VOLTAGE
	LDI	07F		;WAIT 500 MICROSECONDS
	DLY	0
	ST	VP(3)		;TURN ON PROGRAM PULSE
	LDI	0FF
	DLY	0		;DELAY 1 MS
	LDI	0
	ST	VP(3)		;TURN OFF VP
	LDI	20		;WAIT 100 MICROSECONDS
	DLY	0
	LDI	0
	ST	VSS(P3)		;TURN OFF VSS VOLTAGE
	LDI	20		;WAIT 100 MICROSECONDS
	DLY	0
	ST	RD(P3)		;SET UP READ MODE
	ST	CS(P3)		;SELECT PROM SOCKET
	LDI	0
	ST	LOAD(P3)	;CLEAR DATA LATCHES
	LD	RDPRM(P3)	;READ DATA FROM PROM
	XPPC	P1
	JMP	PPROM

; *** COPY PROM TO RANGE IN MEMORY ***

COPY:
	JS	P1,SETRD	;SET READ MODE
	LD	@1(P2)		;RETRIEVE ADDR. FROM STACK
	ADI	2		;ADD 512 OFFSET
	XPAH	P1
	LD	@1(P2)
	XPAL	P1
CPLOOP:
	LD	RDPRM(P3)	;GET PROM DATA
	ST	@-1(P1)		;STORE INTO MEMORY
	ST	CLK(P3)		;BUMP PROM COUNTER
	DLD	LO(P2)		;DECREMENT LOC COUNTER LOW
	JNZ	CPLOOP
	DLD	HI(P2)		;DECREMENT LOC COUNTER HIGH
	JP	CPLOOP		;NOT DONE
RETN1:
	LDI	H(PROMPT)
	XPAH	P1
	LDI	L(PROMPT)-1
	XPAL	P1
	XPPC	P1

; *** VERIFY PROM AGAINST RANGE IN MEMORY ***

VERIFY:
	JS	P1,SETRD	;SET READ MODE
	LD	@1(P2)
	ADI	2		;ADD 512 OFFSET
	XPAH	P1
	LD	@1(P2)
	XPAL	P1
VLOOP:
	LD	RDPRM(P3)	;GET DATA FROM PROM
	XOR	@-1(P1)		;COMPARE AGAINST MEMORY DATA
	JNZ	NOVFY		;DOES NOT VERIFY
	ST	CLK(P3)		;BUMP PROM COUIHER
	DLD	LO(P2)		;DECREMENT LOC COUNTER LOW
	JNZ	VLOOP		;NOT DONE
	DLD	HI(P2)		;DECREMENT LOC COUNTER HIGH
	JP	VLOOP		;NOT DONE
	JMP	RETN1
NOVFY:
	JS	P3,MESG		;GO TO MESSAGE ROUTINE
	.DBYTE	NVRFY
	JMP	RETN1
SETRD:
	JS	P3,GHEX		;GET ADDR. TO COPY TO
	LDI	H(PPRGMR)	;PUT ADDR OF PROGRAMMER
	XPAH	P3		; IN P3
	LDI	L(PPRGMR)
	XPAL	P3
	LDI	1		;SET UPPER LOC COUNTER
	ST	HI+2(P2)
	ST	RD(P3)		;SET READ MODE
	ST	CS(P3)		;SELECT PROM SOCKET
	LDI	0
	ST	LO+2(P2)
	ST	CLR(P3)		;CLEAR PROM COUNTER
	ST	LOAD(P3)	;CLEAR PROM DATA LATCHES
	XPPC	P1

	;.PAGE	'MESSAGES AND COMMAND TABLE'

; *** MESSAGES ***

NOTMSG:
	.DBYTE	0D0A
	.ASCII	'NOT ERASED'
	.BYTE	0
NVRFY:
	.DBYTE	0D0A
	.ASCII	'NO VERIFY'
	.BYTE	0
BADPRM:
	.DBYTE	0D0A
	.ASCII	'BAD PROM AT '
	.BYTE	0
PRMPT:
	.DBYTE	0D0A
	.BYTE	'?',0

; *** COMMAND TABLE ***

CMDTBL:
	.BYTE	'P'
	.DBYTE	PROG-1
	.BYTE	'Y'
	.DBYTE	WOCHK-1
	.BYTE	'E'
	.DBYTE	ERASED-1
	.BYTE	'V'
	.DBYTE	VERIFY-1
	.BYTE	'C'
	.DBYTE	COPY-1
	.BYTE	0

	END
