diff --git a/Firmware/src/LightController/Controller.h b/Firmware/src/LightController/Controller.h index e5aa7d6..a9c1a3d 100644 --- a/Firmware/src/LightController/Controller.h +++ b/Firmware/src/LightController/Controller.h @@ -1,7 +1,9 @@ #pragma once #include +#include #include #include +#include #include #include @@ -11,13 +13,18 @@ using LightAction = etl::pair>; template class Controller { public: - Controller(size_t actionQueueSize, UBaseType_t priority, BaseType_t coreID) + Controller(size_t actionQueueSize, UBaseType_t controllerPriority, + BaseType_t controllerCoreID, UBaseType_t faderPriority, + BaseType_t faderCoreID) : lightPins{PIN...}, lightActions{actionQueueSize}, - lightControllerTask{exec, "control lights", stackDepth, - this, priority, coreID} { + lightControllerTask{exec, "control lights", stackDepth, + this, controllerPriority, controllerCoreID}, + lightFaderTask{execFade, "fade lights", stackDepth, + this, faderPriority, faderCoreID} { for (int pin : lightPins) { pinMode(pin, OUTPUT); } + lightStatesCurrent.second.unlock(); } freertos::Queue &getActionQueue() { return lightActions; } @@ -26,10 +33,7 @@ public: private: static void exec(void *controllerPtr) { - Controller *controller{ - static_cast *>(controllerPtr)}; - etl::array lightStates; - const uint8_t step = 5; + Controller *controller{static_cast(controllerPtr)}; while (true) { auto action{controller->getActionQueue().pop()}; @@ -39,45 +43,84 @@ private: switch (type) { case LightActionType::INCREASE: - if (index.has_value() && index.value() < lightStates.size() && - lightStates[index.value()] <= 255 - step) { - lightStates[index.value()] += step; + if (index.has_value() && + index.value() < controller->lightStatesFinal.size() && + controller->lightStatesFinal[index.value()] <= + 255 - controller->step) { + controller->lightStatesFinal[index.value()] += controller->step; } break; case LightActionType::DECREASE: - if (index.has_value() && index.value() < lightStates.size() && - lightStates[index.value()] >= 0) { - lightStates[index.value()] -= step; + if (index.has_value() && + index.value() < controller->lightStatesFinal.size() && + controller->lightStatesFinal[index.value()] >= 0) { + controller->lightStatesFinal[index.value()] -= controller->step; } break; case LightActionType::TOGGLE: - if (index.has_value() && index.value() < lightStates.size()) { - lightStates[index.value()] = - lightStates[index.value()] == 0 ? 255 : 0; + if (index.has_value() && + index.value() < controller->lightStatesFinal.size()) { + controller->lightStatesCurrent.second.lock(); + controller->lightStatesFinal[index.value()] = + controller->lightStatesFinal[index.value()] == 0 ? 255 : 0; + controller->lightStatesCurrent.first[index.value()] = + controller->lightStatesFinal[index.value()]; + controller->lightStatesCurrent.second.unlock(); } break; case LightActionType::ON: - lightStates.fill(255); + controller->lightStatesCurrent.second.lock(); + controller->lightStatesFinal.fill(255); + controller->lightStatesCurrent.first.fill(255); + controller->lightStatesCurrent.second.unlock(); break; case LightActionType::OFF: - lightStates.fill(0); + controller->lightStatesCurrent.second.lock(); + controller->lightStatesFinal.fill(0); + controller->lightStatesCurrent.first.fill(0); + controller->lightStatesCurrent.second.unlock(); break; default: break; } - - for (size_t lightIndex = 0; lightIndex < lightStates.size(); - ++lightIndex) { - analogWrite(controller->getPins()[lightIndex], - lightStates[lightIndex]); - } } } } + static void execFade(void *controllerPtr) { + Controller *controller{static_cast(controllerPtr)}; + while (true) { + freertos::sleep(controller->fadeRate); + controller->lightStatesCurrent.second.lock(); + for (size_t i = 0; i < controller->lightStatesFinal.size(); i++) { + if (controller->lightStatesCurrent.first[i] < + controller->lightStatesFinal[i]) { + controller->lightStatesCurrent.first[i] += 1; + } else if (controller->lightStatesCurrent.first[i] > + controller->lightStatesFinal[i]) { + controller->lightStatesCurrent.first[i] -= 1; + } + } + + for (size_t lightIndex = 0; + lightIndex < controller->lightStatesCurrent.first.size(); + ++lightIndex) { + analogWrite(controller->getPins()[lightIndex], + controller->lightStatesCurrent.first[lightIndex]); + } + controller->lightStatesCurrent.second.unlock(); + } + } + static const uint32_t stackDepth = 2048; + const uint8_t step = 5; + const size_t fadeRate = 50; etl::array lightPins; freertos::Queue lightActions; freertos::Task lightControllerTask; + freertos::Task lightFaderTask; + etl::array lightStatesFinal; + etl::pair, freertos::Mutex> + lightStatesCurrent; }; } // namespace LightController