Cleaned up repository
- only moving files around
This commit is contained in:
129
esp-firmware/src/TaskLed.h
Normal file
129
esp-firmware/src/TaskLed.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#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 = 8 * 1024;
|
||||
|
||||
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)) {}
|
||||
else if (dispatchEffectId<EffectId::STATIC >(id, effectFunction, ledStrip, msgBuffer, effectStorage)) {}
|
||||
else if (dispatchEffectId<EffectId::STATIC_DETAILED >(id, effectFunction, ledStrip, msgBuffer, effectStorage)) {}
|
||||
else if (dispatchEffectId<EffectId::ALEXA_SWIPE >(id, effectFunction, ledStrip, msgBuffer, effectStorage)) {}
|
||||
else if (dispatchEffectId<EffectId::RANDOM_TWO_COLOR_INTERPOLATION>(id, effectFunction, ledStrip, msgBuffer, effectStorage)) {}
|
||||
else if (dispatchEffectId<EffectId::SWIPE_AND_CHANGE >(id, effectFunction, ledStrip, msgBuffer, effectStorage)) {}
|
||||
else if (dispatchEffectId<EffectId::REVERSE_SWIPE >(id, effectFunction, ledStrip, msgBuffer, effectStorage)) {}
|
||||
// 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 * 2,
|
||||
(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);
|
||||
}
|
||||
Reference in New Issue
Block a user