From 981d929b562610328309ee4e01d66727f5e6896e Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 10:50:20 +0800 Subject: ringbuffer: fix the ambiguous name RT_RINGBUFFER_SIZE could mean "the size of the whole buffer", "the size of the empty space" or "the size of the data". Moreover, it's never a micro anymore. Change it to rt_ringbuffer_data_len before it's too late. Also, RT_RINGBUFFER_EMPTY is changed to rt_ringbuffer_space_len. --- components/drivers/src/ringbuffer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'components/drivers/src/ringbuffer.c') diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 8e7e8c7895..ecc2587042 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -53,7 +53,7 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, RT_ASSERT(rb != RT_NULL); /* whether has enough space */ - size = RT_RINGBUFFER_EMPTY(rb); + size = rt_ringbuffer_space_len(rb); /* no space */ if (size == 0) @@ -100,7 +100,7 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, RT_ASSERT(rb != RT_NULL); /* whether has enough data */ - size = RT_RINGBUFFER_SIZE(rb); + size = rt_ringbuffer_data_len(rb); /* no data */ if (size == 0) @@ -143,7 +143,7 @@ rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch) RT_ASSERT(rb != RT_NULL); /* whether has enough space */ - if (!RT_RINGBUFFER_EMPTY(rb)) + if (!rt_ringbuffer_space_len(rb)) return 0; rb->buffer_ptr[rb->write_index] = ch; @@ -171,7 +171,7 @@ rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch) RT_ASSERT(rb != RT_NULL); /* ringbuffer is empty */ - if (!RT_RINGBUFFER_SIZE(rb)) + if (!rt_ringbuffer_data_len(rb)) return 0; /* put character */ -- cgit v1.3.1 From 4919d29d693491e8eae9697deed7b808c7bcbb93 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 19 Aug 2013 11:52:04 +0800 Subject: ringbuffer: add put_force and putchar_force API Add the APIs that will discard the old data when rb is full. --- components/drivers/include/rtdevice.h | 38 +++++++++++--- components/drivers/src/ringbuffer.c | 93 +++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 7 deletions(-) (limited to 'components/drivers/src/ringbuffer.c') 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) @@ -88,6 +91,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 */ @@ -163,6 +219,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 */ -- cgit v1.3.1