@@ -16,6 +16,11 @@ namespace audio_tools {
1616 * @brief Buffer implementation which is based on a RP2040 queue. This
1717 * class is intended to be used to exchange data between the 2 different
1818 * cores. Multi-core and IRQ safe queue implementation!
19+ *
20+ * In order to increase the efficiency we to not enqueue individual items
21+ * but write them into a temporary buffer of bufferSize and write this
22+ * array to the queue when it is full.
23+ *
1924 * @ingroup buffers
2025 * @ingroup concurrency
2126 * @author Phil Schatzmann
@@ -25,34 +30,40 @@ namespace audio_tools {
2530template <typename T>
2631class BufferRP2040T : public BaseBuffer <T> {
2732 public:
28- BufferRP2040T (size_t bufferSize, int bufferCount = 2 ) : BaseBuffer<T>() {
29- buffer_size = bufferSize * sizeof (T);
30- buffer_size_req_bytes = buffer_size * bufferCount;
33+ BufferRP2040T (int bufferCount) : BaseBuffer<T>() {
34+ buffer_size = 1 ;
35+ buffer_size_bytes = sizeof (T);
36+ buffer_size_req_bytes = buffer_size_bytes * bufferCount;
37+ }
38+
39+ BufferRP2040T (size_t bufferSize, int bufferCount) : BaseBuffer<T>() {
40+ buffer_size = bufferSize;
41+ buffer_size_bytes = bufferSize * sizeof (T);
42+ buffer_size_req_bytes = buffer_size_bytes * bufferCount;
3143 }
3244
3345 ~BufferRP2040T () { reset (); }
3446
35- // / Re-Allocats the memory and the queue
47+ // / Re-Allocats the memory and the queue (size is in entries)
3648 bool resize (size_t size) {
37- buffer_size_req_bytes = size;
38- if (buffer_size_total_bytes != buffer_size_req_bytes) {
39- LOGI (" resize %d -> %d" , buffer_size_total_bytes, buffer_size_req_bytes);
40- assert (buffer_size > 0 );
41- if (is_blocking_write){
42- write_buffer.resize (buffer_size);
43- read_buffer.resize (buffer_size * 2 );
44- }
45- // release existing queue
46- if (buffer_size_total_bytes > 0 ) {
47- queue_free (&queue);
48- }
49+ int req_bytes = size * sizeof (T);
50+ if (buffer_size_alloc_bytes < req_bytes) {
51+ LOGI (" resize %d -> %d" , buffer_size_alloc_bytes / sizeof (T), size);
52+ assert (buffer_size_bytes > 0 );
53+ write_buffer.resize (buffer_size);
54+ read_buffer.resize (buffer_size * 2 );
4955 // create new queu
50- if (buffer_size_req_bytes > 0 ) {
51- int count = buffer_size_req_bytes / buffer_size;
52- LOGI (" queue_init(size:%d, count:%d)" , buffer_size, count);
53- queue_init (&queue, buffer_size, count);
56+ if (req_bytes > buffer_size_alloc_bytes) {
57+ // release existing queue
58+ if (buffer_size_alloc_bytes > 0 ) {
59+ queue_free (&queue);
60+ }
61+
62+ int count = req_bytes / buffer_size_bytes;
63+ LOGI (" queue_init(size:%d, count:%d)" , buffer_size_bytes, count);
64+ queue_init (&queue, buffer_size_bytes, count);
65+ buffer_size_alloc_bytes = req_bytes;
5466 }
55- buffer_size_total_bytes = buffer_size_req_bytes;
5667 }
5768 return true ;
5869 }
@@ -73,13 +84,13 @@ class BufferRP2040T : public BaseBuffer<T> {
7384 // reads multiple values
7485 int readArray (T data[], int len) override {
7586 LOGD (" readArray: %d" , len);
76- if (!is_blocking_write && read_buffer.size ()==0 ){
77- // make sure that the read buffer is big enough
78- read_buffer.resize (len + buffer_size);
79- }
8087 // handle unalloc;ated queue
81- if (buffer_size_total_bytes == 0 ) return 0 ;
82- if (isEmpty () && read_buffer.isEmpty ()) return 0 ;
88+ if (buffer_size_alloc_bytes == 0 ) return 0 ;
89+
90+ // blocking read
91+ while (is_blocking_read && read_buffer.available () + available () < len)
92+ delay (1 );
93+
8394 // fill read buffer if necessary
8495 while (read_buffer.availableForWrite () >= buffer_size) {
8596 LOGD (" reading %d %d " , buffer_size, read_buffer.availableForWrite ());
@@ -102,7 +113,7 @@ class BufferRP2040T : public BaseBuffer<T> {
102113 LOGD (" writeArray: %d" , len);
103114 int result = 0 ;
104115 // make sure that we have the data allocated
105- resize (buffer_size_req_bytes);
116+ resize (buffer_size_req_bytes / sizeof (T) );
106117
107118 if (is_blocking_write) {
108119 result = writeBlocking (data, len);
@@ -115,12 +126,12 @@ class BufferRP2040T : public BaseBuffer<T> {
115126
116127 // checks if the buffer is full
117128 bool isFull () override {
118- if (buffer_size_total_bytes == 0 ) return false ;
129+ if (buffer_size_alloc_bytes == 0 ) return false ;
119130 return queue_is_full (&queue);
120131 }
121132
122133 bool isEmpty () {
123- if (buffer_size_total_bytes == 0 ) return true ;
134+ if (buffer_size_alloc_bytes == 0 ) return true ;
124135 return queue_is_empty (&queue);
125136 }
126137
@@ -130,44 +141,55 @@ class BufferRP2040T : public BaseBuffer<T> {
130141 // clears the buffer
131142 void reset () override {
132143 queue_free (&queue);
133- buffer_size_total_bytes = 0 ;
144+ buffer_size_alloc_bytes = 0 ;
134145 }
135146
136147 // provides the number of entries that are available to read
137148 int available () override {
138- return buffer_size / sizeof (T);
149+ if (buffer_size_alloc_bytes == 0 ) return 0 ;
150+ return (queue_get_level (&queue) * buffer_size);
139151 }
140152
141153 // provides the number of entries that are available to write
142- int availableForWrite () override { return size () - available (); }
154+ int availableForWrite () override {
155+ if (buffer_size_alloc_bytes == 0 ) return size ();
156+ return size () - available (); }
143157
144158 // returns the address of the start of the physical read buffer
145159 T *address () override {
146160 LOGE (" address() not implemented" );
147161 return nullptr ;
148162 }
149163
150- size_t size () { return buffer_size_req_bytes / sizeof (T); }
164+ size_t size () { return buffer_size_alloc_bytes / sizeof (T); }
151165
152166 // / When we use a non blocking write, the write size must be identical with the buffer size
153167 void setBlockingWrite (bool flag){
154168 is_blocking_write = flag;
155169 }
156170
171+ // / When we use a blockingread, the we wait for the data to be available
172+ void setBlockingRead (bool flag){
173+ is_blocking_read = flag;
174+ }
175+
176+
157177 protected:
158178 queue_t queue;
159- int buffer_size_total_bytes = 0 ;
179+ int buffer_size_alloc_bytes = 0 ;
160180 int buffer_size_req_bytes = 0 ;
181+ int buffer_size_bytes = 0 ;
161182 int buffer_size = 0 ;
162183 SingleBuffer<T> write_buffer{0 };
163184 audio_tools::RingBuffer<T> read_buffer{0 };
164185 bool is_blocking_write = true ;
186+ bool is_blocking_read = false ;
165187
166188 int writeBlocking (const T data[], int len) {
167189 LOGD (" writeArray: %d" , len);
168190
169- if (len > buffer_size ){
170- LOGE (" write %d too big for buffer_size: %d" , len, buffer_size );
191+ if (len > buffer_size_bytes ){
192+ LOGE (" write %d too big for buffer_size: %d" , len, buffer_size_bytes );
171193 return 0 ;
172194 }
173195
@@ -184,8 +206,8 @@ class BufferRP2040T : public BaseBuffer<T> {
184206 }
185207
186208 int writeNonBlocking (const T data[], int len) {
187- if (len != buffer_size ){
188- LOGE (" write %d must be buffer_size: %d" , len, buffer_size );
209+ if (len != buffer_size_bytes ){
210+ LOGE (" write %d must be buffer_size: %d" , len, buffer_size_bytes );
189211 return 0 ;
190212 }
191213
0 commit comments