287 lines
7.8 KiB
NASM
287 lines
7.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"
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; macros
|
|
|
|
|
|
.macro mUartBitbangSetupInt0
|
|
inr r16, MCUCR
|
|
cbr r16, (1<<ISC01) | (1<<ISC00)
|
|
sbr r16, (1<<ISC01) | (0<<ISC00) ; falling edge of ATTN
|
|
outr MCUCR, r16
|
|
; sbr r16, (0<<ISC01) | (0<<ISC00) ; low level triggers
|
|
inr r16, COM_IRQ_ADDR_ATTN ; enable irq for ATTN line
|
|
sbr r16, (1<<COM_IRQ_BIT_ATTN)
|
|
outr COM_IRQ_ADDR_ATTN, r16
|
|
.endmacro
|
|
|
|
|
|
|
|
.macro mUartBitbangSetupPci
|
|
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
|
|
.endmacro
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; 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
|
|
.ifdef INT0
|
|
.if COM_IRQ_BIT_ATTN == INT0
|
|
mUartBitbangSetupInt0
|
|
.else
|
|
mUartBitbangSetupPci
|
|
.endif
|
|
.else
|
|
mUartBitbangSetupPci
|
|
.endif
|
|
|
|
#if 0
|
|
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
|
|
#endif
|
|
|
|
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
|
|
|
|
#if 0
|
|
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
|
|
#endif
|
|
|
|
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
|
|
|