; ***************************************************************************
; copyright   : (C) 2023 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.   *
; ***************************************************************************




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

.cseg

COM_RECV_BEGIN:


; ---------------------------------------------------------------------------
; comReceivePacketHandleBuffer
;
; Allocate a buffer and receive a packet into it.
; On success the buffer flags will have COM_BUFFER_FLAGS_RECEIVED set.
; On error the buffer will be deallocated.
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, cleared otherwise
; MODIFIED REGISTERS: R16, R17, X, Y (R1, R18, R19, R20, R21, R22)

comReceivePacketHandleBuffer:
  rcall COM_BufferAlloc
  brcs comReceivePacketHandleBuffer_haveBuffer
  ldi xl, LOW(comStatsRecvNoBuffer)
  ldi xh, HIGH(comStatsRecvNoBuffer)
  rjmp comReceivePacketHandleBuffer_errorWithCounter

comReceivePacketHandleBuffer_haveBuffer:
  ; get pos of data portion for the allocated buffer
  mov xl, yl
  mov xh, yh
  adiw xh:xl, COM_BUFFER_OFFS_DATA
  rcall comReceivePacketToXandCheck             ; (r16, r17, r18, r20, r21, r22, X)
  brcs comReceivePacketHandleBuffer_haveMessage
  push r16
    rcall COM_BufferDeallocBack                 ; (r16, r17, r21)
  pop r16
  cpi r16, COM_ERR_NOTFORME                     ; packet just not for me?
  breq comReceivePacketHandleBuffer_notforme    ; correct, don't count as error
  ldi xl, LOW(comStatsRecvCrcErrs)
  ldi xh, HIGH(comStatsRecvCrcErrs)
  cpi r16, COM_ERR_CHECKSUM
  breq comReceivePacketHandleBuffer_errorWithCounter
  ldi xl, LOW(comStatsRecvErrs)                 ; generic error
  ldi xh, HIGH(comStatsRecvErrs)
  rjmp comReceivePacketHandleBuffer_errorWithCounter

comReceivePacketHandleBuffer_haveMessage:
  ; handle buffer flags
  ldi r16, COM_BUFFER_FLAGS_RECEIVED
  std y+COM_BUFFER_OFFS_FLAGS, r16
  ldi xl, LOW(comStatsPacketsIn)
  ldi xh, HIGH(comStatsPacketsIn)
  rcall Utils_IncrementCounter16                ; (r18, r19, 22)
  sec
  ret

comReceivePacketHandleBuffer_errorWithCounter:
  rcall Utils_IncrementCounter16                ; (r18, r19, 22)
comReceivePacketHandleBuffer_notforme:
  clc
  ret



; ---------------------------------------------------------------------------
; comReceivePacketToXandCheck
;
; Receive a packet to the given SRAM position.
; IN:
; - X: pointer to start of buffer to receive bytes
; OUT:
; - CFLAG: set if okay, clear otherwise
; - R16: error code if CFLAG cleared
; MODIFIED REGISTERS: r16, r17, r18, X (r19, r20, r21, r22)

comReceivePacketToXandCheck:
  push xh
    push xl
      rcall comReceivePacketToSram       ; (r16, r17, R20, R21, R22, X)
    pop xl
  pop xh
  brcc comReceivePacketToXandCheck_error
  rcall cproCheckMessageInBuffer         ; (R16, R17, R18, R19, R20, X)
  ldi r16, COM_ERR_CHECKSUM
  brcc comReceivePacketToXandCheck_error
  sec
  ret
comReceivePacketToXandCheck_error:
  clc
  ret



; ---------------------------------------------------------------------------
; comReceivePacketToSram
;
; Receive a packet to the given SRAM position.
; IN:
; - X: pointer to start of buffer to receive bytes
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r16, r17, X (R20, R21, R22)

comReceivePacketToSram:
  ; read destination address
  rcall comReceiveByte                         ; read byte (R16, R17, R20, R21, R22)
  brcc comReceivePacketToSram_error
  ; compare destination address (accept "00", "FF" and own address)
  tst r16
  breq comReceivePacketToSram_acceptAddr
  cpi r16, 0xff
  breq comReceivePacketToSram_acceptAddr
  lds r17, comAddress
  cp r16, r17
  breq comReceivePacketToSram_acceptAddr
  ldi r16, COM_ERR_NOTFORME
  clc                                          ; not for me
  ret
comReceivePacketToSram_acceptAddr:
  st X+, r16                                   ; store dest address
  ; read msg length
  rcall comReceiveByte                         ; read packet length (R16, R17, R20, R21, R22)
  brcc comReceivePacketToSram_error
  st X+, r16
  cpi r16, (COM_BUFFER_SIZE-3-COM_BUFFER_OFFS_DATA)+1
  brcc comReceivePacketToSram_error            ; packet too long (TODO: count overruns)
  inc r16                                      ; account for checksum byte
  mov r17, r16
comReceivePacketToSram_loop:
    push r17
      rcall comReceiveByte                     ; read byte (R16, R17, R20, R21, R22)
    pop r17
    brcc comReceivePacketToSram_error
    st X+, r16
    dec r17
  brne comReceivePacketToSram_loop
  sec
  ret
comReceivePacketToSram_error:
  ldi r16, COM_ERR_IO
  clc
  ret


COM_RECV_END:
.equ MODULE_SIZE_COM_RECV = COM_RECV_END-COM_RECV_BEGIN


