buffer_stream.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "buffer_stream.h"
  2. struct Buffer {
  3. volatile bool occupied;
  4. volatile size_t size;
  5. uint8_t* data;
  6. size_t max_data_size;
  7. };
  8. struct BufferStream {
  9. size_t stream_overrun_count;
  10. FuriStreamBuffer* stream;
  11. size_t index;
  12. Buffer* buffers;
  13. size_t max_buffers_count;
  14. };
  15. bool buffer_write(Buffer* buffer, const uint8_t* data, size_t size) {
  16. if(buffer->occupied) {
  17. return false;
  18. }
  19. if((buffer->size + size) > buffer->max_data_size) {
  20. return false;
  21. }
  22. memcpy(buffer->data + buffer->size, data, size);
  23. buffer->size += size;
  24. return true;
  25. }
  26. uint8_t* buffer_get_data(Buffer* buffer) {
  27. return buffer->data;
  28. }
  29. size_t buffer_get_size(Buffer* buffer) {
  30. return buffer->size;
  31. }
  32. void buffer_reset(Buffer* buffer) {
  33. buffer->occupied = false;
  34. buffer->size = 0;
  35. }
  36. BufferStream* buffer_stream_alloc(size_t buffer_size, size_t buffers_count) {
  37. furi_assert(buffer_size > 0);
  38. furi_assert(buffers_count > 0);
  39. BufferStream* buffer_stream = malloc(sizeof(BufferStream));
  40. buffer_stream->max_buffers_count = buffers_count;
  41. buffer_stream->buffers = malloc(sizeof(Buffer) * buffer_stream->max_buffers_count);
  42. for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
  43. buffer_stream->buffers[i].occupied = false;
  44. buffer_stream->buffers[i].size = 0;
  45. buffer_stream->buffers[i].data = malloc(buffer_size);
  46. buffer_stream->buffers[i].max_data_size = buffer_size;
  47. }
  48. buffer_stream->stream = furi_stream_buffer_alloc(
  49. sizeof(BufferStream*) * buffer_stream->max_buffers_count, sizeof(BufferStream*));
  50. buffer_stream->stream_overrun_count = 0;
  51. buffer_stream->index = 0;
  52. return buffer_stream;
  53. }
  54. void buffer_stream_free(BufferStream* buffer_stream) {
  55. for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
  56. free(buffer_stream->buffers[i].data);
  57. }
  58. furi_stream_buffer_free(buffer_stream->stream);
  59. free(buffer_stream->buffers);
  60. free(buffer_stream);
  61. }
  62. static inline int8_t buffer_stream_get_free_buffer(BufferStream* buffer_stream) {
  63. int8_t id = -1;
  64. for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
  65. if(buffer_stream->buffers[i].occupied == false) {
  66. id = i;
  67. break;
  68. }
  69. }
  70. return id;
  71. }
  72. bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* data, size_t size) {
  73. Buffer* buffer = &buffer_stream->buffers[buffer_stream->index];
  74. bool result = true;
  75. // write to buffer
  76. if(!buffer_write(buffer, data, size)) {
  77. // if buffer is full - send it
  78. buffer->occupied = true;
  79. // we always have space for buffer in stream
  80. furi_stream_buffer_send(buffer_stream->stream, &buffer, sizeof(Buffer*), 0);
  81. // get new buffer from the pool
  82. int8_t index = buffer_stream_get_free_buffer(buffer_stream);
  83. // check that we have valid buffer
  84. if(index == -1) {
  85. // no free buffer
  86. buffer_stream->stream_overrun_count++;
  87. result = false;
  88. } else {
  89. // write to new buffer
  90. buffer_stream->index = index;
  91. buffer = &buffer_stream->buffers[buffer_stream->index];
  92. buffer_write(buffer, data, size);
  93. }
  94. }
  95. return result;
  96. }
  97. Buffer* buffer_stream_receive(BufferStream* buffer_stream, TickType_t timeout) {
  98. Buffer* buffer;
  99. size_t size =
  100. furi_stream_buffer_receive(buffer_stream->stream, &buffer, sizeof(Buffer*), timeout);
  101. if(size == sizeof(Buffer*)) {
  102. return buffer;
  103. } else {
  104. return NULL;
  105. }
  106. }
  107. size_t buffer_stream_get_overrun_count(BufferStream* buffer_stream) {
  108. return buffer_stream->stream_overrun_count;
  109. }
  110. void buffer_stream_reset(BufferStream* buffer_stream) {
  111. FURI_CRITICAL_ENTER();
  112. furi_stream_buffer_reset(buffer_stream->stream);
  113. buffer_stream->stream_overrun_count = 0;
  114. for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
  115. buffer_reset(&buffer_stream->buffers[i]);
  116. }
  117. FURI_CRITICAL_EXIT();
  118. }