275 lines
7.9 KiB
NASM
275 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:
|
|
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
|
|
|