Compare commits

..

No commits in common. "01f421add39e173329e7d18b4fe8532a3cf2b7bf" and "2a6a6e8697cd631b426fa4e10adf0212ad99654c" have entirely different histories.

3 changed files with 93 additions and 79 deletions

View File

@ -31,7 +31,6 @@
#include "zcl_include.h" #include "zcl_include.h"
#include "sampleLight.h" #include "sampleLight.h"
#include "app_ui.h" #include "app_ui.h"
#include "sampleLightCtrl.h"
/********************************************************************** /**********************************************************************
* LOCAL CONSTANTS * LOCAL CONSTANTS
@ -118,20 +117,9 @@ void buttonShortPressed(u8 btNum)
else if (btNum == VK_SW2) else if (btNum == VK_SW2)
{ {
/* toggle local permit Joining */ /* toggle local permit Joining */
//static u8 duration = 0; static u8 duration = 0;
//duration = duration ? 0 : 0xff; duration = duration ? 0 : 0xff;
//zb_nlmePermitJoiningRequest(duration); zb_nlmePermitJoiningRequest(duration);
// todo remove test for color order
sampleLight_onoff(ZCL_ONOFF_STATUS_OFF);
hwLight_colorUpdate_RGB(255,0,0);
WaitMs(250);
hwLight_colorUpdate_RGB(0,255,0);
WaitMs(250);
hwLight_colorUpdate_RGB(0,0,255);
WaitMs(250);
sampleLight_onoff(ZCL_ONOFF_STATUS_ON);
} }
} }

View File

@ -30,6 +30,7 @@
#include "zcl_include.h" #include "zcl_include.h"
#include "sampleLight.h" #include "sampleLight.h"
#include "sampleLightCtrl.h" #include "sampleLightCtrl.h"
#include <math.h>
/********************************************************************** /**********************************************************************
* LOCAL CONSTANTS * LOCAL CONSTANTS
@ -344,72 +345,34 @@ static float ENFORCE_BOUNDS_FLOAT(float lowerBound, float num, float upperBound)
: num; : num;
} }
/*
A horrible power function for floats
*/
static float fpow(float x, float y) {
float result = 1;
for(int i = 0; i < y; ++i)
{
result *= x;
}
return result;
}
float LINEAR_TO_SRGB_GAMMA_CORRECTION(const float part) float LINEAR_TO_SRGB_GAMMA_CORRECTION(const float part)
{ {
return part <= 0.0031308f ? 12.92f * part : 1.055f * fpow(part, 1.0f / 2.4f) - 0.055f; return part <= 0.0031308 ? 12.92 * part : 1.055 * pow(part, 1.0 / 2.4) - 0.055;
} }
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define roundu8(a) (u8) (a+0.5)
void hwLight_colorUpdate_XY2RGB(u16 xI, u16 yI, u8 level) void hwLight_colorUpdate_XY2RGB(u16 xI, u16 yI, u8 level)
{ {
float x = xI / (float)ZCL_COLOR_ATTR_XY_MAX; float x = xI / 65536.f;
float y = yI / (float)ZCL_COLOR_ATTR_XY_MAX; float y = yI / 65536.f;
// This does not locate the closest point in the gamma spectrum of the lamps. possible #todo // This does not locate the closest point in the gamma spectrum of the lamps. possible #todo
const float z = 1 - x - y; const float z = 1 - x - y;
const float Y = level / (float)ZCL_LEVEL_ATTR_MAX_LEVEL; // This is luminance, but used as brightness const float Y = level / ZCL_LEVEL_ATTR_MAX_LEVEL; // This is luminance, but used as brightness
const float X = ((Y) / y) * x; const float X = ((Y) / y) * x;
const float Z = ((Y) / y) * z; const float Z = ((Y) / y) * z;
// D65 BT.709 conversion https://en.wikipedia.org/wiki/SRGB // D65 BT.709 conversion https://en.wikipedia.org/wiki/SRGB
float r = X * 1.656492f - Y * 0.354851f - Z * 0.255038f; float r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
float g = -X * 0.707196f + Y * 1.655397f + Z * 0.036152f; float g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
float b = X * 0.051713f - Y * 0.121364f + Z * 1.011530f; float b = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
// Normalize to maximum component being 1.0
float maxComponent = MAX(MAX(r, g), b);
if (maxComponent > 1.0) {
r /= maxComponent;
g /= maxComponent;
b /= maxComponent;
}
// Apply LINEAR => SRGB Gamma correction
r = LINEAR_TO_SRGB_GAMMA_CORRECTION(r);
g = LINEAR_TO_SRGB_GAMMA_CORRECTION(g);
b = LINEAR_TO_SRGB_GAMMA_CORRECTION(b);
// Normalize again to avoid out of range
maxComponent = MAX(MAX(r, g), b);
if (maxComponent > 1.0) {
r /= maxComponent;
g /= maxComponent;
b /= maxComponent;
}
// Enforce the lower and upper bounds // Enforce the lower and upper bounds
r = ENFORCE_BOUNDS_FLOAT(0.0f, r * 255, 255.0f); r = ENFORCE_BOUNDS_FLOAT(0.0, r * 255, 255.0);
g = ENFORCE_BOUNDS_FLOAT(0.0f, g * 255, 255.0f); g = ENFORCE_BOUNDS_FLOAT(0.0, g * 255, 255.0);
b = ENFORCE_BOUNDS_FLOAT(0.0f, b * 255, 255.0f); b = ENFORCE_BOUNDS_FLOAT(0.0, b * 255, 255.0);
hwLight_colorUpdate_RGB(roundu8(r), roundu8(g), roundu8(b)); hwLight_colorUpdate_RGB((u8)r, (u8)g, (u8)b);
} }
/********************************************************************* /*********************************************************************

View File

@ -115,7 +115,7 @@ void sampleLight_colorInit(void)
colorInfo.hueRemainingTime = 0; colorInfo.hueRemainingTime = 0;
colorInfo.saturationRemainingTime = 0; colorInfo.saturationRemainingTime = 0;
colorInfo.colorTempRemainingTime = 1; // Start-up with a 1 second transition colorInfo.colorTempRemainingTime = 0;
colorInfo.xyRemainingTime = 0; colorInfo.xyRemainingTime = 0;
// Startup is only defined for color temperature, so why would we load any colors here ... // Startup is only defined for color temperature, so why would we load any colors here ...
@ -369,11 +369,15 @@ static void sampleLight_moveToHueProcess(zcl_colorCtrlMoveToHueCmd_t *cmd)
light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime,
ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE);
sampleLight_colorTimerStop();
if (colorInfo.hueRemainingTime) if (colorInfo.hueRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -417,11 +421,15 @@ static void sampleLight_moveHueProcess(zcl_colorCtrlMoveHueCmd_t *cmd)
light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime,
ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE);
sampleLight_colorTimerStop();
if (colorInfo.hueRemainingTime) if (colorInfo.hueRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -462,11 +470,15 @@ static void sampleLight_stepHueProcess(zcl_colorCtrlStepHueCmd_t *cmd)
light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime,
ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE);
sampleLight_colorTimerStop();
if (colorInfo.hueRemainingTime) if (colorInfo.hueRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -497,11 +509,15 @@ static void sampleLight_moveToSaturationProcess(zcl_colorCtrlMoveToSaturationCmd
light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime,
ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.saturationRemainingTime) if (colorInfo.saturationRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -545,11 +561,15 @@ static void sampleLight_moveSaturationProcess(zcl_colorCtrlMoveSaturationCmd_t *
light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime,
ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.saturationRemainingTime) if (colorInfo.saturationRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -590,11 +610,15 @@ static void sampleLight_stepSaturationProcess(zcl_colorCtrlStepSaturationCmd_t *
light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime,
ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.saturationRemainingTime) if (colorInfo.saturationRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -649,12 +673,34 @@ static void sampleLight_moveToColorProcess(zcl_colorCtrlMoveToColorCmd_t *cmd)
colorInfo.currentX256 = (u16)(pColor->currentX) << 8; colorInfo.currentX256 = (u16)(pColor->currentX) << 8;
colorInfo.currentY256 = (u16)(pColor->currentY) << 8; colorInfo.currentY256 = (u16)(pColor->currentY) << 8;
s16 xDiff = (s16)cmd->colorX - pColor->currentX;
s16 yDiff = (s16)cmd->colorY - pColor->currentY;
// It is recommended to take the shortest path here
if (xDiff > (ZCL_COLOR_ATTR_XY_MAX / 2))
{
xDiff -= (ZCL_COLOR_ATTR_XY_MAX + 1);
}
else if (xDiff < -ZCL_COLOR_ATTR_XY_MAX / 2)
{
xDiff += (ZCL_COLOR_ATTR_XY_MAX + 1);
}
if (yDiff > (ZCL_COLOR_ATTR_XY_MAX / 2))
{
yDiff -= (ZCL_COLOR_ATTR_XY_MAX + 1);
}
else if (yDiff < -ZCL_COLOR_ATTR_XY_MAX / 2)
{
yDiff += (ZCL_COLOR_ATTR_XY_MAX + 1);
}
colorInfo.xyRemainingTime = (cmd->transitionTime == 0) ? 1 : cmd->transitionTime; colorInfo.xyRemainingTime = (cmd->transitionTime == 0) ? 1 : cmd->transitionTime;
colorInfo.stepX256 = ((s32)(cmd->colorX - pColor->currentX)) << 8; colorInfo.stepX256 = ((s32)xDiff) << 8;
colorInfo.stepX256 /= (s32)colorInfo.xyRemainingTime; colorInfo.stepX256 /= (s32)colorInfo.xyRemainingTime;
colorInfo.stepY256 = ((s32)(cmd->colorY - pColor->currentY)) << 8; colorInfo.stepY256 = ((s32)yDiff) << 8;
colorInfo.stepY256 /= (s32)colorInfo.xyRemainingTime; colorInfo.stepY256 /= (s32)colorInfo.xyRemainingTime;
light_applyUpdate_16(&pColor->currentX, &colorInfo.currentX256, &colorInfo.stepX256, &colorInfo.xyRemainingTime, light_applyUpdate_16(&pColor->currentX, &colorInfo.currentX256, &colorInfo.stepX256, &colorInfo.xyRemainingTime,
@ -663,11 +709,16 @@ static void sampleLight_moveToColorProcess(zcl_colorCtrlMoveToColorCmd_t *cmd)
light_applyUpdate_16(&pColor->currentY, &colorInfo.currentY256, &colorInfo.stepY256, &colorInfo.xyRemainingTime, light_applyUpdate_16(&pColor->currentY, &colorInfo.currentY256, &colorInfo.stepY256, &colorInfo.xyRemainingTime,
ZCL_COLOR_ATTR_XY_MIN, ZCL_COLOR_ATTR_XY_MAX, FALSE); ZCL_COLOR_ATTR_XY_MIN, ZCL_COLOR_ATTR_XY_MAX, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.xyRemainingTime) if (colorInfo.xyRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -913,11 +964,15 @@ static void sampleLight_moveToColorTemperatureProcess(zcl_colorCtrlMoveToColorTe
light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime,
colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.colorTempRemainingTime) if (colorInfo.colorTempRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -981,11 +1036,15 @@ static void sampleLight_moveColorTemperatureProcess(zcl_colorCtrlMoveColorTemper
light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime,
colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.colorTempRemainingTime) if (colorInfo.colorTempRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************
@ -1046,11 +1105,15 @@ static void sampleLight_stepColorTemperatureProcess(zcl_colorCtrlStepColorTemper
light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime,
colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE);
sampleLight_colorTimerStop();
if (colorInfo.colorTempRemainingTime) if (colorInfo.colorTempRemainingTime)
{ {
sampleLight_colorTimerStop();
colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL);
} }
else
{
sampleLight_colorTimerStop();
}
} }
/********************************************************************* /*********************************************************************