فهرست منبع

上传文件至 'stm32 环形缓冲'

添加环形缓冲区
kinve 2 سال پیش
والد
کامیت
791078afde
2فایلهای تغییر یافته به همراه221 افزوده شده و 0 حذف شده
  1. 78 0
      stm32 环形缓冲/ringbuffer.c
  2. 143 0
      stm32 环形缓冲/ringbuffer.h

+ 78 - 0
stm32 环形缓冲/ringbuffer.c

@@ -0,0 +1,78 @@
+#include "ringbuffer.h"
+
+/**
+ * @file
+ * Implementation of ring buffer functions.
+ */
+
+void ring_buffer_init(ring_buffer_t *buffer, char *buf, size_t buf_size) {
+  RING_BUFFER_ASSERT(RING_BUFFER_IS_POWER_OF_TWO(buf_size) == 1);
+  buffer->buffer = buf;
+  buffer->buffer_mask = buf_size - 1;
+  buffer->tail_index = 0;
+  buffer->head_index = 0;
+}
+
+void ring_buffer_queue(ring_buffer_t *buffer, char data) {
+  /* Is buffer full? */
+  if(ring_buffer_is_full(buffer)) {
+    /* Is going to overwrite the oldest byte */
+    /* Increase tail index */
+    buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK(buffer));
+  }
+
+  /* Place data in buffer */
+  buffer->buffer[buffer->head_index] = data;
+  buffer->head_index = ((buffer->head_index + 1) & RING_BUFFER_MASK(buffer));
+}
+
+void ring_buffer_queue_arr(ring_buffer_t *buffer, const char *data, ring_buffer_size_t size) {
+  /* Add bytes; one by one */
+  ring_buffer_size_t i;
+  for(i = 0; i < size; i++) {
+    ring_buffer_queue(buffer, data[i]);
+  }
+}
+
+uint8_t ring_buffer_dequeue(ring_buffer_t *buffer, char *data) {
+  if(ring_buffer_is_empty(buffer)) {
+    /* No items */
+    return 0;
+  }
+  
+  *data = buffer->buffer[buffer->tail_index];
+  buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK(buffer));
+  return 1;
+}
+
+ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, char *data, ring_buffer_size_t len) {
+  if(ring_buffer_is_empty(buffer)) {
+    /* No items */
+    return 0;
+  }
+
+  char *data_ptr = data;
+  ring_buffer_size_t cnt = 0;
+  while((cnt < len) && ring_buffer_dequeue(buffer, data_ptr)) {
+    cnt++;
+    data_ptr++;
+  }
+  return cnt;
+}
+
+uint8_t ring_buffer_peek(ring_buffer_t *buffer, char *data, ring_buffer_size_t index) {
+  if(index >= ring_buffer_num_items(buffer)) {
+    /* No items at index */
+    return 0;
+  }
+  
+  /* Add index to pointer */
+  ring_buffer_size_t data_index = ((buffer->tail_index + index) & RING_BUFFER_MASK(buffer));
+  *data = buffer->buffer[data_index];
+  return 1;
+}
+
+extern inline uint8_t ring_buffer_is_empty(ring_buffer_t *buffer);
+extern inline uint8_t ring_buffer_is_full(ring_buffer_t *buffer);
+extern inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer);
+

+ 143 - 0
stm32 环形缓冲/ringbuffer.h

@@ -0,0 +1,143 @@
+#include <inttypes.h>
+#include <stddef.h>
+#include <assert.h>
+/**
+ * @file
+ * Prototypes and structures for the ring buffer module.
+ */
+
+#ifndef RINGBUFFER_H
+#define RINGBUFFER_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define RING_BUFFER_ASSERT(x) assert(x)
+
+/**
+ * Checks if the buffer_size is a power of two.
+ * Due to the design only <tt> RING_BUFFER_SIZE-1 </tt> items
+ * can be contained in the buffer.
+ * buffer_size must be a power of two.
+*/
+#define RING_BUFFER_IS_POWER_OF_TWO(buffer_size) ((buffer_size & (buffer_size - 1)) == 0)
+
+/**
+ * The type which is used to hold the size
+ * and the indicies of the buffer.
+ */
+typedef size_t ring_buffer_size_t;
+
+/**
+ * Used as a modulo operator
+ * as <tt> a % b = (a & (b ? 1)) </tt>
+ * where \c a is a positive index in the buffer and
+ * \c b is the (power of two) size of the buffer.
+ */
+#define RING_BUFFER_MASK(rb) (rb->buffer_mask)
+
+/**
+ * Simplifies the use of <tt>struct ring_buffer_t</tt>.
+ */
+typedef struct ring_buffer_t ring_buffer_t;
+
+/**
+ * Structure which holds a ring buffer.
+ * The buffer contains a buffer array
+ * as well as metadata for the ring buffer.
+ */
+struct ring_buffer_t {
+  /** Buffer memory. */
+  char *buffer;
+  /** Buffer mask. */
+  ring_buffer_size_t buffer_mask;
+  /** Index of tail. */
+  ring_buffer_size_t tail_index;
+  /** Index of head. */
+  ring_buffer_size_t head_index;
+};
+
+/**
+ * Initializes the ring buffer pointed to by <em>buffer</em>.
+ * This function can also be used to empty/reset the buffer.
+ * @param buffer The ring buffer to initialize.
+ * @param buf The buffer allocated for the ringbuffer.
+ * @param buf_size The size of the allocated ringbuffer.
+ */
+void ring_buffer_init(ring_buffer_t *buffer, char *buf, size_t buf_size);
+
+/**
+ * Adds a byte to a ring buffer.
+ * @param buffer The buffer in which the data should be placed.
+ * @param data The byte to place.
+ */
+void ring_buffer_queue(ring_buffer_t *buffer, char data);
+
+/**
+ * Adds an array of bytes to a ring buffer.
+ * @param buffer The buffer in which the data should be placed.
+ * @param data A pointer to the array of bytes to place in the queue.
+ * @param size The size of the array.
+ */
+void ring_buffer_queue_arr(ring_buffer_t *buffer, const char *data, ring_buffer_size_t size);
+
+/**
+ * Returns the oldest byte in a ring buffer.
+ * @param buffer The buffer from which the data should be returned.
+ * @param data A pointer to the location at which the data should be placed.
+ * @return 1 if data was returned; 0 otherwise.
+ */
+uint8_t ring_buffer_dequeue(ring_buffer_t *buffer, char *data);
+
+/**
+ * Returns the <em>len</em> oldest bytes in a ring buffer.
+ * @param buffer The buffer from which the data should be returned.
+ * @param data A pointer to the array at which the data should be placed.
+ * @param len The maximum number of bytes to return.
+ * @return The number of bytes returned.
+ */
+ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, char *data, ring_buffer_size_t len);
+/**
+ * Peeks a ring buffer, i.e. returns an element without removing it.
+ * @param buffer The buffer from which the data should be returned.
+ * @param data A pointer to the location at which the data should be placed.
+ * @param index The index to peek.
+ * @return 1 if data was returned; 0 otherwise.
+ */
+uint8_t ring_buffer_peek(ring_buffer_t *buffer, char *data, ring_buffer_size_t index);
+
+
+/**
+ * Returns whether a ring buffer is empty.
+ * @param buffer The buffer for which it should be returned whether it is empty.
+ * @return 1 if empty; 0 otherwise.
+ */
+inline uint8_t ring_buffer_is_empty(ring_buffer_t *buffer) {
+  return (buffer->head_index == buffer->tail_index);
+}
+
+/**
+ * Returns whether a ring buffer is full.
+ * @param buffer The buffer for which it should be returned whether it is full.
+ * @return 1 if full; 0 otherwise.
+ */
+inline uint8_t ring_buffer_is_full(ring_buffer_t *buffer) {
+  return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK(buffer)) == RING_BUFFER_MASK(buffer);
+}
+
+/**
+ * Returns the number of items in a ring buffer.
+ * @param buffer The buffer for which the number of items should be returned.
+ * @return The number of items in the ring buffer.
+ */
+inline ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer) {
+  return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK(buffer));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RINGBUFFER_H */