mirror of
https://github.com/esphome/esphome.git
synced 2026-10-23 14:38:52 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a22b2d20a | ||
|
|
d361aca9b1 | ||
|
|
1e61d43263 |
No files matched your search
@@ -394,14 +394,14 @@ bool WeikaiChannel::check_channel_down_() {
|
||||
}
|
||||
|
||||
bool WeikaiChannel::peek_byte(uint8_t *buffer) {
|
||||
auto available = this->receive_buffer_.count();
|
||||
if (!available)
|
||||
xfer_fifo_to_buffer_();
|
||||
return this->receive_buffer_.peek(*buffer);
|
||||
if (this->receive_buffer_.empty() && this->xfer_fifo_to_buffer_() == 0)
|
||||
return false;
|
||||
*buffer = this->receive_buffer_.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t WeikaiChannel::available() {
|
||||
size_t available = this->receive_buffer_.count();
|
||||
size_t available = this->receive_buffer_.size();
|
||||
if (!available)
|
||||
available = xfer_fifo_to_buffer_();
|
||||
return available;
|
||||
@@ -409,7 +409,7 @@ size_t WeikaiChannel::available() {
|
||||
|
||||
bool WeikaiChannel::read_array(uint8_t *buffer, size_t length) {
|
||||
bool status = true;
|
||||
auto available = this->receive_buffer_.count();
|
||||
size_t available = this->receive_buffer_.size();
|
||||
if (length > available) {
|
||||
ESP_LOGW(TAG, "read_array: buffer underflow requested %d bytes only %d bytes available", length, available);
|
||||
length = available;
|
||||
@@ -417,7 +417,8 @@ bool WeikaiChannel::read_array(uint8_t *buffer, size_t length) {
|
||||
}
|
||||
// retrieve the bytes from ring buffer
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
this->receive_buffer_.pop(buffer[i]);
|
||||
buffer[i] = this->receive_buffer_.front();
|
||||
this->receive_buffer_.pop();
|
||||
}
|
||||
ESP_LOGVV(TAG, "read_array(ch=%d buffer[0]=%02X, length=%d): status %s", this->channel_, *buffer, length,
|
||||
status ? LOG_STR_LITERAL("OK") : LOG_STR_LITERAL("ERROR"));
|
||||
@@ -448,7 +449,7 @@ size_t WeikaiChannel::xfer_fifo_to_buffer_() {
|
||||
size_t total = 0;
|
||||
while (true) {
|
||||
size_t to_transfer = this->rx_in_fifo_();
|
||||
size_t free = this->receive_buffer_.free();
|
||||
size_t free = RING_BUFFER_SIZE - this->receive_buffer_.size();
|
||||
if (to_transfer == 0 || free == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <memory>
|
||||
#include <cinttypes>
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "wk_reg_def.h"
|
||||
|
||||
@@ -46,84 +47,6 @@ const LogString *reg_to_str(int reg, bool page1);
|
||||
/// Logs a buffer in hexadecimal, 32 values per line, under @p tag at @p level.
|
||||
void print_buffer(const char *tag, const uint8_t *data, size_t length, int level = ESPHOME_LOG_LEVEL_VERY_VERBOSE);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief This is an helper class that provides a simple ring buffers that works as a FIFO
|
||||
/// @details This ring buffer is used to buffer the bytes received in the FIFO of the Weika device. The best way to read
|
||||
/// characters from the device FIFO, is to first check how many bytes were received and then read them all at once.
|
||||
/// Unfortunately in all the code I have reviewed the characters are read one by one in a while loop by checking if
|
||||
/// bytes are available then reading the byte until no more byte available. This is pretty inefficient for two reasons:
|
||||
/// - Fist you need to perform a test for each byte to read
|
||||
/// - and second you call the read byte method for each character.
|
||||
/// .
|
||||
/// Assuming you need to read 100 bytes that results into 200 calls. This is to compare to 2 calls (one to find the
|
||||
/// number of bytes available plus one to read all the bytes) in the best case! If the registers you read are located on
|
||||
/// the micro-controller this is acceptable because the registers can be accessed fast. But when the registers are
|
||||
/// located on a remote device accessing them requires several cycles on a slow bus. As it it not possible to fix this
|
||||
/// problem by asking users to rewrite their code, I have implemented this ring buffer that store the bytes received
|
||||
/// locally.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<typename T, size_t SIZE> class WKRingBuffer {
|
||||
public:
|
||||
/// @brief pushes an item at the tail of the fifo
|
||||
/// @param item item to push
|
||||
/// @return true if item has been pushed, false il item could not pushed (buffer full)
|
||||
bool push(const T item) {
|
||||
if (is_full())
|
||||
return false;
|
||||
this->rb_[this->head_] = item;
|
||||
this->head_ = (this->head_ + 1) % SIZE;
|
||||
this->count_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief return and remove the item at head of the fifo
|
||||
/// @param item item read
|
||||
/// @return true if an item has been retrieved, false il no item available (buffer empty)
|
||||
bool pop(T &item) {
|
||||
if (is_empty())
|
||||
return false;
|
||||
item = this->rb_[this->tail_];
|
||||
this->tail_ = (this->tail_ + 1) % SIZE;
|
||||
this->count_--;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief return the value of the item at fifo's head without removing it
|
||||
/// @param item pointer to item to return
|
||||
/// @return true if item has been retrieved, false il no item available (buffer empty)
|
||||
bool peek(T &item) {
|
||||
if (is_empty())
|
||||
return false;
|
||||
item = this->rb_[this->tail_];
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief test is the Ring Buffer is empty ?
|
||||
/// @return true if empty
|
||||
inline bool is_empty() { return (this->count_ == 0); }
|
||||
|
||||
/// @brief test is the ring buffer is full ?
|
||||
/// @return true if full
|
||||
inline bool is_full() { return (this->count_ == SIZE); }
|
||||
|
||||
/// @brief return the number of item in the ring buffer
|
||||
/// @return the number of items
|
||||
inline size_t count() { return this->count_; }
|
||||
|
||||
/// @brief returns the number of free positions in the buffer
|
||||
/// @return how many items can be added
|
||||
inline size_t free() { return SIZE - this->count_; }
|
||||
|
||||
/// @brief clear the buffer content
|
||||
inline void clear() { this->head_ = this->tail_ = this->count_ = 0; }
|
||||
|
||||
protected:
|
||||
std::array<T, SIZE> rb_{0}; ///< the ring buffer
|
||||
int tail_{0}; ///< position of the next element to read
|
||||
int head_{0}; ///< position of the next element to write
|
||||
size_t count_{0}; ///< count number of element in the buffer
|
||||
};
|
||||
|
||||
class WeikaiComponent;
|
||||
// class WeikaiComponentSPI;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -447,7 +370,7 @@ class WeikaiChannel final : public uart::UARTComponent {
|
||||
#endif
|
||||
|
||||
/// @brief the buffer where we store temporarily the bytes received
|
||||
WKRingBuffer<uint8_t, RING_BUFFER_SIZE> receive_buffer_;
|
||||
StaticRingBuffer<uint8_t, RING_BUFFER_SIZE> receive_buffer_;
|
||||
WeikaiComponent *parent_; ///< our WK2168component parent
|
||||
uint8_t channel_; ///< our Channel number
|
||||
uint8_t data_; ///< a one byte buffer for register read storage
|
||||
|
||||
Reference in new issue
Block a user