; *************************************************************************** ; 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. * ; *************************************************************************** #ifndef AVR_MODULES_COM2W_COMMON_H #define AVR_MODULES_COM2W_COMMON_H ; --------------------------------------------------------------------------- ; @routine com2wPeriodically @global ; ; @clobbers R16, Y com2wPeriodically: push r15 in r15, SREG cli rcall NET_Interface_Periodically ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER inc r16 breq com2wPeriodically_end std Y+COM2W_IFACE_OFFS_MODECOUNTER, r16 com2wPeriodically_end: out SREG, r15 pop r15 ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wSetMode ; ; Doesn't change processor status flags! ; ; @param R16 mode ; @clobbers R17 com2wSetMode: push r15 in r15, SREG cli ldd r17, Y+COM2W_IFACE_OFFS_MODE cp r16, r17 breq com2wSetMode_end std Y+COM2W_IFACE_OFFS_MODE, r16 clr r17 std Y+COM2W_IFACE_OFFS_MODECOUNTER, r17 com2wSetMode_end: out SREG, r15 pop r15 ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wStartReading ; ; @param Y pointer to interface data in SRAM ; @clobbers R16, R17, X com2wStartReading: mov xl, yl mov xh, yh adiw xh:xl, COM2W_IFACE_OFFS_BUFFER std Y+COM2W_IFACE_OFFS_BUFPOS_LOW, xl std Y+COM2W_IFACE_OFFS_BUFPOS_HIGH, xh ldi r16, COM2W_BUFFER_SIZE std Y+COM2W_IFACE_OFFS_BUFLEFT, r16 clr r16 std Y+COM2W_IFACE_OFFS_BUFUSED, r16 ldi r16, COM2W_MODE_READING rcall com2wSetMode ; (R17) ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wByteRecvd ; ; @param r16 byte received ; @param Y pointer to interface data ; @return CFLAG set if okay, cleared on error ; @clobbers r16, r17, r18, X com2wByteRecvd: ldd xl, Y+COM2W_IFACE_OFFS_BUFPOS_LOW ldd xh, Y+COM2W_IFACE_OFFS_BUFPOS_HIGH ldd r17, Y+COM2W_IFACE_OFFS_BUFLEFT ldd r18, Y+COM2W_IFACE_OFFS_BUFUSED tst r17 breq com2wByteRecvd_overflow st X+, r16 std Y+COM2W_IFACE_OFFS_BUFPOS_LOW, xl std Y+COM2W_IFACE_OFFS_BUFPOS_HIGH, xh inc r18 std Y+COM2W_IFACE_OFFS_BUFUSED, r18 dec r17 std Y+COM2W_IFACE_OFFS_BUFLEFT, r17 breq com2wByteRecvd_msgComplete cpi r18, 2 sec brne com2wByteRecvd_end ; determine msg size inc r16 ; last byte was payload length, add byte for crc cp r17, r16 ; compare remaining length against remaining space brcs com2wByteRecvd_eMsgSize std Y+COM2W_IFACE_OFFS_BUFLEFT, r16 tst r16 sec brne com2wByteRecvd_end com2wByteRecvd_msgComplete: push r19 ; pushing these registers is now only needed *here* for every push r20 ; message received. Otherwise they would have been pushed push r24 ; on every bit adding much more execution time to the push r25 ; irq service routine push zl push zh rcall com2wMsgReceived ; (R16, R17, R18, R19, R20, R24, R25, X, Z) pop zh pop zl pop r25 pop r24 pop r20 pop r19 rjmp com2wByteRecvd_end com2wByteRecvd_overflow: ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW rjmp com2wByteRecvd_error com2wByteRecvd_eMsgSize: ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW com2wByteRecvd_error: push r24 push r25 rcall NET_Interface_IncCounter16 ; (R24, R25) pop r25 pop r24 ldi r16, COM2W_MODE_SKIPPING ; error, enter skipping mode rcall com2wSetMode clc com2wByteRecvd_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wMsgReceived ; ; @param Y pointer to interface data in SRAM ; @return CFLAG set if okay, cleared on error ; @clobbers R16, R17, R18, X, Z (R19, R20, R24, R25) com2wMsgReceived: mov xl, yl mov xh, yh adiw xh:xl, COM2W_IFACE_OFFS_BUFFER mov zl, xl ; Z=buffer in IFACE mov zh, xh rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X) brcc com2wMsgReceived_econtent ; msg valid, alloc buffer rcall NET_Buffer_Alloc ; X=buffer, R16=bufnum (R16, R17, X) brcc com2wMsgReceived_enobuf mov r18, r16 ; buffer num rcall NET_Interface_SetIfaceNumInBuffer ; (R16, R17) adiw xh:xl, 1 ; skip buffer header ldd r17, Y+COM2W_IFACE_OFFS_BUFUSED ; always is at least 2 here com2wMsgReceived_copyLoop: ld r16, Z+ st X+, r16 dec r17 brne com2wMsgReceived_copyLoop mov r16, r18 ; buffer num rcall NET_AddIncomingMsgNum ; (R17, R18, X) brcc com2wMsgReceived_enoadd ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW rcall NET_Interface_IncCounter16 ; (R24, R25) sec rjmp com2wMsgReceived_setIdleAndEnd com2wMsgReceived_enoadd: rcall NET_Buffer_ReleaseByNum rjmp com2wMsgReceived_enobuf com2wMsgReceived_enobuf: ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW rjmp com2wMsgReceived_err com2wMsgReceived_econtent: ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW com2wMsgReceived_err: rcall NET_Interface_IncCounter16 ; (R24, R25) clc com2wMsgReceived_setIdleAndEnd: ldi r16, COM2W_MODE_IDLE rcall com2wSetMode ; (R17, doesn't change CFLAG!) com2wMsgReceived_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wWaitTime1 ; ; waits for longer period (e.g. 30ns) ; ; @clobbers R22 com2wWaitTime1: Utils_WaitNanoSecs COM2W_WAITTIME1, 7, r22 ; wait for longer time (minus RCALL and RET) ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wWaitTime2 ; ; waits for shorter period (e.g. 10ns) ; ; @clobbers R22 com2wWaitTime2: Utils_WaitNanoSecs COM2W_WAITTIME2, 7, r22 ; wait for shorter time (minus RCALL and RET) ret ; @end #endif ; AVR_MODULES_COM2W_COMMON_H