/*
 * ParamPassing3a.asm
 * Modified: 28 May 2026
 *   Authors:  Dr. Schwartz, Josh Weaver
 *   Purpose:  Demonstrate the use of parameters with the stack
 */ 
.include "ATxmega128A1Udef.inc"
;******************************INITIALIZATIONS***************************************
.equ	stack_init = 0x3FFF ; Initialize stack pointer (between 0x2000 & 0x3FFF)	
                            ; Default is 0x3FFF
.org 0x0000
	jmp MAIN
;*******************************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 r16, 0x37               ; Load first parameter into r16 and
    push r16                    ; push to stack
    ldi r16, 0xA3               ; Load second parameter into r16 and
    push r16                    ; push to stack

    rcall AVGA                  ; Call subroutine AVGA to get the average
;   rcall AVGB                  ; Call subroutine AVGB to get the average
	
HERE:	
    rjmp HERE
;********************************SUBROUTINES*****************************************
/************************************************************************************
 * Name:     AVGA
 * Purpose:  Get the Average of inputs on the stack
 * Inputs:   No direct input (from stack)
 * Outputs:  r16 is the place for the result
 * Affected: r16, r17, r18, X, Stack
 ***********************************************************************************/
AVGA:
    ; We will use r18 and X to get the return address from the stack.  These
    ; registers will not be changed and will be used to return the address back to
    ; the stack.  Since the address for program memory must be shifted by 1, it will
    ; be placed into Z and modified as needed.
    pop r18         ; Using r18 to handle third byte (HIGHEST) of address location.
    pop XH          ; Grab High byte of return address from stack
    pop XL          ; Grab Low byte of return addres from stack

    pop r17         ; Grab the second parameter from the stack
    pop r16         ; Grab the first parameter from the stack
   
    add r16, r17    ; r16 = r16 + r17
    asr r16         ; Shift A right by 1 bit (divide by 2) keeping bit 7
                    ; (for sign extension) 

    push XL         ; Place the original return address back on the stack
    push XH
    push r18
    ret             ; Return from subroutine
/************************************************************************************
 * Name:     AVGB
 * Purpose:  Get the Average of inputs on the stack
 * Inputs:   No direct input (from stack)
 * Outputs:  r16 is the place for the result
 * Affected: r16, r17, Y, Stack 
 *           ***Modified AND THUS HAS LEFT OVER INFO. EVERY
 *           CALL INCREASES THE SIZE OF THE DATA ON THE STACK!!!
 ***********************************************************************************/
AVGB:
    in YL, CPU_SPL      ; Grab low byte of stack pointer
    in YH, CPU_SPH      ; Grab high byte of stack pointer

    ldd r16, Y+4        ; Grab parameter 1 from the stack given the offset
    ldd r17, Y+5        ; Grab parameter 2 from the stack given the offset

    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
