From 8e59cb82b12f0e9526554932c6e3b2269757d555 Mon Sep 17 00:00:00 2001
From: Jochen Vothknecht <jochen3120@gmail.com>
Date: Sat, 23 Jun 2018 23:31:06 +0200
Subject: [PATCH] Add led-strip HAL

---
 main/peripherals/led_strip.cpp | 83 ++++++++++++++++++++++++++++++++++
 main/peripherals/led_strip.h   | 10 ++++
 main/qthing.h                  | 29 ++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 main/peripherals/led_strip.cpp
 create mode 100644 main/peripherals/led_strip.h

diff --git a/main/peripherals/led_strip.cpp b/main/peripherals/led_strip.cpp
new file mode 100644
index 0000000..cdade0e
--- /dev/null
+++ b/main/peripherals/led_strip.cpp
@@ -0,0 +1,83 @@
+#include "led_strip.h"
+
+
+uint8_t strips_cfged = 0;
+strand_t leds[8];
+
+uint8_t render_frequency = 50;
+
+qthing::led_color_t dummy_handler(uint8_t strip, uint16_t led, qthing::led_color_t last_color) {
+    return(last_color);
+}
+
+qthing::led_color_handler_t led_handler = dummy_handler;
+
+void render_loop(void *ignored) {
+    digitalLeds_initStrands(leds, strips_cfged);
+    TickType_t lastWakeTime = xTaskGetTickCount();
+
+    while (true) {
+        for (uint8_t strip = 0; strip < strips_cfged; strip++) {
+            for (uint16_t led = 0; led < leds[strip].numPixels; led++) {
+                pixelColor_t last = leds[strip].pixels[led];
+                qthing::led_color_t last_led = {last.r, last.g, last.b, last.w};
+                qthing::led_color_t pixel = led_handler(strip, led, last_led);
+                leds[strip].pixels[led] = pixelFromRGBW(pixel.r, pixel.g, pixel.b, pixel.w);
+            }
+        }
+
+        for (uint8_t i = 0; i < strips_cfged; i++) digitalLeds_updatePixels(&leds[i]);
+        vTaskDelayUntil(&lastWakeTime, 1000 / render_frequency / portTICK_PERIOD_MS);
+    }
+}
+
+namespace qthing {
+    void add_ledstrip(gpio_num_t gpio, uint16_t num_leds, qthing::led_strip_types_t led_type) {
+
+        int led_type_translated = 0;
+
+        switch (led_type) {
+            case qthing::led_strip_types_t::LED_WS2812_V1: led_type_translated = led_types::LED_WS2812_V1; break;
+            case qthing::led_strip_types_t::LED_WS2812B_V1: led_type_translated = led_types::LED_WS2812B_V1; break;
+            case qthing::led_strip_types_t::LED_WS2812B_V2: led_type_translated = led_types::LED_WS2812B_V2; break;
+            case qthing::led_strip_types_t::LED_WS2812B_V3: led_type_translated = led_types::LED_WS2812B_V3; break;
+            case qthing::led_strip_types_t::LED_WS2813_V1: led_type_translated = led_types::LED_WS2813_V1; break;
+            case qthing::led_strip_types_t::LED_WS2813_V2: led_type_translated = led_types::LED_WS2813_V2; break;
+            case qthing::led_strip_types_t::LED_WS2813_V3: led_type_translated = led_types::LED_WS2813_V3; break;
+            case qthing::led_strip_types_t::LED_SK6812_V1: led_type_translated = led_types::LED_SK6812_V1; break;
+            case qthing::led_strip_types_t::LED_SK6812W_V1: led_type_translated = led_types::LED_SK6812W_V1; break;
+        }
+
+        leds[strips_cfged] = {
+            .rmtChannel = strips_cfged,
+            .gpioNum = gpio,
+            .ledType = led_type_translated,
+            .brightLimit = 255,
+            .numPixels =  num_leds,
+            .pixels = nullptr, 
+            ._stateVars = nullptr
+        };
+
+        gpio_pad_select_gpio(gpio);
+        gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
+        gpio_set_level(gpio, 0);
+
+        strips_cfged++;
+    }
+
+    void set_led_strip_fps(uint8_t fps) {
+        render_frequency = fps;
+    }
+
+    void enable_leds(uint8_t led_strip_fps) {
+        set_led_strip_fps(led_strip_fps);
+
+        // pin this to app cpu as it may consume a lot of cycles
+        // also assign prio of 2 since arduino's main-loop uses 1 if linked into app
+        xTaskCreatePinnedToCore(render_loop, "render_loop", 10000, NULL, 2, NULL, 1);
+    }
+
+    void set_color_handler(led_color_handler_t led_color_handler) {
+        led_handler = led_color_handler;
+    }
+}
\ No newline at end of file
diff --git a/main/peripherals/led_strip.h b/main/peripherals/led_strip.h
new file mode 100644
index 0000000..66350fd
--- /dev/null
+++ b/main/peripherals/led_strip.h
@@ -0,0 +1,10 @@
+# pragma once
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "driver/gpio.h"
+
+#include "esp32_digital_led_lib.h"
+
+#include <qthing.h>
diff --git a/main/qthing.h b/main/qthing.h
index 7761cb8..f9679c8 100644
--- a/main/qthing.h
+++ b/main/qthing.h
@@ -64,4 +64,33 @@ void enable_lcd(const std::string& topic, uint8_t rs, uint8_t en, uint8_t d4, ui
 void add_wlan_connection_status_handler(connection_status_callback_t handler);
 void add_mqtt_connection_status_handler(connection_status_callback_t handler);
 
+// LED strips
+namespace qthing {
+    enum led_strip_types_t {
+        LED_WS2812_V1,
+        LED_WS2812B_V1,
+        LED_WS2812B_V2,
+        LED_WS2812B_V3,
+        LED_WS2813_V1,
+        LED_WS2813_V2,
+        LED_WS2813_V3,
+        LED_SK6812_V1,
+        LED_SK6812W_V1,
+    };
+
+    typedef union {
+        struct __attribute__ ((packed)) {
+            uint8_t r, g, b, w;
+        };
+        uint32_t num;
+    } led_color_t;
+
+    typedef std::function<led_color_t(uint8_t, uint16_t, led_color_t)> led_color_handler_t;
+
+    void enable_leds(uint8_t led_strip_fps = 50);
+    void add_ledstrip(gpio_num_t gpio, uint16_t num_leds, qthing::led_strip_types_t led_type);
+    void set_color_handler(led_color_handler_t led_color_handler);
+    void set_led_strip_fps(uint8_t fps);
+}
+
 #endif
-- 
GitLab