; *************************************************************************** ; copyright : (C) 2024 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. * ; *************************************************************************** ; --------------------------------------------------------------------------- ; @routine uartBitbang_ReceivePacketIntoBuffer ; ; Receive a packet into buffer pointed to by X. ; Expects interrupts to be disabled. ; ; @param R16 COM address to listen to ; @param R17 maximum value for accepted msg data (i.e. buffersize minus 3) ; @param X buffer to receive to ; @return CFLAG set if okay (packet received), cleared on error ; @return R16 error code if CFLAG is cleared (COM2_ERROR_NOTFORME, COM2_ERROR_IOERROR, COM2_ERROR_DATAERROR) ; @clobbers: r16, r17, r18, X (r19, r20, r21, r22) uartBitbang_ReceivePacketIntoBuffer: mov r18, r17 push r16 ; read destination address rcall uartBitbang_ReceiveByte ; read byte (R16, R17, R20, R21, R22) pop r17 ; pop from R16 to R17 brcc uartBitbang_ReceivePacketIntoBuffer_ioError #ifndef COM_ACCEPT_ALL_DEST ; accept every destination address ; compare destination address (accept "FF" and own address) cp r16, r17 breq uartBitbang_ReceivePacketIntoBuffer_acceptAddr cpi r16, 0xff breq uartBitbang_ReceivePacketIntoBuffer_acceptAddr ldi r16, COM2_ERROR_NOTFORME rjmp uartBitbang_ReceivePacketIntoBuffer_error ; clc/ret #endif uartBitbang_ReceivePacketIntoBuffer_acceptAddr: st X+, r16 ; store dest address, lock buffer ; read msg length rcall uartBitbang_ReceiveByte ; read packet length (R16, R17, R20, R21, R22) brcc uartBitbang_ReceivePacketIntoBuffer_ioError st X+, r16 cp r16, r18 ; (COM2_BUFFER_SIZE-3) brcc uartBitbang_ReceivePacketIntoBuffer_contentError ; packet too long inc r16 ; account for checksum byte mov r17, r16 uartBitbang_ReceivePacketIntoBuffer_loop: push r17 rcall uartBitbang_ReceiveByte ; read byte (R16, R17, R20, R21, R22) pop r17 brcc uartBitbang_ReceivePacketIntoBuffer_ioError st X+, r16 dec r17 brne uartBitbang_ReceivePacketIntoBuffer_loop sec ret uartBitbang_ReceivePacketIntoBuffer_ioError: ldi r16, COM2_ERROR_IOERROR rjmp uartBitbang_ReceivePacketIntoBuffer_error uartBitbang_ReceivePacketIntoBuffer_contentError: ldi r16, COM2_ERROR_DATAERROR uartBitbang_ReceivePacketIntoBuffer_error: clc ret ; @end ; --------------------------------------------------------------------------- ; @routine uartBitbang_SendPacket ; ; Send packet over wire, handle ATTN line. ; ; @param X ptr to buffer to send ; @return CFLAGS set if okay, cleared otherwise (errorcode in R16) ; @clobbers R16, R22 (R17, R21, X) uartBitbang_SendPacket: rcall uartBitbang_AcquireBus brcc uartBitbang_SendPacket_lineBusyError rcall uartBitbang_WaitForOneBitLength ; wait for one bit duration (R22) rcall uartBitbang_WaitForOneBitLength ; wait for one bit duration (R22) adiw xh:xl, COM2_MSG_OFFS_MSGLEN ld r17, X sbiw xh:xl, COM2_MSG_OFFS_MSGLEN inc r17 ; account for dest addr inc r17 ; account for msglen byte inc r17 ; account for crc byte uartBitbang_SendPacket_loop: ld r16, X+ rcall uartBitbang_SendByte ; send byte (R16, R21, R22) brcc uartBitbang_SendPacket_releaseBusRet dec r17 brne uartBitbang_SendPacket_loop sec uartBitbang_SendPacket_releaseBusRet: cbi COM_ATTN_DDR, COM_ATTN_PIN ; release ATTN line (by setting direction to IN) brcc uartBitbang_SendPacket_ioError ; packet successfully sent ret uartBitbang_SendPacket_ioError: ldi r16,COM2_ERROR_COLLISION ret uartBitbang_SendPacket_lineBusyError: ldi r16,COM2_ERROR_BUSY 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 ; --------------------------------------------------------------------------- ; @routine uartBitbang_WaitForOneBitLength ; ; wait for one bit length (minus cycles for call and ret). ; ; @clobbers r22 uartBitbang_WaitForOneBitLength: Utils_WaitNanoSecs COM_BIT_LENGTH, 7, r22 ; wait for one bit duration (minus RCALL/RET) ret ; @end