Quantcast
Channel: MSP430 Technical Forums
Viewing all articles
Browse latest Browse all 2077

A more efficient circular FIFO buffer

$
0
0

For my purposes I just needed a simple FIFO buffer, but implementations I saw either wasted a byte of buffer space, required extra fields or were not very performant. This implementation provides full and empty conditions, a count (if you need it, I did not test it, just fair warning). You can add/remove bytes efficiently even if your buffer is not a power of 2 size.

#ifndef __REVRING_H__
#define __REVRING_H__

#include <stdint.h>

/** @brief Ring buffer that decrements indices as data is stored. */
struct revring_s {
	unsigned head;
	unsigned tail;
	unsigned buffer_size;
	uint8_t buffer[];
};

/** @brief Initialize reverse ring buffer. */
void revring_init(struct revring_s* rr, unsigned buffer_size);

static unsigned revring_empty(const struct revring_s* rr);

static unsigned revring_full(const struct revring_s* rr);

static unsigned revring_count(const struct revring_s* rr);

void revring_add_byte(struct revring_s* rr, uint8_t byte);

uint8_t revring_remove_byte(struct revring_s* rr);


static inline unsigned revring_empty(const struct revring_s* rr){
	return rr->head == rr->tail;
}

static inline unsigned revring_full(const struct revring_s* rr){
	return rr->head == 0;
}

static inline unsigned revring_count(const struct revring_s* rr){
	unsigned ret = rr->buffer_size;
	if(rr->head){
		ret += rr->tail;
		ret -= rr->head;
		ret %= rr->buffer_size;
	}
	return ret;
}
#endif
#include <assert.h>
#include "revring.h"

void revring_init(struct revring_s* rr, unsigned buffer_size){
	rr->head = buffer_size;
	rr->tail = buffer_size;
	rr->buffer_size = buffer_size;
}

void revring_add_byte(struct revring_s* rr, uint8_t byte){
	assert(!revring_full(rr));

	register unsigned idx = rr->head;
	--idx;
	rr->buffer[idx] = byte;

	if(0 == idx)
		idx = rr->buffer_size;
	if(rr->tail == idx)
		idx = 0;

	rr->head = idx;
}

uint8_t revring_remove_byte(struct revring_s* rr){
	assert(!revring_empty(rr));

	register unsigned idx = rr->tail;
	--idx;
	const uint8_t* ret = rr->buffer + idx;
	if(0 == idx)
		idx = rr->buffer_size;

	/* If full, then point head to where tail is currently. */
	if(revring_full(rr))
		rr->head = rr->tail;
	rr->tail = idx;
	return *ret;
}


Viewing all articles
Browse latest Browse all 2077

Trending Articles