207 lines
6.0 KiB
C++
207 lines
6.0 KiB
C++
#include "stairs.h"
|
|
#include <Math.h>
|
|
#include <FS.h>
|
|
#include "debug.h"
|
|
#include "global.h"
|
|
|
|
|
|
|
|
const uint16_t PWMCurve[] =
|
|
{
|
|
0, 10, 11, 12, 12, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21,
|
|
22, 23, 24, 25, 26, 27, 29, 30, 32, 33, 35, 36, 38, 40, 42, 44,
|
|
46, 48, 51, 53, 56, 58, 61, 64, 67, 70, 74, 77, 81, 85, 89, 93,
|
|
97, 102, 107, 112, 117, 123, 129, 135, 141, 148, 155, 162, 169, 177, 186, 194,
|
|
203, 213, 222, 233, 243, 254, 266, 278, 291, 304, 318, 332, 347, 362, 378, 395,
|
|
412, 430, 449, 468, 488, 509, 531, 553, 576, 600, 625, 651, 677, 704, 733, 762,
|
|
792, 823, 854, 887, 920, 955, 990, 1026, 1063, 1101, 1140, 1180, 1220, 1261, 1303, 1346,
|
|
1389, 1433, 1478, 1523, 1569, 1615, 1662, 1709, 1757, 1805, 1853, 1901, 1950, 1999, 2048, 2096,
|
|
2145, 2194, 2242, 2290, 2338, 2386, 2433, 2480, 2526, 2572, 2617, 2662, 2706, 2749, 2792, 2834,
|
|
2875, 2915, 2955, 2994, 3032, 3069, 3105, 3140, 3175, 3208, 3241, 3272, 3303, 3333, 3362, 3391,
|
|
3418, 3444, 3470, 3495, 3519, 3542, 3564, 3586, 3607, 3627, 3646, 3665, 3683, 3700, 3717, 3733,
|
|
3748, 3763, 3777, 3791, 3804, 3817, 3829, 3841, 3852, 3862, 3873, 3882, 3892, 3901, 3909, 3918,
|
|
3926, 3933, 3940, 3947, 3954, 3960, 3966, 3972, 3978, 3983, 3988, 3993, 3998, 4002, 4006, 4010,
|
|
4014, 4018, 4021, 4025, 4028, 4031, 4034, 4037, 4039, 4042, 4044, 4047, 4049, 4051, 4053, 4055,
|
|
4057, 4059, 4060, 4062, 4063, 4065, 4066, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076,
|
|
4077, 4078, 4079, 4079, 4080, 4081, 4082, 4082, 4083, 4083, 4084, 4084, 4085, 4085, 4090, 4095
|
|
};
|
|
|
|
const float LinearFactor = 4095.0f / 255.0f;
|
|
|
|
|
|
void Stairs::init(PCA9685* pwmDriver)
|
|
{
|
|
mPWMDriver = pwmDriver;
|
|
|
|
memset(&mStep[0], 0, sizeof(mStep));
|
|
}
|
|
|
|
|
|
uint8_t Stairs::ease(uint8_t startValue, uint8_t targetValue, uint16_t transitionTime, uint16_t elapsedTime)
|
|
{
|
|
bool up = targetValue > startValue;
|
|
|
|
uint16_t diff = up ? targetValue - startValue : startValue - targetValue;
|
|
uint16_t delta = (diff * elapsedTime) / transitionTime;
|
|
|
|
int16_t currentValue = up ? startValue + delta : startValue - delta;
|
|
if (currentValue < 0) currentValue = 0;
|
|
if (currentValue > 255) currentValue = 255;
|
|
|
|
return currentValue;
|
|
}
|
|
|
|
|
|
inline void Stairs::updateCurrentValue(Step* stepState)
|
|
{
|
|
int32_t stepElapsedTime = -stepState->startTime;
|
|
stepState->currentValue = ease(stepState->startValue, stepState->targetValue, stepState->remainingTime + stepElapsedTime, stepElapsedTime);
|
|
}
|
|
|
|
|
|
inline void Stairs::applyCurrentValue(uint8_t step)
|
|
{
|
|
mPWMDriver->setPWM(step, this->getPWMValue(step, mStep[step].currentValue));
|
|
}
|
|
|
|
|
|
void Stairs::tick()
|
|
{
|
|
if (!mTick) return;
|
|
|
|
uint32_t elapsedTime = mLastTransitionTime != 0 ? currentTime - mLastTransitionTime : 0;
|
|
if (!elapsedTime) return;
|
|
|
|
|
|
mLastTransitionTime = currentTime;
|
|
mTick = false;
|
|
|
|
|
|
for (uint8_t step = 0; step < stepsSettings->count(); step++)
|
|
{
|
|
Step* stepState = &mStep[step];
|
|
|
|
if (stepState->currentValue != stepState->targetValue)
|
|
{
|
|
// If there is a startup delay request, wait for it first
|
|
if (stepState->startTime > 0)
|
|
{
|
|
stepState->startTime -= elapsedTime;
|
|
if (stepState->startTime < 0)
|
|
{
|
|
if (stepState->remainingTime > -stepState->startTime)
|
|
{
|
|
// Shift the remaining time equally
|
|
stepState->remainingTime += stepState->startTime;
|
|
updateCurrentValue(stepState);
|
|
mTick = true;
|
|
}
|
|
else
|
|
{
|
|
// End of the transition
|
|
stepState->remainingTime = 0;
|
|
stepState->currentValue = stepState->targetValue;
|
|
}
|
|
|
|
applyCurrentValue(step);
|
|
}
|
|
else
|
|
mTick = true;
|
|
}
|
|
else if (elapsedTime >= stepState->remainingTime)
|
|
{
|
|
// End of the transition
|
|
stepState->remainingTime = 0;
|
|
stepState->currentValue = stepState->targetValue;
|
|
|
|
applyCurrentValue(step);
|
|
}
|
|
else
|
|
{
|
|
stepState->startTime -= elapsedTime;
|
|
stepState->remainingTime -= elapsedTime;
|
|
|
|
updateCurrentValue(stepState);
|
|
applyCurrentValue(step);
|
|
|
|
mTick = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!mTick)
|
|
mLastTransitionTime = 0;
|
|
}
|
|
|
|
|
|
uint8_t Stairs::get(uint8_t step, bool target)
|
|
{
|
|
if (step >= MaxStepCount) return 0;
|
|
return target ? mStep[step].targetValue : mStep[step].currentValue;
|
|
}
|
|
|
|
|
|
void Stairs::set(uint8_t step, uint8_t brightness, uint16_t transitionTime, uint16_t startTime)
|
|
{
|
|
_d("Stairs :: set step = "); _d(step);
|
|
_d(", brightness = "); _d(brightness);
|
|
_d(", transitionTime = "); _d(transitionTime);
|
|
_d(", startTime = "); _dln(startTime);
|
|
|
|
|
|
if (step >= MaxStepCount) return;
|
|
if (mStep[step].currentValue == brightness)
|
|
return;
|
|
|
|
mStep[step].targetValue = brightness;
|
|
|
|
if (transitionTime > 0)
|
|
{
|
|
mStep[step].startValue = mStep[step].currentValue;
|
|
mStep[step].startTime = startTime;
|
|
mStep[step].remainingTime = transitionTime;
|
|
|
|
if (!mLastTransitionTime)
|
|
mLastTransitionTime = currentTime;
|
|
|
|
mTick = true;
|
|
}
|
|
else
|
|
{
|
|
mStep[step].currentValue = brightness;
|
|
applyCurrentValue(step);
|
|
}
|
|
}
|
|
|
|
|
|
void Stairs::setAll(uint8_t brightness, uint16_t transitionTime, uint16_t startTime)
|
|
{
|
|
for (uint8_t step = 0; step < stepsSettings->count(); step++)
|
|
set(step, brightness, transitionTime, startTime);
|
|
}
|
|
|
|
|
|
uint16_t Stairs::getPWMValue(uint8_t step, uint8_t brightness)
|
|
{
|
|
//_d("Stairs :: Getting PWM value for step "); _d(step); _d(", brightness "); _dln(brightness);
|
|
if (brightness == 0 || brightness == 255)
|
|
{
|
|
//_dln("Stairs :: Full on/off, returning input");
|
|
return brightness == 0 ? 0 : 4095;
|
|
}
|
|
|
|
uint16_t pwmValue;
|
|
if (stepsSettings->useCurve())
|
|
{
|
|
//_dln("Stairs :: Using curve");
|
|
pwmValue = PWMCurve[brightness] + stepsSettings->curveShift(step);
|
|
}
|
|
else
|
|
{
|
|
//_dln("Stairs :: Not using curve");
|
|
pwmValue = brightness * LinearFactor;
|
|
}
|
|
|
|
//_d("Stairs :: Output: "); _dln(pwmValue);
|
|
return pwmValue;
|
|
} |