Another attempt at the XY conversion

main
Martin Böh 2022-04-07 19:22:16 +02:00
parent 95b9fe8eea
commit 356ae0f04e
6 changed files with 32 additions and 177 deletions

View File

@ -35,11 +35,12 @@
*/
#define ZCL_LEVEL_CHANGE_INTERVAL 20 // 50 steps a second, every 20ms
#define ZCL_COLOR_CHANGE_INTERVAL 20 // see above
#define ZCL_ONOFF_TIMER_INTERVAL 20 // the timer interval to change the offWaitTime/onTime attribute of the ONOFF cluster
#define ZCL_REMAINING_TIME_INTERVAL 100 // 1/10th of a second according to the zigbee spec
// Map the required time to our internal steps
#define INTERP_STEPS_FROM_REM_TIME(remTime, base) ((remTime * ZCL_REMAINING_TIME_INTERVAL)/base)
#define INTERP_STEPS_FROM_ONE_TENTH(remTime, base) ((remTime * ZCL_REMAINING_TIME_INTERVAL)/base)
/**********************************************************************
* TYPEDEFS

View File

@ -347,11 +347,6 @@ void hwLight_colorUpdate_RGB(u8 R, u8 G, u8 B)
pwmSetDuty(WARM_LIGHT_PWM_CHANNEL, 0);
}
static u8 ENFORCE_BOUNDS_U8(u8 lowerBound, s16 num, u8 upperBound)
{
return num < lowerBound ? lowerBound : num > upperBound ? upperBound : num;
}
/*
iLog, pow and root functions, taken from
http://rosettacode.org/wiki/Nth_root#C
@ -381,11 +376,11 @@ float _fsqrt(float x, int n) {
return r;
}
float LINEAR_TO_SRGB_GAMMA_CORRECTION(const float part)
float LINEAR_TO_SRGB_GAMMA_CORRECTION(float v)
{
// Optimization for embedded devices without math libraries: a ^ (m / n) == nth_root(a) ^ m
// This uses a gamma value of 2.2 hence the (5/11)
return part <= 0.0031308f ? 12.92f * part : 1.055f * _fpow(_fsqrt(part, 11), 5) - 0.055f;
return v <= 0.0031308f ? 12.92f * v : 1.055f * _fpow(_fsqrt(v, 11), 5) - 0.055f;
}
#define MAX(x,y) ((x) > (y) ? (x) : (y))
@ -400,21 +395,28 @@ void hwLight_colorUpdate_XY2RGB(u16 xI, u16 yI, u8 level)
// This does not locate the closest point in the gamma spectrum of the lamps. possible #todo
const float z = 1.f - x - y;
const float Y = (level / (float)ZCL_LEVEL_ATTR_MAX_LEVEL); // This is luminance, but used as brightness
const float X = (Y / y) * x;
const float Z = (Y / y) * z;
float Y = yI == 0 ? 0.0f : (level / (float)ZCL_LEVEL_ATTR_MAX_LEVEL); // This is luminance, but used as brightness
float X = yI == 0 ? 0.0f : (x * Y) / y;
float Z = yI == 0 ? 0.0f : (z * Y) / y;
// SRGB http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
float r = X * 3.2404542f - Y * -1.5371385f - Z * 0.4985314f;
float g = -X * 0.9692660f + Y * 1.8760108f + Z * 0.0415560f;
float b = X * 0.0556434f - Y * 0.2040259f + Z * 1.0572252f;
float r = MAX(X * 3.2404542f + Y * -1.5371385f + Z * -0.4985314f,0);
float g = MAX(X * -0.9692660f + Y * 1.8760108f + Z * 0.0415560f,0);
float b = MAX(X * 0.0556434f + Y * -0.2040259f + Z * 1.0572252f,0);
// 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);
hwLight_colorUpdate_RGB(ENFORCE_BOUNDS_U8(0, round(r * 255), 255), ENFORCE_BOUNDS_U8(0, round(g * 255), 255), ENFORCE_BOUNDS_U8(0, round(b * 255) , 255));
float maxComponent = MAX(MAX(r, g), b);
if (maxComponent > 1.0f) {
r /= maxComponent;
g /= maxComponent;
b /= maxComponent;
}
hwLight_colorUpdate_RGB(round(r * 255), round(g * 255), round(b * 255));
}
/*********************************************************************

View File

@ -1,144 +0,0 @@
/********************************************************************************************************
* @file zb_afTestCb.c
*
* @brief This is the source file for zb_afTestCb
*
* @author Zigbee Group
* @date 2021
*
* @par Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************************************/
#if (__PROJECT_TL_DIMMABLE_LIGHT__)
/**********************************************************************
* INCLUDES
*/
#include "tl_common.h"
#include "zb_api.h"
#include "zcl_include.h"
#include "sampleLight.h"
#if ZBHCI_EN
#include "zbhci.h"
#endif
#if AF_TEST_ENABLE
/**********************************************************************
* LOCAL CONSTANTS
*/
/**********************************************************************
* TYPEDEFS
*/
/**********************************************************************
* LOCAL FUNCTIONS
*/
/**********************************************************************
* GLOBAL VARIABLES
*/
/**********************************************************************
* LOCAL VARIABLES
*/
u16 g_afTest_rcvReqCnt = 0;
/**********************************************************************
* FUNCTIONS
*/
static void afTest_testReqPrc(apsdeDataInd_t *pApsdeInd)
{
epInfo_t dstEp;
TL_SETSTRUCTCONTENT(dstEp, 0);
dstEp.dstEp = pApsdeInd->indInfo.src_ep;
dstEp.profileId = pApsdeInd->indInfo.profile_id;
dstEp.dstAddrMode = APS_SHORT_DSTADDR_WITHEP;
dstEp.dstAddr.shortAddr = pApsdeInd->indInfo.src_short_addr;
u8 dataLen = 50;
u8 *pBuf = (u8 *)ev_buf_allocate(dataLen);
if (pBuf)
{
u8 *pData = pBuf;
*pData++ = LO_UINT16(g_afTest_rcvReqCnt);
*pData++ = HI_UINT16(g_afTest_rcvReqCnt);
for (u8 i = 0; i < dataLen - 2; i++)
{
*pData++ = i;
}
u8 apsCnt = 0;
#if ZBHCI_EN
zbhciTx(ZCL_CLUSTER_TELINK_SDK_TEST_RSP, pApsdeInd->asduLen, (u8 *)pApsdeInd->asdu);
#else
af_dataSend(pApsdeInd->indInfo.dst_ep, &dstEp, ZCL_CLUSTER_TELINK_SDK_TEST_RSP, dataLen, pBuf, &apsCnt);
#endif
ev_buf_free(pBuf);
}
}
static void afTest_testClearReqPrc(apsdeDataInd_t *pApsdeInd)
{
epInfo_t dstEp;
TL_SETSTRUCTCONTENT(dstEp, 0);
dstEp.dstEp = pApsdeInd->indInfo.src_ep;
dstEp.profileId = pApsdeInd->indInfo.profile_id;
dstEp.dstAddrMode = APS_SHORT_DSTADDR_WITHEP;
dstEp.dstAddr.shortAddr = pApsdeInd->indInfo.src_short_addr;
u8 st = SUCCESS;
u8 apsCnt = 0;
af_dataSend(pApsdeInd->indInfo.dst_ep, &dstEp, ZCL_CLUSTER_TELINK_SDK_TEST_CLEAR_RSP, 1, &st, &apsCnt);
}
void afTest_rx_handler(void *arg)
{
apsdeDataInd_t *pApsdeInd = (apsdeDataInd_t *)arg;
switch (pApsdeInd->indInfo.cluster_id)
{
case ZCL_CLUSTER_TELINK_SDK_TEST_CLEAR_REQ:
g_afTest_rcvReqCnt = 0;
afTest_testClearReqPrc(pApsdeInd);
break;
case ZCL_CLUSTER_TELINK_SDK_TEST_REQ:
g_afTest_rcvReqCnt++;
afTest_testReqPrc(pApsdeInd);
break;
case ZCL_CLUSTER_TELINK_SDK_TEST_RSP:
break;
default:
break;
}
/* Must be free here. */
ev_buf_free((u8 *)arg);
}
void afTest_dataSendConfirm(void *arg)
{
// apsdeDataConf_t *pApsDataCnf = (apsdeDataConf_t *)arg;
}
#endif /* AF_TEST_ENABLE */
#endif /* __PROJECT_TL_DIMMABLE_LIGHT__ */

View File

@ -388,7 +388,7 @@ static void sampleLight_moveToHueProcess(zcl_colorCtrlMoveToHueCmd_t *cmd)
break;
}
colorInfo.hueRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.hueRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepHue256 = ((s32)hueDiff) << 8;
colorInfo.stepHue256 /= (s32)colorInfo.hueRemainingTime;
@ -470,7 +470,7 @@ static void sampleLight_stepHueProcess(zcl_colorCtrlStepHueCmd_t *cmd)
colorInfo.currentHue256 = (u16)(pColor->currentHue) << 8;
colorInfo.hueRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.hueRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepHue256 = (((s32)cmd->stepSize) << 8) / colorInfo.hueRemainingTime;
@ -517,7 +517,7 @@ static void sampleLight_moveToSaturationProcess(zcl_colorCtrlMoveToSaturationCmd
colorInfo.currentSaturation256 = (u16)(pColor->currentSaturation) << 8;
colorInfo.saturationRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.saturationRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepSaturation256 = ((s32)(cmd->saturation - pColor->currentSaturation)) << 8;
colorInfo.stepSaturation256 /= (s32)colorInfo.saturationRemainingTime;
@ -600,7 +600,7 @@ static void sampleLight_stepSaturationProcess(zcl_colorCtrlStepSaturationCmd_t *
colorInfo.currentSaturation256 = (u16)(pColor->currentSaturation) << 8;
colorInfo.saturationRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.saturationRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepSaturation256 = (((s32)cmd->stepSize) << 8) / colorInfo.saturationRemainingTime;
@ -677,7 +677,7 @@ static void sampleLight_moveToColorProcess(zcl_colorCtrlMoveToColorCmd_t *cmd)
colorInfo.currentX256 = (u32)(pColor->currentX) << 8;
colorInfo.currentY256 = (u32)(pColor->currentY) << 8;
u16 remTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
u16 remTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.xyRemainingTime = remTime;
colorInfo.stepX256 = ((s32)(cmd->colorX - pColor->currentX)) << 8;
@ -798,7 +798,7 @@ static void sampleLight_enhancedMoveToHueProcess(zcl_colorCtrlEnhancedMoveToHueC
break;
}
colorInfo.enhancedHueRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.enhancedHueRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepEnhancedHue256 = ((s32)hueDiff) << 8;
colorInfo.stepEnhancedHue256 /= (s32)colorInfo.enhancedHueRemainingTime;
@ -964,7 +964,7 @@ static void sampleLight_moveToColorTemperatureProcess(zcl_colorCtrlMoveToColorTe
colorInfo.currentColorTemp256 = (u32)(pColor->colorTemperatureMireds) << 8;
colorInfo.colorTempRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.colorTempRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepColorTemp256 = ((s32)(cmd->colorTemperature - pColor->colorTemperatureMireds)) << 8;
colorInfo.stepColorTemp256 /= (s32)colorInfo.colorTempRemainingTime;
@ -1087,7 +1087,7 @@ static void sampleLight_stepColorTemperatureProcess(zcl_colorCtrlStepColorTemper
colorInfo.currentColorTemp256 = (u32)(pColor->colorTemperatureMireds) << 8;
colorInfo.colorTempRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.colorTempRemainingTime = (cmd->transitionTime == 0) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL);
colorInfo.stepColorTemp256 = (((s32)cmd->stepSize) << 8) / colorInfo.colorTempRemainingTime;

View File

@ -164,7 +164,7 @@ static void sampleLight_moveToLevelProcess(u8 cmdId, moveToLvl_t *cmd)
{
zcl_levelAttr_t *pLevel = zcl_levelAttrGet();
pLevel->remainingTime = ((cmd->transitionTime == 0) || (cmd->transitionTime == 0xFFFF)) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_LEVEL_CHANGE_INTERVAL);
pLevel->remainingTime = ((cmd->transitionTime == 0) || (cmd->transitionTime == 0xFFFF)) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_LEVEL_CHANGE_INTERVAL);
levelInfo.withOnOff = (cmdId == ZCL_CMD_LEVEL_MOVE_TO_LEVEL_WITH_ON_OFF) ? TRUE : FALSE;
levelInfo.currentLevel256 = (u16)(pLevel->curLevel) << 8;
@ -272,7 +272,7 @@ static void sampleLight_stepProcess(u8 cmdId, step_t *cmd)
{
zcl_levelAttr_t *pLevel = zcl_levelAttrGet();
pLevel->remainingTime = ((cmd->transitionTime == 0) || (cmd->transitionTime == 0xFFFF)) ? 1 : INTERP_STEPS_FROM_REM_TIME(cmd->transitionTime, ZCL_LEVEL_CHANGE_INTERVAL);
pLevel->remainingTime = ((cmd->transitionTime == 0) || (cmd->transitionTime == 0xFFFF)) ? 1 : INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_LEVEL_CHANGE_INTERVAL);
levelInfo.withOnOff = (cmdId == ZCL_CMD_LEVEL_STEP_WITH_ON_OFF) ? TRUE : FALSE;
levelInfo.currentLevel256 = (u16)(pLevel->curLevel) << 8;

View File

@ -32,11 +32,6 @@
#include "sampleLight.h"
#include "sampleLightCtrl.h"
/**********************************************************************
* LOCAL CONSTANTS
*/
#define ZCL_ONOFF_TIMER_INTERVAL 100 // the timer interval to change the offWaitTime/onTime attribute of the ONOFF cluster
/**********************************************************************
* LOCAL VARIABLES
*/
@ -207,6 +202,7 @@ static void sampleLight_onoff_onWithTimedOffProcess(zcl_onoff_onWithTimeOffCmd_t
{
zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
// Discard
if (cmd->onOffCtrl.bits.acceptOnlyWhenOn && (pOnOff->onOff == ZCL_ONOFF_STATUS_OFF))
{
return;
@ -223,7 +219,7 @@ static void sampleLight_onoff_onWithTimedOffProcess(zcl_onoff_onWithTimeOffCmd_t
sampleLight_onoff(ZCL_CMD_ONOFF_ON);
}
if ((pOnOff->onTime < 0xFFFF) && (pOnOff->offWaitTime < 0xFFFF))
if (pOnOff->onTime < 0xFFFF && pOnOff->offWaitTime < 0xFFFF)
{
if (pOnOff->onTime || pOnOff->offWaitTime)
{