;*******************************************************************************
; PROGRAM DESCRIPTION:
; Interface 93CX6 Serial EEPROM with GMS87C1202
;-------------------------------------------------------------------------------
; MICROCONTROLLER : GMS87C1202 (2K ROM, 20 PIN DIP)
; OPER. FREQUENCY : 4MHz
; SERIAL EEPROM   : 93CX6 
;-------------------------------------------------------------------------------
; programmed by Jongpil Shin (HEI) on 2001.1.30     Version 1.00
;*******************************************************************************
;
;*********** USER RAM ASSIGNMENT ************
;
temp_cmd	DS	1		;doubles as a temp register for cmd
temp_addr	DS	1		;doubles as a temp register for addr
;
; The following four registers must be located consecutively in memory.
cmd	DS	1
addr	DS	1
highb	DS	1
lowb	DS	1
;
;******* CONTROL REGISTER ASSIGNMENT ********
;
RA	EQU	0C0H	
RAIO	EQU	0C1H
;
;************* BIT ASSIGNMENT ***************
; The following assignments are for 3-wire, For 4-wire please assign DATAIN and
; DATAOUT to two separate pins.
;
DATAOUT	EQU	1		; Port pin tied to DO pin on 93CX6, 3 wire setup
DATAIN	EQU	1		; Port pin tied to DI pin on 93CX6, 3 wire setup
CLOCK	EQU	2		; Port pin tied to CLK on 93CX6
CS	EQU	3		; Port pin tied to CS on 93CX6		
;
;************ SYMBOL ASSIGNMENT *************
;
SERIAL	EQU	RA
INPUT	EQU	#0000_1110B
NO_ERROR	EQU	0
ERROR	EQU	1
;
;After issuing a WRITE, ERASE, ERAL, or WRAL command the approximate number of machine
;cycle X 256 to wait for the RDY status.
;This value must be adjusted as 10ms for operating frequencies other than 4MHz
TRIES	EQU	8

READ	EQU	1000_0000B	; read command op code
WRITE	EQU	0100_0000B	; write command op code
ERASE	EQU	1100_0000B	; erase command op code
EWEN	EQU	0011_0000B	; erase enable command op code
EWDS	EQU	0000_0000B	; erase disable command op code
ERAL	EQU	0010_0000B	; erase all command op code
WRAL	EQU	0001_0000B	; write all command op code
;
;************ MACRO DEFINITION **************
;
startbit	MACRO	
	SET1	SERIAL.DATAIN
	CLKIT
	ENDM
	
dsel	MACRO			; De-select the 93cX6 device
	CLR1	SERIAL.CS		; Chip Select (CS) = '0' to de-select the device
	ENDM
	
sel	MACRO			; select the 93cX6 device
	SET1	SERIAL.CS		; Chip Select (CS) = '1' to select the device
	ENDM
	
clkit	MACRO			; Clock a serial data bit into or out of the 93CX6 device.
	SET1	SERIAL.CLOCK	; Clock (CLK) = '1'
	NOP			; Adjust the number of nop instructions between the
				; assertion and de-assertion of CLK in proportion to the
				; GMS87C1202 operating frequency.
	CLR1	SERIAL.CLOCK
	ENDM	
	
;************** VECTOR AREA *****************
;
	ORG	0FFFEH
	DW	RESET             		;Reset Vector

	ORG	0F800H

RESET:	LDX	#07FH			;Initialize SP = #7FH
	TXSP				
	LDM	RA,#0000_0000B
	LDM	RAIO,#0000_1111B
          JMP       START

;*******************************************************************************
;                                 DOUTx
;*******************************************************************************
; Dataout x outputs up to 11 bits of op code/data, depending on whether a 
; 46/56/66 serial EEPROM is being used. The number of bits over 8 are saved in
; the cmd register and the rest in the addre register. Before calling this
; routine the 'cmd' and the 'addr' registers should be loaded as follows:
; cmd reg. bit 7|6|5|4|3|2|1|0
;              X|X|X|X|X|X|X|Y| -> not used
;              X|X|X|X|X|X|Y|X| -> not used
;              X|X|X|X|X|Y|X|X| -> not used
;              X|X|X|X|Y|X|X|X| -> 9th bit of address it necessary
;              X|X|X|Y|X|X|X|X| -> LSB of command OP code
;              X|X|Y|X|X|X|X|X| -> 3rd bit of command OP code
;              X|Y|X|X|X|X|X|X| -> 2nd bit of command OP code
;              Y|X|X|X|X|X|X|X| -> MSB of command OP code
;
;*******************************************************************************
;
; addr reg. 6/7/8 bits of address if necessary

dout10:	LDA	{X}		;Load data to be written
	ROL	A		;Take MSB of cmd opcode.
	STC	SERIAL.DATAIN	;Output latch.
	CLKIT			;Clock the 93CX6.
dout9:	
	ROL	A		;Take 2nd bit of cmd opcode.
	STC	SERIAL.DATAIN	;Output latch.
	CLKIT			;Clock the 93CX6.
	
	INC	X		;Increment pointer.
dout8:
	LDY	#8		;Initialize loop counter
	LDA	{X}		;Load address
d_o_8:	ROL	A		;Get the bit info.
	STC	SERIAL.DATAIN
	CLKIT
	DEC	Y
	BNE	d_o_8
	CLR1	SERIAL.DATAIN	; make sure DI pin is low
	LDA	#NO_ERROR
	RET	

;*******************************************************************************
;                                      DIN8
;*******************************************************************************
; Datain 8 will input 8 bits of data from the 93CX6. Before calling this routine,
; the FSR must point to the register being used to hold the incomming data.
;
din8:
	LDM	RAIO,#INPUT	;Set up the RA1 as an input before procedding.
	LDY	#8
	LDA	{X}
d_i_8:	
	CLKIT			;Clock a bit
	LDC	SERIAL.DATAOUT	;Read the incoming bit, then store it into Carry bit
	ROL	A    		;Make room for the incomming bit in the destination register.
	DEC	Y		;Repeat until bit couter Y = 0.
	BNE	d_i_8		;Y still > 0.
	STA	{X}		;Store read word into highb or/and lowb.
	LDM	RAIO,#0000_1111B	;Setup RA1 back to output.
	LDA	#NO_ERROR		;Exit with good status.
	RET
;	
;*******************************************************************************
;                                 RDYCHK  
;*******************************************************************************
; Rdychk will read the 93CX6 READY/BUSY status and wait for RDY status within
; the alloted number of processor cycles. If RDY status is not present after 
; this set period, the routine will return with an error status.
;	
rdychk:	
	LDY	#TRIES		;Initialize time-out counter upper byte of 16 bits
	LDA	#0		;Initialize lower byte of 16 bits (11.28ms)
	
	LDM	RAIO,#INPUT	;Set up the RA0 as an input before procedding
	dsel			;De-select the 93CX6.

; Note: Check the 93CX6 data sheet for minimum CS low time. Depending upon
; processor frequency, a NOP(s) may be between the assertion and de-assertion of
; Chip Select.  	
;	NOP

	sel			;Re-select the 93CX6
notrdy:	BBS	SERIAL.DATAOUT,rdynoerr ;Tset if DO PIN='1' 93CX6 has completed.
	DEC	A		;No, not yet ready. Decrement the A
	BNE	notrdy		;16 bit timer and check for expiration.
	DEC	Y		;still some left time. Try again.
	BNE	notrdy		;no, try again.
	
	LDM	RAIO,#0000_1111B	;Setup RA1 back to output
	LDA	#ERROR		;RDY status was not present in the alloted time,
	RET			;...return with error status.

rdynoerr:	LDM	RAIO,#0000_1111B	;Setup RA1 back to output.
	LDA	#NO_ERROR
	RET
;	
;*******************************************************************************
;                                 SEE  
;*******************************************************************************
; See will control the eitire operation of a 93CX6 device. Prior to calling the
; routine, load a valid command/memory address into location cmd, and for WRITE
; or WRAL commands, load registers highb and lowb with 16 bits of write data.
; Upon exit, the accumulator will contain the completion status.
; Only 93CX6 instruction which require a status check can return with an error
; as the completion status. The values that denote the completion status are
; defined as variables 'error' and 'no_eeror' in the general assignments section.
;
see:	LDA	cmd
	STA	temp_cmd		;save cmd
	LDA	addr
	STA	temp_addr  	;save addr
	LDX	#cmd		;Load X with the loacation of the cmd register.
	sel			;Chip Select (CS) = '1' to select the 93C46.
	startbit			;Sene a start bit.
	BBS	cmd.7,sc10
	BBC	cmd.6,sc10

; READ, WRITE, ERASE instruction are processed by following routine	
	CALL	dout10
see1:	
	LDA	temp_cmd
	STA	cmd
	LDA	temp_addr
	STA	addr
	
	BBS	cmd.6,see2	;Check for a WRITE or ERASE command, yes -> see2
	BBS	cmd.7,read_	;Check for a READ command, if yes, process READ command.
	BBS	cmd.5,see3	;Check for a EWEN or ERAL command.
	BBS	cmd.4,write_	;Check for a WRAL command, if yes, porcess WRAL/WRITE command.
	
exit_:	dsel			;command completed
	LDA	#NO_ERROR		;return with good completion status.
	RET
	
see2:	BBC	cmd.7,write_	;goto WRITE command
exit2_:	CALL	rdychk
	dsel
	RET

see3:	BBC	cmd.4,exit2_	;ERAL command
	BRA	exit_		;WRAL command
	
	
read_:	INC	X		;Increment the X index register to point to the register...
				;...receiving the upper byte of the incomming 93C46 data word.
	CALL	din8		;input the upper byte.
	INC	X		;Increment the Index Register to point to the register...
				;...receiving the lower byte.
	CALL	din8		;Input 8 more bits.
	BRA	exit_		;No, futher processing required, exit now.

write_:	INC	X		;Increment the X index Register to point to the upper byte of
				;...the 16 bit 93CX6 data word to be transmitted.
	CALL	dout8		;Output that byte.
	INC	X		;Increment the X index Register to point to the lower byte.
	CALL	dout8		;Output the lower byte of the 16 bit 93CX6 data word.
	BRA	exit2_		;Exit with a status check.
;	
; EWEN/EWDS, ERAL, WRAL instruction are processed by following routine	
; Above command only have 3rd, 4th bit opcode which is not in the READ, WRITE command
;	
sc10:	ROL	cmd		;The 3rd, 4th bit of command are moved to 1st, 2nd...
	ROL	cmd		;...it will be output after 2 bits of command
	LDA	cmd
	STA	addr		; 
	LDM	cmd,#0
	CALL	dout10		;transfer 10 bits
	JMP	see1	
;			
;	
;*******************************************************************************
;                                 Test Program  
;*******************************************************************************
; We've include a sample program to exercise the GMS87C1202 to 93C66 interface using
; a simple erase, write and verify routine.
; 8 bit organization has been used with a 3 wire interface.
;
start:
	LDM	serial,#0		;Clear the port tied to the 93C66 device.
	LDM	RAIO,#0000_1111B	;Initialize the data direction register for that port.
	LDM	cmd,#EWEN		;Transfer Erase/Write Enable command into cmd register.
	CALL	see		;Enable the 93C66 device.
	
	LDM	cmd,#ERAL		;Transfer Erase All command into 'cmd' register.
	CALL	see		;Erase the 93C66
	CMP	#ERROR		;check completion status.
	BEQ	errloop		;Yes, bad completion status, error-out.
	
TSTPTRN	EQU	0AAH
	
	LDM	cmd,#WRITE	;Transfer Write command into cmd register.	
	LDM	highb,#TSTPTRN	;Initialize the 93C66 data register with write data.
	LDM	addr,#0		;Start at address 0.
test1: 	CALL	see		;Write data word into 93C66 device.
	CMP	#ERROR		;Check if error ?
	BEQ	errloop		;Yes, bad completion status, error-out.
	INC	addr		;No, good. Increment the 8 bit memory address field
	BNE	test1		;Is Write precessing finished up tp 0FFH ?
	
	
		
	
	
	
	
	
errloop:	JMP	errloop	
;






	END
	
			
