diff --git a/ringbuffer.h b/ringbuffer.h new file mode 100644 index 0000000..bc39b14 --- /dev/null +++ b/ringbuffer.h @@ -0,0 +1,115 @@ +/** \file + \brief Header for implementing a ringbuffer. + + This header implements a macro-level ringbuffer. It's meant to be included + only in source files and only where needed. Such a sequence implements a + ringbuffer: + + #define BUFSIZE 64 + volatile uint8_t rxhead = 0; + volatile uint8_t rxtail = 0; + volatile uint8_t rxbuf[BUFSIZE]; + #include "ringbuffer.h" + + Requirements: + + - The name 'BUFSIZE' has to be kept exactly. One can use two or more + ringbuffers in the same source file, but they all have to be the same + size. + + - BUFSIZE has to be a power of two: 2, 4, 8, 16, 32, 64, 128 or 256. + + - In the example above, 'rx' is the name of the buffer. head, + tail and buf have to be named exactly. + + Ringbuffer logic: + + head = written data pointer. + tail = read data pointer. + + When head == tail, buffer is empty. + When head + 1 == tail, buffer is full. + Thus, number of available spaces in buffer is (tail - head) & bufsize. + + Can write: + (tail - head - 1) & (BUFSIZE - 1) + + Write to buffer: + buf[head++] = data; head &= (BUFSIZE - 1); + + Can read: + (head - tail) & (BUFSIZE - 1) + + Read from buffer: + data = buf[tail++]; tail &= (BUFSIZE - 1); +*/ + +/** \def buf_canread() + + Check if we can read from this buffer. Buffer pointers are left unchanged. + + Example: + + if (buf_canread(rx)) { + ... + } + +*/ +#define buf_canread(buffer) ((buffer ## head - buffer ## tail ) & \ + (BUFSIZE - 1)) + +/** \def buf_pop() + + Actually read a byte from this buffer. This also forwards the buffer pointer. + It's imperative to check for availabilty of a byte before. Pop'ing an + empty buffer means to go through the whle buffer again. + + Example: + + uint8_t next_byte; + + if (buf_canread(rx)) { + buf_pop(rx, next_byte); + } + +*/ +#define buf_pop(buffer, data) do { \ + data = buffer ## buf[buffer ## tail]; \ + buffer ## tail = (buffer ## tail + 1) & \ + (BUFSIZE - 1); \ + } while (0) + +/** \def buf_canwrite() + + Check if we can write to this buffer. Buffer pointers are left unchanged. + + Example: + + uint8_t data; + + if (buf_canwrite(tx)) { + printf("There's room in the buffer, please send data.\n"); + } + +*/ +#define buf_canwrite(buffer) ((buffer ## tail - buffer ## head - 1) & \ + (BUFSIZE - 1)) + +/** \def buf_push() + + Actually write to this buffer. This also forwards the buffer pointers. Like + with buf_pop() it's mandatory to test for available room before actually + writing, else valid data is overwritten. + + Example: + + void write_char_to_buffer(uint8_t data) { + if (buf_canwrite(tx)) + buf_push(tx, data); + } +*/ +#define buf_push(buffer, data) do { \ + buffer ## buf[buffer ## head] = data; \ + buffer ## head = (buffer ## head + 1) & \ + (BUFSIZE - 1); \ + } while (0) diff --git a/serial-avr.c b/serial-avr.c index 86df27d..acbdc0a 100644 --- a/serial-avr.c +++ b/serial-avr.c @@ -55,60 +55,7 @@ volatile uint8_t txhead = 0; volatile uint8_t txtail = 0; volatile uint8_t txbuf[BUFSIZE]; -/** Ringbuffer logic. - - head = written data pointer. - tail = read data pointer. - - When head == tail, buffer is empty. - When head + 1 == tail, buffer is full. - Thus, number of available spaces in buffer is (tail - head) & bufsize. - - Can write: - (tail - head - 1) & (BUFSIZE - 1) - - Write to buffer: - buf[head++] = data; head &= (BUFSIZE - 1); - - Can read: - (head - tail) & (BUFSIZE - 1) - - Read from buffer: - data = buf[tail++]; tail &= (BUFSIZE - 1); -*/ -/** \def buf_canread() - - Check if we can read from this buffer. -*/ -#define buf_canread(buffer) ((buffer ## head - buffer ## tail ) & \ - (BUFSIZE - 1)) - -/** \def buf_pop() - - Actually read from this buffer. -*/ -#define buf_pop(buffer, data) do { \ - data = buffer ## buf[buffer ## tail]; \ - buffer ## tail = (buffer ## tail + 1) & \ - (BUFSIZE - 1); \ - } while (0) - -/** \def buf_canwrite() - - Check if we can write to this buffer. -*/ -#define buf_canwrite(buffer) ((buffer ## tail - buffer ## head - 1) & \ - (BUFSIZE - 1)) - -/** \def buf_push() - - Actually write to this buffer. -*/ -#define buf_push(buffer, data) do { \ - buffer ## buf[buffer ## head] = data; \ - buffer ## head = (buffer ## head + 1) & \ - (BUFSIZE - 1); \ - } while (0) +#include "ringbuffer.h" #ifdef XONXOFF #define FLOWFLAG_STATE_XOFF 0