ESPHome 2025.5.0
Loading...
Searching...
No Matches
ring_buffer.cpp
Go to the documentation of this file.
1#include "ring_buffer.h"
2
4#include "esphome/core/log.h"
5
6#ifdef USE_ESP32
7
8#include "helpers.h"
9
10namespace esphome {
11
12static const char *const TAG = "ring_buffer";
13
15 if (this->handle_ != nullptr) {
16 vRingbufferDelete(this->handle_);
18 allocator.deallocate(this->storage_, this->size_);
19 }
20}
21
22std::unique_ptr<RingBuffer> RingBuffer::create(size_t len) {
23 std::unique_ptr<RingBuffer> rb = make_unique<RingBuffer>();
24
25 rb->size_ = len;
26
28 rb->storage_ = allocator.allocate(rb->size_);
29 if (rb->storage_ == nullptr) {
30 return nullptr;
31 }
32
33 rb->handle_ = xRingbufferCreateStatic(rb->size_, RINGBUF_TYPE_BYTEBUF, rb->storage_, &rb->structure_);
34 ESP_LOGD(TAG, "Created ring buffer with size %u", len);
35
36 return rb;
37}
38
39size_t RingBuffer::read(void *data, size_t len, TickType_t ticks_to_wait) {
40 size_t bytes_read = 0;
41
42 void *buffer_data = xRingbufferReceiveUpTo(this->handle_, &bytes_read, ticks_to_wait, len);
43
44 if (buffer_data == nullptr) {
45 return 0;
46 }
47
48 std::memcpy(data, buffer_data, bytes_read);
49
50 vRingbufferReturnItem(this->handle_, buffer_data);
51
52 if (bytes_read < len) {
53 // Data may have wrapped around, so read a second time to receive the remainder
54 size_t follow_up_bytes_read = 0;
55 size_t bytes_remaining = len - bytes_read;
56
57 buffer_data = xRingbufferReceiveUpTo(this->handle_, &follow_up_bytes_read, 0, bytes_remaining);
58
59 if (buffer_data == nullptr) {
60 return bytes_read;
61 }
62
63 std::memcpy((void *) ((uint8_t *) (data) + bytes_read), buffer_data, follow_up_bytes_read);
64
65 vRingbufferReturnItem(this->handle_, buffer_data);
66 bytes_read += follow_up_bytes_read;
67 }
68
69 return bytes_read;
70}
71
72size_t RingBuffer::write(const void *data, size_t len) {
73 size_t free = this->free();
74 if (free < len) {
75 // Free enough space in the ring buffer to fit the new data
76 this->discard_bytes_(len - free);
77 }
78 return this->write_without_replacement(data, len, 0);
79}
80
81size_t RingBuffer::write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait) {
82 if (!xRingbufferSend(this->handle_, data, len, ticks_to_wait)) {
83 // Couldn't fit all the data, so only write what will fit
84 size_t free = std::min(this->free(), len);
85 if (xRingbufferSend(this->handle_, data, free, 0)) {
86 return free;
87 }
88 return 0;
89 }
90 return len;
91}
92
93size_t RingBuffer::available() const {
94 UBaseType_t ux_items_waiting = 0;
95 vRingbufferGetInfo(this->handle_, nullptr, nullptr, nullptr, nullptr, &ux_items_waiting);
96 return ux_items_waiting;
97}
98
99size_t RingBuffer::free() const { return xRingbufferGetCurFreeSize(this->handle_); }
100
101BaseType_t RingBuffer::reset() {
102 // Discards all the available data
103 return this->discard_bytes_(this->available());
104}
105
106bool RingBuffer::discard_bytes_(size_t discard_bytes) {
107 size_t bytes_read = 0;
108
109 void *buffer_data = xRingbufferReceiveUpTo(this->handle_, &bytes_read, 0, discard_bytes);
110 if (buffer_data != nullptr)
111 vRingbufferReturnItem(this->handle_, buffer_data);
112
113 if (bytes_read < discard_bytes) {
114 size_t wrapped_bytes_read = 0;
115 buffer_data = xRingbufferReceiveUpTo(this->handle_, &wrapped_bytes_read, 0, discard_bytes - bytes_read);
116 if (buffer_data != nullptr) {
117 vRingbufferReturnItem(this->handle_, buffer_data);
118 bytes_read += wrapped_bytes_read;
119 }
120 }
121
122 return (bytes_read == discard_bytes);
123}
124
125} // namespace esphome
126
127#endif
An STL allocator that uses SPI or internal RAM.
Definition helpers.h:683
void deallocate(T *p, size_t n)
Definition helpers.h:741
T * allocate(size_t n)
Definition helpers.h:703
size_t free() const
Returns the number of free bytes in the ring buffer.
static std::unique_ptr< RingBuffer > create(size_t len)
size_t write_without_replacement(const void *data, size_t len, TickType_t ticks_to_wait=0)
Writes to the ring buffer without overwriting oldest data.
BaseType_t reset()
Resets the ring buffer, discarding all stored data.
RingbufHandle_t handle_
Definition ring_buffer.h:90
bool discard_bytes_(size_t discard_bytes)
Discards data from the ring buffer.
size_t write(const void *data, size_t len)
Writes to the ring buffer, overwriting oldest data if necessary.
size_t available() const
Returns the number of available bytes in the ring buffer.
size_t read(void *data, size_t len, TickType_t ticks_to_wait=0)
Reads from the ring buffer, waiting up to a specified number of ticks if necessary.
const char *const TAG
Definition spi.cpp:8
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:301
std::unique_ptr< T > make_unique(Args &&...args)
Definition helpers.h:85