Skip to content

Commit fb4c0d2

Browse files
committed
refactor(merge): optimize data discard policy
2 parents bf107f7 + ae18ef0 commit fb4c0d2

File tree

2 files changed

+52
-45
lines changed

2 files changed

+52
-45
lines changed

components/acoustics-porting/porting/sensor/i2smic.hpp

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -145,33 +145,36 @@ class SensorI2SMic final: public Sensor
145145
_frame_index = 0;
146146
_data_bytes_available = 0;
147147

148-
if (_data_buffer)
148+
if (_data_buffer) [[likely]]
149149
{
150-
if (_data_buffer.use_count() > 1)
150+
if (_data_buffer.use_count() > 1) [[unlikely]]
151151
{
152152
LOG(ERROR, "Data buffer is already in use by another process");
153153
return STATUS(EBUSY, "Data buffer is already in use");
154154
}
155+
155156
_data_buffer.reset();
156157
}
157158

158-
if (_rx_chan)
159+
if (_rx_chan) [[likely]]
159160
{
160161
auto ret = i2s_channel_disable(_rx_chan);
161-
if (ret != ESP_OK)
162+
if (ret != ESP_OK) [[unlikely]]
162163
{
163164
LOG(ERROR, "Failed to disable I2S channel: %s", esp_err_to_name(ret));
164165
return STATUS(EIO, "Failed to disable I2S channel");
165166
}
166167
ret = i2s_del_channel(_rx_chan);
167-
if (ret != ESP_OK)
168+
if (ret != ESP_OK) [[unlikely]]
168169
{
169170
LOG(ERROR, "Failed to delete I2S channel: %s", esp_err_to_name(ret));
170171
return STATUS(EIO, "Failed to delete I2S channel");
171172
}
172173
_rx_chan = nullptr;
173174
}
174175

176+
_info.status = Status::Uninitialized;
177+
175178
return STATUS_OK();
176179
}
177180

@@ -213,6 +216,12 @@ class SensorI2SMic final: public Sensor
213216
inline core::Status readDataFrame(core::DataFrame<std::unique_ptr<core::Tensor>> &data_frame,
214217
size_t batch_size) noexcept override
215218
{
219+
if (batch_size == 0) [[unlikely]]
220+
{
221+
LOG(ERROR, "Batch size cannot be zero");
222+
return STATUS(EINVAL, "Batch size cannot be zero");
223+
}
224+
216225
if (!initialized()) [[unlikely]]
217226
{
218227
LOG(ERROR, "Sensor is not initialized");
@@ -229,33 +238,21 @@ class SensorI2SMic final: public Sensor
229238
return STATUS(EBUSY, "Data buffer is already in use");
230239
}
231240

232-
if (batch_size == 0) [[unlikely]]
241+
if (batch_size > _data_buffer_capacity_frames) [[unlikely]]
233242
{
234-
LOG(ERROR, "Batch size cannot be zero");
235-
return STATUS(EINVAL, "Batch size cannot be zero");
243+
LOG(WARNING, "Batch size exceeds buffer capacity: %zu > %zu", batch_size, _data_buffer_capacity_frames);
244+
batch_size = _data_buffer_capacity_frames;
236245
}
237246

238247
const std::lock_guard<std::mutex> lock(_lock);
239248

240249
_info.status = Status::Locked;
241250

242-
const size_t available = internalDataAvailable();
243-
if (available > batch_size) [[unlikely]]
244-
{
245-
[[maybe_unused]] const auto discarded = internalDataDiscard(available - batch_size);
246-
LOG(DEBUG, "Discarded %zu staled frames from data buffer", discarded);
247-
}
248-
while (internalDataAvailable() < batch_size)
249-
{
250-
vTaskDelay(pdMS_TO_TICKS(5));
251-
}
252-
253251
data_frame.timestamp = std::chrono::steady_clock::now();
254252

255253
size_t read = 0;
256254
{
257-
size_t size
258-
= std::min(static_cast<size_t>(batch_size * _channels * sizeof(int16_t)), _data_buffer_capacity_bytes);
255+
size_t size = batch_size * _channels * sizeof(int16_t);
259256
auto ret = i2s_channel_read(_rx_chan, _data_buffer.get(), size, &read,
260257
pdMS_TO_TICKS((_buffered_duration + 1) * 1000));
261258
if (ret != ESP_OK) [[unlikely]]
@@ -264,12 +261,12 @@ class SensorI2SMic final: public Sensor
264261
_info.status = Status::Idle;
265262
return STATUS(EIO, "Failed to read data from I2S channel");
266263
}
267-
internalConsumeData(size);
264+
internalConsumeData(read);
268265

269266
if (read != size) [[unlikely]]
270267
{
271268
LOG(WARNING, "Read %zu bytes, expected %zu bytes", read, size);
272-
if (read == 0)
269+
if (!read) [[unlikely]]
273270
{
274271
_info.status = Status::Idle;
275272
return STATUS(EIO, "No data read from I2S channel");
@@ -278,9 +275,9 @@ class SensorI2SMic final: public Sensor
278275
read = batch_size * (_channels * sizeof(int16_t));
279276
}
280277
}
281-
282278
data_frame.data = core::Tensor::create(core::Tensor::Type::Int16,
283279
core::Tensor::Shape(static_cast<int>(batch_size), static_cast<int>(_channels)), _data_buffer, read);
280+
284281
data_frame.index = _frame_index;
285282
_frame_index += batch_size;
286283

@@ -303,7 +300,7 @@ class SensorI2SMic final: public Sensor
303300
{
304301
const size_t new_data_bytes_available = std::min(data_bytes_available + size, _data_buffer_capacity_bytes);
305302
if (_data_bytes_available.compare_exchange_strong(data_bytes_available, new_data_bytes_available,
306-
std::memory_order_release, std::memory_order_relaxed))
303+
std::memory_order_release, std::memory_order_relaxed)) [[likely]]
307304
{
308305
return false;
309306
}
@@ -339,13 +336,17 @@ class SensorI2SMic final: public Sensor
339336

340337
inline void internalConsumeData(size_t size) noexcept
341338
{
339+
if (!size) [[unlikely]]
340+
{
341+
return;
342+
}
342343
size_t data_bytes_available = _data_bytes_available.load(std::memory_order_acquire);
343344
while (1)
344345
{
345346
size = std::min(size, data_bytes_available);
346347
const size_t new_data_bytes_available = data_bytes_available - size;
347348
if (_data_bytes_available.compare_exchange_strong(data_bytes_available, new_data_bytes_available,
348-
std::memory_order_release, std::memory_order_relaxed))
349+
std::memory_order_release, std::memory_order_relaxed)) [[likely]]
349350
{
350351
return;
351352
}

components/acoustics-porting/porting/sensor/lis3dhtr.hpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class SensorLIS3DHTR final: public Sensor
3030
CONFIG_OBJECT_DECL_INTEGER("scl", "SCL pin number", 6, 1, 20),
3131
CONFIG_OBJECT_DECL_INTEGER("fsr", "Full scale range in G (2, 4, 8, 16)", 2, 2, 16),
3232
CONFIG_OBJECT_DECL_INTEGER("ord", "Output data rate in HZ (1, 10, 25, 50, 100, 200, 400)", 200, 1, 400),
33-
CONFIG_OBJECT_DECL_INTEGER("sr", "Sample rate in Hz", 100, 1, 200) };
33+
CONFIG_OBJECT_DECL_INTEGER("sr", "Sample rate in Hz", 100, 20, 200) };
3434
}
3535

3636
SensorLIS3DHTR() noexcept
@@ -133,7 +133,7 @@ class SensorLIS3DHTR final: public Sensor
133133
LOG(DEBUG, "Allocated buffer of size: %zu bytes at %p", _buffer_capacity, _buffer.get());
134134
}
135135

136-
const TickType_t period = pdMS_TO_TICKS(1000 / sr);
136+
_data_period = 1000 / sr;
137137
if (_timer)
138138
{
139139
auto ret = xTimerDelete(_timer, portMAX_DELAY);
@@ -143,7 +143,7 @@ class SensorLIS3DHTR final: public Sensor
143143
return STATUS(EFAULT, "Failed to delete existing timer");
144144
}
145145
}
146-
_timer = xTimerCreate("lis3dhtr", period, pdTRUE, nullptr, timerCallback);
146+
_timer = xTimerCreate("lis3dhtr", pdMS_TO_TICKS(_data_period), pdTRUE, nullptr, timerCallback);
147147
if (_timer == nullptr)
148148
{
149149
LOG(ERROR, "Failed to create timer");
@@ -282,6 +282,12 @@ class SensorLIS3DHTR final: public Sensor
282282
inline core::Status readDataFrame(core::DataFrame<std::unique_ptr<core::Tensor>> &data_frame,
283283
size_t batch_size) noexcept override
284284
{
285+
if (batch_size == 0) [[unlikely]]
286+
{
287+
LOG(ERROR, "Batch size cannot be zero");
288+
return STATUS(EINVAL, "Batch size cannot be zero");
289+
}
290+
285291
if (!initialized()) [[unlikely]]
286292
{
287293
LOG(ERROR, "Sensor is not initialized");
@@ -298,11 +304,6 @@ class SensorLIS3DHTR final: public Sensor
298304
return STATUS(EBUSY, "Data buffer is already in use");
299305
}
300306

301-
if (batch_size == 0) [[unlikely]]
302-
{
303-
LOG(ERROR, "Batch size cannot be zero");
304-
return STATUS(EINVAL, "Batch size cannot be zero");
305-
}
306307
if (batch_size > _buffer_capacity) [[unlikely]]
307308
{
308309
LOG(WARNING, "Batch size exceeds buffer capacity: %zu > %zu", batch_size, _buffer_capacity);
@@ -318,18 +319,22 @@ class SensorLIS3DHTR final: public Sensor
318319

319320
_info.status = Status::Locked;
320321

321-
const size_t available = _buffer->size();
322-
if (available > batch_size)
323-
{
324-
[[maybe_unused]] const auto discarded = _buffer->read(nullptr, available - batch_size);
325-
LOG(DEBUG, "Discarded %zu staled elements from buffer", discarded);
326-
}
327-
while (_buffer->size() < batch_size)
322+
size_t available = _buffer->size();
323+
auto ts = std::chrono::steady_clock::now();
324+
while (available < batch_size)
328325
{
329326
vTaskDelay(pdMS_TO_TICKS(5));
330-
}
327+
if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - ts)
328+
> std::chrono::milliseconds(50 * _data_buffer_capacity)) [[unlikely]]
329+
{
330+
LOG(ERROR, "Timeout while waiting for data, available: %zu, requested: %zu", available, batch_size);
331+
_info.status = Status::Idle;
332+
return STATUS(ETIMEDOUT, "Timeout while waiting for data");
333+
}
331334

332-
data_frame.timestamp = std::chrono::steady_clock::now();
335+
available = _buffer->size();
336+
}
337+
data_frame.timestamp = ts;
333338

334339
batch_size = _buffer->read(reinterpret_cast<Data *>(_data_buffer.get()), batch_size);
335340
data_frame.data = core::Tensor::create(core::Tensor::Type::Float32,
@@ -379,15 +384,16 @@ class SensorLIS3DHTR final: public Sensor
379384
private:
380385
mutable std::mutex _lock;
381386
driver::LIS3DHTR *_lis3dhtr = nullptr;
382-
static constexpr size_t _buffer_capacity = 2048;
387+
static inline constexpr const size_t _buffer_capacity = 2048;
383388
std::unique_ptr<core::RingBuffer<Data>> _buffer = nullptr;
389+
size_t _data_period = 0;
384390
volatile int _sensor_status = 0;
385391
TimerHandle_t _timer = nullptr;
386392
static SensorLIS3DHTR *_this;
387393

388394
size_t _frame_index = 0;
389395
std::shared_ptr<std::byte[]> _data_buffer = nullptr;
390-
static constexpr size_t _data_buffer_capacity = _buffer_capacity / 2;
396+
static inline constexpr const size_t _data_buffer_capacity = _buffer_capacity / 2;
391397
};
392398

393399
SensorLIS3DHTR *SensorLIS3DHTR::_this = nullptr;

0 commit comments

Comments
 (0)