Separate FreeRTOS task for LED

This commit is contained in:
Martin Bauer
2021-11-17 23:18:10 +01:00
parent c68114dc4c
commit 5a41c03e8e
8 changed files with 302 additions and 91 deletions

124
espmusicmouse/src/TaskLed.h Normal file
View 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);
}

View File

@@ -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();