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.

107 lines
2.9KB

  1. // Copyright 2011 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. //
  16. // -----------------------------------------------------------------------------
  17. //
  18. // Important: All buffer sizes are expected to be less than 256! (fit in 8
  19. // bits), and must be powers of 2.
  20. #ifndef AVRLIBX_IO_RING_BUFFER_H_
  21. #define AVRLIBX_IO_RING_BUFFER_H_
  22. #include "avrlibx/avrlibx.h"
  23. namespace avrlibx {
  24. template<typename Owner>
  25. class RingBuffer {
  26. public:
  27. typedef typename Owner::Value Value;
  28. enum {
  29. size = Owner::buffer_size,
  30. data_size = Owner::data_size
  31. };
  32. RingBuffer() { }
  33. static inline uint8_t capacity() { return size; }
  34. static inline void Write(Value v) {
  35. while (!writable());
  36. Overwrite(v);
  37. }
  38. static inline uint8_t writable() {
  39. return (read_ptr_ - write_ptr_ - 1) & (size - 1);
  40. }
  41. static inline uint8_t NonBlockingWrite(Value v) {
  42. if (writable()) {
  43. Overwrite(v);
  44. return 1;
  45. } else {
  46. return 0;
  47. }
  48. }
  49. static inline void Overwrite(Value v) {
  50. uint8_t w = write_ptr_;
  51. buffer_[w] = v;
  52. write_ptr_ = (w + 1) & (size - 1);
  53. }
  54. static void Overwrite2(Value v1, Value v2) {
  55. uint8_t w = write_ptr_;
  56. buffer_[w] = v1;
  57. buffer_[w + 1] = v2;
  58. write_ptr_ = (w + 2) & (size - 1);
  59. }
  60. static inline uint8_t Requested() { return 0; }
  61. static inline Value Read() {
  62. while (!readable());
  63. return ImmediateRead();
  64. }
  65. static inline uint8_t readable() {
  66. return (write_ptr_ - read_ptr_) & (size - 1);
  67. }
  68. static inline int16_t NonBlockingRead() {
  69. if (readable()) {
  70. return ImmediateRead();
  71. } else {
  72. return -1;
  73. }
  74. }
  75. static inline Value ImmediateRead() {
  76. uint8_t r = read_ptr_;
  77. Value result = buffer_[r];
  78. read_ptr_ = (r + 1) & (size - 1);
  79. return result;
  80. }
  81. static inline void Flush() {
  82. write_ptr_ = read_ptr_;
  83. }
  84. private:
  85. static Value buffer_[size];
  86. static volatile uint8_t read_ptr_;
  87. static volatile uint8_t write_ptr_;
  88. DISALLOW_COPY_AND_ASSIGN(RingBuffer);
  89. };
  90. // Static variables created for each buffer.
  91. template<typename T> volatile uint8_t RingBuffer<T>::read_ptr_ = 0;
  92. template<typename T> volatile uint8_t RingBuffer<T>::write_ptr_ = 0;
  93. template<typename T> typename T::Value RingBuffer<T>::buffer_[];
  94. } // namespace avrlibx
  95. #endif // AVRLIBX_IO_RING_BUFFER_H_