Files
aqhomecontrol/avr/modules/uart_bitbang2/iface.asm
2025-04-26 11:07:15 +02:00

277 lines
7.9 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 UART_BITBANG_IFACE_H
#define UART_BITBANG_IFACE_H
; ***************************************************************************
; includes
;.include "modules/uart_bitbang2/defs.asm"
;.include "modules/uart_bitbang2/lowlevel.asm"
;.include "modules/network/iface.asm"
; ***************************************************************************
; data
.dseg
uart_bitbang_iface: .byte NET_IFACE_SIZE
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine UART_BitBang_Init @global
;
; @return CFLAG set if okay, clear on error
; @clobbers R16, R17, X, Y
UART_BitBang_Init:
ldi yl, LOW(uart_bitbang_iface)
ldi yh, HIGH(uart_bitbang_iface)
rcall NET_Interface_Init ; (R16, R17, X)
; init hw
sbi COM_IRQ_ADDR_ATTN, COM_IRQ_BIT_ATTN ; enable pin change irq for ATTN line
in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
ori r16, (1<<COM_IRQ_GIMSK_ATTN)
out GIMSK, R16
ldi r16, (1<<COM_IRQ_GIFR_ATTN) ; clear pending irq by writing 1 to ATTN bit
out GIFR, r16
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_BitBang_Fini
;
; @return CFLAG set if okay, clear on error
; @clobbers R16, Y
UART_BitBang_Fini:
cbi COM_DATA_DDR, COM_DATA_PIN ; set TXD port as input
cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN port as input
cbi COM_IRQ_ADDR_ATTN, COM_IRQ_BIT_ATTN ; disable pin change irq for ATTN line
in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
andi r16, ~(1<<COM_IRQ_GIMSK_ATTN)
out GIMSK, R16
ldi r16, (1<<COM_IRQ_GIFR_ATTN) ; clear pending irq by writing 1 to ATTN bit
out GIFR, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_BitBang_Every100ms @global
;
; Routine doing periodical stuff (like sending outbound mesages)
;
; @param Y pointer to start of interface data
; @clobbers R16 (R17, R18, R21, R22, R24, R25, X)
UART_BitBang_Every100ms:
ldi yl, LOW(uart_bitbang_iface)
ldi yh, HIGH(uart_bitbang_iface)
push r15
in r15, SREG
cli
rcall NET_Interface_Periodically ; (R16)
rcall uartBitBang_sendNextPkg ; (R16, R17, R18, R21, R22, R24, R25, X)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine uartBitBang_sendNextPkg @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, R21, R22, R24, R25, X)
uartBitBang_sendNextPkg:
rcall NET_Interface_PeekNextOutgoingMsgNum ; (R17, R18, X)
brcc uartBitBang_sendNextPkg_end
rcall NET_Buffer_Locate ; get pointer to buffer (R17)
brcc uartBitBang_sendNextPkg_end
adiw xh:xl, 1 ; skip buffer header
rcall uartBitbang_SendPacket ; (R16, R17, R21, R22, X)
brcc uartBitBang_sendNextPkg_error
rcall NET_Interface_GetNextOutgoingMsgNum ; remove from stack (R17, R18, X)
rcall NET_Buffer_ReleaseByNum ; release buffer (R16, X)
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
sec
rjmp uartBitBang_sendNextPkg_end
uartBitBang_sendNextPkg_error:
rcall NET_Interface_IncCounter16 ; (R24, R25)
uartBitBang_sendNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine uartBitbang_receiveNextPkg
;
; Receive packet.
;
; @return CFLAG set if okay (packet received), cleared on error
; @clobbers R16, R17, X (R18, R19, R20, R21, R22, R24, R25)
uartBitbang_receiveNextPkg:
rcall NET_Buffer_Alloc ; (R16, R17, X)
brcs uartBitbang_receiveNextPkg_gotBuffer
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
clc
rjmp uartBitbang_receiveNextPkg_end
uartBitbang_receiveNextPkg_gotBuffer:
push r16 ; buffer number
adiw xh:xl, 1
rcall uartBitbang_receiveAndCheckPkg ; (r16, r17, r18, r19, r20, r21, r22, X)
pop r17 ; pop buffer number to R17
brcs uartBitbang_receiveNextPkg_gotPkg
tst r16 ; error code=0: pkg not for me
breq uartBitbang_receiveNextPkg_RelBuffer
uartBitbang_receiveNextPkg_incCntRelBuffer:
rcall NET_Interface_IncCounter16 ; (R24, R25)
uartBitbang_receiveNextPkg_RelBuffer:
mov r16, r17
rcall NET_Buffer_ReleaseByNum ; (R16, X)
clc
rjmp uartBitbang_receiveNextPkg_end
uartBitbang_receiveNextPkg_gotPkg:
mov r16, r17
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
brcc uartBitbang_receiveNextPkg_incCntRelBuffer
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
sec
uartBitbang_receiveNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine uartBitbang_receiveAndCheckPkg
;
; Receive a packet into buffer pointed to by X and CRC check it.
; Expects interrupts to be disabled.
;
; @param X buffer to receive to
; @param Y pointer to start of interface data
; @return CFLAG set if okay (packet received), cleared on error
; @return R16 error var offset if CFLAG is cleared
; @clobbers: r16 (r17, r18, r19, r20, r21, r22, X)
uartBitbang_receiveAndCheckPkg:
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
ldi r17, (NET_BUFFERS_SIZE-2)
push xl
push xh
rcall uartBitbang_ReceivePacketIntoBuffer ; (r16, r17, r18, r19, r20, r21, r22, X)
pop xh
pop xl
brcc uartBitbang_receiveAndCheckPkg_end
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
uartBitbang_receiveAndCheckPkg_end:
ret
; @end
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ISR
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; @routine UART_BitBang_PcintIsr @global @isr
;
; ISR for PCINT0/1
;
; @clobbers: none
UART_BitBang_PcintIsr:
push r15
in r15, SREG
sbic COM_ATTN_INPUT, COM_ATTN_PIN
rjmp uartBitbangPcintIsr_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(uart_bitbang_iface)
ldi yh, HIGH(uart_bitbang_iface)
rcall uartBitbang_receiveNextPkg ; (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
uartBitbangPcintIsr_end:
out SREG, r15
pop r15
reti
; @end
#endif ; UART_BITBANG_IFACE_H