diff --git a/avr/common/0BUILD b/avr/common/0BUILD index 67ae26b..38157a9 100644 --- a/avr/common/0BUILD +++ b/avr/common/0BUILD @@ -4,7 +4,7 @@ crc8.asm - fixedbuffers.asm + m_fixedbuffers.asm m_ringbuffer.asm m_ringbuffer_y.asm ringbuffer.asm diff --git a/avr/common/fixedbuffers.asm b/avr/common/m_fixedbuffers.asm similarity index 99% rename from avr/common/fixedbuffers.asm rename to avr/common/m_fixedbuffers.asm index 3ad19d2..f4481b0 100644 --- a/avr/common/fixedbuffers.asm +++ b/avr/common/m_fixedbuffers.asm @@ -92,7 +92,7 @@ l_end: ; @param %1 constant maxBuffers ; @clobbers r16, X -.macro m_fixedbuf_locate: +.macro m_fixedbuf_locate cpi r16, @1 brcc l_end ; idx out of range, use cleared CFLAG tst r16 ; doesn't change CFLAG which is set from CPI above diff --git a/avr/devices/t03/main.asm b/avr/devices/t03/main.asm index c9c8376..40f92ad 100644 --- a/avr/devices/t03/main.asm +++ b/avr/devices/t03/main.asm @@ -70,6 +70,12 @@ ;#define MODULES_MOTION +.equ UART_HW_FIXEDBUFFERS_NUM = 32 +.equ UART_HW_FIXEDBUFFERS_SIZE = 6 + +.equ UART_HW_MSGNUMINBUF_SIZE = 6 +.equ UART_HW_MSGNUMOUTBUF_SIZE = 6 + ; *************************************************************************** ; code segment @@ -134,36 +140,13 @@ firmwareStart: ldi r16, Low(RAMEND) out SPL, r16 ; init LSB stack pointer -#if 0 - ; start by setting all ports as inputs and enable internal pull-up resistors - ldi r16, 0xff - clr r17 -.ifdef PORTA - out DDRA, r17 ; all input - sts PUEA, r16 ; enable pull-up on all -.endif - -.ifdef PORTB - out DDRB, r17 ; all input - sts PUEB, r16 ; enable pull-up on all -.endif - -.ifdef PORTC - out DDRC, r17 ; all input - sts PUEC, r16 ; enable pull-up on all -.endif - -#endif - rcall systemSetSpeed + rcall initHardware ; rcall watchdogOff ; turn off watchdog timer (sometimes it stays on after reboot) - rcall Utils_Init - rcall BaseTimer_Init - rcall LedSimple_Init - + rcall initModules rcall Utils_SetupUid - + sbi LED_SIMPLE_DDR, LED_SIMPLE_PINNUM ; out sbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; off @@ -217,6 +200,40 @@ onSystemTimerTick: +initHardware: + ; set all ports as inputs and enable internal pull-up resistors + ldi r16, 0xff + clr r17 +.ifdef PORTA + out DDRA, r17 ; all input + sts PUEA, r16 ; enable pull-up on all +.endif + +.ifdef PORTB + out DDRB, r17 ; all input + sts PUEB, r16 ; enable pull-up on all +.endif + +.ifdef PORTC + out DDRC, r17 ; all input + sts PUEC, r16 ; enable pull-up on all +.endif + ret +; @end + + + +initModules: + rcall Utils_Init + rcall BaseTimer_Init + rcall LedSimple_Init + rcall UART_HW_Init + ret +; @end + + + + ; *************************************************************************** @@ -226,10 +243,19 @@ onSystemTimerTick: .include "common/utils_wait_fixed.asm" .include "common/utils_copy_from_flash.asm" .include "common/utils_copy_sdram.asm" +.include "common/m_ringbuffer_y.asm" +.include "common/ringbuffer_y.asm" +.include "common/m_fixedbuffers.asm" .include "common/crc8.asm" .include "modules/flash/wait.asm" .include "modules/basetimer/main.asm" .include "modules/led_simple/main.asm" +.include "modules/uart_hw/defs.asm" +.include "modules/uart_hw/buffers.asm" +.include "modules/uart_hw/lowlevel.asm" +.include "modules/uart_hw/lowlevel_uart1.asm" +.include "modules/uart_hw/msglevel_recv.asm" +.include "modules/uart_hw/msglevel_send.asm" diff --git a/avr/modules/uart_hw/0BUILD b/avr/modules/uart_hw/0BUILD index 443b708..76fb158 100644 --- a/avr/modules/uart_hw/0BUILD +++ b/avr/modules/uart_hw/0BUILD @@ -3,7 +3,13 @@ + buffers.asm defs.asm + init_uart1.asm + lowlevel.asm + lowlevel_uart1.asm + msglevel_recv.asm + msglevel_send.asm diff --git a/avr/modules/uart_hw/buffers.asm b/avr/modules/uart_hw/buffers.asm index ec5aee2..0e38a12 100644 --- a/avr/modules/uart_hw/buffers.asm +++ b/avr/modules/uart_hw/buffers.asm @@ -13,6 +13,8 @@ uartHwDataBegin: ; fixed buffers for incoming and outgoing messages uartHw_buffers: .byte UART_HW_FIXEDBUFFERS_NUM*UART_HW_FIXEDBUFFERS_SIZE + uartHw_ringBufferMsgNumIn: .byte UART_HW_MSGNUMINBUF_SIZE + uartHw_ringBufferMsgNumOut: .byte UART_HW_MSGNUMOUTBUF_SIZE uartHwDataEnd: @@ -53,18 +55,34 @@ UART_HW_FixedBuffers_Alloc: ; --------------------------------------------------------------------------- -; @routine UART_HW_FixedBuffers_Release @global +; @routine UART_HW_FixedBuffers_ReleaseByAddr @global ; ; @param X pointer to start of buffers ; @clobbers R16 -UART_HW_FixedBuffers_Release: +UART_HW_FixedBuffers_ReleaseByAddr: m_fixedbuf_release ret ; @end +; --------------------------------------------------------------------------- +; @routine UART_HW_FixedBuffers_ReleaseByNum @global +; +; @param r16 buffer number +; @clobbers X (R16) + +UART_HW_FixedBuffers_ReleaseByNum: + rcall UART_HW_FixedBuffers_Locate ; (R16) + brcc UART_HW_FixedBuffers_ReleaseByNum_end + rcall UART_HW_FixedBuffers_ReleaseByAddr ; (R16) +UART_HW_FixedBuffers_ReleaseByNum_end: + ret +; @end + + + ; --------------------------------------------------------------------------- ; @routine UART_HW_FixedBuffers_Locate ; @@ -99,3 +117,88 @@ UART_HW_FixedBuffers_Locate_end: + + +; --------------------------------------------------------------------------- +; @routine UART_HW_AddIncomingMsg @global +; +; @return CFLAG on success, cleared on error +; @param R16 buffer number of the next incoming message +; @clobbers R17, R18, X + +UART_HW_AddIncomingMsgNum: + push yl + push yh + ldi yl, LOW(uartHw_ringBufferMsgNumIn) + ldi yh, HIGH(uartHw_ringBufferMsgNumIn) + rcall RingBufferY_WriteByte ; R17, R18, X + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine UART_HW_GetNextIncomingMsgNum @global +; +; @return CFLAG on success, cleared on error +; @return R16 buffer number of the next incoming message +; @param Y pointer to start of interface data +; @clobbers R17, R18, X + +UART_HW_GetNextIncomingMsgNum: + push yl + push yh + ldi yl, LOW(uartHw_ringBufferMsgNumIn) + ldi yh, HIGH(uartHw_ringBufferMsgNumIn) + rcall RingBufferY_ReadByte ; R17, R18, X + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine UART_HW_AddOutgoingMsg @global +; +; @return CFLAG on success, cleared on error +; @param R16 buffer number of the next incoming message +; @clobbers R17, R18, X + +UART_HW_AddOutgoingMsgNum: + push yl + push yh + ldi yl, LOW(uartHw_ringBufferMsgNumOut) + ldi yh, HIGH(uartHw_ringBufferMsgNumOut) + rcall RingBufferY_WriteByte ; R17, R18, X + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine UART_HW_GetNextOutgoingMsgNum @global +; +; @return CFLAG on success, cleared on error +; @return R16 buffer number of the next incoming message +; @param Y pointer to start of interface data +; @clobbers R17, R18, X + +UART_HW_GetNextOutgoingMsgNum: + push yl + push yh + ldi yl, LOW(uartHw_ringBufferMsgNumOut) + ldi yh, HIGH(uartHw_ringBufferMsgNumOut) + rcall RingBufferY_ReadByte ; R17, R18, X + pop yh + pop yl + ret +; @end + + + + diff --git a/avr/modules/uart_hw/defs.asm b/avr/modules/uart_hw/defs.asm index 336db9b..1eb33a2 100644 --- a/avr/modules/uart_hw/defs.asm +++ b/avr/modules/uart_hw/defs.asm @@ -22,27 +22,44 @@ .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_IFACE_OFFS_MODE = 0 -.equ UART_HW_IFACE_OFFS_STATUS = 1 -.equ UART_HW_IFACE_OFFS_READTIMER = 2 +.equ UART_HW_IFACE_OFFS_MODE = 0 +.equ UART_HW_IFACE_OFFS_STATUS = 1 +.equ UART_HW_IFACE_OFFS_READTIMER = 2 +.equ UART_HW_IFACE_OFFS_WRITETIMER = 3 +.equ UART_HW_IFACE_OFFS_ERR_OVR = 4 -.equ UART_HW_IFACE_OFFS_READBUF = 3 ; ringbuffer for incoming chars -.equ UART_HW_IFACE_OFFS_READBUF_MAX = UART_HW_IFACE_OFFS_READBUF -.equ UART_HW_IFACE_OFFS_READBUF_USED = UART_HW_IFACE_OFFS_READBUF+1 -.equ UART_HW_IFACE_OFFS_READBUF_RDPOS = UART_HW_IFACE_OFFS_READBUF+2 -.equ UART_HW_IFACE_OFFS_READBUF_WRPOS = UART_HW_IFACE_OFFS_READBUF+3 -.equ UART_HW_IFACE_OFFS_READBUF_DATA = UART_HW_IFACE_OFFS_READBUF+4 ; UART_HW_IFACE_READBUF_SIZE bytes + ; ringbuffer for incoming chars +.equ UART_HW_IFACE_OFFS_READBUF = 5 +.equ UART_HW_IFACE_OFFS_READBUF_MAX = UART_HW_IFACE_OFFS_READBUF +.equ UART_HW_IFACE_OFFS_READBUF_USED = UART_HW_IFACE_OFFS_READBUF+1 +.equ UART_HW_IFACE_OFFS_READBUF_RDPOS = UART_HW_IFACE_OFFS_READBUF+2 +.equ UART_HW_IFACE_OFFS_READBUF_WRPOS = UART_HW_IFACE_OFFS_READBUF+3 +.equ UART_HW_IFACE_OFFS_READBUF_DATA = UART_HW_IFACE_OFFS_READBUF+4 ; UART_HW_IFACE_READBUF_SIZE bytes -.equ UART_HW_IFACE_OFFS_WRITEBUF = UART_HW_IFACE_OFFS_READBUF_DATA+UART_HW_IFACE_READBUF_SIZE -.equ UART_HW_IFACE_OFFS_WRITEBUF_MAX = UART_HW_IFACE_OFFS_WRITEBUF -.equ UART_HW_IFACE_OFFS_WRITEBUF_USED = UART_HW_IFACE_OFFS_WRITEBUF+1 -.equ UART_HW_IFACE_OFFS_WRITEBUF_RDPOS = UART_HW_IFACE_OFFS_WRITEBUF+2 -.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 + ; ringbuffer for outgoing chars +.equ UART_HW_IFACE_OFFS_WRITEBUF = UART_HW_IFACE_OFFS_READBUF_DATA+UART_HW_IFACE_READBUF_SIZE +.equ UART_HW_IFACE_OFFS_WRITEBUF_MAX = UART_HW_IFACE_OFFS_WRITEBUF +.equ UART_HW_IFACE_OFFS_WRITEBUF_USED = UART_HW_IFACE_OFFS_WRITEBUF+1 +.equ UART_HW_IFACE_OFFS_WRITEBUF_RDPOS = UART_HW_IFACE_OFFS_WRITEBUF+2 +.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_SIZE = UART_HW_IFACE_OFFS_WRITEBUF_DATA+UART_HW_IFACE_WRITEBUF_SIZE +.equ UART_HW_IFACE_OFFS_READMSG = UART_HW_IFACE_OFFS_WRITEBUF_DATA+UART_HW_IFACE_WRITEBUF_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 + +.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 +.equ UART_HW_IFACE_OFFS_WRITEMSG_USED = UART_HW_IFACE_OFFS_WRITEMSG+3 ; 1 byte +.equ UART_HW_IFACE_OFFS_WRITEMSG_LEFT = UART_HW_IFACE_OFFS_WRITEMSG+4 ; 1 byte + +.equ UART_HW_IFACE_SIZE = UART_HW_IFACE_OFFS_WRITEMSG_LEFT+1 diff --git a/avr/modules/uart_hw/lowlevel.asm b/avr/modules/uart_hw/lowlevel.asm index 403d121..842eea7 100644 --- a/avr/modules/uart_hw/lowlevel.asm +++ b/avr/modules/uart_hw/lowlevel.asm @@ -27,7 +27,7 @@ UART_HW_Init: rcall Utils_FillSram rcall UART_HW_FixedBuffers_Init - + ldi r16, UART_HW_MSGNUMINBUF_SIZE ldi yl, LOW(uartHw_ringBufferMsgNumIn) ldi yh, HIGH(uartHw_ringBufferMsgNumIn) @@ -37,7 +37,8 @@ UART_HW_Init: ldi yl, LOW(uartHw_ringBufferMsgNumOut) ldi yh, HIGH(uartHw_ringBufferMsgNumOut) rcall RingBufferY_Init - + + sec ret ; @end @@ -67,6 +68,9 @@ UART_HW_InterfaceInit: UART_HW_IFACE_OFFS_WRITEBUF_RDPOS, \ UART_HW_IFACE_OFFS_WRITEBUF_WRPOS, \ UART_HW_IFACE_OFFS_WRITEBUF_DATA + ldi r16, 0xff + std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16 + std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r16 ret ; @end @@ -84,7 +88,7 @@ UART_HW_InterfaceWriteToReadBuffer: push yl push yh adiw yh:yl, UART_HW_IFACE_OFFS_READBUF - rcall RingBufferY_WriteByte ; R17, R18, X + rcall uartHwRingBufferWriteGuarded ; R17, R18, X pop yh pop yl ret @@ -104,7 +108,7 @@ UART_HW_InterfaceReadFromReadBuffer: push yl push yh adiw yh:yl, UART_HW_IFACE_OFFS_READBUF - rcall RingBufferY_ReadByte ; R17, R18, X + rcall uartHwRingBufferReadGuarded ; R17, R18, X pop yh pop yl ret @@ -124,7 +128,7 @@ UART_HW_InterfaceWriteToWriteBuffer: push yl push yh adiw yh:yl, UART_HW_IFACE_OFFS_WRITEBUF - rcall RingBufferY_WriteByte ; R17, R18, X + rcall uartHwRingBufferWriteGuarded ; R17, R18, X pop yh pop yl ret @@ -144,7 +148,7 @@ UART_HW_InterfaceReadFromWriteBuffer: push yl push yh adiw yh:yl, UART_HW_IFACE_OFFS_WRITEBUF - rcall RingBufferY_ReadByte ; R17, R18, X + rcall uartHwRingBufferReadGuarded ; R17, R18, X pop yh pop yl ret @@ -152,6 +156,67 @@ UART_HW_InterfaceReadFromWriteBuffer: +UART_HW_Interface_Run: + + + + +; --------------------------------------------------------------------------- +; @routine uartHwRingBufferReadGuarded +; +; @return CFLAG on success, cleared on error +; @param r16 byte to write +; @param Y pointer to start of interface data +; @clobbers R17, R18, X + +uartHwRingBufferReadGuarded: + push r15 + in r15, SREG + cli + rcall RingBufferY_ReadByte ; R17, R18, X + brcc uartHwRingBufferReadGuarded_error + out SREG, r15 + pop r15 + sec + ret +uartHwRingBufferReadGuarded_error: + out SREG, r15 + pop r15 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwRingBufferWriteGuarded +; +; @return CFLAG on success, cleared on error +; @param r16 byte to write +; @param Y pointer to start of interface data +; @clobbers R17, R18, X + +uartHwRingBufferWriteGuarded: + push r15 + in r15, SREG + cli + rcall RingBufferY_WriteByte ; R17, R18, X + brcc uartHwRingBufferWriteGuarded_error + out SREG, r15 + pop r15 + sec + ret +uartHwRingBufferWriteGuarded_error: + out SREG, r15 + pop r15 + clc + ret +; @end + + + + + diff --git a/avr/modules/uart_hw/lowlevel_tty.asm b/avr/modules/uart_hw/lowlevel_tty.asm index a488ca5..3a96f1c 100644 --- a/avr/modules/uart_hw/lowlevel_tty.asm +++ b/avr/modules/uart_hw/lowlevel_tty.asm @@ -119,7 +119,7 @@ UART_HW_TtyOn1_StopTx: UART_HW_TtyOn1_RxCharIsr: sbis UCSR1A, RXC1 - rjmp UART_HW_TtyOn1_RxCharIsr_end ; no data + rjmp UART_HW_TtyOn1_RxCharIsr_end ; no data in r16, UDR1 rcall UART_HW_InterfaceAddReadByte ; (R17, R18, X) UART_HW_TtyOn1_RxCharIsr_end: diff --git a/avr/modules/uart_hw/lowlevel_uart1.asm b/avr/modules/uart_hw/lowlevel_uart1.asm index 15f85ee..439ddfa 100644 --- a/avr/modules/uart_hw/lowlevel_uart1.asm +++ b/avr/modules/uart_hw/lowlevel_uart1.asm @@ -20,8 +20,7 @@ UART_HW_Uart1_StartRx: lds r16, UCSR1B - sbr r16, (1< 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 + rjmp UART_HW_Uart1_RxCharIsr_end ; no data lds r16, UDR1 - rcall UART_HW_InterfaceWriteToReadBuffer ; (R17, R18, X) + 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 + 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: ret diff --git a/avr/modules/uart_hw/msglevel_recv.asm b/avr/modules/uart_hw/msglevel_recv.asm new file mode 100644 index 0000000..cac2516 --- /dev/null +++ b/avr/modules/uart_hw/msglevel_recv.asm @@ -0,0 +1,280 @@ +; *************************************************************************** +; 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. * +; *************************************************************************** + + +.cseg + + +UART_HW_Interface_RunRead: + rcall uartHwReadEnsureBuffer ; (r16, R17, X) + brcc UART_HW_Interface_RunRead_end + rcall uartHwReadEnsureHeader ; (r16, r17, r20, r21, X) + brcc UART_HW_Interface_RunRead_end + rcall uartHwReadEnsureBody ; (r16, r17, r20, r21, x) + brcc UART_HW_Interface_RunRead_end +UART_HW_Interface_RunRead_HaveMsg: + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_USED + cpi r16, 3 + brcs UART_HW_Interface_RunRead_badMsg + ; check and store msg + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + rcall UART_HW_AddIncomingMsgNum ; (R17, R18, X) + brcs UART_HW_Interface_RunRead_clearBuf + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + rcall UART_HW_FixedBuffers_ReleaseByNum ; (R16, X) +UART_HW_Interface_RunRead_clearBuf: + ldi r16, 0xff + std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16 + rjmp UART_HW_Interface_RunRead_end +UART_HW_Interface_RunRead_badMsg: + ; reset READ buffer settings, enter skip mode + rcall uartHwResetBufferStartSkipping ; (r16, X) +UART_HW_Interface_RunRead_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwEnsureReadBuffer +; +; @param Y pointer to start of interface data +; @clobbers r16 (R17, X) + +uartHwReadEnsureBuffer: + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + cpi r16, 0xff + breq uartHwReadEnsureBuffer_alloc +uartHwReadEnsureBuffer_SecRet: + sec + ret +uartHwReadEnsureBuffer_alloc: + rcall uartHwAllocateReadBuffer ; (r16, R17, X) + brcc uartHwReadEnsureBuffer_error + rcall uartHwReadSetBuffer ; (r16) + rjmp uartHwReadEnsureBuffer_SecRet +uartHwReadEnsureBuffer_error: + ; no buffer, set error status, skip msg + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + rcall UART_HW_FixedBuffers_Locate ; (r16) + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + rcall uartHwReadResetBuffer ; (r16) + ldd r16, Y+UART_HW_IFACE_OFFS_MODE + ori r16, UART_HW_MODE_SKIPPING + std Y+UART_HW_IFACE_OFFS_MODE, r16 + ldd r16, Y+UART_HW_IFACE_OFFS_ERR_OVR + inc r16 + breq UART_HW_Interface_RunRead_end + std Y+UART_HW_IFACE_OFFS_ERR_OVR, r16 + clc +uartHwReadEnsureBuffer_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwReadSetBuffer +; +; @param Y pointer to start of interface data +; @param X pointer to start of buffer +; @param r16 buffer number +; @clobbers r16 + +uartHwReadSetBuffer: + std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16 ; set buffer data + adiw xh:xl, 1 + std Y+UART_HW_IFACE_OFFS_READMSG_PTR, xl + std Y+UART_HW_IFACE_OFFS_READMSG_PTR+1, xh + sbiw xh:xl, 1 + clr r16 + std Y+UART_HW_IFACE_OFFS_READMSG_USED, r16 + std Y+UART_HW_IFACE_OFFS_READMSG_LEFT, r16 + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwReadResetBuffer +; +; @param Y pointer to start of interface data +; @clobbers r16, X + +uartHwReadResetBuffer: + ; reset READ buffer settings, enter skip mode + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + rcall UART_HW_FixedBuffers_Locate ; (X) + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM + rjmp uartHwReadSetBuffer ; (r16) +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwResetBufferStartSkipping +; +; @param Y pointer to start of interface data +; @clobbers r16, X + +uartHwResetBufferStartSkipping: + ; reset READ buffer settings, enter skip mode + rcall uartHwReadResetBuffer + ldd r16, Y+UART_HW_IFACE_OFFS_MODE + ori r16, UART_HW_MODE_SKIPPING + std Y+UART_HW_IFACE_OFFS_MODE, r16 + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwReadEnsureHeader +; +; @param Y pointer to start of interface data +; @clobbers r16 (r17, r20, r21, X) + +uartHwReadEnsureHeader: + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_LEFT + tst r16 + breq uartHwReadEnsureHeader_readHeader + sec + ret +uartHwReadEnsureHeader_readHeader: + ; read and validate header (2 bytes) + rcall uartHwReadAndValidateHeader ; (r16, r17, r20, r21, X) + brcc UART_HW_Interface_RunRead_badMsg + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_USED + cpi r16, 2 ; full header in buffer (2 bytes)? + brcs UART_HW_Interface_RunRead_end ; nope, done for this round +uartHwReadEnsureHeader_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwReadEnsureBody +; +; @param Y pointer to start of interface data +; @clobbers r20 (r16, r17, r21, x) + +uartHwReadEnsureBody: + ldd r20, Y+UART_HW_IFACE_OFFS_READMSG_LEFT + tst r20 + sec + breq uartHwReadEnsureBody_end ; no bytes left, message done + rcall uartHwReadUptoNumBytes ; (r16, r17, r20, r21, X) + ldd r20, Y+UART_HW_IFACE_OFFS_READMSG_LEFT + tst r20 + sec + breq uartHwReadEnsureBody_end ; no bytes left, message done + clc +uartHwReadEnsureBody_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwAllocateReadBuffer +; +; @param Y pointer to start of interface data +; @clobbers r16 (R17, X) + +uartHwAllocateReadBuffer: + rcall UART_HW_FixedBuffers_Alloc ; (R16, R17, X) + brcc uartHwAllocateReadBuffer_end + std Y+UART_HW_IFACE_OFFS_READMSG_BUFNUM, r16 + adiw xh:xl, 1 + std Y+UART_HW_IFACE_OFFS_READMSG_PTR, xl + std Y+UART_HW_IFACE_OFFS_READMSG_PTR+1, xh + clr r16 + std Y+UART_HW_IFACE_OFFS_READMSG_USED, r16 + std Y+UART_HW_IFACE_OFFS_READMSG_LEFT, r16 + sec +uartHwAllocateReadBuffer_end: + ret +; @end + + + + +; --------------------------------------------------------------------------- +; @routine uartHwReadAndValidateHeader +; +; @param Y pointer to start of interface data +; @clobbers r16, r20, X (r17, r21) + +uartHwReadAndValidateHeader: + ; read until we have 2 bytes + ldi r20, 2 + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_USED + sub r20, r16 + rcall uartHwReadUptoNumBytes ; (r16, r17, r20, r21, X) + ; check whether we have 2 bytes + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_USED + cpi r16, 2 + brcs uartHwReadAndValidateHeader_ok ; < 2 bytes in buffer, nothing to do + ; read and check msg len + ldd xl, Y+UART_HW_IFACE_OFFS_READMSG_PTR + ldd xh, Y+UART_HW_IFACE_OFFS_READMSG_PTR+1 + sbiw xh:xl, 1 ; go back one byte, pointing to MSG_LEN + ld r16, X + cpi r16, UART_HW_FIXEDBUFFERS_SIZE-4 ; minus buffer status byte, dest addr, msglen, crc + brcc uartHwReadAndValidateHeader_error ; bad msg length + ; set number of bytes left to read + inc r16 ; account for crc byte + std Y+UART_HW_IFACE_OFFS_READMSG_LEFT, r16 +uartHwReadAndValidateHeader_ok: + sec + ret +uartHwReadAndValidateHeader_error: + clc + ret +; @end + + + + +; --------------------------------------------------------------------------- +; @routine uartHwReadUptoNumBytes +; +; @param Y pointer to start of interface data +; @param R20 number of bytes to read +; @clobbers r16, r20, r21, X (R17) + +uartHwReadUptoNumBytes: + clr r21 + ldd xl, Y+UART_HW_IFACE_OFFS_READMSG_PTR + ldd xh, Y+UART_HW_IFACE_OFFS_READMSG_PTR+1 +uartHwReadUptoNumBytes_loop: + push xl + push xh + rcall UART_HW_InterfaceReadFromWriteBuffer ; (R17, R18, X) + pop xh + pop xl + brcc uartHwReadUptoNumBytes_done + st X+, r16 + inc r21 + dec r20 + brne uartHwReadUptoNumBytes_loop +uartHwReadUptoNumBytes_done: + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_USED + add r16, r21 + std Y+UART_HW_IFACE_OFFS_READMSG_USED, r16 + ldd r16, Y+UART_HW_IFACE_OFFS_READMSG_LEFT + sub r16, r21 + std Y+UART_HW_IFACE_OFFS_READMSG_LEFT, r16 ; might become negative when reading header + std Y+UART_HW_IFACE_OFFS_READMSG_PTR, xl + std Y+UART_HW_IFACE_OFFS_READMSG_PTR+1, xh + ret +; @end + + diff --git a/avr/modules/uart_hw/msglevel_send.asm b/avr/modules/uart_hw/msglevel_send.asm new file mode 100644 index 0000000..a43ea31 --- /dev/null +++ b/avr/modules/uart_hw/msglevel_send.asm @@ -0,0 +1,86 @@ +; *************************************************************************** +; 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. * +; *************************************************************************** + + +.cseg + + +; --------------------------------------------------------------------------- +; @routine UART_HW_Interface_RunWrite @global +; +; @param Y pointer to start of interface data +; @clobbers r16, r19, X (R17, R18, R20, R21) + +UART_HW_Interface_RunWrite: + ldd r19, Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM + cpi r19, 0xff + brne UART_HW_Interface_RunWrite_haveMsg + rcall UART_HW_GetNextOutgoingMsgNum ; (R17, R18, X) + rcall UART_HW_FixedBuffers_Locate ; (R16) + brcc UART_HW_Interface_RunWrite_end + std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r19 + adiw xh:xl, 1 + std Y+UART_HW_IFACE_OFFS_WRITEMSG_PTR, xl + std Y+UART_HW_IFACE_OFFS_WRITEMSG_PTR+1, xh + adiw xh:xl, 1 ; get msg len + ld r16, X + inc r16 + inc r16 + inc r16 + std Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT, r16 + std Y+UART_HW_IFACE_OFFS_WRITEMSG_USED, r16 +UART_HW_Interface_RunWrite_haveMsg: + 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 + tst r16 + brne UART_HW_Interface_RunWrite_end ; still bytes left to write + ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM + rcall UART_HW_FixedBuffers_ReleaseByNum + ldi r16, 0xff ; reset buffer number + std Y+UART_HW_IFACE_OFFS_WRITEMSG_BUFNUM, r16 +UART_HW_Interface_RunWrite_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine uartHwWriteUptoNumBytes +; +; @param Y pointer to start of interface data +; @param R20 number of bytes to read +; @clobbers r16, r20, r21, X (R17, R18) + +uartHwWriteUptoNumBytes: + clr r21 + ldd xl, Y+UART_HW_IFACE_OFFS_WRITEMSG_PTR + ldd xh, Y+UART_HW_IFACE_OFFS_WRITEMSG_PTR+1 +uartHwWriteUptoNumBytes_loop: + ld r16, X+ + push xl + push xh + rcall UART_HW_InterfaceWriteToWriteBuffer ; (R17, R18, X) + pop xh + pop xl + brcc uartHwWriteUptoNumBytes_done + inc r21 + dec r20 + brne uartHwWriteUptoNumBytes_loop +uartHwWriteUptoNumBytes_done: + ldd r16, Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT + sub r16, r21 + std Y+UART_HW_IFACE_OFFS_WRITEMSG_LEFT, r16 + std Y+UART_HW_IFACE_OFFS_WRITEMSG_PTR, xl + std Y+UART_HW_IFACE_OFFS_WRITEMSG_PTR+1, xh + ret +; @end + + +