; ***************************************************************************
; copyright   : (C) 2026 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_MODULES_HOLDTIMER_MAIN_ASM
#define AQH_AVR_MODULES_HOLDTIMER_MAIN_ASM



; ---------------------------------------------------------------------------
; @routine HTIM_Init @global
;
; @param  Z pointer to timer data in FLASH (byte address for lpm!)
; @return Y pointer to data in RAM
; @clobbers r16, r18, r19

HTIM_Init:
  ; get RAM ptr
  lpm yl, Z+
  lpm yh, Z
  sbiw zh:zl, 1
  ; read default reload value
  adiw zh:zl, HTIM_FLASH_OFFS_RELOADVAL_LO
  lpm r18, Z+
  lpm r19, Z
  sbiw zh:zl, (HTIM_FLASH_OFFS_RELOADVAL_LO+1)
  ; setup RAM data
  clr r16
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  std Y+HTIM_RAM_OFFS_CURRVAL_LO, r16
  std Y+HTIM_RAM_OFFS_CURRVAL_HI, r16
  std Y+HTIM_RAM_OFFS_RELOAD_LO, r18
  std Y+HTIM_RAM_OFFS_RELOAD_HI, r19

  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_EnableActor @global
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers R16 (any)

HTIM_EnableActor:
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  sbrc r16, HTIM_FLAGBIT_ACTORENABLED     
    rjmp HTIM_EnableActor_ret             ; jmp if already enabled
  sbr r16, (1<<HTIM_FLAGBIT_ACTORENABLED)
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  sbrs r16, HTIM_FLAGBIT_ACTIVE
    rjmp HTIM_EnableActor_ret
  sbrc r16, HTIM_FLAGBIT_STATE
    rcall htimCallActorOn                 ; turn on actor if state is ON
HTIM_EnableActor_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_DisableActor @global
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers R16

HTIM_DisableActor:
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  sbrs r16, HTIM_FLAGBIT_ACTORENABLED     
    rjmp HTIM_DisableActor_ret             ; jmp if already disabled
  cbr r16, (1<<HTIM_FLAGBIT_ACTORENABLED)
  std Y+HTIM_RAM_OFFS_FLAGS, r16
HTIM_DisableActor_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_Start @global
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers R16

HTIM_Start:
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  sbr r16, (1<<HTIM_FLAGBIT_ACTIVE)
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_Stop @global
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers R16

HTIM_Stop:
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  cbr r16, (1<<HTIM_FLAGBIT_ACTIVE)
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_Trigger @global
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM

HTIM_Trigger:
  ldd r17, Y+HTIM_RAM_OFFS_FLAGS
  sbrs r17, HTIM_FLAGBIT_ACTIVE
    rjmp HTIM_Trigger_ret             ; jmp if not active
  sbrc r17, HTIM_FLAGBIT_ACTORENABLED ; don't reload 
    rcall htimReloadTimer
HTIM_Trigger_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_OnEveryTick @global
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers r16, r16, r24, r25 (any)

HTIM_OnEveryTick:
  ldd r17, Y+HTIM_RAM_OFFS_FLAGS
  sbrs r17, HTIM_FLAGBIT_ACTIVE
    rjmp HTIM_OnEveryTick_ret
  ; active
  ldd r24, Y+HTIM_RAM_OFFS_CURRVAL_LO
  ldd r25, Y+HTIM_RAM_OFFS_CURRVAL_HI
  mov r16, r24                        ; value 0?
  or r16, r25
  breq HTIM_OnEveryTick_ret           ; yes, nothing to do
  sbiw r25:r24, 1
  std Y+HTIM_RAM_OFFS_CURRVAL_LO, r24 ; store new value
  std Y+HTIM_RAM_OFFS_CURRVAL_HI, r25
  brne HTIM_OnEveryTick_ret           ; jmp if not 0
  ; just became zero, turn actor off
  sbrc r17, HTIM_FLAGBIT_STATE
    rcall htimCallActorOff            ; only call if ON
HTIM_OnEveryTick_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_ReadEepromAt
;
; @param  Z pointer to data in FLASH (byte address for lpm!)
; @param  Y pointer to data in RAM
; @param  X EEPROM address
; @return X EEPROM address after the data handled by this routine
; @clobbers r16, r17, Y

HTIM_ReadEepromAt:
  push yl
    push yh
      adiw yh:yl, HTIM_RAM_OFFS_RELOAD_LO             ; start at reload value
      ldi r17, HTIM_EE_SIZE
      bigcall Eeprom_ReadBytes                        ; (r16, r17, X, Y)
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine HTIM_WriteEepromAt
;
; @param  Z pointer to data in FLASH (byte address for lpm!)
; @param  Y pointer to data in RAM
; @param  X EEPROM address
; @return X EEPROM address after the data handled by this routine
; @clobbers r16, r17, r18, Y

HTIM_WriteEepromAt:
  push yl
    push yh
      adiw yh:yl, HTIM_RAM_OFFS_RELOAD_LO    ; start at reload value
      ldi r17, HTIM_EE_SIZE
      bigcall Eeprom_WriteBytes              ; (r16, r17, r18, X, Y)
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine htimCallActorOn
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers any (!Y, !Z)

htimCallActorOn:
  ldd r17, Y+HTIM_RAM_OFFS_FLAGS
  sbr r17, (1<<HTIM_FLAGBIT_STATE)
  std Y+HTIM_RAM_OFFS_FLAGS, r17

  sbrs r17, HTIM_FLAGBIT_ACTORENABLED
    rjmp htimCallActorOn_ret

  adiw zh:zl, HTIM_FLASH_OFFS_ON_PTR_LO
  lpm r18, Z+
  lpm r19, Z
  sbiw zh:zl,(HTIM_FLASH_OFFS_ON_PTR_LO+1)
  mov r16, r18
  or r16, r19
  breq htimCallActorOn_ret
  push r18                 ; jmp via stack
  push r19
htimCallActorOn_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine htimCallActorOff
;
; @param Z pointer to timer data in FLASH (byte address for lpm!)
; @param Y pointer to data in RAM
; @clobbers any (!Y, !Z)

htimCallActorOff:
  ldd r17, Y+HTIM_RAM_OFFS_FLAGS
  cbr r17, (1<<HTIM_FLAGBIT_STATE)
  std Y+HTIM_RAM_OFFS_FLAGS, r17

  adiw zh:zl, HTIM_FLASH_OFFS_OFF_PTR_LO
  lpm r18, Z+
  lpm r19, Z
  sbiw zh:zl,(HTIM_FLASH_OFFS_OFF_PTR_LO+1)
  mov r16, r18
  or r16, r19
  breq htimCallActorOff_ret
  push r18                 ; jmp via stack
  push r19
htimCallActorOff_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine htimReloadTimer
;
; @param  Z   pointer to timer data in FLASH (byte address for lpm!)
; @param  Y   pointer to data in RAM
; @clobbers none

htimReloadTimer:
  ldd r16, Y+HTIM_RAM_OFFS_RELOAD_LO
  std Y+HTIM_RAM_OFFS_CURRVAL_LO, r16
  ldd r16, Y+HTIM_RAM_OFFS_RELOAD_HI
  std Y+HTIM_RAM_OFFS_CURRVAL_HI, r16
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  sbrs r16, HTIM_FLAGBIT_STATE
    rcall htimCallActorOn                ; turn on actor
htimReloadTimer_ret:
  ret
; @end




#endif

