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


.cseg


; ---------------------------------------------------------------------------
; @routine NET_Interface_Init @global
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, X

NET_Interface_Init:
  mov xl, yl
  mov xh, yh
  ldi r17, NET_IFACE_SIZE
  clr r16
  bigcall Utils_FillSram         ; (R17, X)
  push yl
    push yh
      adiw yh:yl, NET_IFACE_OFFS_OUTMSGRINGBUF
      ldi r16, NET_IFACE_OUTMSGBUF_SIZE
      rcall RingBufferY_Init
    pop yh
  pop yl

  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_GetNextMsgId @global
;
; @param  Y       pointer to interface data in SRAM
; @return r25:r24 next msg id
; @clobbers none

NET_Interface_GetNextMsgId:
  ldd r24, Y+NET_IFACE_OFFS_LASTMSGID_LOW
  ldd r25, Y+NET_IFACE_OFFS_LASTMSGID_HIGH
  adiw r25:r24, 1
  std Y+NET_IFACE_OFFS_LASTMSGID_LOW, r24
  std Y+NET_IFACE_OFFS_LASTMSGID_HIGH, r25
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_AddOutgoingMsgNum @global
;
; @return CFLAG on success, cleared on error
; @param r16 byte to write
; @param Y pointer to start of interface data
; @clobbers R17, R18, X

NET_Interface_AddOutgoingMsgNum:
  push yl
    push yh
      adiw yh:yl, NET_IFACE_OFFS_OUTMSGRINGBUF
      rcall RingBufferY_WriteByteGuarded             ; R17, R18, X
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_AddOrReleaseOutMsg @global
;
; Try to add given msg to the given interface's list of outbound messages,
; if that fails release the given message (@ref NET_Buffer_ReleaseByNum)
;
; @return CFLAG on success, cleared on error
; @param r16 byte to write
; @param Y pointer to start of interface data
; @clobbers R16, R17, R18, X

NET_Interface_AddOrReleaseOutMsg:
  rcall NET_Interface_AddOutgoingMsgNum     ; (R17, R18, X)
  brcs NET_Interface_AddOrReleaseOutMsg_ret
  rcall NET_Buffer_ReleaseByNum             ; (R16, X)
  clc
NET_Interface_AddOrReleaseOutMsg_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_GetNextOutgoingMsgNum @global
;
; @return CFLAG on success, cleared on error
; @return R16 byte read
; @param Y pointer to start of interface data
; @clobbers R17, R18, X

NET_Interface_GetNextOutgoingMsgNum:
  push yl
    push yh
      adiw yh:yl, NET_IFACE_OFFS_OUTMSGRINGBUF
      rcall RingBufferY_ReadByteGuarded              ; R17, R18, X
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_PeekNextOutgoingMsgNum @global
;
; @return CFLAG on success, cleared on error
; @return R16 byte read
; @param Y pointer to start of interface data
; @clobbers R17, R18, X

NET_Interface_PeekNextOutgoingMsgNum:
  push yl
    push yh
      adiw yh:yl, NET_IFACE_OFFS_OUTMSGRINGBUF
      rcall RingBufferY_PeekByteGuarded              ; R17, R18, X
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_GetNumOfOutgoingMsgNums @global
;
; @return CFLAG on success, cleared on error
; @return R16 byte read
; @param Y pointer to start of interface data
; @clobbers none

NET_Interface_GetNumOfOutgoingMsgNums:
  ldd r16, Y+(NET_IFACE_OFFS_OUTMSGRINGBUF+RINGBUFFERY_OFFS_USED)
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_IncCounter16 @global
;
; @param Y   pointer to start of interface data
; @param R16 offset to Y for counter to increment
; @clobbers R24, R25

NET_Interface_IncCounter16:
  add yl, r16
  adc yh, r16
  sub yh, r16
  ld r24, Y+
  ld r25, Y
  sbiw yh:yl, 1
  adiw r25:r24, 1
  breq NET_Interface_IncCounter16_end
  st Y+, r24
  st Y, r25
  sbiw yh:yl, 1
NET_Interface_IncCounter16_end:
  sub yl, r16
  sbc yh, r16
  add yh, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_SetIfaceNumInBuffer @global
;
; @param X   pointer to start of buffer
; @param Y   pointer to start of interface data
; @clobbers R16, R17

NET_Interface_SetIfaceNumInBuffer:
  ldd r16, Y+NET_IFACE_OFFS_IFACENUM
  andi r16, 0x0f
  ld r17, X
  andi r17, 0xf0
  or r17, r16
  st X, r17
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_Periodically @global
;
; @param Y   pointer to start of interface data
; @clobbers R16

NET_Interface_Periodically:
  push r15
    in r15, SREG
    cli
    ldd r16, Y+NET_IFACE_OFFS_READTIMER
    inc r16
    breq NET_Interface_Periodically_l1
    std Y+NET_IFACE_OFFS_READTIMER, r16
NET_Interface_Periodically_l1:
    ldd r16, Y+NET_IFACE_OFFS_WRITETIMER
    inc r16
    breq NET_Interface_Periodically_l2
    std Y+NET_IFACE_OFFS_WRITETIMER, r16
NET_Interface_Periodically_l2:
    out SREG, r15
  pop r15
  ret
; @end



; ---------------------------------------------------------------------------
; @routine NET_Interface_ResetStats @global
;
; @param Y   pointer to start of interface data
; @clobbers R16, R17, X

NET_Interface_ResetStats:
  push r15
    in r15, SREG
    cli
    clr r16
    std Y+NET_IFACE_OFFS_PACKETSIN_LOW, r16
    
    mov xl, yl
    mov xh, yh
    adiw xh:xl, NET_IFACE_OFFS_PACKETSIN_LOW
    ldi r17, ((NET_IFACE_OFFS_ERR_MISSED_HIGH+1)-NET_IFACE_OFFS_PACKETSIN_LOW)
    clr r16
    bigcall Utils_FillSram         ; (R17, X)
    out SREG, r15
  pop r15
  ret
; @end



#endif

