aboutsummaryrefslogtreecommitdiff
path: root/main/drv/ws2812b.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/drv/ws2812b.c')
-rw-r--r--main/drv/ws2812b.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/main/drv/ws2812b.c b/main/drv/ws2812b.c
index 3ab6b41..d0699ee 100644
--- a/main/drv/ws2812b.c
+++ b/main/drv/ws2812b.c
@@ -1,12 +1,19 @@
#include <drv/ws2812b.h>
+#include <memory.h>
+
+#define WS2812B_FLAG_DIRTY 1
struct WS2812B {
spi_device_handle_t spi_handle;
+ spi_transaction_t spi_transaction;
+
+ uint8_t flags;
};
ws2812b_t* ws2812b_init(spi_device_handle_t spi)
{
ws2812b_t* ret = heap_caps_malloc(sizeof(ws2812b_t), MALLOC_CAP_DEFAULT);
+ memset(ret, 0, sizeof(*ret));
ret->spi_handle = spi;
return ret;
@@ -27,6 +34,12 @@ static inline void byte_compile(uint8_t byte, uint8_t compl [3])
static inline void compile(ws2812b_buffer_t* buffer)
{
+ if (buffer->buf_ == buffer->buf_1) {
+ buffer->buf_ = buffer->buf_2;
+ } else {
+ buffer->buf_ = buffer->buf_1;
+ }
+
for (size_t i = 0; i < buffer->n_rgb; ++i) {
byte_compile(buffer->rgb[i].g, buffer->buf_ + i * 9 + 0);
byte_compile(buffer->rgb[i].r, buffer->buf_ + i * 9 + 3);
@@ -38,31 +51,49 @@ ws2812b_buffer_t* ws2812b_new_buffer(uint32_t n)
{
ws2812b_buffer_t* ret = heap_caps_malloc(
sizeof(ws2812b_buffer_t) + sizeof(ws2812b_rgb_t) * n, MALLOC_CAP_DEFAULT);
- ret->buf_ = heap_caps_malloc(n * 9, MALLOC_CAP_DMA);
+ ret->buf_1 = heap_caps_malloc(n * 9, MALLOC_CAP_DMA);
+ ret->buf_2 = heap_caps_malloc(n * 9, MALLOC_CAP_DMA);
+ ret->buf_ = ret->buf_1;
ret->n_rgb = n;
return ret;
}
-esp_err_t ws2812b_write_sync(ws2812b_t* drv, ws2812b_buffer_t* buffer)
+esp_err_t ws2812b_wait(ws2812b_t* drv)
{
esp_err_t err;
- compile(buffer);
- spi_transaction_t t = {0};
spi_transaction_t* rt;
-
- t.tx_buffer = buffer->buf_;
- t.length = buffer->n_rgb * 9 * 8;
-
- err = spi_device_queue_trans(drv->spi_handle, &t, portMAX_DELAY);
+ err = spi_device_get_trans_result(
+ drv->spi_handle, &rt, 10 / portTICK_PERIOD_MS);
+ drv->flags &= ~WS2812B_FLAG_DIRTY;
if (err != ESP_OK) {
return err;
}
- err = spi_device_get_trans_result(drv->spi_handle, &rt, portMAX_DELAY);
+ return ESP_OK;
+}
+
+esp_err_t ws2812b_write(ws2812b_t* drv, ws2812b_buffer_t* buffer)
+{
+ compile(buffer);
+
+ if (drv->flags & WS2812B_FLAG_DIRTY) {
+ ws2812b_wait(drv);
+ }
+
+ esp_err_t err;
+
+ memset(&drv->spi_transaction, 0, sizeof(drv->spi_transaction));
+
+ drv->spi_transaction.tx_buffer = buffer->buf_;
+ drv->spi_transaction.length = buffer->n_rgb * 9 * 8;
+
+ err = spi_device_queue_trans(
+ drv->spi_handle, &drv->spi_transaction, portMAX_DELAY);
if (err != ESP_OK) {
return err;
}
+ drv->flags |= WS2812B_FLAG_DIRTY;
return ESP_OK;
}