diff options
-rw-r--r-- | include/drv/ws2812b.h | 9 | ||||
-rw-r--r-- | main/drv/ws2812b.c | 51 | ||||
-rw-r--r-- | main/main.c | 150 |
3 files changed, 137 insertions, 73 deletions
diff --git a/include/drv/ws2812b.h b/include/drv/ws2812b.h index 39f2794..49337ed 100644 --- a/include/drv/ws2812b.h +++ b/include/drv/ws2812b.h @@ -13,7 +13,10 @@ typedef struct { } ws2812b_rgb_t; typedef struct { - uint8_t* buf_; /* Buffer to hold the value to spi. */ + /* Double-buffering strategy for speed-up. */ + uint8_t* buf_1; + uint8_t* buf_2; + uint8_t* buf_; /* Points to either buf_1 or buf_2 */ uint32_t n_rgb; /* Number of rgb values which exist. */ ws2812b_rgb_t rgb[]; /* Colors to write. */ @@ -24,9 +27,11 @@ typedef struct WS2812B ws2812b_t; ws2812b_buffer_t* ws2812b_new_buffer(uint32_t size); +esp_err_t ws2812b_wait(ws2812b_t* drv); + ws2812b_t* ws2812b_init(spi_device_handle_t spi); -esp_err_t ws2812b_write_sync(ws2812b_t* drv, ws2812b_buffer_t* buffer); +esp_err_t ws2812b_write(ws2812b_t* drv, ws2812b_buffer_t* buffer); static inline void ws2812b_buffer_set_rgb( ws2812b_buffer_t* buf, size_t idx, uint8_t r, uint8_t g, uint8_t b) 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; } diff --git a/main/main.c b/main/main.c index ff78f76..4caa26a 100644 --- a/main/main.c +++ b/main/main.c @@ -2,9 +2,9 @@ #include "drv/ws2812b.h" #include "esp_spi_flash.h" #include "esp_system.h" -#include "lwip/sockets.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "lwip/sockets.h" #include "sdkconfig.h" #include "station.h" @@ -43,11 +43,92 @@ #define PIN_NUM_BCKL 5 #endif -void ws_init() +struct { + char color[32]; + ws2812b_t* drv; +} ws_params; + +#define SIZE 300 +void calculate_colors(ws2812b_buffer_t* buffer) +{ + /* RACE Conditions for sure. Need to fix that. */ + ws2812b_rgb_t color = {0}; + if (!strcmp(ws_params.color, "black\n")) { + } else if (!strcmp(ws_params.color, "green\n")) { + color.g = 255; + } else if (!strcmp(ws_params.color, "red\n")) { + color.r = 255; + } else if (!strcmp(ws_params.color, "blue\n")) { + color.b = 255; + } else if (!strcmp(ws_params.color, "yellow\n")) { + color.r = 255; + color.g = 255; + } else if (!strcmp(ws_params.color, "magenta\n")) { + color.r = 255; + color.b = 255; + } else if (!strcmp(ws_params.color, "teal\n")) { + color.g = 255; + color.b = 255; + } else { + color.r = 128; + color.g = 128; + color.b = 128; + } + + int i; + for (i = 0; i < SIZE; ++i) { + ws2812b_buffer_set_color(buffer, i, &color); + } +} + +portTASK_FUNCTION(ws2812b_write_task, params) { + strcpy(ws_params.color, "red\n"); + + ws2812b_buffer_t* buffer = ws2812b_new_buffer(SIZE); + for (;;) { + calculate_colors(buffer); + ws2812b_write(ws_params.drv, buffer); + vTaskDelay(10 / portTICK_PERIOD_MS); + } } -uint8_t buffer[256]; +portTASK_FUNCTION(tcp_server, params) +{ + wifi_init_station("Wort", "JoshIsBau5"); + + int s = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_port = htons(1234); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + int err = bind(s, (struct sockaddr*)&addr, sizeof(addr)); + if (err) { + printf("Error binding to sockaddr: %d\n", err); + return; + } + + printf("Listening ...\n"); + listen(s, 1); + + while (true) { + printf("Waiting for connection... \n"); + + struct sockaddr_in client_addr; + socklen_t size; + int sock = accept(s, (struct sockaddr*)&client_addr, &size); + + printf("Accepted connection\n"); + ssize_t len; + + while ((len = read(sock, ws_params.color, sizeof(ws_params.color) - 1)) > + 0) { + ws_params.color[len] = 0; + printf("Read %s\n", ws_params.color); + } + } +} void app_main(void) { @@ -63,7 +144,7 @@ void app_main(void) }; spi_device_interface_config_t devcfg = { - .clock_speed_hz = 25 * 100 * 1000, /* 2.5 MHz */ + .clock_speed_hz = 24 * 100 * 1000, /* 2.5 MHz */ .mode = 0, .spics_io_num = PIN_NUM_CS, .queue_size = 7, @@ -83,63 +164,10 @@ void app_main(void) printf("Add Device\n"); ESP_ERROR_CHECK(error); - printf("Configuration complete!!\n"); - - wifi_init_station("Wort", "JoshIsBau5"); - - int s = socket(AF_INET, SOCK_STREAM, 0); - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_port = htons(1234); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - int err = bind(s, (struct sockaddr*) &addr, sizeof(addr)); - - if (err) { - printf("Error binding to sockaddr: %d\n", err); - return; - } - - printf("Listening ...\n"); - listen(s, 1); - - ws2812b_t* drv = ws2812b_init(spi); - ws2812b_buffer_t* buffer = ws2812b_new_buffer(5); - - while (true) { - printf("Waiting for connection... \n"); - char buf[128]; - - struct sockaddr_in client_addr; - socklen_t size; - int sock = accept(s, (struct sockaddr*)&client_addr, &size); + ws_params.drv = ws2812b_init(spi); - printf("Accepted connection\n"); - ssize_t len; + printf("Configuration complete!!\n"); - while ((len = read(sock, buf, sizeof(buf) - 1)) > 0) { - buf[len] = 0; - printf("Got %s\n", buf); - - ws2812b_rgb_t color = {0}; - if (!strcmp(buf, "green\n")) { - color.g = 255; - } else if (!strcmp(buf, "red\n")) { - color.r = 255; - } else if (!strcmp(buf, "blue\n")) { - color.b = 255; - } else { - color.r = 255; - color.g = 255; - color.b = 255; - } - - for (int i = 0; i < 5; ++ i) { - ws2812b_buffer_set_color(buffer, i, &color); - } - - ws2812b_write_sync(drv, buffer); - vTaskDelay(10 / portTICK_PERIOD_MS); - } - } + xTaskCreate(ws2812b_write_task, "ws2812b_writer", 4096, NULL, 1, NULL); + xTaskCreate(tcp_server, "tcp_server", 4096, NULL, 2, NULL); } |