Serial: move ringbuffer logic into a separate header file.
This way we can re-use these macros elsewhere.
This commit is contained in:
parent
e71eab04d0
commit
1daaad2447
|
|
@ -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. <name>head,
|
||||
<name>tail and <name>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)
|
||||
55
serial-avr.c
55
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue