ringbuffer.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. */
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include <string.h>
  17. void rt_ringbuffer_init(struct rt_ringbuffer *rb,
  18. rt_uint8_t *pool,
  19. rt_uint16_t size)
  20. {
  21. RT_ASSERT(rb != RT_NULL);
  22. /* initialize read and write index */
  23. rb->read_index = rb->write_index = 0;
  24. /* set buffer pool and size */
  25. rb->buffer_ptr = pool;
  26. rb->buffer_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
  27. }
  28. RTM_EXPORT(rt_ringbuffer_init);
  29. rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
  30. const rt_uint8_t *ptr,
  31. rt_uint16_t length)
  32. {
  33. rt_uint16_t size;
  34. rt_uint16_t mask;
  35. rt_uint16_t write_position;
  36. RT_ASSERT(rb != RT_NULL);
  37. mask = rb->buffer_size - 1;
  38. /* whether has enough space */
  39. size = rb->buffer_size - (rb->write_index - rb->read_index);
  40. /* no space */
  41. if (size == 0)
  42. return 0;
  43. /* drop some data */
  44. if (size < length)
  45. length = size;
  46. write_position = (rb->write_index & mask);
  47. if (rb->buffer_size - write_position> length)
  48. {
  49. /* read_index - write_index = empty space */
  50. memcpy(&rb->buffer_ptr[write_position], ptr, length);
  51. }
  52. else
  53. {
  54. memcpy(&rb->buffer_ptr[write_position], ptr,
  55. rb->buffer_size - write_position);
  56. memcpy(&rb->buffer_ptr[0], &ptr[rb->buffer_size - write_position],
  57. length - (rb->buffer_size - write_position));
  58. }
  59. rb->write_index += length;
  60. return length;
  61. }
  62. RTM_EXPORT(rt_ringbuffer_put);
  63. /**
  64. * put a character into ring buffer
  65. */
  66. rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
  67. {
  68. rt_uint16_t mask;
  69. RT_ASSERT(rb != RT_NULL);
  70. /* whether has enough space */
  71. mask = rb->buffer_size - 1;
  72. /* whether has enough space */
  73. if (rb->write_index - rb->read_index == rb->buffer_size)
  74. return 0;
  75. /* put character */
  76. rb->buffer_ptr[rb->write_index & mask] = ch;
  77. rb->write_index += 1;
  78. return 1;
  79. }
  80. RTM_EXPORT(rt_ringbuffer_putchar);
  81. /**
  82. * get data from ring buffer
  83. */
  84. rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
  85. rt_uint8_t *ptr,
  86. rt_uint16_t length)
  87. {
  88. rt_size_t size;
  89. rt_uint16_t mask;
  90. rt_uint16_t read_position;
  91. RT_ASSERT(rb != RT_NULL);
  92. /* whether has enough data */
  93. mask = rb->buffer_size - 1;
  94. size = rb->write_index - rb->read_index;
  95. /* no data */
  96. if (size == 0)
  97. return 0;
  98. /* less data */
  99. if (size < length)
  100. length = size;
  101. read_position = rb->read_index & mask;
  102. if (rb->buffer_size - read_position >= length)
  103. {
  104. /* copy all of data */
  105. memcpy(ptr, &rb->buffer_ptr[read_position], length);
  106. }
  107. else
  108. {
  109. /* copy first and second */
  110. memcpy(ptr, &rb->buffer_ptr[read_position],
  111. rb->buffer_size - read_position);
  112. memcpy(&ptr[rb->buffer_size - read_position], &rb->buffer_ptr[0],
  113. length - rb->buffer_size + read_position);
  114. }
  115. rb->read_index += length;
  116. return length;
  117. }
  118. RTM_EXPORT(rt_ringbuffer_get);
  119. /**
  120. * get a character from a ringbuffer
  121. */
  122. rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
  123. {
  124. rt_uint16_t mask;
  125. RT_ASSERT(rb != RT_NULL);
  126. /* ringbuffer is empty */
  127. if (rb->read_index == rb->write_index)
  128. return 0;
  129. mask = rb->buffer_size - 1;
  130. /* put character */
  131. *ch = rb->buffer_ptr[rb->read_index & mask];
  132. rb->read_index += 1;
  133. return 1;
  134. }
  135. RTM_EXPORT(rt_ringbuffer_getchar);