Files
aqhomecontrol/avr/modules/com2w/com2w.asm

790 lines
23 KiB
NASM

; ***************************************************************************
; 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_COM2W_H
#define AVR_MODULES_COM2W_COM2W_H
; only currently working com2w module!
.macro M_COM2WCLKSETLOW
sbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as output
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; set CLK low
.endmacro
.macro M_COM2WCLKSETHIGH
cbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as input
.ifndef COM_CLK_PUE
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; disable pullup on CLK
.endif
.endmacro
.macro M_COM2WDATASETLOW
sbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as output
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; set DATA low
.endmacro
.macro M_COM2WDATASETHIGH
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as input
.ifndef COM_DATA_PUE
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable pullup on DATA
.endif
.endmacro
.dseg
com2w_iface: .byte COM2W_IFACE_SIZE
.cseg
; ---------------------------------------------------------------------------
; @routine COM2W_Init
;
; @clobbers
COM2W_Init:
ldi yl, LOW(com2w_iface)
ldi yh, HIGH(com2w_iface)
rcall NET_Interface_Init ; (R16, R17, X)
; setup CLK line (as input, disable internal pull-up resistor)
cbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as input
.ifdef COM_CLK_PUE
inr r16, COM_CLK_PUE
cbr r16, (1<<COM_CLK_PIN) ; disable pullup on CLK
outr COM_CLK_PUE, r16
.else
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; disable pullup on CLK
.endif
; setup DATA line (as input, disable internal pull-up resistor)
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as input
.ifdef COM_DATA_PUE
inr r16, COM_DATA_PUE
cbr r16, (1<<COM_DATA_PIN) ; disable pullup on DATA
outr COM_DATA_PUE, r16
.else
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable pullup on DATA
.endif
; setup pin-change interrupt for CLK
rcall com2wEnableClkIrq
inr r16, COM_IRQ_ADDR_CLK
sbr r16, (1<<COM_IRQ_BIT_CLK) ; enable pin change irq for ATTN line
outr COM_IRQ_ADDR_CLK, r16
inr r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
sbr r16, (1<<COM_IRQ_GIMSK_CLK)
outr GIMSK, r16
ldi r16, (1<<COM_IRQ_GIFR_CLK) ; clear pending irq by writing 1 to ATTN bit
outr GIFR, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2W_Every100ms @global
;
; @clobbers R16, Y
COM2W_Every100ms:
ldi yl, LOW(com2w_iface)
ldi yh, HIGH(com2w_iface)
push r15
in r15, SREG
cli
rcall NET_Interface_Periodically ; (R16)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2W_Run @global
;
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)
COM2W_Run:
push r15
in r15, SREG
cli
ldi yl, LOW(com2w_iface)
ldi yh, HIGH(com2w_iface)
rcall com2wSendNextPkg ; (R16, R17, R18, R20, R22, R24, R25, X)
brcs COM2W_Run_ok
pop r15
clc
rjmp COM2W_Run_ret
COM2W_Run_ok:
pop r15
sec
COM2W_Run_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wReceiveNextPkg
;
; Receive packet.
;
; @param Y pointer to start of interface data
; @clobbers R16, R17, R18, R19, R20, R22, R24, R25, X
com2wReceiveNextPkg:
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
ldi r19, COM2W_BUFFER_SIZE
rcall com2wRecvMsg ; (r16, r17, r18, r19, r20, r22, r24, r25, X)
brcc com2wReceiveNextPkg_end
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
brcc com2wReceiveNextPkg_eCrc
#ifndef COM_ACCEPT_ALL_DEST
; check destination addr
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
adiw xh:xl, NETMSG_OFFS_DESTADDR
ld r16, X ; read destination address
cpi r16, 0xff
breq com2wReceiveNextPkg_forMe
ldd r17, Y+NET_IFACE_OFFS_ADDRESS
cp r16, r17
breq com2wReceiveNextPkg_forMe
; packet not for me, but correctly received, inc counter, but don't light LED
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wReceiveNextPkg_end
com2wReceiveNextPkg_forMe:
#endif
; msg received, alloc buffer for it
rcall NET_Buffer_Alloc ; R16=buffer num (R16, R17, X)
brcs com2wReceiveNextPkg_gotBuffer
; out of memory
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wReceiveNextPkg_end
; copy received message into allocated buffer
com2wReceiveNextPkg_gotBuffer:
mov r19, r16 ; save buffer num
rcall NET_Interface_SetIfaceNumInBuffer ; (R16, R17)
mov r16, r19 ; restore buffer num
push zl
push zh
mov zl, yl
mov zh, yh
adiw zh:zl, COM2W_IFACE_OFFS_BUFFER ; Z=SRC
adiw xh:xl, 1 ; X=DEST
ldd r18, Z+NETMSG_OFFS_MSGLEN
inc r18
inc r18
inc r18
com2wReceiveNextPkg_copyLoop:
ld r17, Z+
st X+, r17
dec r18
brne com2wReceiveNextPkg_copyLoop
pop zh
pop zl
; add to incoming msg pool
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
brcc com2wReceiveNextPkg_eMissed
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
#ifdef MODULES_LED_ACTIVITY
rcall LedActivity_Trigger ; (r16)
#endif
rjmp com2wReceiveNextPkg_end
com2wReceiveNextPkg_eCrc:
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wReceiveNextPkg_end
com2wReceiveNextPkg_eMissed:
push r16
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
pop r16
; fall-through to release buffer
com2wReceiveNextPkg_relBuffer:
rcall NET_Buffer_ReleaseByNum ; (R16, X)
com2wReceiveNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wSendNextPkg @global
;
; Check whether there is an outgoing message in interface data
; and send it if possible.
;
; @return CFLAG set if okay, clear on error
; @param Y pointer to start of interface data
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)
com2wSendNextPkg:
rcall NET_Interface_PeekNextOutgoingMsgNum ; (R17, R18, X)
brcc com2wSendNextPkg_end
rcall NET_Buffer_Locate ; get pointer to buffer (R17)
brcc com2wSendNextPkg_end
adiw xh:xl, 1 ; skip buffer header
rcall com2wSendMsg ; (R16, R18, R20, R22, R24, R25, X)
brcc com2wSendNextPkg_end
rcall NET_Interface_GetNextOutgoingMsgNum ; remove from stack (R17, R18, X)
rcall NET_Buffer_ReleaseByNum ; release buffer (R16, X)
sec
com2wSendNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wSendMsg
;
; @param X pointer to bytes to send
; @param Y pointer to interface data in SRAM
; @return CFLAG set if message sent, cleared otherwise
; @clobbers R16, R18 (R20, R22, R24, R25, X)
com2wSendMsg:
ldi r20, 6 ; wait for about 60us for clock low
rcall com2wWaitForClockLowMulti10Us ; (R16, R20, R22)
brcs com2wSendMsg_busy ; CLK got low while waiting, so line is busy
push r15
in r15, SREG
cli ; atomic disable irq and set CLK low
rcall com2wDisableClkIrq ; (none)
rcall com2wClkSetLow ; reserve bus (none)
out SREG, r15
pop r15
adiw xh:xl, NETMSG_OFFS_MSGLEN
ld r18, X
sbiw xh:xl, NETMSG_OFFS_MSGLEN
inc r18 ; adjust for DESTADDR
inc r18 ; adjust for MSGLEN
inc r18 ; adjust for CRCBYTE
rcall com2wWaitTime1 ; longer wait period (R22)
rcall com2wSendBytes ; (r16, r17, r18, r22, X)
rcall com2wClkSetHigh ; make sure bus is released
rcall com2wDataSetHigh
rcall com2wEnableClkIrq ; (none)
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
sec
ret
com2wSendMsg_busy:
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wSendBytes
;
; @param R18 number of bytes to send
; @param X pointer to bytes to send
; @param Y pointer to interface data in SRAM
; @clobbers: r16, r18, X (r17, r22)
com2wSendBytes:
com2wSendBytes_loop:
rcall com2wClkSetLow ; (none)
rcall com2wWaitTime1 ; longer wait period (R22)
ld r16, X+
rcall com2wSendByte ; (R16, R17, R22)
dec r18
brne com2wSendBytes_loop
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wSendByte
;
; @param R16 byte to send
; @clobbers: r16, r17 (r22)
com2wSendByte:
push r15
in r15, SREG
ldi r17, 8
com2wSendByte_loop:
M_COM2WCLKSETLOW
out SREG, r15 ; probably enable irqs
rcall com2wWaitTime1 ; wait for longer time (R22)
lsr r16
brcs com2wSendByte_send1
M_COM2WDATASETLOW
rjmp com2wSendByte_sent
com2wSendByte_send1:
M_COM2WDATASETHIGH
com2wSendByte_sent:
Utils_WaitNanoSecs 5000, 0, r22 ; wait for very short time to ensure data is stable when clock rises
cli ; ensure time period by disabling irqs
M_COM2WCLKSETHIGH
rcall com2wWaitTime2 ; wait for shorter time (R22)
dec r17
brne com2wSendByte_loop
out SREG, r15
pop r15
rcall com2wWaitTime2 ; wait for shorter time (R22)
M_COM2WDATASETHIGH ; ensure data line is high
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wRecvMsg
;
; Receive a packet into buffer pointed to by X.
; Expects interrupts to be disabled.
;
; @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, r17, r18, r19, r20, r22, r24, r25, X
com2wRecvMsg:
; check buffer size
subi r19, 2
brcs com2wRecvMsg_eBadSize
; read destination address
rcall com2wRecvByte ; (r17, r18, r20, r22)
brcc com2wRecvMsg_eIo
st X+, r16
; read remaining msg size
rcall com2wRecvByte ; (r17, r18, r20, r22)
brcc com2wRecvMsg_eIo
st X+, r16
inc r16 ; account for CRC byte
sub r19, r16
brcs com2wRecvMsg_eBadSize
mov r19, r16
com2wRecvMsg_loop:
rcall com2wRecvByte ; (r17, r18, r20, r22)
brcc com2wRecvMsg_eIo
st X+, r16
dec r19
brne com2wRecvMsg_loop
sec
rjmp com2wRecvMsg_end
com2wRecvMsg_eBadSize:
ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW
rjmp com2wRecvMsg_incCounterRet
com2wRecvMsg_eIo:
ldi r16, NET_IFACE_OFFS_ERR_IO_LOW
com2wRecvMsg_incCounterRet:
rcall NET_Interface_IncCounter16 ; (R24, R25)
rcall com2wRecvByteWaitForQuietClk ; (r18, r20, r22)
com2wRecvMsg_clcRet:
clc
com2wRecvMsg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wRecvByteWaitForQuietClk
;
; Wait until the clock line is consistently high for 1ms.
;
; @clobbers r18, r20, r22
com2wRecvByteWaitForQuietClk:
ldi r18, 200
com2wRecvByteWaitForQuietClk_loop:
ldi r20, 100 ; wait up to 1ms for clock high (R20, R22)
rcall com2wWaitForClockLowMulti10Us
brcs com2wRecvByteWaitForQuietClk_waitForLow
dec r18
brne com2wRecvByteWaitForQuietClk_loop
rjmp com2wRecvByteWaitForQuietClk_ret
com2wRecvByteWaitForQuietClk_waitForLow:
ldi r20, 100 ; wait up to 1ms for clock low (R20, R22)
rcall com2wWaitForClockLowMulti10Us
brcc com2wRecvByteWaitForQuietClk_ret ; not low within 1ms, assume line is quiet
brne com2wRecvByteWaitForQuietClk_loop
com2wRecvByteWaitForQuietClk_ret:
ret
; ---------------------------------------------------------------------------
; @routine com2wRecvByte
;
; @return CFLAG set if byte received, cleared on error
; @return r16 byte received
; @clobbers r17, r18, r20, r22
com2wRecvByte:
ldi r17, 8
clr r16
com2wRecvByte_loop:
ldi r20, 100 ; wait up to 1ms for clock low
rcall com2wWaitForClockLowMulti10Us ; (R20, R22)
brcc com2wRecvByte_end
ldi r20, 100 ; wait up to 1ms for clock high
rcall com2wWaitForClockHighMulti10Us ; (R20, R22)
brcc com2wRecvByte_end
; handle received bit
inr r18, COM_DATA_INPUT
andi r18, (1<<COM_DATA_PIN)
clc
breq com2wRecvByte_clockData
sec
com2wRecvByte_clockData:
ror r16
dec r17
brne com2wRecvByte_loop
sec
com2wRecvByte_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wEnableClkIrq
;
; @clobbers
com2wEnableClkIrq:
push r16
inr r16, COM_IRQ_ADDR_CLK
sbr r16, (1<<COM_IRQ_BIT_CLK) ; enable pin change irq for CLK line
outr COM_IRQ_ADDR_CLK, r16
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wDisableClkIrq
;
; @clobbers none
com2wDisableClkIrq:
push r16
inr r16, COM_IRQ_ADDR_CLK
cbr r16, (1<<COM_IRQ_BIT_CLK) ; disable pin change irq for CLK line
outr COM_IRQ_ADDR_CLK, r16
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wClkSetHigh
;
; @clobbers none
com2wClkSetHigh:
cbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as input
.ifdef COM_CLK_PUE
; cbi COM_CLK_PUE, COM_CLK_PIN ; disable pullup on CLK
.else
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; disable pullup on CLK
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wClkSetLow
;
; @clobbers none
com2wClkSetLow:
sbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as output
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; set CLK low
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wDataSetHigh
;
; @clobbers none
com2wDataSetHigh:
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as input
.ifdef COM_DATA_PUE
; cbi COM_DATA_PUE, COM_CLK_PIN ; disable pullup on DATA
.else
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable pullup on DATA
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wDataSetLow
;
; @clobbers none
com2wDataSetLow:
sbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as output
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; set DATA low
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wWaitForClockHighMulti10Us
;
; Wait for high CLK
;
; @param R20 multiple of 10us to wait (e.g. "2" for "20" us)
; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r20, r22
com2wWaitForClockHighMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
ldi r22, clock/1000000
com2wWaitForClockHighMulti10Us_loop0:
push r20
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20
dec r22 ; +1
brne com2wWaitForClockHighMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
clc ; +1
ret ; +4
com2wWaitForClockHighMulti10Us_stateReached:
pop r20
sec ; +1
ret ; +4
; end version for > 1000000 Hz
.elif clock < 1000000
.error "Clock speed too low"
.else
; begin version for 1000000 Hz
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
clc ; +1
ret ; +4
com2wWaitForClockHighMulti10Us_stateReached:
sec ; +1
ret ; +4
; end version for 1000000 Hz
.endif
; @end
; ---------------------------------------------------------------------------
; @routine com2wWaitForClockLowMulti10Us
;
; Wait for low CLK
;
; @param R20 multiple of 10us to wait (e.g. "2" for "20" us)
; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r20, r22
com2wWaitForClockLowMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
ldi r22, clock/1000000
com2wWaitForClockLowMulti10Us_loop0:
push r20
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20
dec r22 ; +1
brne com2wWaitForClockLowMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
clc ; +1
ret ; +4
com2wWaitForClockLowMulti10Us_stateReached:
pop r20
sec ; +1
ret ; +4
; end version for > 1000000 Hz
.elif clock < 1000000
.error "Clock speed too low"
.else
; begin version for 1000000 Hz
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
clc ; +1
ret ; +4
com2wWaitForClockLowMulti10Us_stateReached:
sec ; +1
ret ; +4
; end version for 1000000 Hz
.endif
; @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
; ---------------------------------------------------------------------------
; @routine com2wPcintIsr @global @isr
;
; ISR for PCINT0/1
;
; @clobbers: none
com2wPcintIsr:
push r15
in r15, SREG
sbic COM_CLK_INPUT, COM_CLK_PIN
rjmp com2wPcintIsr_end
; low, read packet
push r16
push r17
push r18
push r19
push r20
push r21
push r22
push r24
push r25
push xl
push xh
push yl
push yh
ldi yl, LOW(com2w_iface)
ldi yh, HIGH(com2w_iface)
rcall com2wReceiveNextPkg ; (R16, R17, R18, R19, R20, R21, R22, R24, R25, X)
pop yh
pop yl
pop xh
pop xl
pop r25
pop r24
pop r22
pop r21
pop r20
pop r19
pop r18
pop r17
pop r16
com2wPcintIsr_end:
out SREG, r15
pop r15
reti
; @end
#endif ; AVR_MODULES_COM2W_COM2W_H