1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-08-14     Jackistang   add comments for function interface.
9  */
10 #ifndef RINGBUFFER_H__
11 #define RINGBUFFER_H__
12 
13 #include <rtdef.h>
14 #include <rtconfig.h>
15 #include <rtthread.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /* ring buffer */
22 struct rt_ringbuffer
23 {
24     rt_uint8_t *buffer_ptr;
25     /* use the msb of the {read,write}_index as mirror bit. You can see this as
26      * if the buffer adds a virtual mirror and the pointers point either to the
27      * normal or to the mirrored buffer. If the write_index has the same value
28      * with the read_index, but in a different mirror, the buffer is full.
29      * While if the write_index and the read_index are the same and within the
30      * same mirror, the buffer is empty. The ASCII art of the ringbuffer is:
31      *
32      *          mirror = 0                    mirror = 1
33      * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
34      * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Full
35      * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
36      *  read_idx-^                   write_idx-^
37      *
38      * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
39      * | 0 | 1 | 2 | 3 | 4 | 5 | 6 ||| 0 | 1 | 2 | 3 | 4 | 5 | 6 | Empty
40      * +---+---+---+---+---+---+---+|+~~~+~~~+~~~+~~~+~~~+~~~+~~~+
41      * read_idx-^ ^-write_idx
42      */
43 
44     rt_uint32_t read_mirror : 1;
45     rt_uint32_t read_index : 31;
46     rt_uint32_t write_mirror : 1;
47     rt_uint32_t write_index : 31;
48     /* as we use msb of index as mirror bit, the size should be signed and
49      * could only be positive. */
50     rt_int32_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_int32_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_uint32_t length);
70 rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint32_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_uint32_t length);
74 rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr);
75 rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch);
76 rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb);
77 
78 #ifdef RT_USING_HEAP
79 struct rt_ringbuffer* rt_ringbuffer_create(rt_uint32_t length);
80 void rt_ringbuffer_destroy(struct rt_ringbuffer *rb);
81 #endif
82 
83 /**
84  * @brief Get the buffer size of the ring buffer object.
85  *
86  * @param rb        A pointer to the ring buffer object.
87  *
88  * @return  Buffer size.
89  */
rt_ringbuffer_get_size(struct rt_ringbuffer * rb)90 rt_inline rt_uint32_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb)
91 {
92     RT_ASSERT(rb != RT_NULL);
93     return rb->buffer_size;
94 }
95 
96 /** return the size of empty space in rb */
97 #define rt_ringbuffer_space_len(rb) ((rb)->buffer_size - rt_ringbuffer_data_len(rb))
98 
99 
100 #ifdef __cplusplus
101 }
102 #endif
103 
104 #endif
105