 /*
 * Stack1.asm
 *
 *  Modified: 25 Jan 2024
 *  Author: Dr. Schwartz
 *	Quick example of how the stack works.
 *	Subroutine copies the elements in a vector.
 *	
 *	Memory Maps:
 *	Data Memory: I/O Configuration Registers: 0x0000 - 0x0FFF
 *	Data Memory: Internal SRAM: 0x2000 - 0x3FFF
 *	Program Memory: FLASH range: 0x000000 - 0x10FFF
 *	Program Memory:	Application section (in FLASH): 0x0000 - 0xEFFF  
 *		Don't use 0-0xFC, since these are for the interrupt vectors
 *		0xF000-0xFFFF is app table section, but can be used for programs
 *	Note: Programs can go anywhere in the application section of FLASH
 *        and results should be writen to SRAM. 
 */ 

.include "ATxmega128A1Udef.inc"

; Initialize stack pointer (between 0x2000 & 0x3FFF)	
; Normally, 0x3FFF is preferred (and the default)
.equ	stack_init = 0x2FFF	
.equ	vector_size	= 4

.org 0x100
VECTOR:	.db 1,2,3,4

.dseg
.org 0x2ABC					;where test data will be placed
DATA_TAB:	.byte vector_size

.cseg 
.org 0x0000
	rjmp MAIN

.org 0x200
MAIN:
	ldi r16, low(stack_init)
	out CPU_SPL, r16		;initialize low byte of stack pointer 
; sts or out will work above, but out will ONLY work for addresses 
;   less than 63 = 0x3F; CPU_SPL = 61, see ATxmega128A1Udef.inc
	ldi r16, high(stack_init)
	out CPU_SPH, r16		;initialize high byte of stack pointer 
; sts or out will work above, but out will ONLY work for addresses 
;   less than 63 = 0x3F; CPU_SPH = 62, see ATxmega128A1Udef.inc
	ldi r16, vector_size
	push r16				;save something on stack
	pop  r17				;pop it back into a different register

	ldi XL, low(DATA_TAB)
	ldi XH, high(DATA_TAB)

	push XL		;save XL and XH onto the stack
	push XH
	pop  r17	;pop the two bytes into different registers
	pop  YL

	ldi ZL, low(VECTOR<<1)
	ldi ZH, high(VECTOR<<1)

; Call to a subroutine (stores 22 bit = 3 byte PC on the stack)
	rcall COPY_TBL		

HERE:	
	rjmp HERE

; Put this org here only to "know" the address of the subroutine
.org 0x300	
;*********************SUBROUTINES**************************************
; Subroutine Name: COPY_TBL
; Copies a table in program memory (flash) into data memory (SRAM).
; Inputs: Z (points to table in program memory)
;         X (points to table in data memory)
;		  r16 (size of table to copy)
; Ouputs: Table created at X with r16 elements
; Affected: r17

COPY_TBL:
;If you don't want registers trashed by the subroutine, then push
;  them at beginning of subroutine and pop in reverse order at the
;  end of the subroutine.		
	push XL		
	push XH
	push ZL	
	push ZH
	push r16

COPY:
	lpm r17, Z+	;load vector values from FLASH 
	st X+, r17	;copy vector values to SRAM
	dec r16
	brne COPY

; Restore the pushed registers to their initial values,
;   i.e., their values upon entering the subroutine
	pop r16		
	pop ZH
	pop ZL
	pop XH
	pop XL
	
	ret		;return from subroutine
