summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorGrissiom <[email protected]>2013-08-19 11:52:04 +0800
committerGrissiom <[email protected]>2013-08-19 15:32:42 +0800
commit4919d29d693491e8eae9697deed7b808c7bcbb93 (patch)
treeee7eb8a13c6cd83e85a105f9ca83c40b1afe8c2d /components
parent981d929b562610328309ee4e01d66727f5e6896e (diff)
ringbuffer: add put_force and putchar_force API
Add the APIs that will discard the old data when rb is full.
Diffstat (limited to 'components')
-rw-r--r--components/drivers/include/rtdevice.h38
-rw-r--r--components/drivers/src/ringbuffer.c93
2 files changed, 124 insertions, 7 deletions
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index a941b22131..bd6e243b0a 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -134,37 +134,61 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb,
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
const rt_uint8_t *ptr,
rt_uint16_t length);
+rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
+ const rt_uint8_t *ptr,
+ rt_uint16_t length);
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb,
const rt_uint8_t ch);
+rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb,
+ const rt_uint8_t ch);
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
rt_uint8_t *ptr,
rt_uint16_t length);
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch);
+enum rt_ringbuffer_state
+{
+ RT_RINGBUFFER_EMPTY,
+ RT_RINGBUFFER_FULL,
+ /* half full is neither full nor empty */
+ RT_RINGBUFFER_HALFFULL,
+};
+
rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb)
{
RT_ASSERT(rb != RT_NULL);
return rb->buffer_size;
}
-/** return the size of data in rb */
-rt_inline rt_uint16_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
+rt_inline enum rt_ringbuffer_state
+rt_ringbuffer_status(struct rt_ringbuffer *rb)
{
if (rb->read_index == rb->write_index)
{
if (rb->read_mirror == rb->write_mirror)
- /* we are in the same side, the ringbuffer is empty. */
- return 0;
+ return RT_RINGBUFFER_EMPTY;
else
- return rb->buffer_size;
+ return RT_RINGBUFFER_FULL;
}
- else
+ return RT_RINGBUFFER_HALFFULL;
+}
+
+/** return the size of data in rb */
+rt_inline rt_uint16_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
+{
+ switch (rt_ringbuffer_status(rb))
{
+ case RT_RINGBUFFER_EMPTY:
+ return 0;
+ case RT_RINGBUFFER_FULL:
+ return rb->buffer_size;
+ case RT_RINGBUFFER_HALFFULL:
+ default:
if (rb->write_index > rb->read_index)
return rb->write_index - rb->read_index;
else
return rb->buffer_size - (rb->read_index - rb->write_index);
- }
+ };
}
/** return the size of empty space in rb */
diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c
index ecc2587042..6212b10258 100644
--- a/components/drivers/src/ringbuffer.c
+++ b/components/drivers/src/ringbuffer.c
@@ -44,6 +44,9 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb,
}
RTM_EXPORT(rt_ringbuffer_init);
+/**
+ * put a block of data into ring buffer
+ */
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
const rt_uint8_t *ptr,
rt_uint16_t length)
@@ -89,6 +92,59 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
RTM_EXPORT(rt_ringbuffer_put);
/**
+ * put a block of data into ring buffer
+ *
+ * When the buffer is full, it will discard the old data.
+ */
+rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
+ const rt_uint8_t *ptr,
+ rt_uint16_t length)
+{
+ enum rt_ringbuffer_state old_state;
+
+ RT_ASSERT(rb != RT_NULL);
+
+ old_state = rt_ringbuffer_status(rb);
+
+ if (length > rb->buffer_size)
+ length = rb->buffer_size;
+
+ if (rb->buffer_size - rb->write_index > length)
+ {
+ /* read_index - write_index = empty space */
+ memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
+ /* this should not cause overflow because there is enough space for
+ * length of data in current mirror */
+ rb->write_index += length;
+
+ if (old_state == RT_RINGBUFFER_FULL)
+ rb->read_index = rb->write_index;
+
+ return length;
+ }
+
+ memcpy(&rb->buffer_ptr[rb->write_index],
+ &ptr[0],
+ rb->buffer_size - rb->write_index);
+ memcpy(&rb->buffer_ptr[0],
+ &ptr[rb->buffer_size - rb->write_index],
+ length - (rb->buffer_size - rb->write_index));
+
+ /* we are going into the other side of the mirror */
+ rb->write_mirror = ~rb->write_mirror;
+ rb->write_index = length - (rb->buffer_size - rb->write_index);
+
+ if (old_state == RT_RINGBUFFER_FULL)
+ {
+ rb->read_mirror = ~rb->read_mirror;
+ rb->read_index = rb->write_index;
+ }
+
+ return length;
+}
+RTM_EXPORT(rt_ringbuffer_put_force);
+
+/**
* get data from ring buffer
*/
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
@@ -164,6 +220,43 @@ rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
RTM_EXPORT(rt_ringbuffer_putchar);
/**
+ * put a character into ring buffer
+ *
+ * When the buffer is full, it will discard one old data.
+ */
+rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch)
+{
+ enum rt_ringbuffer_state old_state;
+
+ RT_ASSERT(rb != RT_NULL);
+
+ old_state = rt_ringbuffer_status(rb);
+
+ rb->buffer_ptr[rb->write_index] = ch;
+
+ /* flip mirror */
+ if (rb->write_index == rb->buffer_size-1)
+ {
+ rb->write_mirror = ~rb->write_mirror;
+ rb->write_index = 0;
+ if (old_state == RT_RINGBUFFER_FULL)
+ {
+ rb->read_mirror = ~rb->read_mirror;
+ rb->read_index = rb->write_index;
+ }
+ }
+ else
+ {
+ rb->write_index++;
+ if (old_state == RT_RINGBUFFER_FULL)
+ rb->read_index = rb->write_index;
+ }
+
+ return 1;
+}
+RTM_EXPORT(rt_ringbuffer_putchar_force);
+
+/**
* get a character from a ringbuffer
*/
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)