Separate FreeRTOS task for LED
This commit is contained in:
124
espmusicmouse/src/TaskLed.h
Normal file
124
espmusicmouse/src/TaskLed.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
#include "effects/Circular.h"
|
||||
#include "effects/Common.h"
|
||||
#include "drivers/Esp32DriverRGBW.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include <functional>
|
||||
#include <cstring>
|
||||
|
||||
static constexpr int MAX_EFFECT_CONFIG_SIZE = 128;
|
||||
static constexpr int MAX_EFFECT_CLASS_SIZE = 128;
|
||||
|
||||
template <typename TLedStrip>
|
||||
class LedTask
|
||||
{
|
||||
public:
|
||||
void begin(TLedStrip &strip, Esp32DriverRGBW &driver);
|
||||
|
||||
template <typename TEffectConfig>
|
||||
void startEffect(const TEffectConfig &cfg);
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend void _led_task_func(void *);
|
||||
|
||||
QueueHandle_t queue_ = nullptr;
|
||||
TLedStrip *ledStrip_ = nullptr;
|
||||
Esp32DriverRGBW *driver_ = nullptr;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
template <EffectId staticEffectId, typename TLedStrip>
|
||||
bool dispatchEffectId(EffectId dynamicEffectId, std::function<int()> &effectFunction, TLedStrip &ledStrip,
|
||||
unsigned char *msgBuffer, unsigned char *effectStorage)
|
||||
{
|
||||
if (staticEffectId == dynamicEffectId)
|
||||
{
|
||||
typename EffectIdToConfig<staticEffectId>::type cfg;
|
||||
memcpy(&cfg, msgBuffer + sizeof(EffectId), sizeof(decltype(cfg)));
|
||||
using TEffect = typename EffectIdToClass<staticEffectId, TLedStrip>::type;
|
||||
static_assert(sizeof(TEffect) < MAX_EFFECT_CLASS_SIZE, "Effect to big for effectStorage, increase MAX_EFFECT_CLASS_SIZE");
|
||||
TEffect *effect = new (effectStorage) TEffect(cfg, ledStrip);
|
||||
effectFunction = [effect]()
|
||||
{ return (*effect)(); };
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TLedStrip>
|
||||
void _led_task_func(void *params)
|
||||
{
|
||||
LedTask<TLedStrip> *task = reinterpret_cast<LedTask<TLedStrip> *>(params);
|
||||
unsigned char msgBuffer[MAX_EFFECT_CONFIG_SIZE];
|
||||
unsigned char effectStorage[MAX_EFFECT_CLASS_SIZE];
|
||||
|
||||
std::function<int()> effectFunction = []() -> int
|
||||
{ return 100000; };
|
||||
|
||||
int timeoutMsForEffect = 100000; // huge timeout since there is no effect in the beginning
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (xQueueReceive(task->queue_, msgBuffer, (TickType_t)(timeoutMsForEffect / portTICK_PERIOD_MS)) == pdTRUE)
|
||||
{
|
||||
// Read and parse effect from queue
|
||||
EffectId id;
|
||||
memcpy(&id, msgBuffer, sizeof(EffectId));
|
||||
|
||||
TLedStrip &ledStrip = *(task->ledStrip_);
|
||||
// clang-format off
|
||||
if (dispatchEffectId<EffectId::CIRCULAR>(id, effectFunction, ledStrip, msgBuffer, effectStorage)) { Serial.println("Parsed circular");}
|
||||
else if (dispatchEffectId<EffectId::STATIC >(id, effectFunction, ledStrip, msgBuffer, effectStorage)) { Serial.println("Parsed static");}
|
||||
// clang-format on
|
||||
|
||||
timeoutMsForEffect = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeoutMsForEffect = effectFunction();
|
||||
task->driver_->writeSync(task->ledStrip_->rawData(), task->ledStrip_->numLeds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TLedStrip>
|
||||
void LedTask<TLedStrip>::begin(TLedStrip &strip, Esp32DriverRGBW &driver)
|
||||
{
|
||||
queue_ = xQueueCreate(4, MAX_EFFECT_CONFIG_SIZE);
|
||||
if (!queue_)
|
||||
Serial.println("Failed to create LED effect queue");
|
||||
|
||||
ledStrip_ = &strip;
|
||||
driver_ = &driver;
|
||||
|
||||
xTaskCreate(_led_task_func<TLedStrip>, "led task", MAX_EFFECT_CLASS_SIZE + MAX_EFFECT_CONFIG_SIZE + 2048,
|
||||
(void *)(this), 1, nullptr);
|
||||
}
|
||||
|
||||
template <typename TLedStrip>
|
||||
template <typename TEffectConfig>
|
||||
void LedTask<TLedStrip>::startEffect(const TEffectConfig &cfg)
|
||||
{
|
||||
static constexpr auto msgSize = sizeof(TEffectConfig) + sizeof(EffectId);
|
||||
static_assert(msgSize < MAX_EFFECT_CONFIG_SIZE,
|
||||
"Effect config too large, increase MAX_EFFECT_CONFIG_SIZE");
|
||||
|
||||
unsigned char buffer[MAX_EFFECT_CONFIG_SIZE];
|
||||
if (queue_ == nullptr)
|
||||
{
|
||||
Serial.println("Trying to start effect before queue was set up!");
|
||||
return;
|
||||
}
|
||||
EffectId id = EffectConfigToId<TEffectConfig>::id;
|
||||
memcpy(buffer, &id, sizeof(EffectId));
|
||||
memcpy(buffer + sizeof(EffectId), &cfg, sizeof(TEffectConfig));
|
||||
xQueueSend(queue_, (void *)buffer, (TickType_t)10);
|
||||
}
|
||||
@@ -9,6 +9,9 @@
|
||||
#include "containers/LedStripRGBW.h"
|
||||
#include "drivers/Esp32DriverRGBW.h"
|
||||
#include "effects/Circular.h"
|
||||
#include "effects/Static.h"
|
||||
|
||||
#include "TaskLed.h"
|
||||
|
||||
MFRC522 rfid; // Instance of the class
|
||||
|
||||
@@ -18,14 +21,7 @@ MFRC522::MIFARE_Key key;
|
||||
LedStripRGBW<51> ledStrip;
|
||||
Esp32DriverRGBW ledDriver;
|
||||
|
||||
EffectCircular<decltype(ledStrip)> effectFox(EffectCircularConfig{60.0f, 180.0f, ColorRGBW{15, 230, 230, 0} * 0.2f},
|
||||
ledStrip);
|
||||
|
||||
EffectCircular<decltype(ledStrip)> effectOwl(EffectCircularConfig{360.0f, 180.0f, ColorRGBW{0, 0, 0, 150} * 0.2f},
|
||||
ledStrip);
|
||||
|
||||
bool owl = false;
|
||||
bool fox = false;
|
||||
LedTask<decltype(ledStrip)> ledTask;
|
||||
|
||||
void tag_handler(uint8_t *sn)
|
||||
{
|
||||
@@ -38,27 +34,18 @@ void tag_handler(uint8_t *sn)
|
||||
if (sn[4] == 0x30)
|
||||
{
|
||||
Serial.println("Fuchs");
|
||||
fox = true;
|
||||
owl = false;
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
//led.setRange(0, 50, 0, 0, 243, 0);
|
||||
//led.setRange(led.numLeds() - 40, led.numLeds(), 0, 0, 243, 0);
|
||||
ledTask.startEffect(EffectCircularConfig{2 * 360, 180, ColorRGBW{0, 0, 255, 0}});
|
||||
}
|
||||
if (sn[4] == 0xf0)
|
||||
{
|
||||
Serial.println("Eule");
|
||||
owl = true;
|
||||
fox = false;
|
||||
//led.setRange(0, 50, 0, 0, 0, 254);
|
||||
//led.setRange(led.numLeds() - 40, led.numLeds(), 0, 0, 0, 254);
|
||||
ledTask.startEffect(EffectCircularConfig{180, 180, ColorRGBW{0, 0, 0, 128}});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//led.clear();
|
||||
owl = false;
|
||||
fox = false;
|
||||
Serial.println("Nichts");
|
||||
ledTask.startEffect(EffectStaticConfig{ColorRGBW{0, 0, 0, 0}});
|
||||
}
|
||||
//led.transmit();
|
||||
}
|
||||
@@ -101,6 +88,8 @@ void setup()
|
||||
//pinMode(25, INPUT_PULLUP);
|
||||
//pinMode(14, INPUT_PULLUP);
|
||||
//pinMode(13, INPUT_PULLUP);
|
||||
ledTask.begin(ledStrip, ledDriver);
|
||||
ledTask.startEffect(EffectStaticConfig{ColorRGBW{0, 0, 0, 0}});
|
||||
}
|
||||
|
||||
bool btn2state = true;
|
||||
@@ -127,7 +116,9 @@ void loop()
|
||||
delay(3000);
|
||||
}
|
||||
*/
|
||||
int delayVal;
|
||||
|
||||
#if 0
|
||||
int delayVal = 100;
|
||||
if (owl)
|
||||
delayVal = effectOwl();
|
||||
else if (fox)
|
||||
@@ -137,6 +128,8 @@ void loop()
|
||||
|
||||
ledDriver.writeSync(ledStrip.rawData(), ledStrip.numLeds());
|
||||
delay(delayVal);
|
||||
#endif
|
||||
|
||||
/*
|
||||
auto delayMs = animation(led);
|
||||
led.transmit();
|
||||
|
||||
Reference in New Issue
Block a user