; ***************************************************************************
; 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_DEVICES_ALL_HANDLEVALUEMSG_ASM
#define AQH_AVR_DEVICES_ALL_HANDLEVALUEMSG_ASM


; table:
; Byte 0   : command
; Byte 1   : value
; Byte 2, 3: handler fn

; CF set: send ACK



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

.equ HANDLEVALUEMSG_OFFS_COMMAND    = 0
.equ HANDLEVALUEMSG_OFFS_VALUEID    = 1
.equ HANDLEVALUEMSG_OFFS_HANDLER_LO = 2
.equ HANDLEVALUEMSG_OFFS_HANDLER_HI = 3
.equ HANDLEVALUEMSG_SIZE            = 4



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

.cseg



; ---------------------------------------------------------------------------
; @routine Main_HandleValueMsg
;
; Finds a handler for the given message using a table.
; Input for the hander routine is the result of @ref NETMSG_ValueRead
; Output from the handler is CFLAG set if ACK should be send, in this case r23
; should contain the command code to use for the ACK message.
;
; @param Z byte address pointer to handler table (for LPM!)
; @param X pointer to msg
; @param Y argument for handler routine
; @return CFLAG set if msg handled, cleared otherwise
; @clobbers any

Main_HandleValueMsg:
  bigcall NETMSG_ValueRead
  push r22
    push r24
      push r25
        rcall mainFindEntryForValueMsg  ; CF set: Z=routine (r16, r22, r24, r25, Z)
      pop r25
    pop r24
  pop r22
  brcc Main_HandleValueMsg_ret          ; not found, jmp

  push xl
    push xh
      icall                             ; handler, in: y=arg out: CF=needAck, r23=command
    pop xh
  pop xl
  brcs Main_HandleValueMsg_sendAck
  sec
  rjmp Main_HandleValueMsg_ret
Main_HandleValueMsg_sendAck:
  push r23
    bigcall NETMSG_ValueRead
  pop r23
  push xl
    push xh
      bigcall Main_SendValueResponse        ; (R16, R17, R18, R19, R20, R21, R23, R24, R25, X, Y)
    pop xh
  pop xl
  sec
Main_HandleValueMsg_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine mainFindEntryForValueMsg
;
; @param Z byte address pointer to handler table (for LPM!)
; @param r17 value id
; @param r23 command
; @return CFLAG set if entry found
; @param r25:r24 word address pointer to handler routine
; @clobbers r16, r22, r24, r25, Z

mainFindEntryForValueMsg:
mainFindEntryForValueMsg_loop:
    lpm r16, Z+    ; command
    lpm r22, Z+    ; value id
    lpm r24, Z+    ; routine lo
    lpm r25, Z+    ; routine hi
    tst r24
    brne mainFindEntryForValueMsg_l0
    tst r25
    breq mainFindEntryForValueMsg_notFound
mainFindEntryForValueMsg_l0:
    tst r16                             ; command
    breq mainFindEntryForValueMsg_l1
    cp r16, r23
    brne mainFindEntryForValueMsg_next
mainFindEntryForValueMsg_l1:
    tst r22                             ; value id
    breq mainFindEntryForValueMsg_l2
    cp r22, r17
    brne mainFindEntryForValueMsg_next
mainFindEntryForValueMsg_l2:
    mov zl, r24
    mov zh, r25
    sec
    rjmp mainFindEntryForValueMsg_ret
mainFindEntryForValueMsg_next:
  rjmp mainFindEntryForValueMsg_loop
mainFindEntryForValueMsg_notFound:
  clc
mainFindEntryForValueMsg_ret:
  ret
; @end


#endif

