/* 
 * ParamPassing1b.asm
 *   Modified: 4 June 2024
 *   Authors:  Dr. Schwartz, Josh Weaver
 *   Purpose: Demonstrate passing of parameter address (a pointer to program memory) 
 *            to a subroutine using registers
 */ 
.include "ATxmega128A1Udef.inc"
;******************************INITIALIZATIONS***************************************
.equ	stack_init = 0x3FFF ; Initialize stack pointer (between 0x2000 & 0x3FFF)	
                            ; Default is 0x3FFF
.org 0x0000
	jmp MAIN
.org 0x100                  ; Place Data at address 0x100
DATA: .db 0x37, 0xA3        ; Define the data in bytes
;*******************************PROGRAM START****************************************
.org 0x200
MAIN:
    ldi r16, low(stack_init)
    out CPU_SPL, r16	        ; Initialize low byte of stack pointer
    ldi r16, high(stack_init)
    out CPU_SPH, r16	        ; Initialize high byte of stack pointer
	
    ldi ZL, low(DATA << 1)
    ldi ZH, high(DATA << 1)

    rcall AVG               ; Call subroutine AVG to get the average
		
HERE:	
    rjmp HERE
;********************************SUBROUTINES*****************************************
/************************************************************************************
 * Name:     AVG
 * Purpose:  Get the Average of two data bytes in successive memory locations in
 *           program memory pointed to by Z
 * Inputs:   Z is the pointer to program memory location of Data			 
 * Outputs:  r16 is the place for the result
 * Affected: r16, r17, Z
 ***********************************************************************************/
AVG:
    lpm r16, Z+     ; Load r16 with first point in program memory and increment Z
    lpm r17, Z      ; Load r17 with the second point in program memory
    add r16, r17    ; r16 = r16 + r17
    asr r16         ; Shift A right by 1 bit (divide by 2) keeping bit 7
                    ; (for sign extension) 
    ret	            ; Return from subroutine