Skip to content

Commit b4bdb1a

Browse files
committed
AudioLogger add LockGuard
1 parent bca62a5 commit b4bdb1a

File tree

3 files changed

+73
-39
lines changed

3 files changed

+73
-39
lines changed

src/AudioTools/Concurrency/LockGuard.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22
#include "AudioConfig.h"
3-
#include "AudioTools/CoreAudio/AudioLogger.h"
43
#include "Mutex.h"
54

65
namespace audio_tools {
@@ -18,18 +17,15 @@ namespace audio_tools {
1817
class LockGuard {
1918
public:
2019
LockGuard(MutexBase &mutex) {
21-
TRACED();
2220
p_mutex = &mutex;
2321
p_mutex->lock();
2422
}
2523
LockGuard(MutexBase *mutex) {
26-
TRACED();
2724
p_mutex = mutex;
2825
if (p_mutex != nullptr)
2926
p_mutex->lock();
3027
}
3128
~LockGuard() {
32-
TRACED();
3329
if (p_mutex != nullptr)
3430
p_mutex->unlock();
3531
}

src/AudioTools/Concurrency/RP2040/BufferRP2040.h

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace audio_tools {
1515
/**
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
18-
* cores.
18+
* cores. Multi-core and IRQ safe queue implementation!
1919
* @ingroup buffers
2020
* @ingroup concurrency
2121
* @author Phil Schatzmann
@@ -38,8 +38,10 @@ class BufferRP2040T : public BaseBuffer<T> {
3838
if (buffer_size_total_bytes != buffer_size_req_bytes) {
3939
LOGI("resize %d -> %d", buffer_size_total_bytes, buffer_size_req_bytes);
4040
assert(buffer_size > 0);
41-
write_buffer.resize(buffer_size);
42-
read_buffer.resize(buffer_size * 2);
41+
if (is_blocking_write){
42+
write_buffer.resize(buffer_size);
43+
read_buffer.resize(buffer_size * 2);
44+
}
4345
// release existing queue
4446
if (buffer_size_total_bytes > 0) {
4547
queue_free(&queue);
@@ -71,6 +73,10 @@ class BufferRP2040T : public BaseBuffer<T> {
7173
// reads multiple values
7274
int readArray(T data[], int len) override {
7375
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+
}
7480
// handle unalloc;ated queue
7581
if (buffer_size_total_bytes == 0) return 0;
7682
if (isEmpty() && read_buffer.isEmpty()) return 0;
@@ -94,24 +100,17 @@ class BufferRP2040T : public BaseBuffer<T> {
94100

95101
int writeArray(const T data[], int len) override {
96102
LOGD("writeArray: %d", len);
103+
int result = 0;
97104
// make sure that we have the data allocated
98105
resize(buffer_size_req_bytes);
99106

100-
// blocking write: wait for available space
101-
while (availableForWrite()<=len){
102-
delay(5);
103-
};
104-
105-
// fill the write buffer and when it is full flush it to the queue
106-
for (int j = 0; j < len; j++) {
107-
write_buffer.write(data[j]);
108-
if (write_buffer.isFull()) {
109-
LOGD("queue_add_blocking");
110-
queue_add_blocking(&queue, write_buffer.data());
111-
write_buffer.reset();
112-
}
107+
if (is_blocking_write) {
108+
result = writeBlocking(data, len);
109+
} else {
110+
result = writeNonBlocking(data, len);
113111
}
114-
return len;
112+
113+
return result;
115114
}
116115

117116
// checks if the buffer is full
@@ -150,13 +149,52 @@ class BufferRP2040T : public BaseBuffer<T> {
150149

151150
size_t size() { return buffer_size_req_bytes / sizeof(T); }
152151

152+
/// When we use a non blocking write, the write size must be identical with the buffer size
153+
void setBlockingWrite(bool flag){
154+
is_blocking_write = flag;
155+
}
156+
153157
protected:
154158
queue_t queue;
155159
int buffer_size_total_bytes = 0;
156160
int buffer_size_req_bytes = 0;
157161
int buffer_size = 0;
158162
SingleBuffer<T> write_buffer{0};
159163
audio_tools::RingBuffer<T> read_buffer{0};
164+
bool is_blocking_write = true;
165+
166+
int writeBlocking(const T data[], int len) {
167+
LOGD("writeArray: %d", len);
168+
169+
if (len > buffer_size){
170+
LOGE("write %d too big for buffer_size: %d", len, buffer_size);
171+
return 0;
172+
}
173+
174+
// fill the write buffer and when it is full flush it to the queue
175+
for (int j = 0; j < len; j++) {
176+
write_buffer.write(data[j]);
177+
if (write_buffer.isFull()) {
178+
LOGD("queue_add_blocking");
179+
queue_add_blocking(&queue, write_buffer.data());
180+
write_buffer.reset();
181+
}
182+
}
183+
return len;
184+
}
185+
186+
int writeNonBlocking(const T data[], int len) {
187+
if (len != buffer_size){
188+
LOGE("write %d must be buffer_size: %d", len, buffer_size);
189+
return 0;
190+
}
191+
192+
if (queue_try_add(&queue, write_buffer.data())){
193+
return len;
194+
}
195+
return 0;
196+
}
197+
160198
};
161199

162200
using BufferRP2040 = BufferRP2040T<uint8_t>;

src/AudioTools/CoreAudio/AudioLogger.h

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,28 @@
44
#if defined(ARDUINO) && !defined(IS_MIN_DESKTOP)
55
# include "Print.h"
66
#endif
7+
8+
#if defined(RP2040)
9+
# include "AudioTools/Concurrency/RP2040.h"
10+
#elif defined(ESP32)
11+
# include "AudioTools/Concurrency/RTOS.h"
12+
#else
13+
# include "AudioTools/Concurrency/LockGuard.h"
14+
#endif
15+
716
// Logging Implementation
817
#if USE_AUDIO_LOGGING
918

1019
namespace audio_tools {
1120

12-
#if defined(ESP32) && defined(SYNCHRONIZED_LOGGING)
13-
# include "freertos/FreeRTOS.h"
14-
# include "freertos/task.h"
15-
static portMUX_TYPE mutex_logger = portMUX_INITIALIZER_UNLOCKED;
21+
#if defined(RP2040)
22+
MutexRP2040 audio_logger_mutex;
23+
#elif defined(ESP32)
24+
MutexESP32 audio_logger_mutex;
25+
#else
26+
MutexBase audio_logger_mutex; // no locking
1627
#endif
1728

18-
1929
/**
2030
* @brief A simple Logger that writes messages dependent on the log level
2131
* @ingroup tools
@@ -53,7 +63,6 @@ class AudioLogger {
5363
}
5464

5565
AudioLogger &prefix(const char* file, int line, LogLevel current_level){
56-
lock();
5766
printPrefix(file,line,current_level);
5867
return *this;
5968
}
@@ -65,7 +74,6 @@ class AudioLogger {
6574
log_print_ptr->println(print_buffer);
6675
#endif
6776
print_buffer[0]=0;
68-
unlock();
6977
}
7078

7179
char* str() {
@@ -134,17 +142,6 @@ class AudioLogger {
134142
return len;
135143
}
136144

137-
void lock(){
138-
#if defined(ESP32) && defined(SYNCHRONIZED_LOGGING)
139-
portENTER_CRITICAL(&mutex_logger);
140-
#endif
141-
}
142-
143-
void unlock(){
144-
#if defined(ESP32) && defined(SYNCHRONIZED_LOGGING)
145-
portEXIT_CRITICAL(&mutex_logger);
146-
#endif
147-
}
148145
};
149146

150147
static AudioLogger &AudioToolsLogger = AudioLogger::instance();
@@ -188,17 +185,20 @@ class CustomLogLevel {
188185

189186
//#define LOG_OUT(level, fmt, ...) {AudioLogger::instance().prefix(__FILE__,__LINE__, level);cont char PROGMEM *fmt_P=F(fmt); snprintf_P(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, fmt, ##__VA_ARGS__); AudioLogger::instance().println();}
190187
#define LOG_OUT_PGMEM(level, fmt, ...) { \
188+
LockGuard guard{audio_logger_mutex};\
191189
AudioLogger::instance().prefix(__FILE__,__LINE__, level); \
192190
snprintf(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, PSTR(fmt), ##__VA_ARGS__); \
193191
AudioLogger::instance().println();\
194192
}
195193

196194
#define LOG_OUT(level, fmt, ...) { \
195+
LockGuard guard{audio_logger_mutex};\
197196
AudioLogger::instance().prefix(__FILE__,__LINE__, level); \
198197
snprintf(AudioLogger::instance().str(), LOG_PRINTF_BUFFER_SIZE, fmt, ##__VA_ARGS__); \
199198
AudioLogger::instance().println();\
200199
}
201200
#define LOG_MIN(level) { \
201+
LockGuard guard{audio_logger_mutex};\
202202
AudioLogger::instance().prefix(__FILE__,__LINE__, level); \
203203
AudioLogger::instance().println();\
204204
}

0 commit comments

Comments
 (0)