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




; ---------------------------------------------------------------------------
; receive packet into buffer pointed to by X.
;
; IN:
; - R16: COM address to listen to
; - R17: maximum value for accepted msg data (i.e. buffersize minus 3)
; - X  : buffer to receive to
; OUT:
; - CFLAG: set if okay (packet received), cleared on error
; - R16: error code if CFLAG is cleared
; REGS: r16, r17, r18, X (r19, r20, r21, r22)
com2ReceivePacketRaw:
  mov r18, r17
  push r16
    ; read destination address
    rcall com2ReceiveByte                   ; read byte (R16, R17, R20, R21, R22)
  pop r17                                   ; pop from R16 to R17
  brcc com2ReceivePacketRaw_ioError
  ; compare destination address (accept "FF" and own address)
  cp r16, r17
  breq com2ReceivePacketRaw_acceptAddr
  cpi r16, 0xff
  breq com2ReceivePacketRaw_acceptAddr
  ldi r16, COM2_ERROR_NOTFORME
  clc                                    ; not for me
  ret
com2ReceivePacketRaw_acceptAddr:
  st X+, r16                             ; store dest address, lock buffer
  ; read msg length
  rcall com2ReceiveByte                  ; read packet length (R16, R17, R20, R21, R22)
  brcc com2ReceivePacketRaw_ioError
  st X+, r16
  cp r16, r18                            ; (COM2_BUFFER_SIZE-3)
  brcc com2ReceivePacketRaw_contentError ; packet too long
  inc r16                                ; account for checksum byte
  mov r17, r16
com2ReceivePacketRaw_loop:
    push r17
      rcall com2ReceiveByte              ; read byte (R16, R17, R20, R21, R22)
    pop r17
    brcc com2ReceivePacketRaw_ioError
    st X+, r16
    dec r17
  brne com2ReceivePacketRaw_loop
  sec
  ret
com2ReceivePacketRaw_ioError:
  ldi r16, COM2_ERROR_IOERROR
  rjmp com2ReceivePacketRaw_error
com2ReceivePacketRaw_contentError:
  ldi r16, COM2_ERROR_DATAERROR
com2ReceivePacketRaw_error:
  clc
  ret



; ---------------------------------------------------------------------------
; send packet over wire, handle ATTN line.
;
; IN:
; - x  : ptr to buffer to send
; OUT:
; - CFLAGS: set if okay, cleared otherwise (errorcode in R16)
; REGS: R16, R22 (R17, R21, X)

COM2_SendPacketWithAttn:
  push r15
    in r15, SREG
    cli
    Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22      ; wait for one bit duration
    ; check for ATTN line: busy?
    cbi COM_PORT_ATTN, COM_PINNUM_ATTN             ; disable pullup on ATTN
    cbi COM_DDR_ATTN, COM_PINNUM_ATTN              ; set ATTN as input
    nop                                            ; needed to sample current input
    sbis COM_PIN_ATTN, COM_PINNUM_ATTN             ; ATTN low?
      rjmp COM2_SendPacketWithAttn_lineBusyError   ; jump if it is
  
    cbi COM_PORT_ATTN, COM_PINNUM_ATTN             ; set ATTN low
    sbi COM_DDR_ATTN, COM_PINNUM_ATTN              ; set ATTN as output
    Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22      ; wait for one bit duration

    adiw xh:xl, COM2_MSG_OFFS_MSGLEN
    ld r16, X
    sbiw xh:xl, COM2_MSG_OFFS_MSGLEN
    inc r16                                        ; account for dest addr
    inc r16                                        ; account for msglen byte
    inc r16                                        ; account for crc byte
    rcall com2SendPacketRaw                        ; (r16, r17, r21, r22, X)
    
    cbi COM_DDR_ATTN, COM_PINNUM_ATTN              ; release ATTN line (by setting direction to IN)
    brcc COM2_SendPacketWithAttn_ioError
    ; packet successfully sent
    out SREG, r15
  pop r15
  sec
  ret

COM2_SendPacketWithAttn_ioError:
    ldi r16,COM2_ERROR_COLLISION
    rjmp COM2_SendPacketWithAttn_retNc

COM2_SendPacketWithAttn_lineBusyError:
    ldi r16,COM2_ERROR_BUSY
COM2_SendPacketWithAttn_retNc:
  pop r15
  out SREG, r15
  clc
  ret



; ---------------------------------------------------------------------------
; send packet over wire, expects ATTN to be low.
;
; IN:
; - r16: number of bytes to send
; - x  : ptr to buffer to send
; OUT:
; - nothing
; REGS: r16, r17, x (r21, r22)

com2SendPacketRaw:
  mov r17, r16
com2SendPacket_loop:
    ld r16, X+
    rcall com2SendByte                 ; send byte (R16, R21, R22)
    brcc com2SendPacket_ioError
    dec r17
  brne com2SendPacket_loop
  sec
  ret
com2SendPacket_ioError:
  clc
  ret



