256 lines
6.2 KiB
NASM
256 lines
6.2 KiB
NASM
; ***************************************************************************
|
|
; 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
|
|
|
|
|