ringbuffer.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * File : ringbuffer.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2012, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2012-09-30 Bernard first version.
  13. * 2013-05-08 Grissiom reimplement
  14. */
  15. #include <rtthread.h>
  16. #include <rtdevice.h>
  17. #include <string.h>
  18. void rt_ringbuffer_init(struct rt_ringbuffer *rb,
  19. rt_uint8_t *pool,
  20. rt_int16_t size)
  21. {
  22. RT_ASSERT(rb != RT_NULL);
  23. RT_ASSERT(size > 0)
  24. /* initialize read and write index */
  25. rb->read_mirror = rb->read_index = 0;
  26. rb->write_mirror = rb->write_index = 0;
  27. /* set buffer pool and size */
  28. rb->buffer_ptr = pool;
  29. rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  30. }
  31. RTM_EXPORT(rt_ringbuffer_init);
  32. rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
  33. const rt_uint8_t *ptr,
  34. rt_uint16_t length)
  35. {
  36. rt_uint16_t size;
  37. RT_ASSERT(rb != RT_NULL);
  38. /* whether has enough space */
  39. size = RT_RINGBUFFER_EMPTY(rb);
  40. /* no space */
  41. if (size == 0)
  42. return 0;
  43. /* drop some data */
  44. if (size < length)
  45. length = size;
  46. if (rb->buffer_size - rb->write_index > length)
  47. {
  48. /* read_index - write_index = empty space */
  49. memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
  50. /* this should not cause overflow because there is enough space for
  51. * length of data in current mirror */
  52. rb->write_index += length;
  53. return length;
  54. }
  55. memcpy(&rb->buffer_ptr[rb->write_index],
  56. &ptr[0],
  57. rb->buffer_size - rb->write_index);
  58. memcpy(&rb->buffer_ptr[0],
  59. &ptr[rb->buffer_size - rb->write_index],
  60. length - (rb->buffer_size - rb->write_index));
  61. /* we are going into the other side of the mirror */
  62. rb->write_mirror = ~rb->write_mirror;
  63. rb->write_index = length - (rb->buffer_size - rb->write_index);
  64. return length;
  65. }
  66. RTM_EXPORT(rt_ringbuffer_put);
  67. /**
  68. * get data from ring buffer
  69. */
  70. rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
  71. rt_uint8_t *ptr,
  72. rt_uint16_t length)
  73. {
  74. rt_size_t size;
  75. RT_ASSERT(rb != RT_NULL);
  76. /* whether has enough data */
  77. size = RT_RINGBUFFER_SIZE(rb);
  78. /* no data */
  79. if (size == 0)
  80. return 0;
  81. /* less data */
  82. if (size < length)
  83. length = size;
  84. if (rb->buffer_size - rb->read_index > length)
  85. {
  86. /* copy all of data */
  87. memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);
  88. /* this should not cause overflow because there is enough space for
  89. * length of data in current mirror */
  90. rb->read_index += length;
  91. return length;
  92. }
  93. memcpy(&ptr[0],
  94. &rb->buffer_ptr[rb->read_index],
  95. rb->buffer_size - rb->read_index);
  96. memcpy(&ptr[rb->buffer_size - rb->read_index],
  97. &rb->buffer_ptr[0],
  98. length - (rb->buffer_size - rb->read_index));
  99. /* we are going into the other side of the mirror */
  100. rb->read_mirror = ~rb->read_mirror;
  101. rb->read_index = length - (rb->buffer_size - rb->read_index);
  102. return length;
  103. }
  104. RTM_EXPORT(rt_ringbuffer_get);
  105. /**
  106. * put a character into ring buffer
  107. */
  108. rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
  109. {
  110. RT_ASSERT(rb != RT_NULL);
  111. /* whether has enough space */
  112. if (!RT_RINGBUFFER_EMPTY(rb))
  113. return 0;
  114. rb->buffer_ptr[rb->write_index] = ch;
  115. /* flip mirror */
  116. if (rb->write_index == rb->buffer_size-1)
  117. {
  118. rb->write_mirror = ~rb->write_mirror;
  119. rb->write_index = 0;
  120. }
  121. else
  122. {
  123. rb->write_index++;
  124. }
  125. return 1;
  126. }
  127. RTM_EXPORT(rt_ringbuffer_putchar);
  128. /**
  129. * get a character from a ringbuffer
  130. */
  131. rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
  132. {
  133. RT_ASSERT(rb != RT_NULL);
  134. /* ringbuffer is empty */
  135. if (!RT_RINGBUFFER_SIZE(rb))
  136. return 0;
  137. /* put character */
  138. *ch = rb->buffer_ptr[rb->read_index];
  139. if (rb->read_index == rb->buffer_size-1)
  140. {
  141. rb->read_mirror = ~rb->read_mirror;
  142. rb->read_index = 0;
  143. }
  144. else
  145. {
  146. rb->read_index++;
  147. }
  148. return 1;
  149. }
  150. RTM_EXPORT(rt_ringbuffer_getchar);