Files
aqhomecontrol/avr/modules/uart_hw/ttyonuart1.asm
2025-03-27 00:20:58 +01:00

515 lines
12 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. *
; ***************************************************************************
.equ TTYONUART1_SKIPTIME = 2
.equ TTYONUART1_MSG_INTERVAL = 2
.equ TTYONUART1_IFACENUM = 2
.dseg
ttyOnUart1_iface: .byte UART_HW_IFACE_SIZE
.cseg
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_Init @global
;
; @clobbers Y (R16, R17, X)
TtyOnUart1_Init:
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall UART_HW_Interface_Init ; (R16, R17, X)
rcall ttyOnUart1Init ; (R16, R17, X)
ldi r16, TTYONUART1_IFACENUM
std Y+NET_IFACE_OFFS_IFACENUM, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_Periodically @global
;
; @clobbers R16, Y
TtyOnUart1_Periodically:
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
ldd r16, Y+NET_IFACE_OFFS_READTIMER
inc r16
breq TtyOnUart1_Periodically_l1
std Y+NET_IFACE_OFFS_READTIMER, r16
TtyOnUart1_Periodically_l1:
ldd r16, Y+NET_IFACE_OFFS_WRITETIMER
inc r16
breq TtyOnUart1_Periodically_l2
std Y+NET_IFACE_OFFS_WRITETIMER, r16
TtyOnUart1_Periodically_l2:
ret
; @end
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_RxCharIsr @global @isr
;
; @clobbers none
TtyOnUart1_RxCharIsr:
push r15
in r15, SREG
push r16
push r17
push r18
push r24
push r25
push xl
push xh
push yl
push yh
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall ttyOnUart1RxCharIsr ; (R16, R17, R18, R24, R25, X)
pop yh
pop yl
pop xh
pop xl
pop r25
pop r24
pop r18
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_TxUdreIsr @global @isr
;
; @clobbers none
TtyOnUart1_TxUdreIsr:
push r15
in r15, SREG
push r16
push r17
push xl
push xh
push yl
push yh
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall ttyOnUart1TxUdreIsr ; (R16, R17, X)
pop yh
pop yl
pop xh
pop xl
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_TxCharIsr @global @isr
;
; @clobbers none
TtyOnUart1_TxCharIsr:
push r15
in r15, SREG
push r16
push r17
push r18
push xl
push xh
push yl
push yh
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall ttyOnUart1TxCharIsr ; (R16, R17, R18, X)
pop yh
pop yl
pop xh
pop xl
pop r18
pop r17
pop r16
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_SendBuffer @global
;
; @clobbers R16, R17
TtyOnUart1_SendBuffer:
push r15
in r15, SREG
cli
ldd r17, Y+UART_HW_IFACE_OFFS_WRITEMODE
cpi r17, UART_HW_WRITEMODE_IDLE
breq TtyOnUart1_SendBuffer_setBuffer
out SREG, r15
pop r15
clc
ret
TtyOnUart1_SendBuffer_setBuffer:
rcall UART_HW_Interface_SetWriteBuffer ; (R17)
ldi r17, UART_HW_WRITEMODE_WRITING
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r17
rcall ttyOnUart1StartTx ; (R16)
pop r15
out SREG, r15
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine TtyOnUart1_Run @global
;
; @clobbers all
TtyOnUart1_Run:
push r15
in r15, SREG
cli
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall ttyOnUart1RunWriteModes
rcall ttyOnUart1RunReadModes
pop r15
out SREG, r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriteModes
;
; @clobbers all, !Y
ttyOnUart1RunWriteModes:
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMODE ; handle write functions
cpi r16, UART_HW_WRITEMODE_IDLE
breq ttyOnUart1RunWriteIdle
cpi r16, UART_HW_WRITEMODE_WRITING
breq ttyOnUart1RunWriting
cpi r16, UART_HW_WRITEMODE_WAITBUFFEREMPTY
breq ttyOnUart1RunWaitBufferEmpty
cpi r16, UART_HW_WRITEMODE_WRITEBUFFEREMPTY
breq ttyOnUart1RunWriteBufferEmpty
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriteIdle
;
; @clobbers
ttyOnUart1RunWriteIdle:
ldd r16, Y+NET_IFACE_OFFS_WRITETIMER
cpi r16, TTYONUART1_MSG_INTERVAL ; wait a bit between messages
brcs ttyOnUart1RunWriteIdle_end
rcall NET_Interface_GetNextOutgoingMsgNum ; (R17, R18, X)
brcc ttyOnUart1RunWriteIdle_end
rcall NET_Buffer_Locate ; (R17)
rcall TtyOnUart1_SendBuffer ; (R16, R17)
ttyOnUart1RunWriteIdle_end:
ret
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriting
;
; @clobbers
ttyOnUart1RunWriting:
; TODO: check for timeout etc.
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWaitBufferEmpty
;
; @clobbers none
ttyOnUart1RunWaitBufferEmpty:
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEBUFNUM
ldi r17, 0xff
cp r16, r17
breq ttyOnUart1RunWaitBufferEmpty_checkHardware
std Y+UART_HW_IFACE_OFFS_WRITEBUFNUM, r17
rcall NET_Buffer_ReleaseByNum ; (R16, X)
ttyOnUart1RunWaitBufferEmpty_checkHardware:
lds r16, UCSR1A
sbrs r16,TXC1
rjmp ttyOnUart1RunWaitBufferEmpty_checkTimer ; bit still clear, go check timer
ldi r16, UART_HW_WRITEMODE_WRITEBUFFEREMPTY ; bit is set, change mode to WRITEBUFFEREMPTY
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
rjmp ttyOnUart1RunWaitBufferEmpty_end
ttyOnUart1RunWaitBufferEmpty_checkTimer:
ldd r16, Y+NET_IFACE_OFFS_WRITETIMER
cpi r16, 10
brcs ttyOnUart1RunWaitBufferEmpty_end
rcall ttyOnUart1StopTx ; disable transceiver and interrupts (R16)
ldi r16, NET_IFACE_OFFS_ERR_COLLISIONS_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
ttyOnUart1RunWaitBufferEmpty_enterIdle:
ldi r16, UART_HW_WRITEMODE_IDLE
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
ttyOnUart1RunWaitBufferEmpty_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriteBufferEmpty
;
; @clobbers R16, R17, X (R24, R25)
ttyOnUart1RunWriteBufferEmpty:
rcall ttyOnUart1StopTx ; disable transceiver and interrupts (R16)
ldi r16, UART_HW_WRITEMODE_IDLE
std Y+UART_HW_IFACE_OFFS_WRITEMODE, r16
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW ; increment packets counter
rcall NET_Interface_IncCounter16 ; (R24, R25)
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunReadModes
;
; @clobbers all, !Y
ttyOnUart1RunReadModes:
ldd r16, Y+UART_HW_IFACE_OFFS_READMODE ; handle read functions
cpi r16, UART_HW_READMODE_IDLE
breq ttyOnUart1RunReadIdle ; (R16, R17, R24, R25, X)
cpi r16, UART_HW_READMODE_READING
breq ttyOnUart1RunReading ; (none)
cpi r16, UART_HW_READMODE_SKIPPING
breq ttyOnUart1RunSkipping ; (R16)
cpi r16, UART_HW_READMODE_MSGRECEIVED
breq ttyOnUart1RunMsgReceived ; (R16, R17, R18, R24, R25)
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunReadIdle
;
; @clobbers R16 (R17, R24, R25, X)
ttyOnUart1RunReadIdle:
rcall UART_HW_Interface_EnsureReadBuffer ; (R16, R17, R24, R25, X)
brcc ttyOnUart1RunReadIdle_noBuf
ldi r16, UART_HW_READMODE_READING
std Y+UART_HW_IFACE_OFFS_READMODE, r16
rcall ttyOnUart1StartRx ; R16
ret
ttyOnUart1RunReadIdle_noBuf:
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunReading
;
; @clobbers none
ttyOnUart1RunReading:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunSkipping
;
; @clobbers R16
ttyOnUart1RunSkipping:
ldi r17, 0xff
ldd r16, Y+UART_HW_IFACE_OFFS_READBUFNUM
std Y+UART_HW_IFACE_OFFS_READBUFNUM, r17
cp r16, r17
breq ttyOnUart1RunSkipping_checkTimer
rcall NET_Buffer_ReleaseByNum ; (R16, X)
ttyOnUart1RunSkipping_checkTimer:
ldd r16, Y+NET_IFACE_OFFS_READTIMER
cpi r16, TTYONUART1_SKIPTIME
brcs ttyOnUart1RunSkipping_end
; leave skip mode (enter idle)
ldi r16, UART_HW_READMODE_IDLE
std Y+UART_HW_IFACE_OFFS_READMODE, r16
ttyOnUart1RunSkipping_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunMsgReceived
;
; @clobbers R16 (R17, R18, R24, R25)
ttyOnUart1RunMsgReceived:
rjmp UART_HW_Interface_HandleMsgReceived
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1Init @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16, R17, X
ttyOnUart1Init:
M_UART_HW_Uart_Init 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1StartRx @global
;
; @clobbers R16
ttyOnUart1StartRx:
M_UART_HW_Uart_StartRx 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1StopRx @global
;
; @clobbers R16
ttyOnUart1StopRx:
M_UART_HW_Uart_StopRx 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1StartTx @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16
ttyOnUart1StartTx:
M_UART_HW_Uart_StartTx 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1StopTx @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16
ttyOnUart1StopTx:
M_UART_HW_Uart_StopTx 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RxCharIsr @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16 (R17, R18, R24, R25, X)
ttyOnUart1RxCharIsr:
M_UART_HW_Uart_RxCharFullDuplexIsr 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1TxUdreIsr @global
;
; Handler for UDRE1 interrupt called when TX data register is empty.
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16, R17, X
ttyOnUart1TxUdreIsr:
M_UART_HW_Uart_TxUdreIsr 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1TxCharIsr @global
;
; Handler for TXC1 interrupt called when a last byte has been completely sent and
; the data register is empty.
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16
ttyOnUart1TxCharIsr:
M_UART_HW_Uart_TxCharIsr 1
ret
; @end