Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CircularBuffer.h 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. CircularBuffer - An Arduino circular buffering library for arbitrary types.
  3. Created by Ivo Pullens, Emmission, 2014-2016 -- www.emmission.nl
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. */
  16. /**
  17. * @file CircularBuffer.h
  18. *
  19. * Circular buffering for arbitrary types.
  20. */
  21. #ifndef CircularBuffer_h
  22. #define CircularBuffer_h
  23. /**
  24. * The circular buffer class.
  25. * Pass the datatype to be stored in the buffer as template parameter.
  26. */
  27. template <class T> class CircularBuffer
  28. {
  29. public:
  30. /**
  31. * Constructor
  32. * @param buffer Preallocated buffer of at least size records.
  33. * @param size Number of records available in the buffer.
  34. */
  35. CircularBuffer(T* buffer, const uint8_t size )
  36. : m_size(size), m_buff(buffer)
  37. {
  38. clear();
  39. }
  40. /**
  41. * Clear all entries in the circular buffer.
  42. */
  43. void clear(void)
  44. {
  45. MY_CRITICAL_SECTION {
  46. m_front = 0;
  47. m_fill = 0;
  48. }
  49. }
  50. /**
  51. * Test if the circular buffer is empty.
  52. * @return True, when empty.
  53. */
  54. inline bool empty(void) const
  55. {
  56. bool empty;
  57. MY_CRITICAL_SECTION {
  58. empty = !m_fill;
  59. }
  60. return empty;
  61. }
  62. /**
  63. * Test if the circular buffer is full.
  64. * @return True, when full.
  65. */
  66. inline bool full(void) const
  67. {
  68. bool full;
  69. MY_CRITICAL_SECTION {
  70. full = m_fill == m_size;
  71. }
  72. return full;
  73. }
  74. /**
  75. * Return the number of records stored in the buffer.
  76. * @return number of records.
  77. */
  78. inline uint8_t available(void) const
  79. {
  80. uint8_t ret_value;
  81. MY_CRITICAL_SECTION {
  82. ret_value = m_fill;
  83. }
  84. return ret_value;
  85. }
  86. /**
  87. * Aquire unused record on front of the buffer, for writing.
  88. * After filling the record, it has to be pushed to actually
  89. * add it to the buffer.
  90. * @return Pointer to record, or NULL when buffer is full.
  91. */
  92. T* getFront(void) const
  93. {
  94. MY_CRITICAL_SECTION {
  95. if (!full())
  96. {
  97. return get(m_front);
  98. }
  99. }
  100. return static_cast<T*>(NULL);
  101. }
  102. /**
  103. * Push record to front of the buffer.
  104. * @param record Record to push. If record was aquired previously (using getFront) its
  105. * data will not be copied as it is already present in the buffer.
  106. * @return True, when record was pushed successfully.
  107. */
  108. bool pushFront(T* record)
  109. {
  110. MY_CRITICAL_SECTION {
  111. if (!full())
  112. {
  113. T* f = get(m_front);
  114. if (f != record) {
  115. *f = *record;
  116. }
  117. m_front = (m_front+1) % m_size;
  118. m_fill++;
  119. return true;
  120. }
  121. }
  122. return false;
  123. }
  124. /**
  125. * Aquire record on back of the buffer, for reading.
  126. * After reading the record, it has to be pop'ed to actually
  127. * remove it from the buffer.
  128. * @return Pointer to record, or NULL when buffer is empty.
  129. */
  130. T* getBack(void) const
  131. {
  132. MY_CRITICAL_SECTION {
  133. if (!empty())
  134. {
  135. return get(back());
  136. }
  137. }
  138. return static_cast<T*>(NULL);
  139. }
  140. /**
  141. * Remove record from back of the buffer.
  142. * @return True, when record was pop'ed successfully.
  143. */
  144. bool popBack(void)
  145. {
  146. MY_CRITICAL_SECTION {
  147. if (!empty())
  148. {
  149. m_fill--;
  150. return true;
  151. }
  152. }
  153. return false;
  154. }
  155. protected:
  156. /**
  157. * Internal getter for records.
  158. * @param idx Record index in buffer.
  159. * @return Ptr to record.
  160. */
  161. inline T * get(const uint8_t idx) const
  162. {
  163. return &(m_buff[idx]);
  164. }
  165. /**
  166. * Internal getter for index of last used record in buffer.
  167. * @return Index of last record.
  168. */
  169. inline uint8_t back(void) const
  170. {
  171. return (m_front - m_fill + m_size) % m_size;
  172. }
  173. const uint8_t m_size; //!< Total number of records that can be stored in the buffer.
  174. T* const m_buff; //!< Ptr to buffer holding all records.
  175. volatile uint8_t m_front; //!< Index of front element (not pushed yet).
  176. volatile uint8_t m_fill; //!< Amount of records currently pushed.
  177. };
  178. #endif // CircularBuffer_h