.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_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