; ***************************************************************************
; copyright   : (C) 2025 by Martin Preuss
; email       : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome".                              *
; * Please see toplevel file COPYING of that project for license details.   *
; ***************************************************************************

#ifndef AQH_AVR_WIN_OBJECT_H
#define AQH_AVR_WIN_OBJECT_H


.cseg



; ---------------------------------------------------------------------------
; @routine OBJ_Init @global
;
; Generally every object only reports its signals to a single other object
; (called the target). However, every object can receive signals from multiple
; sender objects. To allow this the target assigns its own id (called idForTarget)
; to the new object in order to determine who sent the signal and to act accordingly.
; There are system signals which don't use idForTarget (like OBJ_SIGNAL_DESTROY).
;
; @param Y pointer to object in SRAM
; @param r18 options
; @clobbers r16, r17, X

OBJ_Init:
  mov xl, yl
  mov xh, yh
  clr r16
  ldi r17, OBJ_OFFS_SIZE
  bigcall Utils_FillSram             ; (R17, X)
  bigcall Tree_InitObject            ; (R16)
  std Y+OBJ_OFFS_OPTIONS, r18
  ldi r16, LOW(OBJ_DefaultHandler)
  std Y+OBJ_OFFS_HANDLERFN_LO, r16
  ldi r16, HIGH(OBJ_DefaultHandler)
  std Y+OBJ_OFFS_HANDLERFN_HI, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_SetTarget @global
;
; @param r19 srcIdForTarget
; @param X pointer to target
; @clobbers none

OBJ_SetTarget:
  std Y+OBJ_OFFS_TARGET_LO, xl
  std Y+OBJ_OFFS_TARGET_HI, xh
  std Y+OBJ_OFFS_IDFORTARGET, r19
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_SetHandler @global
;
; @param Y pointer to object SRAM
; @param Z pointer to handler function (word address)
; @clobbers none

OBJ_SetHandler:
  std Y+OBJ_OFFS_HANDLERFN_LO, zl
  std Y+OBJ_OFFS_HANDLERFN_HI, zh
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_GetHandler @global
;
; @param  Y pointer to object SRAM
; @return Z pointer to handler function (word address)
; @clobbers none

OBJ_GetHandler:
  ldd zl, Y+OBJ_OFFS_HANDLERFN_LO
  ldd zh, Y+OBJ_OFFS_HANDLERFN_HI
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_DefaultHandler @global
;
; This is a default signal handler which does nothing.
;
; @param Y pointer to object SRAM
; @param r18 signal
; @param r19 srcIdForTarget
; @param R20 1st param
; @param R21 2nd param
; @param X   3rd param
; @clobbers any

OBJ_DefaultHandler:
  clc
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_Fini @global
;
; This routine calls OBJ_Fini on every child object, Then it sends the signal
; OBJ_SIGNAL_DESTROY to this object allowing it to release all its ressources
; (including memory space if using heap or other dynamic ressources).
;
; @param Y pointer to object in SRAM
; @clobbers any, !Y

OBJ_Fini:
  ; fini children
  push yl
    push yh
      bigcall Tree_GetFirstChildObject ; (none)
OBJ_Fini_loop:
        mov r16, xl
        or r16, xh
        breq OBJ_Fini_loopEnd
        mov yl, xl
        mov yh, xh
        bigcall Tree_GetNextSibling
        push xl                      ; next
          push xh                    ; next
            rcall OBJ_Fini
          pop xh                     ; next
        pop xl                       ; next
      rjmp OBJ_Fini_loop
OBJ_Fini_loopEnd:
    pop yh
  pop yl

  bigcall Tree_UnlinkObject            ; (r16, r17, x)

  push yl
    push yh
      ldi r18, OBJ_SIGNAL_DESTROY
      clr r19
      rcall OBJ_Handler
    pop yh                           ; probably no longer usable pointer,
  pop yl                             ; especially if using heap!
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_Handler @global
;
; Signal handler for an object. A signal can have up to 3 parameters
; conveyed in registers R20, R21 and X.
;
; @param Y pointer to object SRAM
; @param r18 signal
; @param r19 srcIdForTarget
; @param R20 1st param
; @param R21 2nd param
; @param X   3rd param

OBJ_Handler:
  ldd r17, Y+OBJ_OFFS_HANDLERFN_LO
  push r17
  ldd r17, Y+OBJ_OFFS_HANDLERFN_HI
  push r17
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_ForwardSignalToChildren @global
;
; Signal handler for an object. A signal can have up to 3 parameters
; conveyed in registers R18, R19 and X.
;
; @param Y pointer to object SRAM
; @param r18 signal
; @param R20 1st param
; @param R21 2nd param
; @param X   3rd param
; @clobbers any, !r18, !r20, !r21, !Y

OBJ_ForwardSignalToChildren:
  push yl
    push yh
      bigcall Tree_GetFirstChildObject     ; (none)
OBJ_ForwardSignalToChildren_loop:
        clc
        mov r17, xl
        or r17, xh
        breq OBJ_ForwardSignalToChildren_loopEnd
        mov yl, xl
        mov yh, xh
        push r18
          push r20
            push r21
              push xl
                push xh
                  push yl
                    push yh
                      clr r19             ; srcId for target set to 0 (this is a direct call to the handler)
                      rcall OBJ_Handler
                    pop yh
                  pop yl
                pop xh
              pop xl
            pop r21
          pop r20
        pop r18
        rcall Tree_GetNextSibling
      rjmp OBJ_ForwardSignalToChildren_loop
OBJ_ForwardSignalToChildren_loopEnd:
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine OBJ_EmitSignal @global
;
; @param Y pointer to object SRAM
; @param r18 signal
; @param R20 1st param
; @param R21 2nd param
; @param X   3rd param
; @clobbers any, !Y

OBJ_EmitSignal:
  push yl
    push yh
      ldd r16, Y+OBJ_OFFS_TARGET_LO
      ldd r17, Y+OBJ_OFFS_TARGET_HI
      ldd r19, Y+OBJ_OFFS_IDFORTARGET
      mov yl, r16
      mov yh, r17
      or r16, r17
      breq OBJ_EmitSignal_end
      rcall OBJ_Handler
OBJ_EmitSignal_end:
    pop yh
  pop yl
  ret
; @end



#endif ; AQH_AVR_WIN_OBJECT_H

