mirror of
https://github.com/esphome/esphome.git
synced 2026-02-21 00:45:35 -07:00
[epaper_spi] New epaper component (#10462)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com> Co-authored-by: Tudor Sandu <tm.sandu@gmail.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
5
esphome/components/split_buffer/__init__.py
Normal file
5
esphome/components/split_buffer/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
|
||||
# Allows split_buffer to be configured in yaml, to allow use of the C++ api.
|
||||
|
||||
CONFIG_SCHEMA = {}
|
||||
133
esphome/components/split_buffer/split_buffer.cpp
Normal file
133
esphome/components/split_buffer/split_buffer.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "split_buffer.h"
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::split_buffer {
|
||||
|
||||
static constexpr const char *const TAG = "split_buffer";
|
||||
|
||||
SplitBuffer::~SplitBuffer() { this->free(); }
|
||||
|
||||
bool SplitBuffer::init(size_t total_length) {
|
||||
this->free(); // Clean up any existing allocation
|
||||
|
||||
if (total_length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->total_length_ = total_length;
|
||||
size_t current_buffer_size = total_length;
|
||||
|
||||
RAMAllocator<uint8_t *> ptr_allocator;
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
|
||||
// Try to allocate the entire buffer first
|
||||
while (current_buffer_size > 0) {
|
||||
// Calculate how many buffers we need of this size
|
||||
size_t needed_buffers = (total_length + current_buffer_size - 1) / current_buffer_size;
|
||||
|
||||
// Try to allocate array of buffer pointers
|
||||
uint8_t **temp_buffers = ptr_allocator.allocate(needed_buffers);
|
||||
if (temp_buffers == nullptr) {
|
||||
// If we can't even allocate the pointer array, don't need to continue
|
||||
ESP_LOGE(TAG, "Failed to allocate pointers");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize all pointers to null
|
||||
for (size_t i = 0; i < needed_buffers; i++) {
|
||||
temp_buffers[i] = nullptr;
|
||||
}
|
||||
|
||||
// Try to allocate all the buffers
|
||||
bool allocation_success = true;
|
||||
for (size_t i = 0; i < needed_buffers; i++) {
|
||||
size_t this_buffer_size = current_buffer_size;
|
||||
// Last buffer might be smaller if total_length is not divisible by current_buffer_size
|
||||
if (i == needed_buffers - 1 && total_length % current_buffer_size != 0) {
|
||||
this_buffer_size = total_length % current_buffer_size;
|
||||
}
|
||||
|
||||
temp_buffers[i] = allocator.allocate(this_buffer_size);
|
||||
if (temp_buffers[i] == nullptr) {
|
||||
allocation_success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize buffer to zero
|
||||
memset(temp_buffers[i], 0, this_buffer_size);
|
||||
}
|
||||
|
||||
if (allocation_success) {
|
||||
// Success! Store the result
|
||||
this->buffers_ = temp_buffers;
|
||||
this->buffer_count_ = needed_buffers;
|
||||
this->buffer_size_ = current_buffer_size;
|
||||
ESP_LOGD(TAG, "Allocated %zu * %zu bytes - %zu bytes", this->buffer_count_, this->buffer_size_,
|
||||
this->total_length_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allocation failed, clean up and try smaller buffers
|
||||
for (size_t i = 0; i < needed_buffers; i++) {
|
||||
if (temp_buffers[i] != nullptr) {
|
||||
allocator.deallocate(temp_buffers[i], 0);
|
||||
}
|
||||
}
|
||||
ptr_allocator.deallocate(temp_buffers, 0);
|
||||
|
||||
// Halve the buffer size and try again
|
||||
current_buffer_size = current_buffer_size / 2;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "Failed to allocate %zu bytes", total_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SplitBuffer::free() {
|
||||
if (this->buffers_ != nullptr) {
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
for (size_t i = 0; i < this->buffer_count_; i++) {
|
||||
if (this->buffers_[i] != nullptr) {
|
||||
allocator.deallocate(this->buffers_[i], 0);
|
||||
}
|
||||
}
|
||||
RAMAllocator<uint8_t *> ptr_allocator;
|
||||
ptr_allocator.deallocate(this->buffers_, 0);
|
||||
this->buffers_ = nullptr;
|
||||
}
|
||||
this->buffer_count_ = 0;
|
||||
this->buffer_size_ = 0;
|
||||
this->total_length_ = 0;
|
||||
}
|
||||
|
||||
uint8_t &SplitBuffer::operator[](size_t index) {
|
||||
if (index >= this->total_length_) {
|
||||
ESP_LOGE(TAG, "Out of bounds - %zu >= %zu", index, this->total_length_);
|
||||
// Return reference to a static dummy byte to avoid crash
|
||||
static uint8_t dummy = 0;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
size_t buffer_index = index / this->buffer_size_;
|
||||
size_t offset_in_buffer = index - this->buffer_size_ * buffer_index;
|
||||
|
||||
return this->buffers_[buffer_index][offset_in_buffer];
|
||||
}
|
||||
|
||||
const uint8_t &SplitBuffer::operator[](size_t index) const {
|
||||
if (index >= this->total_length_) {
|
||||
ESP_LOGE(TAG, "Out of bounds - %zu >= %zu", index, this->total_length_);
|
||||
// Return reference to a static dummy byte to avoid crash
|
||||
static const uint8_t DUMMY = 0;
|
||||
return DUMMY;
|
||||
}
|
||||
|
||||
size_t buffer_index = index / this->buffer_size_;
|
||||
size_t offset_in_buffer = index - this->buffer_size_ * buffer_index;
|
||||
|
||||
return this->buffers_[buffer_index][offset_in_buffer];
|
||||
}
|
||||
|
||||
} // namespace esphome::split_buffer
|
||||
40
esphome/components/split_buffer/split_buffer.h
Normal file
40
esphome/components/split_buffer/split_buffer.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace esphome::split_buffer {
|
||||
|
||||
class SplitBuffer {
|
||||
public:
|
||||
SplitBuffer() = default;
|
||||
~SplitBuffer();
|
||||
|
||||
// Initialize the buffer with the desired total length
|
||||
bool init(size_t total_length);
|
||||
|
||||
// Free all allocated buffers
|
||||
void free();
|
||||
|
||||
// Access operators
|
||||
uint8_t &operator[](size_t index);
|
||||
const uint8_t &operator[](size_t index) const;
|
||||
|
||||
// Get the total length
|
||||
size_t size() const { return this->total_length_; }
|
||||
|
||||
// Get buffer information
|
||||
size_t get_buffer_count() const { return this->buffer_count_; }
|
||||
size_t get_buffer_size() const { return this->buffer_size_; }
|
||||
|
||||
// Check if successfully initialized
|
||||
bool is_valid() const { return this->buffers_ != nullptr && this->buffer_count_ > 0; }
|
||||
|
||||
private:
|
||||
uint8_t **buffers_{nullptr};
|
||||
size_t buffer_count_{0};
|
||||
size_t buffer_size_{0};
|
||||
size_t total_length_{0};
|
||||
};
|
||||
|
||||
} // namespace esphome::split_buffer
|
||||
Reference in New Issue
Block a user