90 lines
2.0 KiB
C
90 lines
2.0 KiB
C
#ifndef RINGBUFFER_H_
|
|
#define RINGBUFFER_H_
|
|
|
|
/**
|
|
* \brief Ringbuffer Datenstruktur
|
|
* \file ringbuffer.h
|
|
*
|
|
* Diese Datei ist eine Hilfestellung für Aufgabe 2.
|
|
* Sie erspart euch den Aufwand, selber einen Ringbuffer zu implementieren.
|
|
*/
|
|
|
|
struct ring_buff {
|
|
unsigned int head;
|
|
unsigned int tail;
|
|
unsigned int size;
|
|
unsigned int mask;
|
|
char *buffer;
|
|
};
|
|
|
|
/**
|
|
* \brief Überprüft ob eine positive Zahl eine Zweierpotenz ist
|
|
*
|
|
* Beispiel: (0b100 & 0b011) == 0b000.
|
|
*/
|
|
#define is_power_of_two(val) (((val) & ((val) - 1)) == 0)
|
|
|
|
/**
|
|
* \brief Macro um einen Ringbuffer zu erstellen
|
|
* \param name Bezeichnung des Buffers
|
|
* \param size Größe des Buffers
|
|
*
|
|
*/
|
|
#define create_ringbuffer(name, size) \
|
|
static_assert((size) >= 1, "Size of Ringbuffer has to be at least 1"); \
|
|
static_assert(is_power_of_two(size), "Size of Ringbuffer has to be a power of 2"); \
|
|
static char _b_##name[size]; \
|
|
static struct ring_buff _##name = { 0, 0, (size), (size) - 1, _b_##name }; \
|
|
static volatile struct ring_buff *name = &_##name
|
|
|
|
[[nodiscard]] static bool buff_is_empty(volatile struct ring_buff *b)
|
|
{
|
|
return b->head == b->tail;
|
|
}
|
|
|
|
[[nodiscard]] static bool buff_is_full(volatile struct ring_buff *b)
|
|
{
|
|
return ((b->tail & b->mask) == (b->head & b->mask)) && !buff_is_empty(b);
|
|
}
|
|
|
|
static bool buff_putc(volatile struct ring_buff *b, char c)
|
|
{
|
|
if (buff_is_full(b)) {
|
|
return true;
|
|
}
|
|
|
|
b->buffer[b->head & b->mask] = c;
|
|
b->head++;
|
|
|
|
return false;
|
|
}
|
|
|
|
static char buff_getc(volatile struct ring_buff *b)
|
|
{
|
|
while (buff_is_empty(b)) {
|
|
}
|
|
|
|
char c = b->buffer[b->tail & b->mask];
|
|
b->tail++;
|
|
|
|
return c;
|
|
}
|
|
|
|
[[nodiscard, maybe_unused]] static char buff_peekc(volatile struct ring_buff *b)
|
|
{
|
|
while (buff_is_empty(b)) {
|
|
}
|
|
|
|
return b->buffer[b->tail & b->mask];
|
|
}
|
|
|
|
[[nodiscard, maybe_unused]] static char buff_peekc_last(volatile struct ring_buff *b)
|
|
{
|
|
while (buff_is_empty(b)) {
|
|
}
|
|
|
|
return b->buffer[(b->head - 1) & b->mask];
|
|
}
|
|
|
|
#endif
|