ringbuffer.c 5.0 KB
Newer Older
1 2 3 4 5
/*
 * File      : ringbuffer.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2012, RT-Thread Development Team
 *
Y
yiyue.fang 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 20 21 22
 *
 * Change Logs:
 * Date           Author       Notes
 * 2012-09-30     Bernard      first version.
23
 * 2013-05-08     Grissiom     reimplement
24 25 26 27 28 29 30 31
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>

void rt_ringbuffer_init(struct rt_ringbuffer *rb,
                        rt_uint8_t           *pool,
G
Grissiom 已提交
32
                        rt_int16_t            size)
33 34
{
    RT_ASSERT(rb != RT_NULL);
G
Grissiom 已提交
35
    RT_ASSERT(size > 0)
36 37

    /* initialize read and write index */
G
Grissiom 已提交
38 39
    rb->read_mirror = rb->read_index = 0;
    rb->write_mirror = rb->write_index = 0;
40 41 42 43 44 45 46 47 48 49 50 51

    /* set buffer pool and size */
    rb->buffer_ptr = pool;
    rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
}
RTM_EXPORT(rt_ringbuffer_init);

rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
                            const rt_uint8_t     *ptr,
                            rt_uint16_t           length)
{
    rt_uint16_t size;
52

53 54 55
    RT_ASSERT(rb != RT_NULL);

    /* whether has enough space */
G
Grissiom 已提交
56
    size = rt_ringbuffer_space_len(rb);
57 58 59 60

    /* no space */
    if (size == 0)
        return 0;
G
Grissiom 已提交
61

62 63 64 65
    /* drop some data */
    if (size < length)
        length = size;

G
Grissiom 已提交
66
    if (rb->buffer_size - rb->write_index > length)
67 68
    {
        /* read_index - write_index = empty space */
G
Grissiom 已提交
69 70 71 72 73
        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;
        return length;
74
    }
G
Grissiom 已提交
75 76 77 78 79 80 81 82 83 84 85

    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);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

    return length;
}
RTM_EXPORT(rt_ringbuffer_put);

/**
 *  get data from ring buffer
 */
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
                            rt_uint8_t           *ptr,
                            rt_uint16_t           length)
{
    rt_size_t size;

    RT_ASSERT(rb != RT_NULL);
G
Grissiom 已提交
101

102
    /* whether has enough data  */
G
Grissiom 已提交
103
    size = rt_ringbuffer_data_len(rb);
104 105 106 107

    /* no data */
    if (size == 0)
        return 0;
G
Grissiom 已提交
108

109 110 111 112
    /* less data */
    if (size < length)
        length = size;

G
Grissiom 已提交
113
    if (rb->buffer_size - rb->read_index > length)
114 115
    {
        /* copy all of data */
G
Grissiom 已提交
116 117 118 119 120
        memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
        /* this should not cause overflow because there is enough space for
         * length of data in current mirror */
        rb->read_index += length;
        return length;
121
    }
G
Grissiom 已提交
122 123 124 125 126 127 128 129 130 131 132

    memcpy(&ptr[0],
           &rb->buffer_ptr[rb->read_index],
           rb->buffer_size - rb->read_index);
    memcpy(&ptr[rb->buffer_size - rb->read_index],
           &rb->buffer_ptr[0],
           length - (rb->buffer_size - rb->read_index));

    /* we are going into the other side of the mirror */
    rb->read_mirror = ~rb->read_mirror;
    rb->read_index = length - (rb->buffer_size - rb->read_index);
133 134 135 136 137

    return length;
}
RTM_EXPORT(rt_ringbuffer_get);

138 139 140 141 142 143 144 145
/**
 * put a character into ring buffer
 */
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
{
    RT_ASSERT(rb != RT_NULL);

    /* whether has enough space */
G
Grissiom 已提交
146
    if (!rt_ringbuffer_space_len(rb))
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
        return 0;

    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;
    }
    else
    {
        rb->write_index++;
    }

    return 1;
}
RTM_EXPORT(rt_ringbuffer_putchar);

166 167 168 169 170 171
/**
 * get a character from a ringbuffer
 */
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
{
    RT_ASSERT(rb != RT_NULL);
G
Grissiom 已提交
172

173
    /* ringbuffer is empty */
G
Grissiom 已提交
174
    if (!rt_ringbuffer_data_len(rb))
175 176 177
        return 0;

    /* put character */
G
Grissiom 已提交
178 179 180 181 182 183 184 185 186 187 188
    *ch = rb->buffer_ptr[rb->read_index];

    if (rb->read_index == rb->buffer_size-1)
    {
        rb->read_mirror = ~rb->read_mirror;
        rb->read_index = 0;
    }
    else
    {
        rb->read_index++;
    }
189 190 191 192

    return 1;
}
RTM_EXPORT(rt_ringbuffer_getchar);
193