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



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

.equ COM2WR_BUFFERSIZE              = NET_BUFFERS_SIZE-1


.equ COM2WR_MODE_IDLE               = 0
.equ COM2WR_MODE_SKIPPING           = 1
.equ COM2WR_MODE_READING            = 2
.equ COM2WR_MODE_WRITING            = 3
.equ COM2WR_MODE_NUM                = 4


.equ COM2WR_IFACE_OFFS_BEGIN        = NET_IFACE_SIZE
.equ COM2WR_IFACE_OFFS_MODE         = COM2WR_IFACE_OFFS_BEGIN+0
.equ COM2WR_IFACE_OFFS_MODECOUNTER  = COM2WR_IFACE_OFFS_BEGIN+1
.equ COM2WR_IFACE_OFFS_CURRBYTE     = COM2WR_IFACE_OFFS_BEGIN+2
.equ COM2WR_IFACE_OFFS_BITCOUNTER   = COM2WR_IFACE_OFFS_BEGIN+3
.equ COM2WR_IFACE_OFFS_BUFPOS_LO    = COM2WR_IFACE_OFFS_BEGIN+4
.equ COM2WR_IFACE_OFFS_BUFPOS_HI    = COM2WR_IFACE_OFFS_BEGIN+5
.equ COM2WR_IFACE_OFFS_BUFUSED      = COM2WR_IFACE_OFFS_BEGIN+6
.equ COM2WR_IFACE_OFFS_BUFLEFT      = COM2WR_IFACE_OFFS_BEGIN+7
.equ COM2WR_IFACE_OFFS_BUFFER       = COM2WR_IFACE_OFFS_BEGIN+8

.equ COM2WR_IFACE_SIZE              = COM2WR_IFACE_OFFS_BUFFER+COM2WR_BUFFERSIZE



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

.cseg



; ---------------------------------------------------------------------------
; @routine COM2WR_Iface_StartReading
;
; @param Y pointer to interface data in SDRAM
; @clobbers r16, X

COM2WR_Iface_StartReading:
  rcall com2wrResetReadBuffer
  ldi r16, COM2WR_MODE_READING
  std Y+COM2WR_IFACE_OFFS_MODE, r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine COM2WR_Iface_StartSkipping
;
; @param Y pointer to interface data in SDRAM
; @clobbers r16, X

COM2WR_Iface_StartSkipping:
  ldi r16, COM2WR_MODE_SKIPPING
  std Y+COM2WR_IFACE_OFFS_MODE, r16
  rcall com2wrResetReadBuffer
  ret
; @end



; ---------------------------------------------------------------------------
; @routine COM2WR_Iface_RecvHandleBit
;
; @param Y pointer to interface data in SDRAM
; @param R18 current CLK bit
; @param R19 current DATA bit
; @clobbers

COM2WR_Iface_RecvHandleBit:
  ldd r16, Y+COM2WR_IFACE_OFFS_MODE
  cpi r16, COM2WR_MODE_READING
  breq COM2WR_Iface_RecvHandleBit_reading
  cpi r16, COM2WR_MODE_IDLE
  breq COM2WR_Iface_RecvHandleBit_idle
  rjmp COM2WR_Iface_RecvHandleBit_ret
COM2WR_Iface_RecvHandleBit_reading:
  tst r18                                  ; CLK now HIGH?
  breq COM2WR_Iface_RecvHandleBit_ret      ; nope, ignore
  ; TODO: read bit
  rjmp COM2WR_Iface_RecvHandleBit_ret
COM2WR_Iface_RecvHandleBit_idle:
  tst r18                                  ; CLK became LOW?
  brne COM2WR_Iface_RecvHandleBit_ret      ; nope, ignore
  rcall COM2WR_Iface_StartReading          ; (R16, X)
COM2WR_Iface_RecvHandleBit_ret:
  ret
; @end



com2wrRecvBit:
  ldd r16, Y+COM2WR_IFACE_OFFS_CURRBYTE
  lsr r19                                  ; databit to carryflag
  ror r16                                  ; carryflag to current byte
  std Y+COM2WR_IFACE_OFFS_CURRBYTE, r16
  ldd r17, Y+COM2WR_IFACE_OFFS_BITCOUNTER
  dec r17
  std Y+COM2WR_IFACE_OFFS_BITCOUNTER, r17
  brne com2wrRecvBit_ret
  ; byte complete, test counter for remaining bytes
  ldd r17, Y+COM2WR_IFACE_OFFS_BUFLEFT
  tst r17
  breq com2wrRecvBit_overrun
  dec r17
  std Y+COM2WR_IFACE_OFFS_BUFLEFT, r17
  ; store current byte
  ldd xl, Y+COM2WR_IFACE_OFFS_BUFPOS_LO
  ldd xh, Y+COM2WR_IFACE_OFFS_BUFPOS_HI
  st X+, r16
  std Y+COM2WR_IFACE_OFFS_BUFPOS_LO, xl
  std Y+COM2WR_IFACE_OFFS_BUFPOS_HI, xh
  ; increment byte counter, check for size, adjust remaining byte counter if msgsize received
  ldd r18, Y+COM2WR_IFACE_OFFS_BUFUSED
  inc r18
  std Y+COM2WR_IFACE_OFFS_BUFUSED, r18
  cpi r18, 2                               ; two bytes (DESTADDR, MSGLEN)?
  brne com2wrRecvBit_ret                   ; no, jmp
  inc r16                                  ; last recvd byte contains remaining msg size, add CRC byte
  std Y+COM2WR_IFACE_OFFS_BUFLEFT, r16     ; set remaining bytes counter (TODO: check size!)
  rjmp com2wrRecvBit_ret
com2wrRecvBit_overrun:
  ; TODO

com2wrRecvBit_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine com2wrResetReadBuffer
;
; @param Y pointer to interface data in SDRAM
; @clobbers r16, X

com2wrResetReadBuffer:
  ldi r16, 8
  std Y+COM2WR_IFACE_OFFS_BITCOUNTER, r16
  clr r16
  std Y+COM2WR_IFACE_OFFS_BUFUSED, r16
  std Y+COM2WR_IFACE_OFFS_MODECOUNTER, r16
  ldi xl, COM2WR_IFACE_OFFS_BUFFER
  clr xh
  add xl, yl
  adc xh, yh
  std Y+COM2WR_IFACE_OFFS_BUFPOS_LO, xl
  std Y+COM2WR_IFACE_OFFS_BUFPOS_HI, xh
  ldi r16, COM2WR_BUFFERSIZE
  std Y+COM2WR_IFACE_OFFS_BUFLEFT, r16
  ret
; @end



#endif ; AVR_MOD_COM2WROUTER_IFACE_ASM

