Skip to content

Commit f4ed4f1

Browse files
committed
BufferRP2040 blocking read
1 parent b5e0aef commit f4ed4f1

File tree

3 files changed

+97
-39
lines changed

3 files changed

+97
-39
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "AudioTools.h"
2+
#include "AudioTools/Concurrency/RP2040.h"
3+
4+
BufferRP2040T<int> buffer(10, 20); //20 blocks with 10 ints->100 ints
5+
6+
void setup() {
7+
Serial.begin(115200);
8+
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
9+
while (!Serial)
10+
;
11+
delay(1000);
12+
Serial.println("testing...");
13+
14+
assert(buffer.size() == 200);
15+
assert(buffer.available() == 0);
16+
assert(buffer.availableForWrite() == 200);
17+
for (int j = 0; j < 10; j++) {
18+
assert(buffer.write(j));
19+
}
20+
assert(buffer.size() == 200);
21+
assert(buffer.available() == 10);
22+
23+
int tmp[20];
24+
assert(buffer.readArray(tmp, 20) == 10);
25+
26+
for (int j = 0; j < 10; j++) {
27+
assert(tmp[j] == j);
28+
}
29+
30+
assert(buffer.writeArray(tmp, 10) == 10);
31+
32+
Serial.println("success!");
33+
}
34+
35+
void loop() {
36+
}
File renamed without changes.

src/AudioTools/Concurrency/RP2040/BufferRP2040.h

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -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 {
2530
template <typename T>
2631
class 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

Comments
 (0)