; ***************************************************************************
; 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_APPS_FAN_CONTROL_MAIN_ASM
#define AQH_AVR_APPS_FAN_CONTROL_MAIN_ASM


.equ APP_FANCONTROL_TEMP_LIMIT = 2400


.cseg



; ---------------------------------------------------------------------------
; @routine AppFanControl_Init

AppFanControl_Init:
  ldi zl, LOW(appFanControlObjectFlash*2)
  ldi zh, HIGH(appFanControlObjectFlash*2)
  
  ; preset RAM
  lpm xl, Z+
  lpm xh, Z
  sbiw zh:zl, 1
  clr r16
  ldi r17,TCA_RAM_SIZE
  bigcall Utils_FillSram

  ; init base class
  bigcall TCA_Init

  ; preset source limits (low=1, high=65535)
  lpm yl, Z+
  lpm yh, Z
  sbiw zh:zl, 1
  ldi r16, 1
  std Y+(TCA_RAM_OFFS_TRIGGER_SOURCE1+TCA_SOURCE_OFFS_LOWLIM_LO), r16
  std Y+(TCA_RAM_OFFS_TRIGGER_SOURCE2+TCA_SOURCE_OFFS_LOWLIM_LO), r16
  ldi r16, 0xff
  std Y+(TCA_RAM_OFFS_TRIGGER_SOURCE1+TCA_SOURCE_OFFS_HIGHLIM_LO), r16
  std Y+(TCA_RAM_OFFS_TRIGGER_SOURCE1+TCA_SOURCE_OFFS_HIGHLIM_HI), r16
  std Y+(TCA_RAM_OFFS_TRIGGER_SOURCE2+TCA_SOURCE_OFFS_HIGHLIM_LO), r16
  std Y+(TCA_RAM_OFFS_TRIGGER_SOURCE2+TCA_SOURCE_OFFS_HIGHLIM_HI), r16

  ; preset guard limits (low=24.0 Grad, high=65535)
  ldi r16, LOW(APP_FANCONTROL_TEMP_LIMIT)
  ldi r17, HIGH(APP_FANCONTROL_TEMP_LIMIT)
  std Y+(TCA_RAM_OFFS_GUARD_SOURCE+TCA_SOURCE_OFFS_LOWLIM_LO), r16
  std Y+(TCA_RAM_OFFS_GUARD_SOURCE+TCA_SOURCE_OFFS_LOWLIM_HI), r17
  ldi r16, 0xff
  std Y+(TCA_RAM_OFFS_GUARD_SOURCE+TCA_SOURCE_OFFS_HIGHLIM_LO), r16
  std Y+(TCA_RAM_OFFS_GUARD_SOURCE+TCA_SOURCE_OFFS_HIGHLIM_HI), r16
  
;  ldi r16, 2
  ldi r16, 1
  std Y+HTIM_RAM_OFFS_MODE, r16

  ; setup from eeprom
  push yl
    push yh
      rcall appFanControlReadEeprom
    pop yh
  pop yl

  ; start in given mode
  rcall appFanControlUpdate
  ret
; @end



; ---------------------------------------------------------------------------
; @routine AppFanControl_OnEveryTick @global

AppFanControl_OnEveryTick:
  ldi zl, LOW(appFanControlObjectFlash*2)
  ldi zh, HIGH(appFanControlObjectFlash*2)

  lpm yl, Z+
  lpm yh, Z
  sbiw zh:zl, 1

  bigcall TCA_OnEveryTick

  ; check update flag
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  sbrs r16, TCA_FLAGBIT_UPDATED
    rjmp AppFanControl_OnEveryTick_ret         ; jump if clear (value unchanged)
  ; value updated
  cbr r16, (1<<TCA_FLAGBIT_UPDATED) ; clear update bit
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  rcall appFanControlWriteEeprom
  rcall appFanControlUpdate
AppFanControl_OnEveryTick_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine appFanControlUpdate

appFanControlUpdate:
  ldd r16, Y+HTIM_RAM_OFFS_FLAGS
  ldd r17, Y+HTIM_RAM_OFFS_MODE
  cpi r17, 2                       ; auto?
  breq appFanControlUpdate_auto
  ; non-auto
  cbr r16, (1<<HTIM_FLAGBIT_ACTIVE) | (1<<HTIM_FLAGBIT_ACTORENABLED) ; disable timer
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  cpi r17, 1                       ; on?
  breq appFanControlUpdate_on
  rcall appFanControlActorOff
  rjmp appFanControlUpdate_ret
appFanControlUpdate_auto:
  sbr r16, (1<<HTIM_FLAGBIT_ACTIVE) | (1<<HTIM_FLAGBIT_ACTORENABLED) ; enable timer
  std Y+HTIM_RAM_OFFS_FLAGS, r16
  sbrs r16, HTIM_FLAGBIT_STATE
    rjmp appFanControlUpdate_ret   ; jump if clear (actor is off)
  rcall appFanControlActorOn
  rjmp appFanControlUpdate_ret
appFanControlUpdate_on:
  rcall appFanControlActorOn
appFanControlUpdate_ret:
  ret
; @end




; ---------------------------------------------------------------------------
; @routine appFanControlReadEeprom
;
; @param  Y pointer to data in RAM

appFanControlReadEeprom:
  ldi r16, APP_FANCONTROL_EEID
  bigcall EepromTlv_FindFirst
  brcc appFanControlReadEeprom_ret

  ; let base class read
  bigcall TCA_ReadEepromAt              ; (r16, r17, Y)
  brcc appFanControlReadEeprom_ret

  push yl
    push yh
      adiw yh:yl, APP_FANCONTROL_RAM_OFFS_BEGIN
      ldi r17, (APP_FANCONTROL_EE_SIZE-APP_FANCONTROL_EE_OFFS_BEGIN)
      bigcall Eeprom_ReadBytes                    ; (r16, r17, X, Y)
    pop yh
  pop yl
appFanControlReadEeprom_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine appFanControlWriteEeprom
;
; @param  Y pointer to data in RAM

appFanControlWriteEeprom:
   ldi r16, APP_FANCONTROL_EEID
   bigcall EepromTlv_FindFirst
   brcs appFanControlWriteEeprom_write
   ; create eeprom TLV
   ldi r16, APP_FANCONTROL_EEID
   ldi r17, APP_FANCONTROL_EE_SIZE
   bigcall EepromTlv_AddTlv
   brcc appFanControlWriteEeprom_ret
appFanControlWriteEeprom_write:
  ; let base class write
  bigcall TCA_WriteEepromAt
  brcc appFanControlWriteEeprom_ret
  push yl
    push yh
      adiw yh:yl, APP_FANCONTROL_RAM_OFFS_BEGIN
      ldi r17, (APP_FANCONTROL_EE_SIZE-APP_FANCONTROL_EE_OFFS_BEGIN)
      bigcall Eeprom_WriteBytes                    ; (r16, r17, r18, X, Y)
    pop yh
  pop yl
appFanControlWriteEeprom_ret:
  ret
; @end



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

appFanControlActorOn:
  ldd r16, Y+APP_FANCONTROL_RAM_OFFS_VALUE_LO
  rcall appFanControlSetFanDutyFromTable
  bigcall AppFanControl_ReportState
  ret
; @end



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

appFanControlActorOff:
  clr r16
  rcall appFanControlSetFanDutyFromTable
  bigcall AppFanControl_ReportState
  ret
; @end



; ---------------------------------------------------------------------------
; @routine appFanControlSetFanDutyFromTable

; @param r16 step value

appFanControlSetFanDutyFromTable:
  cpi r16, APP_FANCONTROL_STEPS
  brcs appFanControlSetFanDutyFromTable_getValue
  ldi r16, APP_FANCONTROL_STEPS-1
appFanControlSetFanDutyFromTable_getValue:
  push yl
    push yh
      push zl
        push zh
          adiw zh:zl, APP_FANCONTROL_FLASH_OFFS_STEPTABLE
          clr r17
          add zl, r16   ; 3 entries per step
          adc zh, r17
          add zl, r16
          adc zh, r17
          add zl, r16
          adc zh, r17
          lpm r16, Z+
          bigcall MultiFan_SetFan1Duty
          lpm r16, Z+
          bigcall MultiFan_SetFan2Duty
          lpm r16, Z+
          bigcall MultiFan_SetFan3Duty
        pop zh
      pop zl
    pop yh
  pop yl
  ret
; @end




appFanControlObjectFlash:
  .dw appFanControlObjectRam  ; HTIM_FLASH_OFFS_RAMPTR
  .dw appFanControlActorOn    ; HTIM_FLASH_OFFS_ON_PTR
  .dw appFanControlActorOff   ; HTIM_FLASH_OFFS_OFF_PTR
  .dw (5*60*10)               ; HTIM_FLASH_OFFS_RELOADVAL
  .db  0, 0, 0,  20, 20, 20,  40, 40, 40,  70, 70, 70,  100, 100, 100,  0 ; speed table for 5 steps




.dseg


appFanControlObjectRam:
  .byte APP_FANCONTROL_RAM_SIZE


#endif


