ring.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "ring.h"
  2. #include <flipper_v2.h>
  3. struct Ring {
  4. uint8_t* data;
  5. size_t size;
  6. volatile size_t read_ptr;
  7. volatile size_t write_ptr;
  8. };
  9. Ring* ring_alloc(size_t size) {
  10. Ring* ring = furi_alloc(sizeof(Ring));
  11. ring->size = size + 1;
  12. ring->data = furi_alloc(ring->size);
  13. ring_clear(ring);
  14. return ring;
  15. }
  16. void ring_free(Ring* ring) {
  17. furi_assert(ring);
  18. free(ring->data);
  19. free(ring);
  20. }
  21. size_t ring_size(Ring* ring) {
  22. furi_assert(ring);
  23. return ring->size - 1;
  24. }
  25. inline static size_t ring_read_calculate(Ring* ring, size_t r, size_t w) {
  26. if(w >= r) {
  27. return w - r;
  28. } else {
  29. return ring->size - (r - w);
  30. }
  31. }
  32. size_t ring_read_space(Ring* ring) {
  33. furi_assert(ring);
  34. const size_t r = ring->read_ptr;
  35. const size_t w = ring->write_ptr;
  36. return ring_read_calculate(ring, r, w);
  37. }
  38. inline static size_t ring_write_calculate(Ring* ring, size_t r, size_t w) {
  39. if(r > w) {
  40. return r - w - 1;
  41. } else {
  42. return ring->size - (r - w);
  43. }
  44. }
  45. size_t ring_write_space(Ring* ring) {
  46. furi_assert(ring);
  47. const size_t r = ring->read_ptr;
  48. const size_t w = ring->write_ptr;
  49. return ring_write_calculate(ring, r, w);
  50. }
  51. size_t ring_push(Ring* ring, const uint8_t* data, size_t size) {
  52. furi_assert(ring);
  53. furi_assert(data);
  54. const size_t r = ring->read_ptr;
  55. size_t w = ring->write_ptr;
  56. const size_t write_space = ring_write_calculate(ring, r, w);
  57. if(write_space == 0) return 0;
  58. const size_t to_write = size > write_space ? write_space : size;
  59. size_t end, first, second;
  60. end = w + to_write;
  61. if(end > ring->size) {
  62. first = ring->size - w;
  63. second = end % ring->size;
  64. } else {
  65. first = to_write;
  66. second = 0;
  67. }
  68. memcpy(ring->data + w, data, first);
  69. w = (w + first) % ring->size;
  70. if(second) {
  71. memcpy(ring->data + w, data + first, second);
  72. w = (w + second) % ring->size;
  73. }
  74. ring->write_ptr = w;
  75. return to_write;
  76. }
  77. size_t ring_pull(Ring* ring, uint8_t* data, size_t size) {
  78. furi_assert(ring);
  79. furi_assert(data);
  80. size_t r = ring->read_ptr;
  81. const size_t w = ring->write_ptr;
  82. const size_t read_space = ring_read_calculate(ring, r, w);
  83. if(read_space == 0) return 0;
  84. size_t to_read = size > read_space ? read_space : size;
  85. size_t end, first, second;
  86. end = r + to_read;
  87. if(end > ring->size) {
  88. first = ring->size - r;
  89. second = end % ring->size;
  90. } else {
  91. first = to_read;
  92. second = 0;
  93. }
  94. memcpy(data, ring->data + r, first);
  95. r = (r + first) % ring->size;
  96. if(second) {
  97. memcpy(data + first, ring->data + r, second);
  98. r = (r + second) % ring->size;
  99. }
  100. ring->read_ptr = r;
  101. return to_read;
  102. }
  103. void ring_clear(Ring* ring) {
  104. furi_assert(ring);
  105. ring->read_ptr = 0;
  106. ring->write_ptr = 0;
  107. }