Implement light fading
This commit is contained in:
parent
0af1561820
commit
851cbb6e52
1 changed files with 67 additions and 24 deletions
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <FreeRTOS/Mutex.h>
|
||||||
#include <FreeRTOS/Queue.h>
|
#include <FreeRTOS/Queue.h>
|
||||||
#include <FreeRTOS/Task.h>
|
#include <FreeRTOS/Task.h>
|
||||||
|
#include <FreeRTOS/Util.h>
|
||||||
#include <etl/optional.h>
|
#include <etl/optional.h>
|
||||||
#include <etl/span.h>
|
#include <etl/span.h>
|
||||||
|
|
||||||
|
@ -11,13 +13,18 @@ using LightAction = etl::pair<LightActionType, etl::optional<uint8_t>>;
|
||||||
|
|
||||||
template <int... PIN> class Controller {
|
template <int... PIN> class Controller {
|
||||||
public:
|
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},
|
: lightPins{PIN...}, lightActions{actionQueueSize},
|
||||||
lightControllerTask{exec, "control lights", stackDepth,
|
lightControllerTask{exec, "control lights", stackDepth,
|
||||||
this, priority, coreID} {
|
this, controllerPriority, controllerCoreID},
|
||||||
|
lightFaderTask{execFade, "fade lights", stackDepth,
|
||||||
|
this, faderPriority, faderCoreID} {
|
||||||
for (int pin : lightPins) {
|
for (int pin : lightPins) {
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
}
|
}
|
||||||
|
lightStatesCurrent.second.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
freertos::Queue<LightAction> &getActionQueue() { return lightActions; }
|
freertos::Queue<LightAction> &getActionQueue() { return lightActions; }
|
||||||
|
@ -26,10 +33,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void exec(void *controllerPtr) {
|
static void exec(void *controllerPtr) {
|
||||||
Controller<PIN...> *controller{
|
Controller *controller{static_cast<Controller *>(controllerPtr)};
|
||||||
static_cast<Controller<PIN...> *>(controllerPtr)};
|
|
||||||
etl::array<uint8_t, sizeof...(PIN)> lightStates;
|
|
||||||
const uint8_t step = 5;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto action{controller->getActionQueue().pop()};
|
auto action{controller->getActionQueue().pop()};
|
||||||
|
@ -39,45 +43,84 @@ private:
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LightActionType::INCREASE:
|
case LightActionType::INCREASE:
|
||||||
if (index.has_value() && index.value() < lightStates.size() &&
|
if (index.has_value() &&
|
||||||
lightStates[index.value()] <= 255 - step) {
|
index.value() < controller->lightStatesFinal.size() &&
|
||||||
lightStates[index.value()] += step;
|
controller->lightStatesFinal[index.value()] <=
|
||||||
|
255 - controller->step) {
|
||||||
|
controller->lightStatesFinal[index.value()] += controller->step;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LightActionType::DECREASE:
|
case LightActionType::DECREASE:
|
||||||
if (index.has_value() && index.value() < lightStates.size() &&
|
if (index.has_value() &&
|
||||||
lightStates[index.value()] >= 0) {
|
index.value() < controller->lightStatesFinal.size() &&
|
||||||
lightStates[index.value()] -= step;
|
controller->lightStatesFinal[index.value()] >= 0) {
|
||||||
|
controller->lightStatesFinal[index.value()] -= controller->step;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LightActionType::TOGGLE:
|
case LightActionType::TOGGLE:
|
||||||
if (index.has_value() && index.value() < lightStates.size()) {
|
if (index.has_value() &&
|
||||||
lightStates[index.value()] =
|
index.value() < controller->lightStatesFinal.size()) {
|
||||||
lightStates[index.value()] == 0 ? 255 : 0;
|
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;
|
break;
|
||||||
case LightActionType::ON:
|
case LightActionType::ON:
|
||||||
lightStates.fill(255);
|
controller->lightStatesCurrent.second.lock();
|
||||||
|
controller->lightStatesFinal.fill(255);
|
||||||
|
controller->lightStatesCurrent.first.fill(255);
|
||||||
|
controller->lightStatesCurrent.second.unlock();
|
||||||
break;
|
break;
|
||||||
case LightActionType::OFF:
|
case LightActionType::OFF:
|
||||||
lightStates.fill(0);
|
controller->lightStatesCurrent.second.lock();
|
||||||
|
controller->lightStatesFinal.fill(0);
|
||||||
|
controller->lightStatesCurrent.first.fill(0);
|
||||||
|
controller->lightStatesCurrent.second.unlock();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t lightIndex = 0; lightIndex < lightStates.size();
|
static void execFade(void *controllerPtr) {
|
||||||
|
Controller *controller{static_cast<Controller *>(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) {
|
++lightIndex) {
|
||||||
analogWrite(controller->getPins()[lightIndex],
|
analogWrite(controller->getPins()[lightIndex],
|
||||||
lightStates[lightIndex]);
|
controller->lightStatesCurrent.first[lightIndex]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
controller->lightStatesCurrent.second.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t stackDepth = 2048;
|
static const uint32_t stackDepth = 2048;
|
||||||
|
const uint8_t step = 5;
|
||||||
|
const size_t fadeRate = 50;
|
||||||
etl::array<int, sizeof...(PIN)> lightPins;
|
etl::array<int, sizeof...(PIN)> lightPins;
|
||||||
freertos::Queue<LightAction> lightActions;
|
freertos::Queue<LightAction> lightActions;
|
||||||
freertos::Task lightControllerTask;
|
freertos::Task lightControllerTask;
|
||||||
|
freertos::Task lightFaderTask;
|
||||||
|
etl::array<uint8_t, sizeof...(PIN)> lightStatesFinal;
|
||||||
|
etl::pair<etl::array<uint8_t, sizeof...(PIN)>, freertos::Mutex>
|
||||||
|
lightStatesCurrent;
|
||||||
};
|
};
|
||||||
} // namespace LightController
|
} // namespace LightController
|
||||||
|
|
Reference in a new issue