/******************************************************************************************************** * @file zcl_colorCtrlCb.c * * @brief This is the source file for zcl_colorCtrlCb * * @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" #include "sampleLightCtrl.h" #include "app_ui.h" #ifdef ZCL_LIGHT_COLOR_CONTROL /********************************************************************** * TYPEDEFS */ typedef struct { s32 stepHue256; u16 currentHue256; u16 hueRemainingTime; s32 stepSaturation256; u16 currentSaturation256; u16 saturationRemainingTime; s32 stepColorTemp256; u32 currentColorTemp256; u16 colorTempRemainingTime; u16 colorTempMinMireds; u16 colorTempMaxMireds; s32 stepX256; s32 stepY256; u32 currentX256; u32 currentY256; u16 xyRemainingTime; u32 currentEnhancedHue256; s32 stepEnhancedHue256; u16 enhancedHueRemainingTime; } zcl_colorInfo_t; /********************************************************************** * LOCAL VARIABLES */ static zcl_colorInfo_t colorInfo = { .stepHue256 = 0, .currentHue256 = 0, .hueRemainingTime = 0, .stepSaturation256 = 0, .currentSaturation256 = 0, .saturationRemainingTime = 0, .stepColorTemp256 = 0, .currentColorTemp256 = 0, .colorTempRemainingTime = 0, .colorTempMinMireds = 0, .colorTempMaxMireds = 0, .stepX256 = 0, .stepY256 = 0, .currentX256 = 0, .currentY256 = 0, .xyRemainingTime = 0, .currentEnhancedHue256 = 0, .stepEnhancedHue256 = 0, .enhancedHueRemainingTime = 0, }; static ev_timer_event_t *colorTimerEvt = NULL; static ev_timer_event_t *colorLoopTimerEvt = NULL; /********************************************************************** * FUNCTIONS */ void sampleLight_updateColorMode(u8 colorMode); /********************************************************************* * @fn sampleLight_colorInit * * @brief * * @param None * * @return None */ void sampleLight_colorInit(void) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); colorInfo.currentHue256 = (u16)(pColor->currentHue) << 8; colorInfo.currentSaturation256 = (u16)(pColor->currentSaturation) << 8; colorInfo.currentColorTemp256 = (u32)(pColor->colorTemperatureMireds) << 8; colorInfo.currentX256 = (u32)(pColor->currentX) << 8; colorInfo.currentY256 = (u32)(pColor->currentY) << 8; colorInfo.currentEnhancedHue256 = (u32)(pColor->enhancedCurrentHue) << 8; colorInfo.hueRemainingTime = 0; colorInfo.saturationRemainingTime = 0; colorInfo.colorTempRemainingTime = 0; colorInfo.xyRemainingTime = 0; colorInfo.enhancedHueRemainingTime = 0; // Startup is only defined for color temperature, so why would we load any colors here ... pColor->colorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; pColor->enhancedColorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, pColor->colorTempPhysicalMinMireds, pColor->colorTempPhysicalMaxMireds, FALSE); } /********************************************************************* * @fn sampleLight_updateColorMode * * @brief * * @param ZCL_COLOR_MODE_CURRENT_HUE_SATURATION * ZCL_COLOR_MODE_CURRENT_X_Y * ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS * ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION * * @return None */ void sampleLight_updateColorMode(u8 colorMode) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); if (colorMode == ZCL_COLOR_MODE_CURRENT_X_Y) { led_off(LED_STATUS_R); led_on(LED_STATUS_G); led_off(LED_STATUS_B); } else if (colorMode == ZCL_COLOR_MODE_CURRENT_HUE_SATURATION) { if (pColor->enhancedColorMode == ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION) { led_on(LED_STATUS_G); } led_off(LED_STATUS_R); led_off(LED_STATUS_G); led_on(LED_STATUS_B); } else if (colorMode == ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS) { led_on(LED_STATUS_R); led_off(LED_STATUS_G); led_off(LED_STATUS_B); } } /********************************************************************* * @fn sampleLight_updateColor * * @brief * * @param None * * @return None */ void sampleLight_updateColor(void) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); zcl_levelAttr_t *pLevel = zcl_levelAttrGet(); if (pColor->colorMode == ZCL_COLOR_MODE_CURRENT_X_Y) { hwLight_colorUpdate_XY2RGB(pColor->currentX, pColor->currentY, pLevel->curLevel); } else if (pColor->colorMode == ZCL_COLOR_MODE_CURRENT_HUE_SATURATION) { // If we are in the enhanced mode, we have to make use of the enhanced hue values! bool enhanced = pColor->enhancedColorMode == ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION; hwLight_colorUpdate_HSV2RGB(enhanced ? pColor->enhancedCurrentHue : pColor->currentHue, pColor->currentSaturation, pLevel->curLevel, enhanced); } else if (pColor->colorMode == ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS) { hwLight_colorUpdate_colorTemperature(pColor->colorTemperatureMireds, pLevel->curLevel); } } /********************************************************************* * @fn sampleLight_colorTimerEvtCb * * @brief * * @param arg * * @return 0: timer continue on; -1: timer will be canceled */ static s32 sampleLight_colorTimerEvtCb(void *arg) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); // It is safe to use the enhanced mode here, because we control it ourselves. if ((pColor->enhancedColorMode == ZCL_COLOR_MODE_CURRENT_HUE_SATURATION) || (pColor->enhancedColorMode == ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION)) { if (colorInfo.saturationRemainingTime) { light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); } if (colorInfo.hueRemainingTime) { light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); } if (colorInfo.enhancedHueRemainingTime) { light_applyUpdate_16(&pColor->enhancedCurrentHue, &colorInfo.currentEnhancedHue256, &colorInfo.stepEnhancedHue256, &colorInfo.enhancedHueRemainingTime, ZCL_COLOR_ATTR_ENHANCED_HUE_MIN, ZCL_COLOR_ATTR_ENHANCED_HUE_MAX, TRUE); } } else if (pColor->enhancedColorMode == ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS) { if (colorInfo.colorTempRemainingTime) { light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); } } else if (pColor->enhancedColorMode == ZCL_COLOR_MODE_CURRENT_X_Y) { if (colorInfo.xyRemainingTime) { light_applyXYUpdate_16(&pColor->currentX, &colorInfo.currentX256, &colorInfo.stepX256, &pColor->currentY, &colorInfo.currentY256, &colorInfo.stepY256, &colorInfo.xyRemainingTime, ZCL_COLOR_ATTR_XY_MIN, ZCL_COLOR_ATTR_XY_MAX, FALSE); } } if (colorInfo.saturationRemainingTime || colorInfo.hueRemainingTime || colorInfo.enhancedHueRemainingTime || colorInfo.colorTempRemainingTime || colorInfo.xyRemainingTime) { return 0; } else { colorTimerEvt = NULL; return -1; } } /********************************************************************* * @fn sampleLight_colorTimerStop * * @brief * * @param None * * @return None */ static void sampleLight_colorTimerStop(void) { if (colorTimerEvt) { TL_ZB_TIMER_CANCEL(&colorTimerEvt); } } /********************************************************************* * @fn sampleLight_colorLoopTimerEvtCb * * @brief * * @param arg * * @return 0: timer continue on; -1: timer will be canceled */ static s32 sampleLight_colorLoopTimerEvtCb(void *arg) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); if (pColor->colorLoopActive) { } else { colorLoopTimerEvt = NULL; return -1; } return 0; } /********************************************************************* * @fn sampleLight_colorLoopTimerStop * * @brief * * @param None * * @return None */ static void sampleLight_colorLoopTimerStop(void) { if (colorLoopTimerEvt) { TL_ZB_TIMER_CANCEL(&colorLoopTimerEvt); } } /********************************************************************* * @fn sampleLight_moveToHueProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveToHueProcess(zcl_colorCtrlMoveToHueCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; colorInfo.currentHue256 = (u16)(pColor->currentHue) << 8; s16 hueDiff = (s16)cmd->hue - pColor->currentHue; switch (cmd->direction) { case COLOR_CTRL_DIRECTION_SHORTEST_DISTANCE: if (hueDiff > (ZCL_COLOR_ATTR_HUE_MAX / 2)) { hueDiff -= (ZCL_COLOR_ATTR_HUE_MAX + 1); } else if (hueDiff < -ZCL_COLOR_ATTR_HUE_MAX / 2) { hueDiff += (ZCL_COLOR_ATTR_HUE_MAX + 1); } break; case COLOR_CTRL_DIRECTION_LONGEST_DISTANCE: if ((hueDiff > 0) && (hueDiff < (ZCL_COLOR_ATTR_HUE_MAX / 2))) { hueDiff -= (ZCL_COLOR_ATTR_HUE_MAX + 1); } else if ((hueDiff < 0) && (hueDiff > -ZCL_COLOR_ATTR_HUE_MAX / 2)) { hueDiff += (ZCL_COLOR_ATTR_HUE_MAX + 1); } break; case COLOR_CTRL_DIRECTION_UP: if (hueDiff < 0) { hueDiff += ZCL_COLOR_ATTR_HUE_MAX; } break; case COLOR_CTRL_DIRECTION_DOWN: if (hueDiff > 0) { hueDiff -= ZCL_COLOR_ATTR_HUE_MAX; } break; default: break; } 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; light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); sampleLight_colorTimerStop(); if (colorInfo.hueRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_moveHueProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveHueProcess(zcl_colorCtrlMoveHueCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; colorInfo.currentHue256 = (u16)(pColor->currentHue) << 8; switch (cmd->moveMode) { case COLOR_CTRL_MOVE_STOP: colorInfo.stepHue256 = 0; colorInfo.hueRemainingTime = 0; break; case COLOR_CTRL_MOVE_UP: colorInfo.stepHue256 = (((s32)cmd->rate) << 8) / 10; colorInfo.hueRemainingTime = 0xFFFF; break; case COLOR_CTRL_MOVE_DOWN: colorInfo.stepHue256 = ((-(s32)cmd->rate) << 8) / 10; colorInfo.hueRemainingTime = 0xFFFF; break; default: break; } light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); sampleLight_colorTimerStop(); if (colorInfo.hueRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_stepHueProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_stepHueProcess(zcl_colorCtrlStepHueCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; colorInfo.currentHue256 = (u16)(pColor->currentHue) << 8; 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; switch (cmd->stepMode) { case COLOR_CTRL_STEP_MODE_UP: break; case COLOR_CTRL_STEP_MODE_DOWN: colorInfo.stepHue256 = -colorInfo.stepHue256; break; default: break; } light_applyUpdate(&pColor->currentHue, &colorInfo.currentHue256, &colorInfo.stepHue256, &colorInfo.hueRemainingTime, ZCL_COLOR_ATTR_HUE_MIN, ZCL_COLOR_ATTR_HUE_MAX, TRUE); sampleLight_colorTimerStop(); if (colorInfo.hueRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_moveToSaturationProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveToSaturationProcess(zcl_colorCtrlMoveToSaturationCmd_t *cmd, bool preserveMode) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); if (!preserveMode) { sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; } colorInfo.currentSaturation256 = (u16)(pColor->currentSaturation) << 8; 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; light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); sampleLight_colorTimerStop(); if (colorInfo.saturationRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_moveSaturationProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveSaturationProcess(zcl_colorCtrlMoveSaturationCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; colorInfo.currentSaturation256 = (u16)(pColor->currentSaturation) << 8; switch (cmd->moveMode) { case COLOR_CTRL_MOVE_STOP: colorInfo.stepSaturation256 = 0; colorInfo.saturationRemainingTime = 0; break; case COLOR_CTRL_MOVE_UP: colorInfo.stepSaturation256 = (((s32)cmd->rate) << 8) / 10; colorInfo.saturationRemainingTime = 0xFFFF; break; case COLOR_CTRL_MOVE_DOWN: colorInfo.stepSaturation256 = ((-(s32)cmd->rate) << 8) / 10; colorInfo.saturationRemainingTime = 0xFFFF; break; default: break; } light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); sampleLight_colorTimerStop(); if (colorInfo.saturationRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_stepSaturationProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_stepSaturationProcess(zcl_colorCtrlStepSaturationCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; colorInfo.currentSaturation256 = (u16)(pColor->currentSaturation) << 8; 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; switch (cmd->stepMode) { case COLOR_CTRL_STEP_MODE_UP: break; case COLOR_CTRL_STEP_MODE_DOWN: colorInfo.stepSaturation256 = -colorInfo.stepSaturation256; break; default: break; } light_applyUpdate(&pColor->currentSaturation, &colorInfo.currentSaturation256, &colorInfo.stepSaturation256, &colorInfo.saturationRemainingTime, ZCL_COLOR_ATTR_SATURATION_MIN, ZCL_COLOR_ATTR_SATURATION_MAX, FALSE); sampleLight_colorTimerStop(); if (colorInfo.saturationRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_moveToHueAndSaturationProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveToHueAndSaturationProcess(zcl_colorCtrlMoveToHueAndSaturationCmd_t *cmd) { zcl_colorCtrlMoveToHueCmd_t moveToHueCmd; zcl_colorCtrlMoveToSaturationCmd_t moveToSaturationCmd; moveToHueCmd.hue = cmd->hue; moveToHueCmd.direction = COLOR_CTRL_DIRECTION_SHORTEST_DISTANCE; moveToHueCmd.transitionTime = cmd->transitionTime; moveToSaturationCmd.saturation = cmd->saturation; moveToSaturationCmd.transitionTime = cmd->transitionTime; sampleLight_moveToHueProcess(&moveToHueCmd); sampleLight_moveToSaturationProcess(&moveToSaturationCmd, false); } /*** * * HEAVY TODO BELOW this is entirely unimplemented and causing issues if XY support is indicated! * / /* * @fn sampleLight_moveToColorProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveToColorProcess(zcl_colorCtrlMoveToColorCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_X_Y); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_X_Y; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_X_Y; // Development override, something is wrong pColor->currentX = cmd->colorX; pColor->currentY = cmd->colorY; sampleLight_colorTimerStop(); light_fresh(); /* colorInfo.currentX256 = (u32)(pColor->currentX) << 8; colorInfo.currentY256 = (u32)(pColor->currentY) << 8; u16 remTime = INTERP_STEPS_FROM_ONE_TENTH(cmd->transitionTime, ZCL_COLOR_CHANGE_INTERVAL); // Instantaneous update or follow the time-steps calculated above. colorInfo.xyRemainingTime = remTime == 0 ? 1 : remTime; colorInfo.stepX256 = ((s32)(cmd->colorX - pColor->currentX)) << 8; colorInfo.stepX256 /= (s32)remTime; colorInfo.stepY256 = ((s32)(cmd->colorY - pColor->currentY)) << 8; colorInfo.stepY256 /= (s32)remTime; light_applyXYUpdate_16(&pColor->currentX, &colorInfo.currentX256, &colorInfo.stepX256, &pColor->currentY, &colorInfo.currentY256, &colorInfo.stepY256, &colorInfo.xyRemainingTime, ZCL_COLOR_ATTR_XY_MIN, ZCL_COLOR_ATTR_XY_MAX, FALSE); sampleLight_colorTimerStop(); if (colorInfo.xyRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } */ } /********************************************************************* * @fn sampleLight_moveColorProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveColorProcess(zcl_colorCtrlMoveColorCmd_t *cmd) { /* zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_X_Y); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_X_Y; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_X_Y; */ } /********************************************************************* * @fn sampleLight_stepColorProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_stepColorProcess(zcl_colorCtrlStepColorCmd_t *cmd) { /* zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_X_Y); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_X_Y; pColor->enhancedColorMode = ZCL_COLOR_MODE_CURRENT_X_Y; */ } /********************************************************************* * @fn sampleLight_enhancedMoveToHueProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_enhancedMoveToHueProcess(zcl_colorCtrlEnhancedMoveToHueCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION; colorInfo.currentEnhancedHue256 = (u32)(pColor->enhancedCurrentHue) << 8; s32 hueDiff = (s32)cmd->enhancedHue - pColor->enhancedCurrentHue; switch (cmd->direction) { case COLOR_CTRL_DIRECTION_SHORTEST_DISTANCE: if (hueDiff > (ZCL_COLOR_ATTR_ENHANCED_HUE_MAX / 2)) { hueDiff -= (ZCL_COLOR_ATTR_ENHANCED_HUE_MAX + 1); } else if (hueDiff < -ZCL_COLOR_ATTR_ENHANCED_HUE_MAX / 2) { hueDiff += (ZCL_COLOR_ATTR_ENHANCED_HUE_MAX + 1); } break; case COLOR_CTRL_DIRECTION_LONGEST_DISTANCE: if ((hueDiff > 0) && (hueDiff < (ZCL_COLOR_ATTR_ENHANCED_HUE_MAX / 2))) { hueDiff -= (ZCL_COLOR_ATTR_ENHANCED_HUE_MAX + 1); } else if ((hueDiff < 0) && (hueDiff > -ZCL_COLOR_ATTR_ENHANCED_HUE_MAX / 2)) { hueDiff += (ZCL_COLOR_ATTR_ENHANCED_HUE_MAX + 1); } break; case COLOR_CTRL_DIRECTION_UP: if (hueDiff < 0) { hueDiff += ZCL_COLOR_ATTR_ENHANCED_HUE_MAX; } break; case COLOR_CTRL_DIRECTION_DOWN: if (hueDiff > 0) { hueDiff -= ZCL_COLOR_ATTR_ENHANCED_HUE_MAX; } break; default: break; } 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; light_applyUpdate_16(&pColor->enhancedCurrentHue, &colorInfo.currentEnhancedHue256, &colorInfo.stepEnhancedHue256, &colorInfo.enhancedHueRemainingTime, ZCL_COLOR_ATTR_ENHANCED_HUE_MIN, ZCL_COLOR_ATTR_ENHANCED_HUE_MAX, TRUE); sampleLight_colorTimerStop(); if (colorInfo.enhancedHueRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_enhancedMoveHueProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_enhancedMoveHueProcess(zcl_colorCtrlEnhancedMoveHueCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION; switch (cmd->moveMode) { case COLOR_CTRL_MOVE_STOP: break; case COLOR_CTRL_MOVE_UP: break; case COLOR_CTRL_MOVE_DOWN: break; default: break; } } /********************************************************************* * @fn sampleLight_enhancedStepHueProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_enhancedStepHueProcess(zcl_colorCtrlEnhancedStepHueCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_CURRENT_HUE_SATURATION); pColor->colorMode = ZCL_COLOR_MODE_CURRENT_HUE_SATURATION; pColor->enhancedColorMode = ZCL_ENHANCED_COLOR_MODE_CURRENT_HUE_SATURATION; switch (cmd->stepMode) { case COLOR_CTRL_STEP_MODE_UP: break; case COLOR_CTRL_STEP_MODE_DOWN: break; default: break; } } /********************************************************************* * @fn sampleLight_enhancedMoveToHueAndSaturationProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_enhancedMoveToHueAndSaturationProcess(zcl_colorCtrlEnhancedMoveToHueAndSaturationCmd_t *cmd) { zcl_colorCtrlEnhancedMoveToHueCmd_t enhancedMoveToHueCmd; zcl_colorCtrlMoveToSaturationCmd_t moveToSaturationCmd; enhancedMoveToHueCmd.enhancedHue = cmd->enhancedHue; enhancedMoveToHueCmd.direction = COLOR_CTRL_DIRECTION_SHORTEST_DISTANCE; enhancedMoveToHueCmd.transitionTime = cmd->transitionTime; moveToSaturationCmd.saturation = cmd->saturation; moveToSaturationCmd.transitionTime = cmd->transitionTime; sampleLight_moveToSaturationProcess(&moveToSaturationCmd, true); sampleLight_enhancedMoveToHueProcess(&enhancedMoveToHueCmd); } /********************************************************************* * @fn sampleLight_colorLoopSetProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_colorLoopSetProcess(zcl_colorCtrlColorLoopSetCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); if (cmd->updateFlags.bits.direction) { pColor->colorLoopDirection = cmd->direction; } if (cmd->updateFlags.bits.time) { pColor->colorLoopTime = cmd->time; } if (cmd->updateFlags.bits.startHue) { pColor->colorLoopStartEnhancedHue = cmd->startHue; } if (cmd->updateFlags.bits.action) { switch (cmd->action) { case COLOR_LOOP_SET_DEACTION: break; case COLOR_LOOP_SET_ACTION_FROM_COLOR_LOOP_START_ENHANCED_HUE: break; case COLOR_LOOP_SET_ACTION_FROM_ENHANCED_CURRENT_HUE: break; default: break; } } } /********************************************************************* * @fn sampleLight_moveToColorTemperatureProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveToColorTemperatureProcess(zcl_colorCtrlMoveToColorTemperatureCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS); pColor->colorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; pColor->enhancedColorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; colorInfo.colorTempMinMireds = pColor->colorTempPhysicalMinMireds; colorInfo.colorTempMaxMireds = pColor->colorTempPhysicalMaxMireds; colorInfo.currentColorTemp256 = (u32)(pColor->colorTemperatureMireds) << 8; 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; light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); sampleLight_colorTimerStop(); if (colorInfo.colorTempRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_moveColorTemperatureProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_moveColorTemperatureProcess(zcl_colorCtrlMoveColorTemperatureCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS); pColor->colorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; pColor->enhancedColorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; if (cmd->colorTempMinMireds) { colorInfo.colorTempMinMireds = (cmd->colorTempMinMireds < pColor->colorTempPhysicalMinMireds) ? pColor->colorTempPhysicalMinMireds : cmd->colorTempMinMireds; } else { colorInfo.colorTempMinMireds = pColor->colorTempPhysicalMinMireds; } if (cmd->colorTempMaxMireds) { colorInfo.colorTempMaxMireds = (cmd->colorTempMaxMireds > pColor->colorTempPhysicalMaxMireds) ? pColor->colorTempPhysicalMaxMireds : cmd->colorTempMaxMireds; } else { colorInfo.colorTempMaxMireds = pColor->colorTempPhysicalMaxMireds; } colorInfo.currentColorTemp256 = (u32)(pColor->colorTemperatureMireds) << 8; switch (cmd->moveMode) { case COLOR_CTRL_MOVE_STOP: colorInfo.stepColorTemp256 = 0; colorInfo.colorTempRemainingTime = 0; break; case COLOR_CTRL_MOVE_UP: colorInfo.stepColorTemp256 = (((s32)cmd->rate) << 8) / 10; colorInfo.colorTempRemainingTime = 0xFFFF; break; case COLOR_CTRL_MOVE_DOWN: colorInfo.stepColorTemp256 = ((-(s32)cmd->rate) << 8) / 10; colorInfo.colorTempRemainingTime = 0xFFFF; break; default: break; } light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); sampleLight_colorTimerStop(); if (colorInfo.colorTempRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_stepColorTemperatureProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_stepColorTemperatureProcess(zcl_colorCtrlStepColorTemperatureCmd_t *cmd) { zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); sampleLight_updateColorMode(ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS); pColor->colorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; pColor->enhancedColorMode = ZCL_COLOR_MODE_COLOR_TEMPERATURE_MIREDS; if (cmd->colorTempMinMireds) { colorInfo.colorTempMinMireds = (cmd->colorTempMinMireds < pColor->colorTempPhysicalMinMireds) ? pColor->colorTempPhysicalMinMireds : cmd->colorTempMinMireds; } else { colorInfo.colorTempMinMireds = pColor->colorTempPhysicalMinMireds; } if (cmd->colorTempMaxMireds) { colorInfo.colorTempMaxMireds = (cmd->colorTempMaxMireds > pColor->colorTempPhysicalMaxMireds) ? pColor->colorTempPhysicalMaxMireds : cmd->colorTempMaxMireds; } else { colorInfo.colorTempMaxMireds = pColor->colorTempPhysicalMaxMireds; } colorInfo.currentColorTemp256 = (u32)(pColor->colorTemperatureMireds) << 8; 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; switch (cmd->stepMode) { case COLOR_CTRL_STEP_MODE_UP: break; case COLOR_CTRL_STEP_MODE_DOWN: colorInfo.stepColorTemp256 = -colorInfo.stepColorTemp256; break; default: break; } light_applyUpdate_16(&pColor->colorTemperatureMireds, &colorInfo.currentColorTemp256, &colorInfo.stepColorTemp256, &colorInfo.colorTempRemainingTime, colorInfo.colorTempMinMireds, colorInfo.colorTempMaxMireds, FALSE); sampleLight_colorTimerStop(); if (colorInfo.colorTempRemainingTime) { colorTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_colorTimerEvtCb, NULL, ZCL_COLOR_CHANGE_INTERVAL); } } /********************************************************************* * @fn sampleLight_stopMoveStepProcess * * @brief * * @param cmd * * @return None */ static void sampleLight_stopMoveStepProcess(void) { // zcl_lightColorCtrlAttr_t *pColor = zcl_colorAttrGet(); colorInfo.hueRemainingTime = 0; colorInfo.saturationRemainingTime = 0; colorInfo.colorTempRemainingTime = 0; sampleLight_colorTimerStop(); } /********************************************************************* * @fn sampleLight_colorCtrlCb * * @brief Handler for ZCL COLOR CONTROL command. This function will set Color Control attribute first. * * @param pAddrInfo * @param cmdId - color cluster command id * @param cmdPayload * * @return status_t */ status_t sampleLight_colorCtrlCb(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload) { if (pAddrInfo->dstEp == SAMPLE_LIGHT_ENDPOINT) { switch (cmdId) { case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_TO_HUE: sampleLight_moveToHueProcess((zcl_colorCtrlMoveToHueCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_HUE: sampleLight_moveHueProcess((zcl_colorCtrlMoveHueCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_STEP_HUE: sampleLight_stepHueProcess((zcl_colorCtrlStepHueCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_TO_SATURATION: sampleLight_moveToSaturationProcess((zcl_colorCtrlMoveToSaturationCmd_t *)cmdPayload, false); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_SATURATION: sampleLight_moveSaturationProcess((zcl_colorCtrlMoveSaturationCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_STEP_SATURATION: sampleLight_stepSaturationProcess((zcl_colorCtrlStepSaturationCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_TO_HUE_AND_SATURATION: sampleLight_moveToHueAndSaturationProcess((zcl_colorCtrlMoveToHueAndSaturationCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_TO_COLOR: sampleLight_moveToColorProcess((zcl_colorCtrlMoveToColorCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_COLOR: sampleLight_moveColorProcess((zcl_colorCtrlMoveColorCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_STEP_COLOR: sampleLight_stepColorProcess((zcl_colorCtrlStepColorCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE: sampleLight_enhancedMoveToHueProcess((zcl_colorCtrlEnhancedMoveToHueCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_ENHANCED_MOVE_HUE: sampleLight_enhancedMoveHueProcess((zcl_colorCtrlEnhancedMoveHueCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_ENHANCED_STEP_HUE: sampleLight_enhancedStepHueProcess((zcl_colorCtrlEnhancedStepHueCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_ENHANCED_MOVE_TO_HUE_AND_SATURATION: sampleLight_enhancedMoveToHueAndSaturationProcess((zcl_colorCtrlEnhancedMoveToHueAndSaturationCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_COLOR_LOOP_SET: sampleLight_colorLoopSetProcess((zcl_colorCtrlColorLoopSetCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_TO_COLOR_TEMPERATURE: sampleLight_moveToColorTemperatureProcess((zcl_colorCtrlMoveToColorTemperatureCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_MOVE_COLOR_TEMPERATURE: sampleLight_moveColorTemperatureProcess((zcl_colorCtrlMoveColorTemperatureCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_STEP_COLOR_TEMPERATURE: sampleLight_stepColorTemperatureProcess((zcl_colorCtrlStepColorTemperatureCmd_t *)cmdPayload); break; case ZCL_CMD_LIGHT_COLOR_CONTROL_STOP_MOVE_STEP: sampleLight_stopMoveStepProcess(); break; default: break; } } return ZCL_STA_SUCCESS; } #endif /* ZCL_LIGHT_COLOR_CONTROL */ #endif /* __PROJECT_TL_DIMMABLE_LIGHT__ */