; *************************************************************************** ; 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. * ; *************************************************************************** ; *************************************************************************** ; code ; --------------------------------------------------------------------------- ; @routine uartBitbang_ReceiveAndCheckMsg ; ; Receive a packet into buffer pointed to by X. ; Expects interrupts to be disabled. ; ; @param R18 COM address to listen to ; @param R19 max buffer size ; @param X buffer to receive to ; @return CFLAG set if msg received, cleared on error ; @clobbers R16, R19 (R17, R20, R21, R22, R24, R25) uartBitbang_ReceiveAndCheckMsg: push xl push xh rcall uartBitbang_RawReceiveMsg ; (R16, R17, R19, R20, R21, R22, R24, R25, X) pop xh pop xl brcs uartBitbang_ReceiveAndCheckMsg_recvd ; fall-through, return with CF cleared (from uartBitbang_RawReceiveMsg) ret uartBitbang_ReceiveAndCheckMsg_recvd: push xl push xh rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X) pop xh pop xl brcs uartBitbang_ReceiveAndCheckMsg_msgOk ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) clc ret uartBitbang_ReceiveAndCheckMsg_msgOk: ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) sec ret ; @end ; --------------------------------------------------------------------------- ; @routine uartBitbang_RawReceiveMsg ; ; Receive a packet into buffer pointed to by X. ; Expects interrupts to be disabled. ; ; @param R18 COM address to listen to ; @param R19 max buffer size ; @param X buffer to receive to ; @return CFLAG set if msg received, cleared on error (see R16) ; @return R16 if CFLAG cleared: 0=message not for this node, otherwise error ; @clobbers R16, R19 (R17, R20, R21, R22, R24, R25, X) uartBitbang_RawReceiveMsg: cpi r19, 3 brcs uartBitbang_RawReceiveMsg_eBadSize ; read destination address rcall uartBitbang_ReceiveByte ; read byte (R16, R17, R20, R21, R22) brcc uartBitbang_RawReceiveMsg_eIo cp r16, r18 breq uartBitbang_RawReceiveMsg_forMe cpi r16, 0xff breq uartBitbang_RawReceiveMsg_forMe clr r16 ; not for me rjmp uartBitbang_RawReceiveMsg_clcRet uartBitbang_RawReceiveMsg_forMe: subi r19, 1 brcs uartBitbang_RawReceiveMsg_eBadSize st X+, r16 ; read size of msg payload (e.g. number of msg bytes following minus CRC byte) rcall uartBitbang_ReceiveByte ; read byte (R16, R17, R20, R21, R22) brcc uartBitbang_RawReceiveMsg_eIo subi r19, 1 brcs uartBitbang_RawReceiveMsg_eBadSize st X+, r16 ; store msg payload size inc r16 ; account for crc byte sub r19, r16 ; check msg size against remaining buffer size brcs uartBitbang_RawReceiveMsg_eBadSize mov r19, r16 uartBitbang_RawReceiveMsg_loop: rcall uartBitbang_ReceiveByte ; read byte (R16, R17, R20, R21, R22) brcc uartBitbang_RawReceiveMsg_eIo st X+, r16 ; store msg dec r19 brne uartBitbang_RawReceiveMsg_loop sec rjmp uartBitbang_RawReceiveMsg_end uartBitbang_RawReceiveMsg_eBadSize: ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW rjmp uartBitbang_RawReceiveMsg_incCounterRet uartBitbang_RawReceiveMsg_eIo: ldi r16, NET_IFACE_OFFS_ERR_IO_LOW uartBitbang_RawReceiveMsg_incCounterRet: rcall NET_Interface_IncCounter16 ; (R24, R25) uartBitbang_RawReceiveMsg_clcRet: clc uartBitbang_RawReceiveMsg_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine uartBitbang_SendMsg ; ; Send packet over wire, handle ATTN line. ; ; @param X ptr to buffer to send ; @return CFLAGS set if okay, cleared otherwise (index of error variable in R16) ; @return R16 index of error variable (if CFLAGS cleared) ; @clobbers R16 (R17, R21, R22, R24, R25, X) uartBitbang_SendMsg: rcall uartBitbang_AcquireBus brcc uartBitbang_SendMsg_lineBusyError rcall uartBitbang_WaitForOneBitLength ; wait for one bit duration (R22) rcall uartBitbang_WaitForOneBitLength ; wait for one bit duration (R22) rcall uartBitbang_RawSendMsg ; (R16, R17, R21, R22, R24, R25, X) cbi COM_ATTN_DDR, COM_ATTN_PIN ; release ATTN line (by setting direction to IN) ret uartBitbang_SendMsg_lineBusyError: ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) clc ret ; @end ; --------------------------------------------------------------------------- ; @routine uartBitbang_RawSendMsg ; ; Send packet over wire. ; ; @param X ptr to buffer to send ; @return CFLAGS set if okay, cleared otherwise (index of error variable in R16) ; @return R16 index of error variable (if CFLAGS cleared) ; @clobbers R16, R17 (R21, R22, R24, R25, X) uartBitbang_RawSendMsg: adiw xh:xl, NETMSG_OFFS_MSGLEN ld r17, X sbiw xh:xl, NETMSG_OFFS_MSGLEN inc r17 ; account for dest addr inc r17 ; account for msglen byte inc r17 ; account for crc byte uartBitbang_RawSendMsg_loop: rcall uartBitbang_WaitForOneBitLength ; wait for one bit duration (R22) ld r16, X+ rcall uartBitbang_SendByte ; send byte (R16, R21, R22) brcc uartBitbang_RawSendMsg_ioError dec r17 brne uartBitbang_RawSendMsg_loop ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) sec ret uartBitbang_RawSendMsg_ioError: ldi r16, NET_IFACE_OFFS_ERR_COLLISIONS_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) clc ret ; @end ; --------------------------------------------------------------------------- ; @routine uartBitbang_WaitForAttnHigh ; ; Wait up to 1ms for data pin to become high ; @return CFLAG set if okay, clear otherwise ; @clobbers R17, R22 uartBitbang_WaitForAttnHigh: cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN port as input cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable internal pullup for ATTN UART_BB_M_WAIT_FOR_PIN_HIGH COM_ATTN_INPUT, COM_ATTN_PIN ret ; @end ; --------------------------------------------------------------------------- ; @routine uartBitbang_AcquireBus ; ; Reserve bus if free (otherwise return error) ; Expects interrupts to be disabled. ; ; @return CFLAG set if okay (bus acquired), cleared on error ; @clobbers: none uartBitbang_AcquireBus: ; check for ATTN line: busy? cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN as input cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable pullup on ATTN nop ; needed to sample current input sbis COM_ATTN_INPUT, COM_ATTN_PIN ; ATTN low? rjmp uartBitbang_AcquireBus_busy ; jump if it is sbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN as output cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; set ATTN low sec ret uartBitbang_AcquireBus_busy: clc ret ; @end