Files
aqhomecontrol/avr/modules/com2w2/main.asm
Martin Preuss db3f88f3af avr: added com2w2 (slightly improved version of com2w).
- move IRQ control to main code (only the main code knows exactly which
  combination of pins is used for com2)
- split one big module into multiple smaller files (easier to maintain)
2026-07-05 20:06:00 +02:00

235 lines
6.3 KiB
NASM

; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_MAIN_H
#define AVR_MODULES_COM2W2_MAIN_H
.cseg
; ---------------------------------------------------------------------------
; @routine COM2W2_Init
;
; @clobbers
COM2W2_Init:
ldi yl, LOW(com2w2_iface)
ldi yh, HIGH(com2w2_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
.ifdef COM_SETUPIRQ_FN
bigcall COM_SETUPIRQ_FN
.endif
; setup pin-change interrupt for CLK
rcall com2w2EnableClkIrq
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2W2_Every100ms @global
;
; @clobbers R16, Y
COM2W2_Every100ms:
ldi yl, LOW(com2w2_iface)
ldi yh, HIGH(com2w2_iface)
push r15
in r15, SREG
cli
rcall NET_Interface_Periodically ; (R16)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2W2_Run @global
;
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)
COM2W2_Run:
push r15
in r15, SREG
cli
ldi yl, LOW(com2w2_iface)
ldi yh, HIGH(com2w2_iface)
rcall com2w2SendNextPkg ; (R16, R17, R18, R20, R22, R24, R25, X)
brcs COM2W2_Run_ok
pop r15
clc
rjmp COM2W2_Run_ret
COM2W2_Run_ok:
pop r15
sec
COM2W2_Run_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2ReceiveNextPkg
;
; Receive packet.
;
; @param Y pointer to start of interface data
; @clobbers R16, R17, R18, R19, R20, R22, R24, R25, X
com2w2ReceiveNextPkg:
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
ldi r19, COM2W2_BUFFER_SIZE
rcall com2w2RecvMsg ; (r16, r17, r18, r19, r20, r22, r24, r25, X)
brcc com2w2ReceiveNextPkg_end
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
brcc com2w2ReceiveNextPkg_eCrc
#ifndef COM_ACCEPT_ALL_DEST
; check destination addr
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
adiw xh:xl, NETMSG_OFFS_DESTADDR
ld r16, X ; read destination address
cpi r16, 0xff
breq com2w2ReceiveNextPkg_forMe
ldd r17, Y+NET_IFACE_OFFS_ADDRESS
cp r16, r17
breq com2w2ReceiveNextPkg_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 com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_forMe:
#endif
; msg received, alloc buffer for it
rcall NET_Buffer_Alloc ; R16=buffer num (R16, R17, X)
brcs com2w2ReceiveNextPkg_gotBuffer
; out of memory
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2w2ReceiveNextPkg_end
; copy received message into allocated buffer
com2w2ReceiveNextPkg_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, COM2W2_IFACE_OFFS_BUFFER ; Z=SRC
adiw xh:xl, 1 ; X=DEST
ldd r18, Z+NETMSG_OFFS_MSGLEN
inc r18
inc r18
inc r18
com2w2ReceiveNextPkg_copyLoop:
ld r17, Z+
st X+, r17
dec r18
brne com2w2ReceiveNextPkg_copyLoop
pop zh
pop zl
; add to incoming msg pool
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
brcc com2w2ReceiveNextPkg_eMissed
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
#ifdef LED1_NETWORK_ACTIVITY
bigcall LED1_SetActivityTiming
#endif
rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_eCrc:
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_eMissed:
push r16
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
pop r16
; fall-through to release buffer
com2w2ReceiveNextPkg_relBuffer:
rcall NET_Buffer_ReleaseByNum ; (R16, X)
com2w2ReceiveNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2SendNextPkg @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)
com2w2SendNextPkg:
rcall NET_Interface_PeekNextOutgoingMsgNum ; (R17, R18, X)
brcc com2w2SendNextPkg_end
rcall NET_Buffer_Locate ; get pointer to buffer (R17)
brcc com2w2SendNextPkg_end
adiw xh:xl, 1 ; skip buffer header
rcall com2w2SendMsg ; (R16, R18, R20, R22, R24, R25, X)
brcc com2w2SendNextPkg_end
rcall NET_Interface_GetNextOutgoingMsgNum ; remove from stack (R17, R18, X)
rcall NET_Buffer_ReleaseByNum ; release buffer (R16, X)
sec
com2w2SendNextPkg_end:
ret
; @end
#endif