; ***************************************************************************
; 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 VALSCHED_OFFS_TIMER          = 0
.equ VALSCHED_OFFS_FLAGS          = 1
.equ VALSCHED_DATA_SIZE           = 2

.equ VALSCHED_FLAGS_VALUE_BIT     = 0
.equ VALSCHED_FLAGS_TOSEND_BIT    = 1
.equ VALSCHED_FLAGS_REPEAT_BIT    = 2
.equ VALSCHED_FLAGS_FIRSTLOOP_BIT = 3
.equ VALSCHED_FLAGS_REPEAT0_BIT   = 6
.equ VALSCHED_FLAGS_REPEAT1_BIT   = 7

.equ VALSCHED_REPORTTIME1      = 1   ; report after 100ms
.equ VALSCHED_REPORTTIME2      = 11  ; report after 1100ms
.equ VALSCHED_REPORTTIME3      = 22  ; report after 2200ms

.equ VALSCHED_INTERVAL         = 200 ; 20s interval



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

.cseg



; ---------------------------------------------------------------------------
; @routine ValueScheduler_Init @global
;
; @param Y  pointer to instance data

ValueScheduler_Init:
  clr r16
  std Y+VALSCHED_OFFS_FLAGS, r16
  dec r16
  std Y+VALSCHED_OFFS_TIMER, r16   ; init timer in hold state
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ValueScheduler_Fini @global
;
; @param Y  pointer to instance data

ValueScheduler_Fini:
  ldi r16, 0xff
  std Y+VALSCHED_OFFS_TIMER, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ValueScheduler_Every100ms @global
;
; @param Y  pointer to instance data
; @clobbers r16, r17

ValueScheduler_Every100ms:
  ldd r17, Y+VALSCHED_OFFS_FLAGS
  ldd r16, Y+VALSCHED_OFFS_TIMER
  inc r16
  breq ValueScheduler_Every100ms_end             ; timer on hold
  std Y+VALSCHED_OFFS_TIMER, r16
  ; check first report time
  cpi r16, VALSCHED_REPORTTIME1
  breq ValueScheduler_Every100ms_setSendFlag
  sbrs r17, VALSCHED_FLAGS_FIRSTLOOP_BIT
    rjmp ValueScheduler_Every100ms_checkInterval ; jump if not first round
  ; check second report time
  cpi r16, VALSCHED_REPORTTIME2
  breq ValueScheduler_Every100ms_setSendFlag
  ; only check next report time for "1" values
  sbrs r17, VALSCHED_FLAGS_VALUE_BIT
    rjmp ValueScheduler_Every100ms_checkInterval ; jump if value is 0 (only repeat once for value 0)
  ; check third report time
  cpi r16, VALSCHED_REPORTTIME3
  breq ValueScheduler_Every100ms_setSendFlag
ValueScheduler_Every100ms_checkInterval:
  cpi r16, VALSCHED_INTERVAL
  brcs ValueScheduler_Every100ms_end
  ; interval finished, check for repeat
  ldd r17, Y+VALSCHED_OFFS_FLAGS
  cbr r17, (1<<VALSCHED_FLAGS_FIRSTLOOP_BIT) ; not first loop
  std Y+VALSCHED_OFFS_FLAGS, r17
  clr r16
  sbrs r17, VALSCHED_FLAGS_REPEAT_BIT
    dec r16                           ; bit not set, stop counter after this interval
  std Y+VALSCHED_OFFS_TIMER, r16
  rjmp ValueScheduler_Every100ms_end
ValueScheduler_Every100ms_setSendFlag:
  ldd r16, Y+VALSCHED_OFFS_FLAGS
  sbr r16, (1<<VALSCHED_FLAGS_TOSEND_BIT)
  std Y+VALSCHED_OFFS_FLAGS, r16
ValueScheduler_Every100ms_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ValueScheduler_CheckSend @global
;
; Check whether the value should be sent.
;
; @param Y  pointer to instance data
; @return CFLAG set if value should be sent, cleared otherwise
; @clobbers r16

ValueScheduler_CheckSend:
  ldd r16, Y+VALSCHED_OFFS_FLAGS
  sec
  sbrs r16, VALSCHED_FLAGS_TOSEND_BIT
    clc
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ValueScheduler_MarkSent @global
;
; Tells this module that a value message has been sent.
;
; @param Y  pointer to instance data
; @clobbers r16

ValueScheduler_MarkSent:
  ldd r16, Y+VALSCHED_OFFS_FLAGS
  cbr r16, (1<<VALSCHED_FLAGS_TOSEND_BIT)
  std Y+VALSCHED_OFFS_FLAGS, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ValueScheduler_SetValue @global
;
; Reduces value to 1 bit.
;
; @param Y  pointer to instance data
; @param r16 value
; @clobbers r17

ValueScheduler_SetValue:
  clr r17
  tst r16
  breq ValueScheduler_SetValue_reduced
  inc r17
ValueScheduler_SetValue_reduced:
  rcall ValueScheduler_GetValue                ; R16=current value (none)
  cp r17, r16
  breq ValueScheduler_SetValue_end
  ; value changed
  tst r17
  breq ValueScheduler_SetValue_set0
  ; set 1
  ldd r17, Y+VALSCHED_OFFS_FLAGS
  sbr r17, (1<<VALSCHED_FLAGS_FIRSTLOOP_BIT)  ; mark first loop

  sbr r17, (1<<VALSCHED_FLAGS_REPEAT_BIT)     ; set repeat bit
  sbrs r17, VALSCHED_FLAGS_REPEAT1_BIT
    cbr r17, (1<<VALSCHED_FLAGS_REPEAT_BIT)   ; clear repeat bit if not wanted for "1"
  sbr r17, (1<<VALSCHED_FLAGS_VALUE_BIT)      ; 1: set value bit
  std Y+VALSCHED_OFFS_FLAGS, r17              ; store new byte
  rjmp ValueScheduler_SetValue_resetTimer
ValueScheduler_SetValue_set0:
  ldd r17, Y+VALSCHED_OFFS_FLAGS
  sbr r17, (1<<VALSCHED_FLAGS_FIRSTLOOP_BIT)  ; mark first loop
  sbr r17, (1<<VALSCHED_FLAGS_REPEAT_BIT)
  sbrs r17, VALSCHED_FLAGS_REPEAT0_BIT
    cbr r17, (1<<VALSCHED_FLAGS_REPEAT_BIT)   ; clear repeat bit if not wanted for "0"
  cbr r17, (1<<VALSCHED_FLAGS_VALUE_BIT)      ; 0: clear value bit
  std Y+VALSCHED_OFFS_FLAGS, r17              ; store new byte
ValueScheduler_SetValue_resetTimer:
  clr r17                                     ; reset timer
  std Y+VALSCHED_OFFS_TIMER, r17
;  ldd r16, Y+VALSCHED_OFFS_FLAGS              ; reset TOSEND flag
;  cbr r16, (1<<VALSCHED_FLAGS_TOSEND_BIT)
;  std Y+VALSCHED_OFFS_FLAGS, r16
ValueScheduler_SetValue_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine ValueScheduler_GetValue @global
;
; Return current value (reduced to 1 bit).
;
; @param Y  pointer to instance data
; @return R16 value (reduced to 1 bit!)
; @clobbers none

ValueScheduler_GetValue:
  ldd r16, Y+VALSCHED_OFFS_FLAGS
  andi r16, 1                       ; CAVE: assumes data bit is bit0!!
  ret
; @end








