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


.cseg


; ---------------------------------------------------------------------------
; @routine COM2W2_Init
;
; @clobbers 

COM2W2_Init:
  ldi yl, LOW(com2w2_iface)
  ldi yh, HIGH(com2w2_iface)
  rcall NET_Interface_Init                 ; (R16, R17, X)

  ; setup CLK line (as input, disable internal pull-up resistor)
  cbi COM_CLK_DDR, COM_CLK_PIN           ; set CLK as input
.ifdef COM_CLK_PUE
  inr r16, COM_CLK_PUE
  cbr r16, (1<<COM_CLK_PIN)               ; disable pullup on CLK
  outr COM_CLK_PUE, r16
.else
  cbi COM_CLK_OUTPUT, COM_CLK_PIN        ; disable pullup on CLK
.endif

  ; setup DATA line (as input, disable internal pull-up resistor)
  cbi COM_DATA_DDR, COM_DATA_PIN         ; set DATA as input
.ifdef COM_DATA_PUE
  inr r16, COM_DATA_PUE
  cbr r16, (1<<COM_DATA_PIN)              ; disable pullup on DATA
  outr COM_DATA_PUE, r16
.else
  cbi COM_DATA_OUTPUT, COM_DATA_PIN      ; disable pullup on DATA
.endif

.ifdef COM_SETUPIRQ_FN
  bigcall COM_SETUPIRQ_FN
.endif

  ; setup pin-change interrupt for CLK
  rcall com2w2EnableClkIrq

  ret
; @end



; ---------------------------------------------------------------------------
; @routine COM2W2_Every100ms @global
;
; @clobbers R16, Y

COM2W2_Every100ms:
  ldi yl, LOW(com2w2_iface)
  ldi yh, HIGH(com2w2_iface)
  push r15
    in r15, SREG
    cli
    rcall NET_Interface_Periodically         ; (R16)
    out SREG, r15
  pop r15
  ret
; @end



; ---------------------------------------------------------------------------
; @routine COM2W2_Run @global
;
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)

COM2W2_Run:
  push r15
    in r15, SREG
    cli
    ldi yl, LOW(com2w2_iface)
    ldi yh, HIGH(com2w2_iface)
    rcall com2w2SendNextPkg     ; (R16, R17, R18, R20, R22, R24, R25, X)
    brcs COM2W2_Run_ok
  pop r15
  clc
  rjmp COM2W2_Run_ret
COM2W2_Run_ok:
  pop r15
  sec
COM2W2_Run_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine com2w2ReceiveNextPkg
;
; Receive packet.
;
; @param Y pointer to start of interface data
; @clobbers R16, R17, R18, R19, R20, R22, R24, R25, X

com2w2ReceiveNextPkg:
  mov xl, yl
  mov xh, yh
  adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
  ldi r19, COM2W2_BUFFER_SIZE
  rcall com2w2RecvMsg                              ; (r16, r17, r18, r19, r20, r22, r24, r25, X)
  brcc com2w2ReceiveNextPkg_end
  
  mov xl, yl
  mov xh, yh
  adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
  rcall NETMSG_CheckMessageInBuffer               ; (R16, R17, R18, R19, R20, X)
  brcc com2w2ReceiveNextPkg_eCrc

#ifndef COM_ACCEPT_ALL_DEST
  ; check destination addr
  mov xl, yl
  mov xh, yh
  adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
  adiw xh:xl, NETMSG_OFFS_DESTADDR
  ld r16, X                                       ; read destination address
  cpi r16, 0xff
  breq com2w2ReceiveNextPkg_forMe
  ldd r17, Y+NET_IFACE_OFFS_ADDRESS
  cp r16, r17
  breq com2w2ReceiveNextPkg_forMe
  ; packet not for me, but correctly received, inc counter, but don't light LED
  ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
  rcall NET_Interface_IncCounter16                ; (R24, R25)
  rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_forMe:
#endif

  ; msg received, alloc buffer for it
  rcall NET_Buffer_Alloc                          ; R16=buffer num (R16, R17, X)
  brcs com2w2ReceiveNextPkg_gotBuffer
  ; out of memory
  ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
  rcall NET_Interface_IncCounter16                ; (R24, R25)
  rjmp com2w2ReceiveNextPkg_end

  ; copy received message into allocated buffer
com2w2ReceiveNextPkg_gotBuffer:
  mov r19, r16                               ; save buffer num
  rcall NET_Interface_SetIfaceNumInBuffer    ; (R16, R17)
  mov r16, r19                               ; restore buffer num
  push zl
    push zh
      mov zl, yl
      mov zh, yh
      adiw zh:zl, COM2W2_IFACE_OFFS_BUFFER    ; Z=SRC
      adiw xh:xl, 1                          ; X=DEST
      ldd r18, Z+NETMSG_OFFS_MSGLEN
      inc r18
      inc r18
      inc r18
com2w2ReceiveNextPkg_copyLoop:
        ld r17, Z+
        st X+, r17
        dec r18
      brne com2w2ReceiveNextPkg_copyLoop
    pop zh
  pop zl

  ; add to incoming msg pool
  rcall NET_AddIncomingMsgNum                     ; (R17, R18, X)
  brcc com2w2ReceiveNextPkg_eMissed
  ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
  rcall NET_Interface_IncCounter16                ; (R24, R25)
#ifdef LED1_NETWORK_ACTIVITY
  bigcall LED1_SetActivityTiming
#endif
  rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_eCrc:
  ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
  rcall NET_Interface_IncCounter16                ; (R24, R25)
  rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_eMissed:
  push r16
    ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
    rcall NET_Interface_IncCounter16              ; (R24, R25)
  pop r16
  ; fall-through to release buffer
com2w2ReceiveNextPkg_relBuffer:
  rcall NET_Buffer_ReleaseByNum                   ; (R16, X)
com2w2ReceiveNextPkg_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine com2w2SendNextPkg @global
;
; Check whether there is an outgoing message in interface data
; and send it if possible.
;
; @return CFLAG set if okay, clear on error
; @param Y pointer to start of interface data
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)

com2w2SendNextPkg:
  rcall NET_Interface_PeekNextOutgoingMsgNum ; (R17, R18, X)
  brcc com2w2SendNextPkg_end
  rcall NET_Buffer_Locate                    ; get pointer to buffer (R17)
  brcc com2w2SendNextPkg_end
  adiw xh:xl, 1                              ; skip buffer header
  rcall com2w2SendMsg                         ; (R16, R18, R20, R22, R24, R25, X)
  brcc com2w2SendNextPkg_end
  rcall NET_Interface_GetNextOutgoingMsgNum  ; remove from stack (R17, R18, X)
  rcall NET_Buffer_ReleaseByNum              ; release buffer (R16, X)
  sec
com2w2SendNextPkg_end:
  ret
; @end







#endif

