diff --git a/sampleLight.h b/sampleLight.h index acd6453..78f506f 100644 --- a/sampleLight.h +++ b/sampleLight.h @@ -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 diff --git a/sampleLightCtrl.c b/sampleLightCtrl.c index 676f9f4..ad78bdb 100644 --- a/sampleLightCtrl.c +++ b/sampleLightCtrl.c @@ -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)); } /********************************************************************* diff --git a/zb_afTestCb.c b/zb_afTestCb.c deleted file mode 100644 index 9d7193b..0000000 --- a/zb_afTestCb.c +++ /dev/null @@ -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__ */ diff --git a/zcl_colorCtrlCb.c b/zcl_colorCtrlCb.c index 81f25c0..2708f72 100644 --- a/zcl_colorCtrlCb.c +++ b/zcl_colorCtrlCb.c @@ -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; diff --git a/zcl_levelCb.c b/zcl_levelCb.c index 34ab1db..0da88e1 100644 --- a/zcl_levelCb.c +++ b/zcl_levelCb.c @@ -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; diff --git a/zcl_onOffCb.c b/zcl_onOffCb.c index 157f12d..156300c 100644 --- a/zcl_onOffCb.c +++ b/zcl_onOffCb.c @@ -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) {