; ***************************************************************************
; 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.   *
; ***************************************************************************


; ***************************************************************************
; defines

.equ FILTER_STABILIZE_OFFS_STATUSBYTE        = 0
.equ FILTER_STABILIZE_OFFS_TIMER             = 1
.equ FILTER_STABILIZE_OFFS_COUNTER           = 2
.equ FILTER_STABILIZE_OFFS_STABLECOUNTVAL    = 3
.equ FILTER_STABILIZE_DATA_SIZE              = 4

.equ FILTER_STABILIZE_STATUS_LASTVALUE_BIT   = 0
.equ FILTER_STABILIZE_STATUS_STABLEVALUE_BIT = 1
.equ FILTER_STABILIZE_STATUS_REPORT0_BIT     = 4
.equ FILTER_STABILIZE_STATUS_REPORT1_BIT     = 5
.equ FILTER_STABILIZE_STATUS_REPEAT0_BIT     = 6
.equ FILTER_STABILIZE_STATUS_REPEAT1_BIT     = 7

.equ FILTER_STABILIZE_REPORTTIME1            = 1   ; report after 100ms
.equ FILTER_STABILIZE_REPORTTIME2            = 11  ; report after 1100ms
.equ FILTER_STABILIZE_REPORTTIME3            = 22  ; report after 2200ms
.equ FILTER_STABILIZE_REPEATTIME             = 200 ; 20s



; ***************************************************************************
; code

.cseg


; ---------------------------------------------------------------------------
; @routine FilterStabilize_Init @global
;
; @param Y  pointer to filter data

FilterStabilize_Init:
  clr r16
  std Y+FILTER_STABILIZE_OFFS_COUNTER, r16
  std Y+FILTER_STABILIZE_OFFS_STATUSBYTE, r16
  dec r16
  std Y+FILTER_STABILIZE_OFFS_TIMER, r16  ; hold timer
  ret
; @end



; ---------------------------------------------------------------------------
; @routine FilterStabilize_Fini @global
;
; @param Y  pointer to filter data

FilterStabilize_Fini:
  ; nothing to do
  ret
; @end



; ---------------------------------------------------------------------------
; @routine FilterStabilize_GetValue @global
;
; Values are reduced to 1 bit (i.e. either "0" or "1").
;
; @param Y  pointer to filter data
; @return R19:R18 value

FilterStabilize_GetValue:
  ldd r18, Y+FILTER_STABILIZE_OFFS_STATUSBYTE
  lsr r18, FILTER_STABILIZE_STATUS_STABLEVALUE_BIT
  andi r18, 1
  clr r19
  ret
; @end



; ---------------------------------------------------------------------------
; @routine FilterStabilize_SetValue @global
;
; The stored value is reduced to 1 bit (i.e. either "0" or "1").
;
; @param Y  pointer to filter data
; @param R19:R18 value
; @clobbers r16, r17

FilterStabilize_SetValue:
  mov r16, r18
  or r16, r19
  breq FilterStabilize_SetValue_set
  ldi r16, (1<<FILTER_STABILIZE_STATUS_LASTVALUE_BIT)
FilterStabilize_SetValue_set:
  ldd r17, Y+FILTER_STABILIZE_OFFS_STATUSBYTE
  eor r17, r16
  andi r17, FILTER_STABILIZE_STATUS_LASTVALUE_BIT
  breq FilterStabilize_SetValue_noChange            ; no change
  ; changed
  ldd r16, Y+FILTER_STABILIZE_OFFS_STATUSBYTE
  eor r16, r17                                      ; change lastValue bit in status byte
  std Y+FILTER_STABILIZE_OFFS_STATUSBYTE, r16
  clr r16                                           ; reset counter
  std Y+FILTER_STABILIZE_OFFS_COUNTER, r16
  dec r16
  std Y+FILTER_STABILIZE_OFFS_TIMER, r16            ; timer=255 (hold timer)
  rjmp FilterStabilize_SetValue_end
FilterStabilize_SetValue_noChange:
  ldd r16, Y+FILTER_STABILIZE_OFFS_COUNTER
  inc r16
  breq FilterStabilize_SetValue_end                 ; stop counter at 255
  std Y+FILTER_STABILIZE_OFFS_COUNTER, r16
  ldd r17, Y+FILTER_STABILIZE_OFFS_STABLECOUNTVAL
  cpi r16, r17
  brne FilterStabilize_SetValue_end
  ; copy last value to stable value
  ldd r16, Y+FILTER_STABILIZE_OFFS_STATUSBYTE
  mov r17, r16
  lsl r17, (FILTER_STABILIZE_STATUS_STABLEVALUE_BIT-FILTER_STABILIZE_STATUS_LASTVALUE_BIT) ; r17=new value
  andi r17, (1<<FILTER_STABILIZE_STATUS_STABLEVALUE_BIT)  ; isolate new stable bit
  andi r16, ~(1<<FILTER_STABILIZE_STATUS_STABLEVALUE_BIT) ; clear stable bit
  or r16, r17                                             ; or-in new stable bit
  std Y+FILTER_STABILIZE_OFFS_STATUSBYTE, r16
  ; start timer
  clr r16
  std Y+FILTER_STABILIZE_OFFS_TIMER, r16
FilterStabilize_SetValue_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine FilterStabilize_Every100ms @global
;
; @return CFLAG set if value should be reported, cleared otherwise
; @param  Y     pointer to filter data
; @clobbers r16, r18, r19

FilterStabilize_Every100ms:
  ldd r16, Y+FILTER_STABILIZE_OFFS_TIMER
  inc r16
  breq FilterStabilize_Every100ms_clcRet            ; hold counter at 255
  std Y+FILTER_STABILIZE_OFFS_TIMER, r16
  cpi r16, FILTER_STABILIZE_REPEATTIME
  breq FilterStabilize_Every100ms_repeat
  cpi r16, FILTER_STABILIZE_REPORTTIME1
  breq FilterStabilize_Every100ms_report
  cpi r16, FILTER_STABILIZE_REPORTTIME2
  breq FilterStabilize_Every100ms_report
  cpi r16, FILTER_STABILIZE_REPORTTIME3
  breq FilterStabilize_Every100ms_report
  rjmp FilterStabilize_Every100ms_clcRet
FilterStabilize_Every100ms_report:
  ldd r18, Y+FILTER_STABILIZE_OFFS_STATUSBYTE
  sbrc r18, FILTER_STABILIZE_STATUS_STABLEVALUE_BIT
    rjmp FilterStabilize_Every100ms_report1
FilterStabilize_Every100ms_report0:                 ; value is 0
  sbrs r18, FILTER_STABILIZE_STATUS_REPORT0_BIT
    rjmp FilterStabilize_Every100ms_clcRet          ; REPORT0 not set
  rjmp FilterStabilize_Every100ms_secRet
FilterStabilize_Every100ms_report1:                 ; value is 1
  sbrs r18, FILTER_STABILIZE_STATUS_REPORT1_BIT
    rjmp FilterStabilize_Every100ms_clcRet          ; REPORT1 not set
  rjmp FilterStabilize_Every100ms_secRet
FilterStabilize_Every100ms_repeat:
  ldd r18, Y+FILTER_STABILIZE_OFFS_STATUSBYTE
  sbrc r18, FILTER_STABILIZE_STATUS_STABLEVALUE_BIT
    rjmp FilterStabilize_Every100ms_repeat1
FilterStabilize_Every100ms_repeat0:                 ; value is 0
  sbrs r18, FILTER_STABILIZE_STATUS_REPEAT0_BIT
    rjmp FilterStabilize_Every100ms_clcRet          ; REPEAT0 not set
  rjmp FilterStabilize_Every100ms_resetTimer
FilterStabilize_Every100ms_repeat1:                 ; value is 1
  sbrs r18, FILTER_STABILIZE_STATUS_REPEAT1_BIT
    rjmp FilterStabilize_Every100ms_clcRet          ; REPEAT1 not set
FilterStabilize_Every100ms_resetTimer:
  clr r16
  std Y+FILTER_STABILIZE_OFFS_TIMER, r16
FilterStabilize_Every100ms_clcRet:
  clc
  ret
FilterStabilize_Every100ms_secRet:
  sec
  ret
; @end


