; *************************************************************************** ; copyright : (C) 2023 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. * ; *************************************************************************** ; =========================================================================== ; ; Macros for working with message buffers. ; ; Helpfull defines: ; - COM2_BUFFER_NUM number of buffers to provide ; - COM2_BUFFER_SIZE size of each buffer (CAVE: change COM2_M_BufferPosToX when changing value!) ; ; Variables: ; - buffersUsed: .byte 1 holds number of buffers in use ; - maxBuffersUsed: .byte 1 holds max number of buffers every in use at the same time ; - buffersWritePos: .byte 1 holds current write pos ; - buffersReadPos: .byte 1 holds current read pos ; - buffers: .byte COM2_BUFFER_SIZE*COM2_BUFFER_NUM ; --------------------------------------------------------------------------- ; @macro COM2_M_BufferAlloc ; ; Allocate a message buffer. ; ; COM2_M_BufferAlloc COM2_BUFFER_NUM, com2MaxBuffersUsed, com2RecvBuffersUsed, com2RecvBuffersWritePos ; ; @param %0 max number of buffers ; @param %1 pointer to byte containing max number of buffers ever used ; @param %2 pointer to byte containing number of buffers currently in use ; @param %3 pointer to byte containing the write pointer ; @param %4 pointer to routine to calculate buffer pos (e.g. uartBitbang_BufferPosToX) ; @return CFLAG set if okay, clear otherwise ; @return X pos to allocated buffer ; @clobbers R16, R17, R21 .macro COM2_M_BufferAlloc in r21, SREG ; save global interrupt enable bit from SREG cli lds r17, @2 cpi r17, @0 brcc l_error ; no buffer available inc r17 ; increment number of buffers used sts @2, r17 ; store new value lds r16, @1 ; calc max buffers used cp r16, r17 brcc l0 sts @1, r17 l0: lds r16, @3 ; get current write pos mov r17, r16 ; increment for next call inc r17 cpi r17, @0 ; CF set if COM_BUFFER_NUM > R17 brcs l1 clr r17 ; wraparound l1: sts @3, r17 ; store new writepos for next caller rcall @4 ; *_BufferPosToX(R16, R17) out SREG, r21 ; restore global interrupt enable bit in SREG sec rjmp l_end l_error: out SREG, r21 clc l_end: .endmacro ; @end ; --------------------------------------------------------------------------- ; @macro COM2_M_BufferDeallocBack ; ; Release a transfer buffer at the end of the list by decreasing the write pos. ; This releases the last allocated buffer! ; ; COM2_M_BufferDeallocBack COM2_BUFFER_NUM, com2RecvBuffersUsed, com2RecvBuffersWritePos ; ; @param %0 maximum number of buffers ; @param %1 pointer to a byte containing number of buffers used ; @param %2 pointer to a byte containing current write pos ; @return CFLAG set if okay, clear otherwise ; @clobbers r16, r17, r21 .macro COM2_M_BufferDeallocBack in r21, SREG ; save global interrupt enable bit from SREG cli lds r17, @1 tst r17 breq l_error ; no buffer allocated, nothing to release dec r17 sts @1, r17 ; store new value lds r17, @2 tst r17 ; 0? brne l1 ; nope go directly decrement r17 ldi r17, @0 ; wrap-around l1: dec r17 sts @2, r17 out SREG, r21 sec rjmp l_end l_error: out SREG, r21 clc l_end: .endmacro ; @end ; --------------------------------------------------------------------------- ; @macro COM2_M_BufferDeallocFront ; ; Release a transfer buffer by increasing the read pos. ; ; COM2_M_BufferDeallocFront COM2_BUFFER_NUM com2RecvBuffersUsed com2RecvBuffersReadPos ; ; @param %0 maximum number of buffers ; @param %1 pointer to a byte containing number of buffers used ; @param %2 pointer to a byte containing current read pos ; @return CFLAG set if okay, clear otherwise ; @clobbers r16, r17, r21 .macro COM2_M_BufferDeallocFront in r21, SREG ; save global interrupt enable bit from SREG cli lds r17, @1 tst r17 breq l_error ; no buffer allocated, nothing to release dec r17 sts @1, r17 ; store new value lds r17, @2 inc r17 cpi r17, @0 brcs l1 clr r17 ; wrap-around l1: sts @2, r17 out SREG, r21 sec rjmp l_end l_error: out SREG, r21 clc l_end: .endmacro ; @end ; --------------------------------------------------------------------------- ; @macro COM2_M_BufferPosToX ; ; Get a pointer to the SRAM position of the given buffer. ; CAVE: Code must correspond to COM2_BUFFER_SIZE!! ; ; COM2_M_BufferPosToX com2RecvBuffers ; ; @param %0 pointer to a 2 byte var containing pointer to buffers ; @param R16 buffer number (starting with 0) ; @return X pointer to buffer in SRAM ; @clobbers R16, R17 .macro COM2_M_BufferPosToX ; calculate offset clr r17 mov xl, r16 clr xh lsl xl rol xh ; *2 add xl, r16 adc xh, r17 ; *3 lsl xl rol xh ; *6 lsl xl rol xh ; *12 lsl xl rol xh ; *24 ; add base position of buffers ldi r16, LOW(@0) ldi r17, HIGH(@0) add xl, r16 adc xh, r17 .endmacro ; @end