1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 */
9 #ifndef RINGBUFFER_H__
10 #define RINGBUFFER_H__
11
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15
16 #include <rtthread.h>
17
18 /* ring buffer */
19 struct rt_ringbuffer
20 {
21 rt_uint8_t *buffer_ptr;
22 /* use the msb of the {read,write}_index as mirror bit. You can see this as
23 * if the buffer adds a virtual mirror and the pointers point either to the
24 * normal or to the mirrored buffer. If the write_index has the same value
25 * with the read_index, but in a different mirror, the buffer is full.
26 * While if the write_index and the read_index are the same and within the
27 * same mirror, the buffer is empty. The ASCII art of the ringbuffer is:
28 *
29 * mirror = 0 mirror = 1
30 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
31 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Full
32 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
33 * read_idx-^ write_idx-^
34 *
35 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
36 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty
37 * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
38 * read_idx-^ ^-write_idx
39 *
40 * The tradeoff is we could only use 32KiB of buffer for 16 bit of index.
41 * But it should be enough for most of the cases.
42 *
43 * Ref: http://en.wikipedia.org/wiki/Circular_buffer#Mirroring */
44 rt_uint16_t read_mirror : 1;
45 rt_uint16_t read_index : 15;
46 rt_uint16_t write_mirror : 1;
47 rt_uint16_t write_index : 15;
48 /* as we use msb of index as mirror bit, the size should be signed and
49 * could only be positive. */
50 rt_int16_t buffer_size;
51 };
52
53 enum rt_ringbuffer_state
54 {
55 RT_RINGBUFFER_EMPTY,
56 RT_RINGBUFFER_FULL,
57 /* half full is neither full nor empty */
58 RT_RINGBUFFER_HALFFULL,
59 };
60
61 /**
62 * RingBuffer for DeviceDriver
63 *
64 * Please note that the ring buffer implementation of RT-Thread
65 * has no thread wait or resume feature.
66 */
67 void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size);
68 void rt_ringbuffer_reset(struct rt_ringbuffer *rb);
69 rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length);
70 rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length);
71 rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch);
72 rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch);
73 rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint16_t length);
74 rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch);
75 rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb);
76
77 #ifdef RT_USING_HEAP
78 struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t length);
79 void rt_ringbuffer_destroy(struct rt_ringbuffer *rb);
80 #endif
81
rt_ringbuffer_get_size(struct rt_ringbuffer * rb)82 rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb)
83 {
84 RT_ASSERT(rb != RT_NULL);
85 return rb->buffer_size;
86 }
87
88 /** return the size of empty space in rb */
89 #define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb))
90
91
92 #ifdef __cplusplus
93 }
94 #endif
95
96 #endif
97