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


.cseg



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

UART_HW_Interface_Init:
  rcall NET_Interface_Init                  ; (R16, R17, X)
  ldi r16, 0xff
  std Y+UART_HW_IFACE_OFFS_READBUFNUM, r16
  std Y+UART_HW_IFACE_OFFS_WRITEBUFNUM, r16
  ldi r16, UART_HW_READMODE_IDLE
  std Y+UART_HW_IFACE_OFFS_READMODE, r16
  ldi r16, UART_HW_WRITEMODE_IDLE
  std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine UART_HW_Interface_SetReadBuffer @global
;
; @param Y pointer to interface data in SRAM
; @param r16 read buffer number
; @param X   pointer to read buffer
; @clobbers R17

UART_HW_Interface_SetReadBuffer:
  std Y+UART_HW_IFACE_OFFS_READBUFNUM, r16
  adiw xh:xl, 1
  std Y+UART_HW_IFACE_OFFS_READBUFPOS_LOW, xl
  std Y+UART_HW_IFACE_OFFS_READBUFPOS_HIGH, xh
  sbiw xh:xl, 1
  clr r17
  std Y+UART_HW_IFACE_OFFS_READBUFUSED, r17
  ldi r17, NET_BUFFERS_SIZE-1
  std Y+UART_HW_IFACE_OFFS_READBUFLEFT, r17
  ret
; @end



; ---------------------------------------------------------------------------
; @routine UART_HW_Interface_SetWriteBuffer @global
;
; @param Y pointer to interface data in SRAM
; @param r16 write buffer number
; @param X   pointer to write buffer
; @clobbers r17

UART_HW_Interface_SetWriteBuffer:
  std Y+UART_HW_IFACE_OFFS_WRITEBUFNUM, r16
  adiw xh:xl, 1
  std Y+UART_HW_IFACE_OFFS_WRITEBUFPOS_LOW, xl   ; begin of msg (dest addr byte)
  std Y+UART_HW_IFACE_OFFS_WRITEBUFPOS_HIGH, xh
  adiw xh:xl, 1                                  
  ld r17, X                                      ; payload length byte
  sbiw xh:xl, 2                                  ; back to start of buffer
  inc r17
  inc r17
  inc r17
  std Y+UART_HW_IFACE_OFFS_WRITEBUFUSED, r17
  std Y+UART_HW_IFACE_OFFS_WRITEBUFLEFT, r17
  ret
; @end




; ---------------------------------------------------------------------------
; @routine UART_HW_Interface_EnsureReadBuffer
;
; @clobbers R16 (R17, R24, R25, X)

UART_HW_Interface_EnsureReadBuffer:
  ldd r16, Y+UART_HW_IFACE_OFFS_READBUFNUM
  cpi r16, 0xff
  breq UART_HW_Interface_EnsureReadBuffer_alloc
UART_HW_Interface_EnsureReadBuffer_secRet:
  sec
UART_HW_Interface_EnsureReadBuffer_ret:
  ret
UART_HW_Interface_EnsureReadBuffer_alloc:
  rcall NET_Buffer_Alloc                        ; (R16, R17, X)
  brcc UART_HW_Interface_EnsureReadBuffer_ret
  rcall UART_HW_Interface_SetReadBuffer         ; (R17)
  rcall NET_Interface_SetIfaceNumInBuffer       ; (R16, R17)
  rjmp UART_HW_Interface_EnsureReadBuffer_secRet
UART_HW_Interface_EnsureReadBuffer_noBuf:
  ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
  rcall NET_Interface_IncCounter16              ; (R24, R25)
  clc
  ret
; @end



; ---------------------------------------------------------------------------
; @routine UART_HW_Interface_HandleMsgReceived
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, X (R17, R18, R24, R25)

UART_HW_Interface_HandleMsgReceived:
  ; unset buffer
  ldi r17, 0xff
  ldd r16, Y+UART_HW_IFACE_OFFS_READBUFNUM
  std Y+UART_HW_IFACE_OFFS_READBUFNUM, r17
  cp r16, r17
  breq UART_HW_Interface_HandleMsgReceived_enterIdle        ; SNH!
  ; check checksum
  rcall NET_Buffer_Locate                        ; (R17)
  push r16
    adiw xh:xl, 1
    rcall NETMSG_CheckMessageInBuffer            ; (R16, R17, R18, R19, R20, X)
  pop r16
  brcs UART_HW_Interface_HandleMsgReceived_addMsg
  ; invalid msg
  rcall NET_Buffer_ReleaseByNum                  ; (R16, X)
  ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
  rjmp UART_HW_Interface_HandleMsgReceived_incCounterGoIdle
UART_HW_Interface_HandleMsgReceived_addMsg:
  rcall NET_AddIncomingMsgNum                    ; (R17, R18, X)
  brcs UART_HW_Interface_HandleMsgReceived_enterIdle
  ; could not add msg
  rcall NET_Buffer_ReleaseByNum                  ; (R16, X)
  ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
UART_HW_Interface_HandleMsgReceived_incCounterGoIdle:
  rcall NET_Interface_IncCounter16               ; (R24, R25)
UART_HW_Interface_HandleMsgReceived_enterIdle:
  ldi r17, UART_HW_READMODE_IDLE
  std Y+UART_HW_IFACE_OFFS_READMODE, r17         ; set read mode
  ret
; @end



