Files
aqhomecontrol/avr/modules/uart_bitbang2/iface.asm
2025-05-31 14:20:05 +02:00

243 lines
6.8 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
cbi COM_DATA_DDR, COM_DATA_PIN ; set TXD port as input
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable internal pullup for DATA
cbi COM_ATTN_DDR, COM_ATTN_PIN ; set ATTN port as input
cbi COM_ATTN_OUTPUT, COM_ATTN_PIN ; disable internal pullup for ATTN
; enable IRQ
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_SendMsg ; (R16, R17, R21, R22, R24, R25, X)
brcc uartBitBang_sendNextPkg_end
rcall NET_Interface_GetNextOutgoingMsgNum ; remove from stack (R17, R18, X)
rcall NET_Buffer_ReleaseByNum ; release buffer (R16, X)
sec
rjmp uartBitBang_sendNextPkg_end
uartBitBang_sendNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine uartBitbang_receiveNextPkg
;
; Receive packet.
;
; @param Y pointer to start of interface data
; @clobbers R16, R17, R18, R19, R20, R21, R22, R24, R25, X
uartBitbang_receiveNextPkg:
rcall NET_Buffer_Alloc ; R16=buffer num (R16, R17, X)
brcs uartBitbang_receiveNextPkg_gotBuffer
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp uartBitbang_receiveNextPkg_end
uartBitbang_receiveNextPkg_gotBuffer:
push r16 ; buffer number
adiw xh:xl, 1
ldd r18, Y+NET_IFACE_OFFS_ADDRESS
ldi r19, NET_BUFFERS_SIZE-1
rcall uartBitbang_ReceiveAndCheckMsg ; (R16, R17, R19, R20, R21, R22, R24, R25)
pop r16
brcc uartBitbang_receiveNextPkg_relBuffer
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
brcs uartBitbang_receiveNextPkg_end
push r16
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
pop r16
; fall-through to release buffer
uartBitbang_receiveNextPkg_relBuffer:
rcall NET_Buffer_ReleaseByNum ; (R16, X)
uartBitbang_receiveNextPkg_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