started reorganizing code into subfolders.
This commit is contained in:
255
avr/common/ringbuffer.asm
Normal file
255
avr/common/ringbuffer.asm
Normal file
@@ -0,0 +1,255 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.equ RINGBUFFER_OFFS_MAXSIZE = 0
|
||||
.equ RINGBUFFER_OFFS_USED = 1
|
||||
.equ RINGBUFFER_OFFS_READPOS = 2
|
||||
.equ RINGBUFFER_OFFS_WRITEPOS = 3
|
||||
.equ RINGBUFFER_OFFS_DATA = 4
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
RINGBUFFER_BEGIN:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; RingBuffer_Init
|
||||
;
|
||||
; IN:
|
||||
; - Y: base address of the ringbuffer in SRAM
|
||||
; - R16: maximum size in bytes (pure data excluding headers like pos pointers etc).
|
||||
; OUT:
|
||||
; - R16: pos of allocated buffer
|
||||
; REGISTERS MODIFIED: r16, r17, r18, r19, r20, r21
|
||||
RingBuffer_Init:
|
||||
clr r17
|
||||
std y+RINGBUFFER_OFFS_MAXSIZE, r16
|
||||
std y+RINGBUFFER_OFFS_USED, r17
|
||||
std y+RINGBUFFER_OFFS_READPOS, r17
|
||||
std y+RINGBUFFER_OFFS_WRITEPOS, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; RingBuffer_Alloc
|
||||
;
|
||||
; IN:
|
||||
; - Y: base address of the ringbuffer in SRAM
|
||||
; - R16: number of bytes to allocate
|
||||
; OUT:
|
||||
; - R16: pos of allocated buffer
|
||||
; REGISTERS MODIFIED: r16, r17, r18, r19, r20, r21
|
||||
|
||||
RingBuffer_Alloc:
|
||||
in r21, SREG ; save global interrupt enable bit from SREG
|
||||
cli
|
||||
ldd r17, y+RINGBUFFER_OFFS_MAXSIZE
|
||||
ldd r18, y+RINGBUFFER_OFFS_USED
|
||||
ldd r19, y+RINGBUFFER_OFFS_WRITEPOS
|
||||
|
||||
cpi r16, 2 ; alloc at least two bytes
|
||||
brcs RingBuffer_Alloc_error ; too few bytes
|
||||
|
||||
mov r20, r16 ; to_alloc
|
||||
add r20, r18 ; to_alloc + used
|
||||
cp r20, r17 ; new_used < max?
|
||||
brcc RingBuffer_Alloc_error
|
||||
|
||||
std y+RINGBUFFER_OFFS_USED, r20
|
||||
mov r20, r19 ; current write pos (for later)
|
||||
add r19, r16 ; current_writepos+to_alloc
|
||||
cp r19, r17 ; new_writepos < max?
|
||||
brcs RingBuffer_Alloc_l1
|
||||
sub r19, r17
|
||||
RingBuffer_Alloc_l1:
|
||||
std y+RINGBUFFER_OFFS_WRITEPOS, r19
|
||||
mov r16, r20
|
||||
|
||||
; preset first byte (this is the length byte in COM module) with 0
|
||||
push r16
|
||||
mov r18, r16
|
||||
clr r16
|
||||
rcall RingBuffer_Write
|
||||
rcall RingBuffer_Write
|
||||
pop r16
|
||||
|
||||
out SREG, r21 ; restore global interrupt enable bit in SREG
|
||||
sec
|
||||
ret
|
||||
|
||||
RingBuffer_Alloc_error:
|
||||
out SREG, r21
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; RingBuffer_DeallocRead
|
||||
;
|
||||
; IN:
|
||||
; - Y: base address of the ringbuffer in SRAM
|
||||
; - R16: number of bytes to deallocate (e.g. number of bytes to skip in read ptr)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGISTERS MODIFIED: r17, r18, r19, r20, r21
|
||||
|
||||
RingBuffer_DeallocRead:
|
||||
in r21, SREG
|
||||
cli
|
||||
ldd r17, y+RINGBUFFER_OFFS_MAXSIZE
|
||||
ldd r18, y+RINGBUFFER_OFFS_USED
|
||||
ldd r19, y+RINGBUFFER_OFFS_READPOS
|
||||
|
||||
mov r20, r18
|
||||
sub r20, r16 ; used - to_dealloc
|
||||
brcs RingBuffer_DeallocRead_error ; overflow -> error
|
||||
std y+RINGBUFFER_OFFS_USED, r20
|
||||
mov r20, r19 ; readpos
|
||||
add r20, r16 ; readpos + to_dealloc
|
||||
cp r20, r17 ; new readpos > max?
|
||||
brcs RingBuffer_DeallocRead_l1 ; no, rjmp
|
||||
sub r20, r17 ; wrap around
|
||||
RingBuffer_DeallocRead_l1:
|
||||
std y+RINGBUFFER_OFFS_READPOS, r20
|
||||
out SREG, r21
|
||||
sec
|
||||
ret
|
||||
|
||||
RingBuffer_DeallocRead_error:
|
||||
out SREG, r21
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; RingBuffer_DeallocWrite
|
||||
;
|
||||
; IN:
|
||||
; - Y: base address of the ringbuffer in SRAM
|
||||
; - R16: number of bytes to deallocate (e.g. number of bytes to move back write ptr)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGISTERS MODIFIED: r17, r18, r19, r20, r21
|
||||
|
||||
RingBuffer_DeallocWrite:
|
||||
in r21, SREG
|
||||
cli
|
||||
ldd r17, y+RINGBUFFER_OFFS_MAXSIZE
|
||||
ldd r18, y+RINGBUFFER_OFFS_USED
|
||||
ldd r19, y+RINGBUFFER_OFFS_WRITEPOS
|
||||
|
||||
mov r20, r18 ; used
|
||||
sub r20, r16 ; used - to_dealloc
|
||||
brcs RingBuffer_DeallocWrite_error ; overflow -> error
|
||||
std y+RINGBUFFER_OFFS_USED, r20
|
||||
mov r20, r19 ; writepos
|
||||
sub r20, r16 ; writepos - to_dealloc
|
||||
brcc RingBuffer_DeallocWrite_l1 ; no, rjmp
|
||||
add r20, r17 ; wrap around
|
||||
RingBuffer_DeallocWrite_l1:
|
||||
std y+RINGBUFFER_OFFS_WRITEPOS, r20
|
||||
out SREG, r21
|
||||
sec
|
||||
ret
|
||||
|
||||
RingBuffer_DeallocWrite_error:
|
||||
out SREG, r21
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; RingBuffer_Write
|
||||
;
|
||||
; Write a byte into the ringbuffer.
|
||||
;
|
||||
; IN:
|
||||
; - Y: pointer to buffer
|
||||
; - R16: byte to write
|
||||
; - R18: pos pointer inside ring buffer to write to next
|
||||
; - R19: maximum size of the ringbuffer (for wrap-around)
|
||||
; OUT:
|
||||
; - R18: incremented pos pointer inside ringbuffer
|
||||
; MODIFIED REGS: r3, r22
|
||||
|
||||
RingBuffer_Write:
|
||||
push yh
|
||||
push yl
|
||||
clr r3
|
||||
ldi r22, RINGBUFFER_OFFS_DATA
|
||||
add yl, r22
|
||||
adc yh, r3
|
||||
add yl, r18
|
||||
adc yh, r3
|
||||
st y, r16
|
||||
pop yl
|
||||
pop yh
|
||||
inc r18
|
||||
cp r18, r19 ; r19 > r18; yes: CF set
|
||||
brcs RingBuffer_Write_end
|
||||
sub r18, r19
|
||||
|
||||
RingBuffer_Write_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; RingBuffer_Read
|
||||
;
|
||||
; Read a byte from the ringbuffer.
|
||||
;
|
||||
; IN:
|
||||
; - Y: pointer to buffer
|
||||
; - R18: pos pointer inside ring buffer to read from next
|
||||
; - R19: maximum size of the ringbuffer (for wrap-around)
|
||||
; OUT:
|
||||
; - R16: byte read
|
||||
; - R18: incremented pos pointer inside ringbuffer
|
||||
; MODIFIED REGS: r3, r22
|
||||
|
||||
RingBuffer_Read:
|
||||
push yh
|
||||
push yl
|
||||
clr r3
|
||||
ldi r22, RINGBUFFER_OFFS_DATA
|
||||
add yl, r22
|
||||
adc yh, r3
|
||||
add yl, r18
|
||||
adc yh, r3
|
||||
ld r16, y
|
||||
pop yl
|
||||
pop yh
|
||||
inc r18
|
||||
cp r18, r19
|
||||
brcs RingBuffer_Read_end
|
||||
sub r18, r19
|
||||
|
||||
RingBuffer_Read_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
RINGBUFFER_END:
|
||||
.equ MODULE_SIZE_RINGBUFFER = RINGBUFFER_END-RINGBUFFER_BEGIN
|
||||
|
||||
|
||||
Reference in New Issue
Block a user