Compare commits

...
2 changed files with 11 additions and 87 deletions

No files matched your search

+9 -8
View File
@@ -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;
}
+2 -79
View File
@@ -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