avr: more work on ardware uart code.

This commit is contained in:
Martin Preuss
2025-02-09 21:06:31 +01:00
parent 601559ca6e
commit 703f8042f9
8 changed files with 698 additions and 97 deletions

View File

@@ -129,7 +129,8 @@ devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; v
firmwareVersion: .db FIRMWARE_VARIANT_TEMP_WINDOW, FIRMWARE_VERSION_MAJOR
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
;firmwareStart: rjmp main
firmwareStart:
cli
; setup stack
@@ -160,10 +161,11 @@ main_loop:
and r16, r17
ori r16, (1<<SE) ; sleep mode "idle", enable
out MCUCR, r16
sei ; make sure interrupts really are enabled
sei ; make sure interrupts really are enabled
sleep ; sleep, wait for interrupt
rcall BaseTimer_Run
rcall TtyOnUart1_Run
rjmp main_loop
@@ -196,6 +198,7 @@ onSystemTimerTick:
rcall LedSimple_Every100ms
#endif
rcall TtyOnUart1_Periodically
ret
@@ -228,6 +231,7 @@ initModules:
rcall BaseTimer_Init
rcall LedSimple_Init
rcall UART_HW_Init
rcall TtyOnUart1_Init
ret
; @end
@@ -255,9 +259,11 @@ initModules:
.include "modules/uart_hw/defs.asm"
.include "modules/uart_hw/buffers.asm"
.include "modules/uart_hw/lowlevel.asm"
.include "modules/uart_hw/m_lowlevel_uart.asm"
.include "modules/uart_hw/lowlevel_uart1.asm"
.include "modules/uart_hw/msglevel_recv.asm"
.include "modules/uart_hw/msglevel_send.asm"
.include "modules/uart_hw/ttyonuart1.asm"

View File

@@ -10,26 +10,32 @@
.equ UART_HW_IFACE_READBUF_SIZE = 8
.equ UART_HW_IFACE_WRITEBUF_SIZE = 8
.equ UART_HW_IFACE_OUTMSGBUF_SIZE = 4
.equ UART_HW_BUFFER_INUSE_BIT = 7
.equ UART_HW_BUFFER_IFACENUM1_BIT = 1
.equ UART_HW_BUFFER_IFACENUM0_BIT = 0
.equ UART_HW_MODE_READMASK = 0x0f
.equ UART_HW_MODE_WRITEMASK = 0xf0
.equ UART_HW_MODE_OFF = 0
.equ UART_HW_MODE_IDLE = 1
.equ UART_HW_MODE_READING = 2
.equ UART_HW_MODE_WRITING = 4
.equ UART_HW_MODE_SKIPPING = 8
.equ UART_HW_MODE_WAITATTNLOW = 16 ; waiting after setting ATTN low
.equ UART_HW_MODE_SKIPPING = 3
.equ UART_HW_MODE_W_IDLE = 0
.equ UART_HW_MODE_WRITING = 8
.equ UART_HW_MODE_WAITBUFFEREMPTY = 9
.equ UART_HW_MODE_WRITEBUFFEREMPTY = 10
.equ UART_HW_STATUS_UNDERRUN = 0x01
.equ UART_HW_STATUS_OVERRUN = 0x02
.equ UART_HW_STATUS_HWERR = 0x04
.equ UART_HW_STATUS_SOFTERR = 0x08
.equ UART_HW_STATUS_ATTN = 0x80
.equ UART_HW_STATUS_UNDERRUN_BIT = 0
.equ UART_HW_STATUS_OVERRUN_BIT = 1
.equ UART_HW_STATUS_HWERR_BIT = 2
.equ UART_HW_STATUS_SOFTERR_BIT = 3
.equ UART_HW_STATUS_ATTN_BIT = 7
.equ UART_HW_IFACE_OFFS_IFACENUM = 0 ; interface number (put into received messages)
@@ -56,12 +62,22 @@
.equ UART_HW_IFACE_OFFS_WRITEBUF_WRPOS = UART_HW_IFACE_OFFS_WRITEBUF+3
.equ UART_HW_IFACE_OFFS_WRITEBUF_DATA = UART_HW_IFACE_OFFS_WRITEBUF+4
.equ UART_HW_IFACE_OFFS_READMSG = UART_HW_IFACE_OFFS_WRITEBUF_DATA+UART_HW_IFACE_WRITEBUF_SIZE
; ringbuffer for outgoing messages
.equ UART_HW_IFACE_OFFS_OUTMSGBUF = UART_HW_IFACE_OFFS_WRITEBUF_DATA+UART_HW_IFACE_WRITEBUF_SIZE
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_MAX = UART_HW_IFACE_OFFS_OUTMSGBUF
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_USED = UART_HW_IFACE_OFFS_OUTMSGBUF+1
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_RDPOS = UART_HW_IFACE_OFFS_OUTMSGBUF+2
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_WRPOS = UART_HW_IFACE_OFFS_OUTMSGBUF+3
.equ UART_HW_IFACE_OFFS_OUTMSGBUF_DATA = UART_HW_IFACE_OFFS_OUTMSGBUF+4
; ref to recv buffer
.equ UART_HW_IFACE_OFFS_READMSG = UART_HW_IFACE_OFFS_OUTMSGBUF_DATA+UART_HW_IFACE_OUTMSGBUF_SIZE
.equ UART_HW_IFACE_OFFS_READMSG_BUFNUM = UART_HW_IFACE_OFFS_READMSG ; 1 byte
.equ UART_HW_IFACE_OFFS_READMSG_PTR = UART_HW_IFACE_OFFS_READMSG+1 ; 2 bytes
.equ UART_HW_IFACE_OFFS_READMSG_USED = UART_HW_IFACE_OFFS_READMSG+3 ; 1 byte
.equ UART_HW_IFACE_OFFS_READMSG_LEFT = UART_HW_IFACE_OFFS_READMSG+4 ; 1 byte
; ref to transmit buffer
.equ UART_HW_IFACE_OFFS_WRITEMSG = UART_HW_IFACE_OFFS_READMSG_LEFT+1
.equ UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM = UART_HW_IFACE_OFFS_WRITEMSG ; 1 byte
.equ UART_HW_IFACE_OFFS_WRITEMSG_PTR = UART_HW_IFACE_OFFS_WRITEMSG+1 ; 2 bytes

View File

@@ -57,17 +57,27 @@ UART_HW_InterfaceInit:
ldi r17, UART_HW_IFACE_SIZE
clr r16
rcall Utils_FillSram ; (R17, X)
; reset ringbuffer for recvd chars
m_ringbuffer_y_reset UART_HW_IFACE_READBUF_SIZE, \
UART_HW_IFACE_OFFS_READBUF_USED, \
UART_HW_IFACE_OFFS_READBUF_RDPOS, \
UART_HW_IFACE_OFFS_READBUF_WRPOS, \
UART_HW_IFACE_OFFS_READBUF_DATA
; reset ringbuffer for chars to transmit
m_ringbuffer_y_reset UART_HW_IFACE_WRITEBUF_SIZE, \
UART_HW_IFACE_OFFS_WRITEBUF_USED, \
UART_HW_IFACE_OFFS_WRITEBUF_RDPOS, \
UART_HW_IFACE_OFFS_WRITEBUF_WRPOS, \
UART_HW_IFACE_OFFS_WRITEBUF_DATA
; reset ringbuffer for messages to be sent
m_ringbuffer_y_reset UART_HW_IFACE_OUTMSGBUF_SIZE, \
UART_HW_IFACE_OFFS_OUTMSGBUF_USED, \
UART_HW_IFACE_OFFS_OUTMSGBUF_RDPOS, \
UART_HW_IFACE_OFFS_OUTMSGBUF_WRPOS, \
UART_HW_IFACE_OFFS_OUTMSGBUF_DATA
ldi r16, 0xff
std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16
std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r16
@@ -156,7 +166,46 @@ UART_HW_InterfaceReadFromWriteBuffer:
UART_HW_Interface_Run:
; ---------------------------------------------------------------------------
; @routine UART_HW_InterfaceAddOutgoingMsgNum @global
;
; @return CFLAG on success, cleared on error
; @param r16 byte to write
; @param Y pointer to start of interface data
; @clobbers R17, R18, X
UART_HW_InterfaceAddOutgoingMsgNum:
push yl
push yh
adiw yh:yl, UART_HW_IFACE_OFFS_OUTMSGBUF
rcall uartHwRingBufferWriteGuarded ; R17, R18, X
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_HW_InterfaceGetNextOutgoingMsgNum @global
;
; @return CFLAG on success, cleared on error
; @return R16 byte read
; @param Y pointer to start of interface data
; @clobbers R17, R18, X
UART_HW_InterfaceGetNextOutgoingMsgNum:
push yl
push yh
adiw yh:yl, UART_HW_IFACE_OFFS_OUTMSGBUF
rcall uartHwRingBufferReadGuarded ; R17, R18, X
pop yh
pop yl
ret
; @end

View File

@@ -20,26 +20,7 @@
; @clobbers R16, R17, X
UART_HW_Uart1_Init:
rcall UART_HW_InterfaceInit
; set baudrate
.if clock == 8000000
ldi r16, 25 ; (19.2Kb/s at 8MHz)
ldi r17, 0
.endif
.if clock == 1000000
ldi r16, 2 ; (19.2Kb/s at 1MHz)
ldi r17, 0
.endif
sts UBRR1H, r17
sts UBRR1L, r16
; set character format
ldi r16, (1<<USBS1)|(3<<UCSZ10)
sts UCSR1C, r16
M_UART_HW_Uart_Init 1
ret
; @end
@@ -51,9 +32,7 @@ UART_HW_Uart1_Init:
; @clobbers none
UART_HW_Uart1_StartRx:
lds r16, UCSR1B
sbr r16, (1<<RXCIE1) | (1<<RXEN1) ; enable RX complete interrupt, enable receive
sts UCSR1B, r16
M_UART_HW_Uart_StartRx 1
ret
; @end
@@ -65,9 +44,7 @@ UART_HW_Uart1_StartRx:
; @clobbers R16
UART_HW_Uart1_StopRx:
lds r16, UCSR1B
cbr r16, (1<<RXCIE1 | (1<<RXEN1)) ; disable RX complete interrupt, disable receive
sts UCSR1B, r16
M_UART_HW_Uart_StopRx 1
ret
; @end
@@ -80,9 +57,7 @@ UART_HW_Uart1_StopRx:
; @clobbers R16
UART_HW_Uart1_StartTx:
lds r16, UCSR1B
sbr r16, (1<<UDRIE1) | (1<<TXEN1) ; enable TX data register empty interrupt, enable transceive
sts UCSR1B, r16
M_UART_HW_Uart_StartTx 1
ret
; @end
@@ -95,9 +70,21 @@ UART_HW_Uart1_StartTx:
; @clobbers R16
UART_HW_Uart1_StopTx:
lds r16, UCSR1B
cbr r16, (1<<UDRIE1) | (1<<TXEN1) ; disable TX data register empty interrupt, disable transceive
sts UCSR1B, r16
M_UART_HW_Uart_StopTx 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_HW_Uart1_Flush
;
; Flush receiption buffer.
;
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16
UART_HW_Uart1_Flush:
M_UART_HW_Uart_Flush 1
ret
; @end
@@ -110,24 +97,22 @@ UART_HW_Uart1_StopTx:
; @clobbers R16 (R17, R18, X)
UART_HW_Uart1_RxCharIsr:
lds r16, UCSR1A ; check for errors
andi r16, (1<<FE1) | (1<<DOR1) | (1<<UPE1)
breq UART_HW_Uart1_RxCharIsr_recv ; no error, receive next char
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set error status
ori r16, UART_HW_STATUS_HWERR ; -> HWERR
rjmp UART_HW_Uart1_RxCharIsr_setStatusAndEnd
UART_HW_Uart1_RxCharIsr_recv:
lds r16, UCSR1A
sbrs r16, RXC1
rjmp UART_HW_Uart1_RxCharIsr_end ; no data
lds r16, UDR1
rcall UART_HW_InterfaceWriteToReadBuffer ; (R17, R18, X)
brcs UART_HW_Uart1_RxCharIsr_end
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set overrun error
ori r16, UART_HW_STATUS_OVERRUN ; -> OVERRUN
UART_HW_Uart1_RxCharIsr_setStatusAndEnd:
std Y+UART_HW_IFACE_OFFS_STATUS, r16
UART_HW_Uart1_RxCharIsr_end:
M_UART_HW_Uart_RxCharIsr 1
ret
; @end
; ---------------------------------------------------------------------------
; @routine UART_HW_Uart1_TxUdreIsr @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, R18, X)
UART_HW_Uart1_TxUdreIsr:
M_UART_HW_Uart_TxUdreIsr 1
ret
; @end
@@ -136,28 +121,14 @@ UART_HW_Uart1_RxCharIsr_end:
; ---------------------------------------------------------------------------
; @routine UART_HW_Uart1_TxCharIsr @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, (R17, R18, X)
UART_HW_Uart1_TxCharIsr:
lds r16, UCSR1A
sbrs r16,UDRE1
rjmp UART_HW_Uart1_TxCharIsr_end ; not ready
rcall UART_HW_InterfaceReadFromWriteBuffer ; (R17, R18, X)
brcs UART_HW_Uart1_TxCharIsr_send ; got a byte, go send
; disable further DRE1 interrupts
lds r16, UCSR1B
cbr r16, (1<<UDRIE1) ; disable TX data register empty interrupt
sts UCSR1B, r16
; set underrun status (TODO: maybe change this later)
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set underrun error
ori r16, UART_HW_STATUS_UNDERRUN
std Y+UART_HW_IFACE_OFFS_STATUS, r16
rjmp UART_HW_Uart1_TxCharIsr_end
UART_HW_Uart1_TxCharIsr_send:
sts UDR1, r16
UART_HW_Uart1_TxCharIsr_end:
M_UART_HW_Uart_TxCharIsr 1
ret
; @end

View File

@@ -0,0 +1,222 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_Init
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16, R17, X
.macro M_UART_HW_Uart_Init
rcall UART_HW_InterfaceInit
; set baudrate
.if clock == 8000000
ldi r16, 25 ; (19.2Kb/s at 8MHz)
ldi r17, 0
.endif
.if clock == 1000000
ldi r16, 2 ; (19.2Kb/s at 1MHz)
ldi r17, 0
.endif
sts UBRR@0H, r17
sts UBRR@0L, r16
; set character format
ldi r16, (1<<USBS@0)|(3<<UCSZ@00)
sts UCSR@0C, r16
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_StartRx
;
; @param %0 UART number ("0" for UART0)
; @clobbers none
.macro M_UART_HW_Uart_StartRx
lds r16, UCSR@0B
sbr r16, (1<<RXCIE@0) | (1<<RXEN@0) ; enable RX complete interrupt, enable receive
sts UCSR@0B, r16
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_StopRx
;
; @param %0 UART number ("0" for UART0)
; @clobbers R16
.macro M_UART_HW_Uart_StopRx
lds r16, UCSR@0B
cbr r16, (1<<RXCIE@0 | (1<<RXEN@0)) ; disable RX complete interrupt, disable receive
sts UCSR@0B, r16
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_StartTx
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16
.macro M_UART_HW_Uart_StartTx
lds r16, UCSR@0A
cbr r16, (1<<TXC@0) ; clear TXCn interrupt
sts UCSR@0A, r16
lds r16, UCSR@0B
sbr r16, (1<<UDRIE@0) | (1<<TXC@0) | (1<<TXEN@0) ; enable TX UDRE and TXC1 interrupt, enable transceive
sts UCSR@0B, r16
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_StopTx
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_STATE)
; @clobbers R16
.macro M_UART_HW_Uart_StopTx
lds r16, UCSR@0B
cbr r16, (1<<UDRIE@0) | (1<<TXC@0) | (1<<TXEN@0) ; disable TX UDRE and TXC1 interrupt, enable transceive
sts UCSR@0B, r16
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_Flush
;
; Flush receiption buffer.
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16
.macro M_UART_HW_Uart_Flush
l_loop_%:
lds r16, UCSR@0A
sbrs r16, RXC@0
rjmp l_end_%
lds r16, UDR@0
clr r16
std Y+UART_HW_IFACE_OFFS_READTIMER, r16
rjmp l_loop_%
l_end_%:
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_RxCharIsr
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16 (R17, R18, X)
.macro M_UART_HW_Uart_RxCharIsr
lds r16, UCSR@0A ; check for errors
andi r16, (1<<FE@0) | (1<<DOR@0) | (1<<UPE@0)
breq l_recv_% ; no error, receive next char
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set error status
ori r16, (1<<UART_HW_STATUS_HWERR_BIT) ; -> HWERR
rjmp l_setStatusAndEnd_%
l_recv_%:
lds r16, UCSR@0A
sbrs r16, RXC@0
rjmp l_end_% ; no data
lds r16, UDR@0
rcall UART_HW_InterfaceWriteToReadBuffer ; (R17, R18, X)
brcc l_overrun_%
clr r16
std Y+UART_HW_IFACE_OFFS_READTIMER, r16 ; reset read timer
rjmp l_end_%
l_overrun_%:
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set overrun error
ori r16, (1<<UART_HW_STATUS_OVERRUN_BIT) ; -> OVERRUN
l_setStatusAndEnd_%:
std Y+UART_HW_IFACE_OFFS_STATUS, r16
l_end_%:
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_TxUdreIsr
;
; Handler for UDREn interrupt called when TX data register is empty.
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16, (R17, R18, X)
.macro M_UART_HW_Uart_TxUdreIsr
lds r16, UCSR@0A
sbrs r16,UDRE@0
rjmp l_end_% ; not ready
rcall UART_HW_InterfaceReadFromWriteBuffer ; (R17, R18, X)
brcs l_send_% ; got a byte, go send
; disable further DRE1 interrupts
lds r16, UCSR@0B
cbr r16, (1<<UDRIE@0) ; disable TX data register empty interrupt
sts UCSR@0B, r16
rjmp l_end_%
l_send_%:
sts UDR@0, r16
clr r16
std Y+UART_HW_IFACE_OFFS_WRITETIMER, r16 ; reset write timer
l_end_%:
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_UART_HW_Uart_TxCharIsr
;
; Handler for TXCn interrupt called when a last byte has been completely sent and
; the data register is empty..
;
; @param %0 UART number ("0" for UART0)
; @param Y pointer to interface data in SRAM (see @ref UART_HW_IFACE_OFFS_MODE)
; @clobbers R16, (R17, R18, X)
.macro M_UART_HW_Uart_TxCharIsr
; disable further TXC1 interrupts
lds r16, UCSR@0B
cbr r16, (1<<TXC@0) ; disable TXC1 interrupt
sts UCSR@0B, r16
; set underrun status (TODO: maybe change this later)
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS ; set underrun error
ori r16, (1<<UART_HW_STATUS_UNDERRUN_BIT)
std Y+UART_HW_IFACE_OFFS_STATUS, r16
.endmacro
; @end

View File

@@ -19,9 +19,7 @@
; incoming message ringbuffer.
;
; @param Y pointer to start of interface data
; @param X pointer to start of buffer
; @param r16 buffer number
; @clobbers R16, R17, R18, R19, R20, R21, X
; @clobbers R16, R20 (R17, R18, R18, R19, R20, R21, X)
UART_HW_Interface_RunRead:
ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM
@@ -71,12 +69,12 @@ UART_HW_Interface_RunRead_HaveMsg:
std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16
rjmp UART_HW_Interface_RunRead_end
UART_HW_Interface_RunRead_ovrError:
rcall uartHwIncOvrCounter
rcall uartHwReadResetBuffer
rcall uartHwIncOvrCounter ; (R16)
rcall uartHwReadResetBuffer ; (R16, X)
rjmp UART_HW_Interface_RunRead_end
UART_HW_Interface_RunRead_dataError:
rcall uartHwIncContentCounter
rcall uartHwResetBufferStartSkipping
rcall uartHwIncContentCounter ; (R16)
rcall uartHwResetBufferStartSkipping ; (R16, X)
UART_HW_Interface_RunRead_end:
ret
; @end
@@ -129,11 +127,11 @@ uartHwReadResetBuffer_haveBuffer:
; @routine uartHwResetBufferStartSkipping
;
; @param Y pointer to start of interface data
; @clobbers r16, X
; @clobbers r16 (X)
uartHwResetBufferStartSkipping:
; reset READ buffer settings, enter skip mode
rcall uartHwReadResetBuffer
rcall uartHwReadResetBuffer ; (R16, X)
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
ori r16, UART_HW_MODE_SKIPPING
std Y+UART_HW_IFACE_OFFS_MODE, r16

View File

@@ -12,19 +12,19 @@
; ---------------------------------------------------------------------------
; @routine UART_HW_Interface_RunWrite @global
; @routine UART_HW_Interface_RunWriting @global
;
; Get messages via @ref UART_HW_GetNextOutgoingMsgNum and fill them into
; the outbound ringbuffer of this interface.
; Write current message to ringbuffer.
;
; @param Y pointer to start of interface data
; @clobbers r16, r19, X (R17, R18, R20, R21)
UART_HW_Interface_RunWrite:
UART_HW_Interface_RunWriting:
ldd r19, Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM
cpi r19, 0xff
breq UART_HW_Interface_RunWrite_end ; nothing to do
cpi r19, 0xff ; invalid buffer number?
breq UART_HW_Interface_RunWrite_end ; yes, invalid, nothing to do
UART_HW_Interface_RunWrite_haveMsg:
; there are still bytes left in the buffer, send them
ldd r20, Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT
rcall uartHwWriteUptoNumBytes ; (r16, r17, r18, r20, r21, X)
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT
@@ -33,8 +33,12 @@ UART_HW_Interface_RunWrite_haveMsg:
; message completely sent to interface, release buffer
ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM
rcall UART_HW_FixedBuffers_ReleaseByNum
ldi r16, 0xff ; reset buffer number
ldi r16, 0xff ; set invalid buffer number
std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r16
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
cbr r16, UART_HW_MODE_WRITEMASK
ori r16, UART_HW_MODE_WAITBUFFEREMPTY
std Y+UART_HW_IFACE_OFFS_MODE, r16
UART_HW_Interface_RunWrite_end:
ret
; @end
@@ -47,6 +51,7 @@ UART_HW_Interface_RunWrite_end:
; Set given fixed buffer as source for @ref UART_HW_Interface_RunWrite.
;
; @param r16 buffer num
; @param Y pointer to start of interface data
; @clobbers r16, r19, X
UART_HW_Interface_WriteSetBuffer:

View File

@@ -0,0 +1,334 @@
; ***************************************************************************
; 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_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_Uart1_Init ; (R16, R17, X)
ldi r16, TTYONUART1_IFACENUM
std Y+UART_HW_IFACE_OFFS_IFACENUM, r16
ldi r16, UART_HW_MODE_IDLE | UART_HW_MODE_W_IDLE ; start in full idle mode
std Y+UART_HW_IFACE_OFFS_MODE, 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+UART_HW_IFACE_OFFS_READTIMER
inc r16
breq TtyOnUart1_Periodically_l1
std Y+UART_HW_IFACE_OFFS_READTIMER, r16
TtyOnUart1_Periodically_l1:
ldd r16, Y+UART_HW_IFACE_OFFS_WRITETIMER
inc r16
breq TtyOnUart1_Periodically_l2
std Y+UART_HW_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 xl
push xh
push yl
push yh
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall UART_HW_Uart1_RxCharIsr ; (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_TxUdreIsr @global @isr
;
; @clobbers none
TtyOnUart1_TxUdreIsr:
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 UART_HW_Uart1_TxUdreIsr ; (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_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 UART_HW_Uart1_TxCharIsr ; (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_Run @global
;
; @clobbers all
TtyOnUart1_Run:
ldi yl, LOW(ttyOnUart1_iface)
ldi yh, HIGH(ttyOnUart1_iface)
rcall ttyOnUart1RunWriteModes
rcall ttyOnUart1RunReadModes
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriteModes
;
; @clobbers all, !Y
ttyOnUart1RunWriteModes:
ldd r16, Y+UART_HW_IFACE_OFFS_MODE ; handle write functions
cbr r16, UART_HW_MODE_READMASK
cpi r16, UART_HW_MODE_W_IDLE
breq ttyOnUart1RunWIdle
cpi r16, UART_HW_MODE_WRITING
breq ttyOnUart1RunWriting
cpi r16, UART_HW_MODE_WAITBUFFEREMPTY
breq ttyOnUart1RunWaitBufferEmpty
cpi r16, UART_HW_MODE_WRITEBUFFEREMPTY
breq ttyOnUart1RunWriteBufferEmpty
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWIdle
;
; @clobbers all, !Y
ttyOnUart1RunWIdle:
rcall UART_HW_InterfaceGetNextOutgoingMsgNum ; (R17, R18, X)
brcc ttyOnUart1RunWIdle_end
rcall UART_HW_Interface_WriteSetBuffer ; (r16, r19, X)
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
cbr r16, UART_HW_MODE_WRITEMASK
ori r16, UART_HW_MODE_WRITING
std Y+UART_HW_IFACE_OFFS_MODE, r16
rcall ttyOnUart1RunWriting ; fill ringbuffer
rcall UART_HW_Uart1_StartTx ; enable transceiver and interrupts
ttyOnUart1RunWIdle_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriting
;
; @clobbers all, !Y
ttyOnUart1RunWriting:
rjmp UART_HW_Interface_RunWriting ; (R16, R17, R18, R19, R20, R21, X)
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWaitBufferEmpty
;
; @clobbers all, !Y
ttyOnUart1RunWaitBufferEmpty:
ldd r16, Y+UART_HW_IFACE_OFFS_STATUS
sbrs r16, UART_HW_STATUS_UNDERRUN_BIT ; underrun bit set?
ret ; return if bit still clear
cbr r16, (1<<UART_HW_STATUS_UNDERRUN_BIT)
std Y+UART_HW_IFACE_OFFS_STATUS, r16
ldd r16, Y+UART_HW_IFACE_OFFS_MODE ; change mode to WRITEBUFFEREMPTY and go handle that
cbr r16, UART_HW_MODE_WRITEMASK
ori r16, UART_HW_MODE_WRITEBUFFEREMPTY
std Y+UART_HW_IFACE_OFFS_MODE, r16
rjmp ttyOnUart1RunWriteBufferEmpty
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunWriteBufferEmpty
;
; @clobbers all, !Y
ttyOnUart1RunWriteBufferEmpty:
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
cbr r16, UART_HW_MODE_WRITEMASK
ori r16, UART_HW_MODE_W_IDLE
std Y+UART_HW_IFACE_OFFS_MODE, r16
rcall UART_HW_Uart1_StopTx ; disable transceiver and interrupts
rjmp ttyOnUart1RunWIdle
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunReadModes
;
; @clobbers all, !Y
ttyOnUart1RunReadModes:
ldd r16, Y+UART_HW_IFACE_OFFS_MODE ; handle read functions
cbr r16, UART_HW_MODE_WRITEMASK
cpi r16, UART_HW_MODE_IDLE
breq ttyOnUart1RunIdle
cpi r16, UART_HW_MODE_READING
breq ttyOnUart1RunReading
cpi r16, UART_HW_MODE_SKIPPING
breq ttyOnUart1RunSkipping
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunIdle
;
; @clobbers all, !Y
ttyOnUart1RunIdle:
rcall UART_HW_Uart1_StartRx
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
cbr r16, UART_HW_MODE_READMASK
ori r16, UART_HW_MODE_READING
std Y+UART_HW_IFACE_OFFS_MODE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunReading
;
; @clobbers all, !Y
ttyOnUart1RunReading:
rjmp UART_HW_Interface_RunRead ; (R16, R17, R18, R18, R19, R20, R21, X)
; @end
; ---------------------------------------------------------------------------
; @routine ttyOnUart1RunSkipping
;
; @clobbers all, !Y
ttyOnUart1RunSkipping:
rcall UART_HW_Uart1_Flush ; (R16)
ldd r16, Y+UART_HW_IFACE_OFFS_READTIMER
cpi r16, TTYONUART1_SKIPTIME
brcs ttyOnUart1RunSkipping_end
ldd r16, Y+UART_HW_IFACE_OFFS_MODE
cbr r16, UART_HW_MODE_READMASK
ori r16, UART_HW_MODE_READING
std Y+UART_HW_IFACE_OFFS_MODE, r16
ttyOnUart1RunSkipping_end:
ret
; @end