/* Input_Port.asm
 *
 * Modified: 4 June 2026
 * Author:  Dr. Schwartz
 *
 * This is the minimum code required to setup an input port with
 * address decoding utilizing the CS of the XMEGA. This solution
 * assumes the user is providing their own output enable, OE(L), 
 * to the input port's tri-state buffer chip using CS0(L) and RE(L), 
 * i.e., OE (from PLD to tri-state buffer) = f(CS0,RE).
 */
.include "ATxmega128A1Udef.inc"
;***********INITIALIZATIONS***************************************
.equ IN_PORT = 0x37E000		; Could use something like 0x6000	
.equ IN_PORT_END = 0x37FFFF	; Something like this MIGHT be useful
.equ BIT41	= 0b00010010	; CS0 is in bit 4; RE is in bit 1
.equ BIT2	= 0b00000100	; ALE1 is in bit 2
.equ BIT421	= 0b00010110	; CS0 in bit 4; ALE, bit 2; RE, bit 1
.equ BIT0	= 0b00000001	; EBI_CTRL: 3-PORT (IFMODE) and 
							;   ALE1 mode (SRMODE)
.org 0x0000	
	rjmp MAIN

.org 0x200
MAIN:
; See doc8385, Table 33-7, column SRAM 1PORT ALE1 (PortH)
; Bit7654: CS3(L) [A19], CS2(L) [A18], CS1(L) [A17], CS0(L) [A16],
; Bit210: ALE1(H), RE(L), WE(L)
; See 8331, sect 27.9. See also doc8385, Table 33-7
;	ALE1 is false (L) by default.
; Set active-low EBI signals to false (H), RE(L) and CS0(L)
	ldi r16, BIT41
	sts PORTH_OUTSET, r16

; Initialize DIR for PORTH outputs CS0(L), ALE1(H), and RE(L),
;   bits 4, 2, and 1
	ldi r16, BIT421
	sts PORTH_DIRSET, r16
	
; Initialize PORTK pins for outputs (A15-A8,A7-A0)
; See doc8385, Table 33-9; doc8331, sec 27.9.
	ldi r16, 0xFF	
	sts PORTK_DIRSET, r16

; First paragraph of doc8331 section 27.9 says EBI will 
; OVERRIDE the direction and/of value of data bus pins!
; See also doc8385, Table 33-8; doc8331, sec 27.9.
;	ldi r16, 0xFF
;	sts PORTJ_DIRSET, r16
	
; Initialize EBI_CTRL for 3-port (H, J, K) (IFMODE), ALE1 (SRMODE)
; Instead of BIT0, can use EBI_IFMODE_3PORT_gc | EBI_SRMODE_ALE1_gc 
	ldi r16, BIT0
;	ldi r16, EBI_IFMODE_3PORT_gc | EBI_SRMODE_ALE1_gc	
	sts EBI_CTRL, r16

;Reserve a CS zone for our input port. The base address register  
;  is made up of 12 bits for address (A23:A12). 
;  Lower 12 bits of the address (A11-A0) are assumed to be zero. 
;    This limits our choice of the base addresses.

;Load the middle byte (A15:8) of the 3-byte address into a   
;  register and store it as the LOW byte of the Base Address,
;  BASEADDRL.  This will store only bits A15:A12 and ignore
;  anything in A11:8 (assumed to be 0). 
;Initialize low byte of the EBI CS0 base address (byte2 of address).
	ldi r16, byte2(IN_PORT)
	sts EBI_CS0_BASEADDR, r16

;Load the highest byte (A23:16) of the 3-byte address into a 
;  register and store it as the HIGH byte of the Base Address.
;Initialize high byte of the EBI CS0 base address (byte3 of address).
	ldi r16, byte3(IN_PORT)
	sts EBI_CS0_BASEADDR+1, r16
	
; Set to 8K CS space and turn on SRAM mode, 0x37_E000-0x37_FFFF
	ldi r16, EBI_CS_ASPACE_8KB_gc | EBI_CS_MODE_SRAM_gc ; 0x15
	sts EBI_CS0_CTRLA, r16					

; Point to the IN_PORT with X
	ldi r16, byte3(IN_PORT)
	sts CPU_RAMPX, r16
	ldi XH, high(IN_PORT)
	ldi XL, low(IN_PORT)

; Repeatedly read the input port
; Put a breakpoint on the rjmp and check r16!
TEST:
	ld r16, X
	rjmp TEST
