; Xflash Williams System 9 and 11 CPU board Test Program
; Edward Cheung - ed@edcheung.com

; Typical Assemble command c:\Progra~1\a68\a68 xflash.asm -l xflash.lst -o xflash.hex
;   Build on pinball laptop
;   Use System_11 = 0
;   With Hex Editor or S4 replicate 0-3FFF and paste to 4000-7FFF
; For a System 9, ROM is at 0xC000 to 0xFFFF (16 kB / 27128)  
;  PIA addresses are at: 2100,2400,2800 (led and input), 3000.
; For a System 11, it is at 0x8000 to 0xFFFF (32 kB / 27256)
;  Additional PIAs at 2C00, 3400

; 3/16/21 - created System 11 configuration
; 3/18/21 - PIA tests working
; 3/19/21 - RAM test working.  Confirmed by checking one location past RAM
; 3/20/21 - Converted to System 9.  Implemented better addressing.  
;             The only hard addresses are ORG statements.  
;             Added switches to handle both 9 and 11.
; 3/21/21 - 1.0 - version compatible with both 9 and 11.  
;             Build code for System 9 (16k image) and 
;             duplicate to fill 32k.  This will run on both System 9 and 11.
; 3/24/21 - 1.1 - Added compatibility with System 9&11 sound section.
;11/25/22 - 1.2 - Expanded RAM check section from 2 to 10 passes.  
;                 Inverted CA2, CB2 to cause flipper relay to click

SYSTEM_11  SET 0

		IF	SYSTEM_11 	; Setup location of ROM in CPU address space
ROM_OFFSET SET $8000
		ELSE
ROM_OFFSET SET $C000
		ENDI

HEADER	ORG $0	
		FCC "XFlash v1.2 edcheung.com"

; Inits go here
INIT	ORG	$1000		;@D000 to CPU
		JMP MAIN+ROM_OFFSET

; Top of main.  Cycle through PIAs and toggle outputs
MAIN	ORG	$2000		;@E000 to CPU
PIA_DEL SET $6000	; C000 ~ half second delay

PIA_DTA	SET $2000
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2100
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port, CB2 low
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2400
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2800
		LDA A PIA_DTA+1	; A <- CRA for CA1
		TST A
		BMI SKIP_28	; Branch if MSbit set
		LDA A PIA_DTA+3	; A <- CRB for CB1
		TST A
		BMI SKIP_28	; Branch if MSbit set

		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
SKIP_28		NOP

PIA_DTA	SET $3000
		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2C00
		LDA A PIA_DTA+1	; A <- CRA for CA1
		TST A
		BMI SKIP_2C	; Branch if MSbit set
		LDA A PIA_DTA+3	; A <- CRB for CB1
		TST A
		BMI SKIP_2C	; Branch if MSbit set

		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
SKIP_2C		NOP

PIA_DTA	SET $3400
		LDA A PIA_DTA+1	; A <- CRA for CA1
		TST A
		BMI SKIP_34	; Branch if MSbit set
		LDA A PIA_DTA+3	; A <- CRB for CB1
		TST A
		BMI SKIP_34	; Branch if MSbit set

		LDA A #$00	; Access DDR
		STA A PIA_DTA+1	;   2801 <- 0x00 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x00 (literal)
		LDA A #$FF	; All as outputs
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
		LDA A #$34	; Access Data Port
		STA A PIA_DTA+1	;   2801 <- 0x34 (literal)
		STA A PIA_DTA+3	;   2803 <- 0x34 (literal)
		LDA A #$FF	; All outputs high
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)
SKIP_34		NOP

		LDX #$0000	; Half of delay
LOOP1		INX
		CPX #PIA_DEL
		BNE LOOP1

PIA_DTA	SET $2000
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $2100
		LDA A #$3C	; access Data Register, CB2 high
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0xFF (literal)
		STA A PIA_DTA+2	;   2802 <- 0xFF (literal)

PIA_DTA	SET $2400
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $2800
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $2C00
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $3000
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

PIA_DTA	SET $3400
		LDA A #$3C	; A2 low
		STA A PIA_DTA+1	;   2801 <- 0x3C (literal)
		STA A PIA_DTA+3	;   2803 <- 0x3C (literal)
		LDA A #$00	; All outputs low
		STA A PIA_DTA	;   2800 <- 0x00 (literal)
		STA A PIA_DTA+2	;   2802 <- 0x00 (literal)

		LDX #$0000	; Half delay
LOOP2		INX
		CPX #PIA_DEL
		BNE LOOP2
		JMP MAIN+ROM_OFFSET

; Interrupt on pushbutton to check RAM
RAM_CHECK	ORG $3000	;@F000 to CPU
RAM_ADR SET $800;Number of RAM checked.  Starting with 0x00, last one checked is -1
RAM_DAT	SET $55	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP1	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP1	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP2	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP2	; Loop back to next check

RAM_DAT	SET $AA	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP3	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP3	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP4	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP4	; Loop back to next check
		
RAM_DAT	SET $03	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP5	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP5	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP6	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP6	; Loop back to next check

RAM_DAT	SET $0F	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP7	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP7	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP8	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP8	; Loop back to next check

RAM_DAT	SET $3F	;Data to use in test
		LDX #$0000	; initialize index
RAM_LOOP9	LDA A #RAM_DAT 	; Write constant to RAM
		STA A 0,X
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP9	; Loop back to next write
;
		LDX #$0000	; initialize index
RAM_LOOP10	LDA A #RAM_DAT 	
		CMP A 0,X	; Compare RAM
		BNE RAM_BAD	; Check if good data
		INX
		CPX #RAM_ADR
		BNE RAM_LOOP10	; Loop back to next check

		JMP MAIN+ROM_OFFSET

RAM_BAD		NOP
		LDA A #$00	; All outputs low to light LED2
		STA A $2800	;   2800 <- 0xFF (literal)
		JMP HALT+ROM_OFFSET	; Halt

HALT	ORG	$3800		;@F800 to CPU
		JMP HALT+ROM_OFFSET	;Infinite loop to Halt

; Set up Vectors
		IF	SYSTEM_11 	; If System 11
		ORG $7FF8
		ELSE
		ORG $3FF8
		ENDI
		FDB INIT+ROM_OFFSET		; Periodic Int: IRQ Vector (not used)
		FDB INIT+ROM_OFFSET		; SW int (not used)
		FDB RAM_CHECK+ROM_OFFSET; Push button: NMI Interrupt
		FDB INIT+ROM_OFFSET		; Power Up: RESET Interrupt
		END
