Pico-Arduino
RingBufferN.h
1 /*
2  Copyright (c) 2014 Arduino. All right reserved.
3 
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 
9  This library 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.
12  See the GNU Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #ifdef __cplusplus
20 
21 #ifndef _RING_BUFFER_
22 #define _RING_BUFFER_
23 
24 #include <stdint.h>
25 #include <string.h>
26 
27 namespace arduino {
28 
29 // Define constants and variables for buffering incoming serial data. We're
30 // using a ring buffer (I think), in which head is the index of the location
31 // to which to write the next incoming character and tail is the index of the
32 // location from which to read.
33 #define SERIAL_BUFFER_SIZE 64
34 
35 template <int N>
36 class RingBufferN
37 {
38  public:
39  uint8_t _aucBuffer[N] ;
40  volatile int _iHead ;
41  volatile int _iTail ;
42  volatile int _numElems;
43 
44  public:
45  RingBufferN( void ) ;
46  void store_char( uint8_t c ) ;
47  void clear();
48  int read_char();
49  int available();
50  int availableForStore();
51  int peek();
52  bool isFull();
53 
54  private:
55  int nextIndex(int index);
56  inline bool isEmpty() const { return (_numElems == 0); }
57 };
58 
59 // Commente out because of Conflict with ESP01 library
60 #ifndef RINGBUFFER_TYPEDEF_OFF
61  typedef RingBufferN<SERIAL_BUFFER_SIZE> RingBuffer;
62 #endif
63 
64 template <int N>
65 RingBufferN<N>::RingBufferN( void )
66 {
67  memset( _aucBuffer, 0, N ) ;
68  clear();
69 }
70 
71 template <int N>
72 void RingBufferN<N>::store_char( uint8_t c )
73 {
74  // if we should be storing the received character into the location
75  // just before the tail (meaning that the head would advance to the
76  // current location of the tail), we're about to overflow the buffer
77  // and so we don't write the character or advance the head.
78  if (!isFull())
79  {
80  _aucBuffer[_iHead] = c ;
81  _iHead = nextIndex(_iHead);
82  _numElems++;
83  }
84 }
85 
86 template <int N>
87 void RingBufferN<N>::clear()
88 {
89  _iHead = 0;
90  _iTail = 0;
91  _numElems = 0;
92 }
93 
94 template <int N>
95 int RingBufferN<N>::read_char()
96 {
97  if (isEmpty())
98  return -1;
99 
100  uint8_t value = _aucBuffer[_iTail];
101  _iTail = nextIndex(_iTail);
102  _numElems--;
103 
104  return value;
105 }
106 
107 template <int N>
108 int RingBufferN<N>::available()
109 {
110  return _numElems;
111 }
112 
113 template <int N>
114 int RingBufferN<N>::availableForStore()
115 {
116  return (N - _numElems);
117 }
118 
119 template <int N>
120 int RingBufferN<N>::peek()
121 {
122  if (isEmpty())
123  return -1;
124 
125  return _aucBuffer[_iTail];
126 }
127 
128 template <int N>
129 int RingBufferN<N>::nextIndex(int index)
130 {
131  return (uint32_t)(index + 1) % N;
132 }
133 
134 template <int N>
135 bool RingBufferN<N>::isFull()
136 {
137  return (_numElems == N);
138 }
139 
140 }
141 
142 #endif /* _RING_BUFFER_ */
143 #endif /* __cplusplus */