This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2530: Convert old Z-stack samplelight to new Z-stack 3.0 samplelight

Part Number: CC2530
Other Parts Discussed in Thread: Z-STACK, , , CC253

Hi, I wanted to know how I could convert my old samplelight.c file into the new Z-stack 3.0 samplelight. What major changes would I have to do to get my code working with the Z-stack 3.0 samplelight? I've been trying, but am struggling, and I would appreciate any help towards my cause.

5040.zcl_samplelight.c
/**************************************************************************************************
  Filename:       zcl_sampleLight.c
  Revised:        $Date: 2014-10-24 16:04:46 -0700 (Fri, 24 Oct 2014) $
  Revision:       $Revision: 40796 $


  Description:    Zigbee Cluster Library - sample device application.


  Copyright 2006-2014 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com.
**************************************************************************************************/

/*********************************************************************
  This application implements a ZigBee HA 1.2 Light. It can be configured as an
  On/Off light, or as a dimmable light. The following flags must be defined in
  the compiler's pre-defined symbols.

  ZCL_ON_OFF
  ZCL_LEVEL_CTRL    (only if dimming functionality desired)
  HOLD_AUTO_START
  ZCL_EZMODE

  This device supports all mandatory and optional commands/attributes for the
  OnOff (0x0006) and LevelControl (0x0008) clusters.

  SCREEN MODES
  ----------------------------------------
  Main:
    - SW1: Toggle local light
    - SW2: Invoke EZMode
    - SW4: Enable/Disable local permit join
    - SW5: Go to Help screen
  ----------------------------------------
*********************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include "ZComDef.h"
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "MT_SYS.h"

#include "nwk_util.h"

#include "zcl.h"
#include "zcl_general.h"
#include "zcl_ha.h"
#include "zcl_ezmode.h"
#include "zcl_diagnostic.h"

#include "zcl_samplelight.h"

#include "onboard.h"

/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"

#if ( defined (ZGP_DEVICE_TARGET) || defined (ZGP_DEVICE_TARGETPLUS) \
      || defined (ZGP_DEVICE_COMBO) || defined (ZGP_DEVICE_COMBO_MIN) )
#include "zgp_translationtable.h"
  #if (SUPPORTED_S_FEATURE(SUPP_ZGP_FEATURE_TRANSLATION_TABLE))
    #define ZGP_AUTO_TT
  #endif
#endif

#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
#include "math.h"
#include "hal_timer.h"
#endif

#include "NLMEDE.h"

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */
#if (defined HAL_BOARD_ZLIGHT)
#define LEVEL_MAX                 0xFE
#define LEVEL_MIN                 0x0
#define GAMMA_VALUE               2
#define PWM_FULL_DUTY_CYCLE       1000
#elif (defined HAL_PWM)
#define LEVEL_MAX                 0xFE
#define LEVEL_MIN                 0x0
#define GAMMA_VALUE               2
#define PWM_FULL_DUTY_CYCLE       100
#endif

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
byte zclSampleLight_TaskID;
uint8 zclSampleLightSeqNum;


/*********************************************************************
 * GLOBAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
afAddrType_t zclSampleLight_DstAddr;

#ifdef ZCL_EZMODE
static void zclSampleLight_ProcessZDOMsgs( zdoIncomingMsg_t *pMsg );
static void zclSampleLight_EZModeCB( zlcEZMode_State_t state, zclEZMode_CBData_t *pData );


// register EZ-Mode with task information (timeout events, callback, etc...)
static const zclEZMode_RegisterData_t zclSampleLight_RegisterEZModeData =
{
  &zclSampleLight_TaskID,
  SAMPLELIGHT_EZMODE_NEXTSTATE_EVT,
  SAMPLELIGHT_EZMODE_TIMEOUT_EVT,
  &zclSampleLightSeqNum,
  zclSampleLight_EZModeCB
};

#else
uint16 bindingInClusters[] =
{
  ZCL_CLUSTER_ID_GEN_ON_OFF
#ifdef ZCL_LEVEL_CTRL
  , ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL
#endif
};
#define ZCLSAMPLELIGHT_BINDINGLIST (sizeof(bindingInClusters) / sizeof(bindingInClusters[0]))

#endif  // ZCL_EZMODE

// Test Endpoint to allow SYS_APP_MSGs
static endPointDesc_t sampleLight_TestEp =
{
  SAMPLELIGHT_ENDPOINT,
  &zclSampleLight_TaskID,
  (SimpleDescriptionFormat_t *)NULL,  // No Simple description for this test endpoint
  (afNetworkLatencyReq_t)0            // No Network Latency req
};

uint8 giLightScreenMode = LIGHT_MAINMODE;   // display the main screen mode first

uint8 gPermitDuration = 0;    // permit joining default to disabled

devStates_t zclSampleLight_NwkState = DEV_INIT;

#if ZCL_LEVEL_CTRL
uint8 zclSampleLight_WithOnOff;       // set to TRUE if state machine should set light on/off
uint8 zclSampleLight_NewLevel;        // new level when done moving
bool  zclSampleLight_NewLevelUp;      // is direction to new level up or down?
int32 zclSampleLight_CurrentLevel32;  // current level, fixed point (e.g. 192.456)
int32 zclSampleLight_Rate32;          // rate in units, fixed point (e.g. 16.123)
uint8 zclSampleLight_LevelLastLevel;  // to save the Current Level before the light was turned OFF
#endif

/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void zclSampleLight_HandleKeys( byte shift, byte keys );
static void zclSampleLight_BasicResetCB( void );
static void zclSampleLight_IdentifyCB( zclIdentify_t *pCmd );
static void zclSampleLight_IdentifyQueryRspCB( zclIdentifyQueryRsp_t *pRsp );
static void zclSampleLight_OnOffCB( uint8 cmd );
static void zclSampleLight_ProcessIdentifyTimeChange( void );
#ifdef ZCL_LEVEL_CTRL
static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd );
static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd );
static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd );
static void zclSampleLight_LevelControlStopCB( void );
static void zclSampleLight_DefaultMove( void );
static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel );
static uint16 zclSampleLight_GetTime ( uint8 level, uint16 time );
static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate );
static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time );
static void zclSampleLight_AdjustLightLevel( void );
#endif

// app display functions
static void zclSampleLight_LcdDisplayUpdate( void );
#ifdef LCD_SUPPORTED
static void zclSampleLight_LcdDisplayMainMode( void );
static void zclSampleLight_LcdDisplayHelpMode( void );
#endif
static void zclSampleLight_DisplayLight( void );

#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
void zclSampleLight_UpdateLampLevel( uint8 level );
#endif

// Functions to process ZCL Foundation incoming Command/Response messages
static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *msg );
#ifdef ZCL_READ
static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
#endif
#ifdef ZCL_WRITE
static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
#endif
static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
#ifdef ZCL_DISCOVER
static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg );
static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg );
static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg );
#endif

/*********************************************************************
 * STATUS STRINGS
 */
#ifdef LCD_SUPPORTED
const char sDeviceName[]   = "  Sample Light";
const char sClearLine[]    = " ";
const char sSwLight[]      = "SW1: ToggleLight";  // 16 chars max
const char sSwEZMode[]     = "SW2: EZ-Mode";
char sSwHelp[]             = "SW5: Help       ";  // last character is * if NWK open
const char sLightOn[]      = "    LIGHT ON ";
const char sLightOff[]     = "    LIGHT OFF";
 #if ZCL_LEVEL_CTRL
 char sLightLevel[]        = "    LEVEL ###"; // displays level 1-254
 #endif
#endif

/*********************************************************************
 * ZCL General Profile Callback table
 */
static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks =
{
  zclSampleLight_BasicResetCB,            // Basic Cluster Reset command
  zclSampleLight_IdentifyCB,              // Identify command
#ifdef ZCL_EZMODE
  NULL,                                   // Identify EZ-Mode Invoke command
  NULL,                                   // Identify Update Commission State command
#endif
  NULL,                                   // Identify Trigger Effect command
  zclSampleLight_IdentifyQueryRspCB,      // Identify Query Response command
  zclSampleLight_OnOffCB,                 // On/Off cluster commands
  NULL,                                   // On/Off cluster enhanced command Off with Effect
  NULL,                                   // On/Off cluster enhanced command On with Recall Global Scene
  NULL,                                   // On/Off cluster enhanced command On with Timed Off
#ifdef ZCL_LEVEL_CTRL
  zclSampleLight_LevelControlMoveToLevelCB, // Level Control Move to Level command
  zclSampleLight_LevelControlMoveCB,        // Level Control Move command
  zclSampleLight_LevelControlStepCB,        // Level Control Step command
  zclSampleLight_LevelControlStopCB,        // Level Control Stop command
#endif
#ifdef ZCL_GROUPS
  NULL,                                   // Group Response commands
#endif
#ifdef ZCL_SCENES
  NULL,                                  // Scene Store Request command
  NULL,                                  // Scene Recall Request command
  NULL,                                  // Scene Response command
#endif
#ifdef ZCL_ALARMS
  NULL,                                  // Alarm (Response) commands
#endif
#ifdef SE_UK_EXT
  NULL,                                  // Get Event Log command
  NULL,                                  // Publish Event Log command
#endif
  NULL,                                  // RSSI Location command
  NULL                                   // RSSI Location Response command
};

/*********************************************************************
 * @fn          zclSampleLight_Init
 *
 * @brief       Initialization function for the zclGeneral layer.
 *
 * @param       none
 *
 * @return      none
 */
#define enable P0_6
#define phase P0_5
#define pin P1_4

static int no = 1;

#define PERIODIC_EVT 0x4000
#define PERIODIC_EVT4 0x0020
#define offline 0x0010
#define TURNOFF_MOTOR_EVT 0x0400

uint8 direction;
uint16 nv_test_id=0x0401;

void zclSampleLight_Init( byte task_id )
{
  zclSampleLight_TaskID = task_id;
  osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10 );
  osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 10 );  
  osal_start_timerEx( zclSampleLight_TaskID, offline, 10 );

  // Set destination address to indirect
  zclSampleLight_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
  zclSampleLight_DstAddr.endPoint = 0;
  zclSampleLight_DstAddr.addr.shortAddr = 0;

  // This app is part of the Home Automation Profile
  zclHA_Init( &zclSampleLight_SimpleDesc );

  // Register the ZCL General Cluster Library callback functions
  zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );

  // Register the application's attribute list
  zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, zclSampleLight_NumAttributes, zclSampleLight_Attrs );

  // Register the Application to receive the unprocessed Foundation command/response messages
  zcl_registerForMsg( zclSampleLight_TaskID );

#ifdef ZCL_DISCOVER
  // Register the application's command list
  zcl_registerCmdList( SAMPLELIGHT_ENDPOINT, zclCmdsArraySize, zclSampleLight_Cmds );
#endif

  // Register for all key events - This app will handle all key events
  RegisterForKeys( zclSampleLight_TaskID );

  // Register for a test endpoint
  afRegister( &sampleLight_TestEp );

#ifdef ZCL_EZMODE
  // Register EZ-Mode
  zcl_RegisterEZMode( &zclSampleLight_RegisterEZModeData );

  // Register with the ZDO to receive Match Descriptor Responses
  ZDO_RegisterForZDOMsg(task_id, Match_Desc_rsp);
#endif


#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
  HalTimer1Init( 0 );
  halTimer1SetChannelDuty( WHITE_LED, 0 );
  halTimer1SetChannelDuty( RED_LED, 0 );
  halTimer1SetChannelDuty( BLUE_LED, 0 );
  halTimer1SetChannelDuty( GREEN_LED, 0 );

  // find if we are already on a network from NV_RESTORE
  uint8 state;
  NLME_GetRequest( nwkNwkState, 0, &state );

  if ( state < NWK_ENDDEVICE )
  {
    // Start EZMode on Start up to avoid button press
    osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_START_EZMODE_EVT, 500 );
  }
#if ZCL_LEVEL_CTRL
  zclSampleLight_DefaultMove();
#endif
#endif // #if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)

#ifdef ZCL_DIAGNOSTIC
  // Register the application's callback function to read/write attribute data.
  // This is only required when the attribute data format is unknown to ZCL.
  zcl_registerReadWriteCB( SAMPLELIGHT_ENDPOINT, zclDiagnostic_ReadWriteAttrCB, NULL );

  if ( zclDiagnostic_InitStats() == ZSuccess )
  {
    // Here the user could start the timer to save Diagnostics to NV
  }
#endif

#ifdef LCD_SUPPORTED
  HalLcdWriteString ( (char *)sDeviceName, HAL_LCD_LINE_3 );
#endif  // LCD_SUPPORTED

#ifdef ZGP_AUTO_TT
  zgpTranslationTable_RegisterEP ( &zclSampleLight_SimpleDesc );
#endif
  
  osal_nv_item_init(nv_test_id, 1, &direction);
  osal_nv_read(nv_test_id, 0, 1, &direction);
  
  P0SEL &= (~((BV(5))|(BV(6))));
  P0DIR |= ((BV(5))|(BV(6)));
  
  P1SEL &= (~((BV(3))|(BV(7))));
  P1DIR |= ((BV(3))|(BV(7)));
  P1_3=0;
  P1_7=0;

  P2SEL &= (~(BV(0)));
  P2DIR |= (BV(0));
  P2_0=0;
  
  P1DIR |= 0x01;
  pin=0;
  
  zclSampleLight_OnOff = LIGHT_ON;
  
  zclReportCmd_t rptcmd;
  rptcmd.numAttr = 1;
  rptcmd.attrList[0].attrID = ATTRID_ON_OFF;
  rptcmd.attrList[0].dataType = ZCL_DATATYPE_BOOLEAN;
  rptcmd.attrList[0].attrData = (uint8*)&zclSampleLight_OnOff;

  // Set destination address to indirect
  zclSampleLight_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
  zclSampleLight_DstAddr.addr.shortAddr = 0;
  zclSampleLight_DstAddr.endPoint=1;
  zcl_SendReportCmd(SAMPLELIGHT_ENDPOINT,&zclSampleLight_DstAddr, ZCL_CLUSTER_ID_GEN_ON_OFF, &rptcmd, ZCL_FRAME_CLIENT_SERVER_DIR, false, 0 );
  
  ZDApp_ChangeState(DEV_NWK_DISC);
  ZDApp_StartJoiningCycle();
  osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );

  if(direction==0){
    enable = 1;
    phase = 0;  
  }
  else if(direction==1){
    enable = 1;
    phase = 1;
  }
  osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
}

/*********************************************************************
 * @fn          zclSample_event_loop
 *
 * @brief       Event Loop Processor for zclGeneral.
 *
 * @param       none
 *
 * @return      none
 */
#include <hal_adc.h>
#include <OSAL_PwrMgr.h>

#define KEYHOLD_EVT  0x0100    //define event for key hold

uint16 adc_ain2=0; 
int KeyPressCnt=0;
int seven = 1;  
int scan=0;
int disconnect = 0;
int b=1;
int start=1;

uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
{
  if(DEV_NWK_BACKOFF){
    pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY;
    if(devState==DEV_NWK_BACKOFF){
      scan=1;
    }
  }
  
  if(disconnect==1 & (devState==DEV_NWK_DISC || devState==DEV_NWK_BACKOFF)){
    disconnect=0;
    osal_start_timerEx( zclSampleLight_TaskID, offline, 30000 );
  }
  
  if( events & offline )
  {
    ZDApp_SetRejoinBackoffDuration(86400000);
    ZDApp_SetRejoinScanDuration(10000);
    return (events ^ offline);
  }
  
  if( events & TURNOFF_MOTOR_EVT )
  {
    enable = 0;
    if(start==1){
      phase=0;
      start=0;
    }
    else if(zclSampleLight_OnOff==LIGHT_ON){
      phase = 1;
    }
    else if(zclSampleLight_OnOff==LIGHT_OFF){
      phase = 0;
    }
    return (events ^ TURNOFF_MOTOR_EVT);
  }
  
  if(P2_0==0){
    seven=0;
  }
  
  if ( events & KEYHOLD_EVT)
  {
    if ( P2_0==1 )
    {
      if (KeyPressCnt>40){
        KeyPressCnt=0;
        extern void ZDApp_ResetTimerStart( uint16 delay );
        zgWriteStartupOptions(ZG_STARTUP_SET, (ZCD_STARTOPT_DEFAULT_NETWORK_STATE | ZCD_STARTOPT_DEFAULT_CONFIG_STATE) );
        
        pin=1;
        for(int i=0; i<500; i++){
          Onboard_wait(10000);
        }
        
        SystemReset();
      }    
      else{
        pin=0;        
        KeyPressCnt++;
        osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
      }
    }
    return ( events ^ KEYHOLD_EVT );
  }
  
  if( events & PERIODIC_EVT4 ){
    osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
    
    if(b==1){
      pin=1;
      b=0;
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 25 );
    }
    else if(b==0){
      pin=0;
      b=1;
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 2000 );
    }
    return (events ^ PERIODIC_EVT4);
  }
  
  if( events & PERIODIC_EVT )
  {
    HalAdcSetReference(HAL_ADC_REF_125V);
    adc_ain2=HalAdcRead(HAL_ADC_CHN_AIN7,HAL_ADC_RESOLUTION_10);

    if(adc_ain2<=155){           //155=2.6v   //177=3v   //188=3.3v  //160=2.5v
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 25 );
    }
    else if(adc_ain2>155){
      pin=0;
      osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
    }

    osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10000 );
    return (events ^ PERIODIC_EVT);
  }
  
  afIncomingMSGPacket_t *MSGpkt;

  (void)task_id;  // Intentionally unreferenced parameter

  if ( events & SYS_EVENT_MSG )
  {
    while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclSampleLight_TaskID )) )
    {
      switch ( MSGpkt->hdr.event )
      {
#ifdef ZCL_EZMODE
        case ZDO_CB_MSG:
          zclSampleLight_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
          break;
#endif
        case ZCL_INCOMING_MSG:
          // Incoming ZCL Foundation command/response messages
          zclSampleLight_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
          break;

        case KEY_CHANGE:
          zclSampleLight_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
          break;

        case ZDO_STATE_CHANGE:
          zclSampleLight_NwkState = (devStates_t)(MSGpkt->hdr.status);

          // now on the network
          if ( (zclSampleLight_NwkState == DEV_ZB_COORD) ||
               (zclSampleLight_NwkState == DEV_ROUTER)   ||
               (zclSampleLight_NwkState == DEV_END_DEVICE) )
          {
            disconnect = 1;
            
            ZDApp_SetRejoinBackoffDuration(5000);
            ZDApp_SetRejoinScanDuration(10000);
            
            giLightScreenMode = LIGHT_MAINMODE;
            zclSampleLight_LcdDisplayUpdate();
#ifdef ZCL_EZMODE
            zcl_EZModeAction( EZMODE_ACTION_NETWORK_STARTED, NULL );
#endif // ZCL_EZMODE
          }
          break;

        default:
          break;
      }

      // Release the memory
      osal_msg_deallocate( (uint8 *)MSGpkt );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT )
  {
    if ( zclSampleLight_IdentifyTime > 0 )
      zclSampleLight_IdentifyTime--;
    zclSampleLight_ProcessIdentifyTimeChange();

    return ( events ^ SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT );
  }

  if ( events & SAMPLELIGHT_MAIN_SCREEN_EVT )
  {
    giLightScreenMode = LIGHT_MAINMODE;
    zclSampleLight_LcdDisplayUpdate();

    return ( events ^ SAMPLELIGHT_MAIN_SCREEN_EVT );
  }

#ifdef ZCL_EZMODE
#if (defined HAL_BOARD_ZLIGHT)
  // event to start EZMode on startup with a delay
  if ( events & SAMPLELIGHT_START_EZMODE_EVT )
  {
    // Invoke EZ-Mode
    zclEZMode_InvokeData_t ezModeData;

    // Invoke EZ-Mode
    ezModeData.endpoint = SAMPLELIGHT_ENDPOINT; // endpoint on which to invoke EZ-Mode
    if ( (zclSampleLight_NwkState == DEV_ZB_COORD) ||
         (zclSampleLight_NwkState == DEV_ROUTER)   ||
         (zclSampleLight_NwkState == DEV_END_DEVICE) )
    {
      ezModeData.onNetwork = TRUE;      // node is already on the network
    }
    else
    {
      ezModeData.onNetwork = FALSE;     // node is not yet on the network
    }
    ezModeData.initiator = FALSE;          // OnOffLight is a target
    ezModeData.numActiveOutClusters = 0;
    ezModeData.pActiveOutClusterIDs = NULL;
    ezModeData.numActiveInClusters = 0;
    ezModeData.pActiveOutClusterIDs = NULL;
    zcl_InvokeEZMode( &ezModeData );

    return ( events ^ SAMPLELIGHT_START_EZMODE_EVT );
  }
#endif // #if (defined HAL_BOARD_ZLIGHT)

  // going on to next state
  if ( events & SAMPLELIGHT_EZMODE_NEXTSTATE_EVT )
  {
    zcl_EZModeAction ( EZMODE_ACTION_PROCESS, NULL );   // going on to next state
    return ( events ^ SAMPLELIGHT_EZMODE_NEXTSTATE_EVT );
  }

  // the overall EZMode timer expired, so we timed out
  if ( events & SAMPLELIGHT_EZMODE_TIMEOUT_EVT )
  {
    zcl_EZModeAction ( EZMODE_ACTION_TIMED_OUT, NULL ); // EZ-Mode timed out
    return ( events ^ SAMPLELIGHT_EZMODE_TIMEOUT_EVT );
  }
#endif // ZLC_EZMODE

#ifdef ZCL_LEVEL_CTRL
  if ( events & SAMPLELIGHT_LEVEL_CTRL_EVT )
  {
    zclSampleLight_AdjustLightLevel();
    return ( events ^ SAMPLELIGHT_LEVEL_CTRL_EVT );
  }
#endif

  // Discard unknown events
  return 0;
}

/*********************************************************************
 * @fn      zclSampleLight_HandleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys - bit field for key events. Valid entries:
 *                 HAL_KEY_SW_5
 *                 HAL_KEY_SW_4
 *                 HAL_KEY_SW_2
 *                 HAL_KEY_SW_1
 *
 * @return  none
 */
static void zclSampleLight_HandleKeys( byte shift, byte keys )
{
  if ( keys & HAL_KEY_SW_3 )
  {
    if(direction==0){
      direction=1;
    }
    else if(direction==1){
      direction=0;
    }
    
    enable = 0; 
    if(start==1){
      phase=0;
      start=0;
    }
    else if(zclSampleLight_OnOff==LIGHT_ON){
      phase = 1;
    }
    else if(zclSampleLight_OnOff==LIGHT_OFF){
      phase = 0;
    }
    seven=0;
    
    if(direction==0){
      osal_nv_write(nv_test_id, 0, 1, &direction);      //Write nv_test = 0
    }
    else if(direction==1){
      osal_nv_write(nv_test_id, 0, 1, &direction);      //Write nv_test = 1
    }
  }
  
  while(P1_7==1){
    if(direction==0){
      if(no==1){
        enable = 1;
        phase = 1;

        for(int i=0; i<3; i++){
          Onboard_wait(10000);
        } 
      }
      else if(no==0){
        enable = 1;
        phase = 0;
          
        for(int i=0; i<3; i++){
          Onboard_wait(10000);
        } 
      }
    }
      
    else if(direction==1){
      if(no==1){
        enable = 1;
        phase = 0;

        for(int i=0; i<3; i++){
          Onboard_wait(10000);
        } 
      }
      else if(no==0){
        enable = 1;
        phase = 1;
          
        for(int i=0; i<3; i++){
          Onboard_wait(10000);
        } 
      }
    }
    seven=1;
  }  
  
  if(P1_7==0 & seven==1){   
    enable = 0;
    if(start==1){
      phase=0;
      start=0;
    }
    else if(zclSampleLight_OnOff==LIGHT_ON){
      phase = 1;
    }
    else if(zclSampleLight_OnOff==LIGHT_OFF){
      phase = 0;
    }
  }
  
  if(P2_0==0){
    seven=0;
  }

  if ( keys & HAL_KEY_SW_1 & seven==0 )
  {
    seven=2;
    if(scan==1){
      ZDApp_ChangeState(DEV_NWK_DISC);
      ZDApp_StartJoiningCycle();
      osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );
      scan=0;
    }
    
    KeyPressCnt=0;
    osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
    
    zclSampleLight_OnOff = zclSampleLight_OnOff ? LIGHT_OFF : LIGHT_ON;
    
    for(int i=0; i<30; i++){
      Onboard_wait(10000);
    } 
  }

  // update the display, including the light
  zclSampleLight_LcdDisplayUpdate();
}

/*********************************************************************
 * @fn      zclSampleLight_LcdDisplayUpdate
 *
 * @brief   Called to update the LCD display.
 *
 * @param   none
 *
 * @return  none
 */
void zclSampleLight_LcdDisplayUpdate( void )
{
#ifdef LCD_SUPPORTED
  if ( giLightScreenMode == LIGHT_HELPMODE )
  {
    zclSampleLight_LcdDisplayHelpMode();
  }
  else
  {
    zclSampleLight_LcdDisplayMainMode();
  }
#endif

  osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
  
  zclReportCmd_t rptcmd;
  rptcmd.numAttr = 1;
  rptcmd.attrList[0].attrID = ATTRID_ON_OFF;
  rptcmd.attrList[0].dataType = ZCL_DATATYPE_BOOLEAN;
  rptcmd.attrList[0].attrData = (uint8*)&zclSampleLight_OnOff;

  // Set destination address to indirect
  zclSampleLight_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
  zclSampleLight_DstAddr.addr.shortAddr = 0;
  zclSampleLight_DstAddr.endPoint=1;
  zcl_SendReportCmd(SAMPLELIGHT_ENDPOINT,&zclSampleLight_DstAddr, ZCL_CLUSTER_ID_GEN_ON_OFF, &rptcmd, ZCL_FRAME_CLIENT_SERVER_DIR, false, 0 );
  
  zclSampleLight_DisplayLight();
}

#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
/*********************************************************************
 * @fn      zclSampleLight_UpdateLampLevel
 *
 * @brief   Update lamp level output with gamma compensation
 *
 * @param   level
 *
 * @return  none
 */
void zclSampleLight_UpdateLampLevel( uint8 level )

{
  uint16 gammaCorrectedLevel;

  // gamma correct the level
  gammaCorrectedLevel = (uint16) ( pow( ( (float)level / LEVEL_MAX ), (float)GAMMA_VALUE ) * (float)LEVEL_MAX);

  halTimer1SetChannelDuty(WHITE_LED, (uint16)(((uint32)gammaCorrectedLevel*PWM_FULL_DUTY_CYCLE)/LEVEL_MAX) );
}
#endif

/*********************************************************************
 * @fn      zclSampleLight_DisplayLight
 *
 * @brief   Displays current state of light on LED and also on main display if supported.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_DisplayLight( void )
{
  if(direction==0){
    if ( zclSampleLight_OnOff == LIGHT_ON & no == 0 )
    {
      enable = 1;    
      phase = 0;

      no = 1;
    }
    else if ( zclSampleLight_OnOff == LIGHT_OFF & no == 1 )
    {
      enable = 1;
      phase = 1;
      
      no = 0;
    }
  }
  
  else if(direction==1){
    if ( zclSampleLight_OnOff == LIGHT_ON & no == 0 )
    {
      enable = 1;    
      phase = 1;

      no = 1;
    }
    else if ( zclSampleLight_OnOff == LIGHT_OFF & no == 1 )
    {
      enable = 1;
      phase = 0;
      
      no = 0;
    }
  }

#ifdef LCD_SUPPORTED
  if (giLightScreenMode == LIGHT_MAINMODE)
  {
#ifdef ZCL_LEVEL_CTRL
    // display current light level
    if ( ( zclSampleLight_LevelCurrentLevel == ATTR_LEVEL_MIN_LEVEL ) &&
         ( zclSampleLight_OnOff == LIGHT_OFF ) )
    {
      HalLcdWriteString( (char *)sLightOff, HAL_LCD_LINE_2 );
    }
    else if ( ( zclSampleLight_LevelCurrentLevel >= ATTR_LEVEL_MAX_LEVEL ) ||
              ( zclSampleLight_LevelCurrentLevel == zclSampleLight_LevelOnLevel ) ||
               ( ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT ) &&
                 ( zclSampleLight_LevelCurrentLevel == zclSampleLight_LevelLastLevel ) ) )
    {
      HalLcdWriteString( (char *)sLightOn, HAL_LCD_LINE_2 );
    }
    else    // "    LEVEL ###"
    {
      zclHA_uint8toa( zclSampleLight_LevelCurrentLevel, &sLightLevel[10] );
      HalLcdWriteString( (char *)sLightLevel, HAL_LCD_LINE_2 );
    }
#else
    if ( zclSampleLight_OnOff )
    {
      HalLcdWriteString( (char *)sLightOn, HAL_LCD_LINE_2 );
    }
    else
    {
      HalLcdWriteString( (char *)sLightOff, HAL_LCD_LINE_2 );
    }
#endif // ZCL_LEVEL_CTRL
  }
#endif // LCD_SUPPORTED
}

#ifdef LCD_SUPPORTED
/*********************************************************************
 * @fn      zclSampleLight_LcdDisplayMainMode
 *
 * @brief   Called to display the main screen on the LCD.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_LcdDisplayMainMode( void )
{
  // display line 1 to indicate NWK status
  if ( zclSampleLight_NwkState == DEV_ZB_COORD )
  {
    zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZC );
  }
  else if ( zclSampleLight_NwkState == DEV_ROUTER )
  {
    zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZR );
  }
  else if ( zclSampleLight_NwkState == DEV_END_DEVICE )
  {
    zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZED );
  }

  // end of line 3 displays permit join status (*)
  if ( gPermitDuration )
  {
    sSwHelp[15] = '*';
  }
  else
  {
    sSwHelp[15] = ' ';
  }
  HalLcdWriteString( (char *)sSwHelp, HAL_LCD_LINE_3 );
}

/*********************************************************************
 * @fn      zclSampleLight_LcdDisplayHelpMode
 *
 * @brief   Called to display the SW options on the LCD.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_LcdDisplayHelpMode( void )
{
  HalLcdWriteString( (char *)sSwLight, HAL_LCD_LINE_1 );
  HalLcdWriteString( (char *)sSwEZMode, HAL_LCD_LINE_2 );
  HalLcdWriteString( (char *)sSwHelp, HAL_LCD_LINE_3 );
}
#endif  // LCD_SUPPORTED

/*********************************************************************
 * @fn      zclSampleLight_ProcessIdentifyTimeChange
 *
 * @brief   Called to process any change to the IdentifyTime attribute.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_ProcessIdentifyTimeChange( void )
{
  if ( zclSampleLight_IdentifyTime > 0 )
  {
    osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT, 1000 );
    HalLedBlink ( HAL_LED_4, 0xFF, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME );
  }
  else
  {
#ifdef ZCL_EZMODE
    if ( zclSampleLight_IdentifyCommissionState & EZMODE_COMMISSION_OPERATIONAL )
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_ON );
    }
    else
    {
      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
    }
#endif

    osal_stop_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT );
  }
}

/*********************************************************************
 * @fn      zclSampleLight_BasicResetCB
 *
 * @brief   Callback from the ZCL General Cluster Library
 *          to set all the Basic Cluster attributes to default values.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_BasicResetCB( void )
{
  NLME_LeaveReq_t leaveReq;
  // Set every field to 0
  osal_memset( &leaveReq, 0, sizeof( NLME_LeaveReq_t ) );

  // This will enable the device to rejoin the network after reset.
  leaveReq.rejoin = TRUE;

  // Set the NV startup option to force a "new" join.
  zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );

  // Leave the network, and reset afterwards
  if ( NLME_LeaveReq( &leaveReq ) != ZSuccess )
  {
    // Couldn't send out leave; prepare to reset anyway
    ZDApp_LeaveReset( FALSE );
  }
}

/*********************************************************************
 * @fn      zclSampleLight_IdentifyCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an Identity Command for this application.
 *
 * @param   srcAddr - source address and endpoint of the response message
 * @param   identifyTime - the number of seconds to identify yourself
 *
 * @return  none
 */
static void zclSampleLight_IdentifyCB( zclIdentify_t *pCmd )
{
  zclSampleLight_IdentifyTime = pCmd->identifyTime;
  zclSampleLight_ProcessIdentifyTimeChange();
}

/*********************************************************************
 * @fn      zclSampleLight_IdentifyQueryRspCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an Identity Query Response Command for this application.
 *
 * @param   srcAddr - requestor's address
 * @param   timeout - number of seconds to identify yourself (valid for query response)
 *
 * @return  none
 */
static void zclSampleLight_IdentifyQueryRspCB(  zclIdentifyQueryRsp_t *pRsp )
{
  (void)pRsp;
#ifdef ZCL_EZMODE
  {
    zclEZMode_ActionData_t data;
    data.pIdentifyQueryRsp = pRsp;
    zcl_EZModeAction ( EZMODE_ACTION_IDENTIFY_QUERY_RSP, &data );
  }
#endif
}

/*********************************************************************
 * @fn      zclSampleLight_OnOffCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an On/Off Command for this application.
 *
 * @param   cmd - COMMAND_ON, COMMAND_OFF or COMMAND_TOGGLE
 *
 * @return  none
 */
static void zclSampleLight_OnOffCB( uint8 cmd )
{
  afIncomingMSGPacket_t *pPtr = zcl_getRawAFMsg();

  zclSampleLight_DstAddr.addr.shortAddr = pPtr->srcAddr.addr.shortAddr;


  // Turn on the light
  if ( cmd == COMMAND_ON )
  {
    zclSampleLight_OnOff = LIGHT_ON;
  }
  // Turn off the light
  else if ( cmd == COMMAND_OFF )
  {
    zclSampleLight_OnOff = LIGHT_OFF;
  }
  // Toggle the light
  else if ( cmd == COMMAND_TOGGLE )
  {
    if ( zclSampleLight_OnOff == LIGHT_OFF )
    {
      zclSampleLight_OnOff = LIGHT_ON;
    }
    else
    {
      zclSampleLight_OnOff = LIGHT_OFF;
    }
  }

#if ZCL_LEVEL_CTRL
  zclSampleLight_DefaultMove( );
#endif

  // update the display
  zclSampleLight_LcdDisplayUpdate( );
}

#ifdef ZCL_LEVEL_CTRL
/*********************************************************************
 * @fn      zclSampleLight_TimeRateHelper
 *
 * @brief   Calculate time based on rate, and startup level state machine
 *
 * @param   newLevel - new level for current level
 *
 * @return  diff (directly), zclSampleLight_CurrentLevel32 and zclSampleLight_NewLevel, zclSampleLight_NewLevelUp
 */
static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel )
{
  uint32 diff;
  uint32 newLevel32;

  // remember current and new level
  zclSampleLight_NewLevel = newLevel;
  zclSampleLight_CurrentLevel32 = (uint32)1000 * zclSampleLight_LevelCurrentLevel;

  // calculate diff
  newLevel32 = (uint32)1000 * newLevel;
  if ( zclSampleLight_LevelCurrentLevel > newLevel )
  {
    diff = zclSampleLight_CurrentLevel32 - newLevel32;
    zclSampleLight_NewLevelUp = FALSE;  // moving down
  }
  else
  {
    diff = newLevel32 - zclSampleLight_CurrentLevel32;
    zclSampleLight_NewLevelUp = TRUE;   // moving up
  }

  return ( diff );
}

/*********************************************************************
 * @fn      zclSampleLight_MoveBasedOnRate
 *
 * @brief   Calculate time based on rate, and startup level state machine
 *
 * @param   newLevel - new level for current level
 * @param   rate16   - fixed point rate (e.g. 16.123)
 *
 * @return  none
 */
static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate )
{
  uint32 diff;

  // determine how much time (in 10ths of seconds) based on the difference and rate
  zclSampleLight_Rate32 = rate;
  diff = zclSampleLight_TimeRateHelper( newLevel );
  zclSampleLight_LevelRemainingTime = diff / rate;
  if ( !zclSampleLight_LevelRemainingTime )
  {
    zclSampleLight_LevelRemainingTime = 1;
  }

  osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
}

/*********************************************************************
 * @fn      zclSampleLight_MoveBasedOnTime
 *
 * @brief   Calculate rate based on time, and startup level state machine
 *
 * @param   newLevel  - new level for current level
 * @param   time      - in 10ths of seconds
 *
 * @return  none
 */
static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time )
{
  uint16 diff;

  // determine rate (in units) based on difference and time
  diff = zclSampleLight_TimeRateHelper( newLevel );
  zclSampleLight_LevelRemainingTime = zclSampleLight_GetTime( newLevel, time );
  zclSampleLight_Rate32 = diff / time;

  osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
}

/*********************************************************************
 * @fn      zclSampleLight_GetTime
 *
 * @brief   Determine amount of time that MoveXXX will take to complete.
 *
 * @param   level = new level to move to
 *          time  = 0xffff=default, or 0x0000-n amount of time in tenths of seconds.
 *
 * @return  none
 */
static uint16 zclSampleLight_GetTime( uint8 level, uint16 time )
{
  // there is a hiearchy of the amount of time to use for transistioning
  // check each one in turn. If none of defaults are set, then use fastest
  // time possible.
  if ( time == 0xFFFF )
  {
    // use On or Off Transition Time if set (not 0xffff)
    if ( zclSampleLight_OnOff == LIGHT_ON )
    {
      time = zclSampleLight_LevelOffTransitionTime;
    }
    else
    {
      time = zclSampleLight_LevelOnTransitionTime;
    }

    // else use OnOffTransitionTime if set (not 0xffff)
    if ( time == 0xFFFF )
    {
      time = zclSampleLight_LevelOnOffTransitionTime;
    }

    // else as fast as possible
    if ( time == 0xFFFF )
    {
      time = 1;
    }
  }

  if ( !time )
  {
    time = 1; // as fast as possible
  }

  return ( time );
}

/*********************************************************************
 * @fn      zclSampleLight_DefaultMove
 *
 * @brief   We were turned on/off. Use default time to move to on or off.
 *
 * @param   zclSampleLight_OnOff - must be set prior to calling this function.
 *
 * @return  none
 */
static void zclSampleLight_DefaultMove( void )
{
  uint8  newLevel;
  uint32 rate;      // fixed point decimal (3 places, eg. 16.345)
  uint16 time;

  // if moving to on position, move to on level
  if ( zclSampleLight_OnOff )
  {
    if ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT )
    {
      // The last Level (before going OFF) should be used)
      newLevel = zclSampleLight_LevelLastLevel;
    }
    else
    {
      newLevel = zclSampleLight_LevelOnLevel;
    }

    time = zclSampleLight_LevelOnTransitionTime;
  }
  else
  {
    newLevel = ATTR_LEVEL_MIN_LEVEL;

    if ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT )
    {
      // Save the current Level before going OFF to use it when the light turns ON
      // it should be back to this level
      zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
    }

    time = zclSampleLight_LevelOffTransitionTime;
  }

  // else use OnOffTransitionTime if set (not 0xffff)
  if ( time == 0xFFFF )
  {
    time = zclSampleLight_LevelOnOffTransitionTime;
  }

  // else as fast as possible
  if ( time == 0xFFFF )
  {
    time = 1;
  }

  // calculate rate based on time (int 10ths) for full transition (1-254)
  rate = 255000 / time;    // units per tick, fixed point, 3 decimal places (e.g. 8500 = 8.5 units per tick)

  // start up state machine.
  zclSampleLight_WithOnOff = TRUE;
  zclSampleLight_MoveBasedOnRate( newLevel, rate );
}

/*********************************************************************
 * @fn      zclSampleLight_AdjustLightLevel
 *
 * @brief   Called each 10th of a second while state machine running
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_AdjustLightLevel( void )
{
  // one tick (10th of a second) less
  if ( zclSampleLight_LevelRemainingTime )
  {
    --zclSampleLight_LevelRemainingTime;
  }

  // no time left, done
  if ( zclSampleLight_LevelRemainingTime == 0)
  {
    zclSampleLight_LevelCurrentLevel = zclSampleLight_NewLevel;
  }

  // still time left, keep increment/decrementing
  else
  {
    if ( zclSampleLight_NewLevelUp )
    {
      zclSampleLight_CurrentLevel32 += zclSampleLight_Rate32;
    }
    else
    {
      zclSampleLight_CurrentLevel32 -= zclSampleLight_Rate32;
    }
    zclSampleLight_LevelCurrentLevel = (uint8)( zclSampleLight_CurrentLevel32 / 1000 );
  }

#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
  zclSampleLight_UpdateLampLevel(zclSampleLight_LevelCurrentLevel);
#endif

  // also affect on/off
  if ( zclSampleLight_WithOnOff )
  {
    if ( zclSampleLight_LevelCurrentLevel > ATTR_LEVEL_MIN_LEVEL )
    {
      zclSampleLight_OnOff = LIGHT_ON;
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
      ENABLE_LAMP;
#endif
    }
    else
    {
      zclSampleLight_OnOff = LIGHT_OFF;
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
      DISABLE_LAMP;
#endif
    }
  }

  // display light level as we go
  zclSampleLight_DisplayLight( );

  // keep ticking away
  if ( zclSampleLight_LevelRemainingTime )
  {
    osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
  }
}

/*********************************************************************
 * @fn      zclSampleLight_LevelControlMoveToLevelCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received a LevelControlMoveToLevel Command for this application.
 *
 * @param   pCmd - ZigBee command parameters
 *
 * @return  none
 */
static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd )
{
  zclSampleLight_WithOnOff = pCmd->withOnOff;
  zclSampleLight_MoveBasedOnTime( pCmd->level, pCmd->transitionTime );
  enable=1;
  osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 10000);
}

/*********************************************************************
 * @fn      zclSampleLight_LevelControlMoveCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received a LevelControlMove Command for this application.
 *
 * @param   pCmd - ZigBee command parameters
 *
 * @return  none
 */
static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd )
{
  uint8 newLevel;
  uint32 rate;

  // convert rate from units per second to units per tick (10ths of seconds)
  // and move at that right up or down
  zclSampleLight_WithOnOff = pCmd->withOnOff;

  if ( pCmd->moveMode == LEVEL_MOVE_UP )
  {
    newLevel = ATTR_LEVEL_MAX_LEVEL;  // fully on
  }
  else
  {
    newLevel = ATTR_LEVEL_MIN_LEVEL; // fully off
  }

  rate = (uint32)100 * pCmd->rate;
  zclSampleLight_MoveBasedOnRate( newLevel, rate );
}

/*********************************************************************
 * @fn      zclSampleLight_LevelControlStepCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an On/Off Command for this application.
 *
 * @param   pCmd - ZigBee command parameters
 *
 * @return  none
 */
static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd )
{
  uint8 newLevel;

  // determine new level, but don't exceed boundaries
  if ( pCmd->stepMode == LEVEL_MOVE_UP )
  {
    if ( (uint16)zclSampleLight_LevelCurrentLevel + pCmd->amount > ATTR_LEVEL_MAX_LEVEL )
    {
      newLevel = ATTR_LEVEL_MAX_LEVEL;
    }
    else
    {
      newLevel = zclSampleLight_LevelCurrentLevel + pCmd->amount;
    }
  }
  else
  {
    if ( pCmd->amount >= zclSampleLight_LevelCurrentLevel )
    {
      newLevel = ATTR_LEVEL_MIN_LEVEL;
    }
    else
    {
      newLevel = zclSampleLight_LevelCurrentLevel - pCmd->amount;
    }
  }

  // move to the new level
  zclSampleLight_WithOnOff = pCmd->withOnOff;
  zclSampleLight_MoveBasedOnTime( newLevel, pCmd->transitionTime );
}

/*********************************************************************
 * @fn      zclSampleLight_LevelControlStopCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an Level Control Stop Command for this application.
 *
 * @param   pCmd - ZigBee command parameters
 *
 * @return  none
 */
static void zclSampleLight_LevelControlStopCB( void )
{
  // stop immediately
  osal_stop_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT );
  zclSampleLight_LevelRemainingTime = 0;
  enable=0;
}
#endif

/******************************************************************************
 *
 *  Functions for processing ZCL Foundation incoming Command/Response messages
 *
 *****************************************************************************/

/*********************************************************************
 * @fn      zclSampleLight_ProcessIncomingMsg
 *
 * @brief   Process ZCL Foundation incoming message
 *
 * @param   pInMsg - pointer to the received message
 *
 * @return  none
 */
static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
{
  switch ( pInMsg->zclHdr.commandID )
  {
#ifdef ZCL_READ
    case ZCL_CMD_READ_RSP:
      zclSampleLight_ProcessInReadRspCmd( pInMsg );
      break;
#endif
#ifdef ZCL_WRITE
    case ZCL_CMD_WRITE_RSP:
      zclSampleLight_ProcessInWriteRspCmd( pInMsg );
      break;
#endif
#ifdef ZCL_REPORT
    // Attribute Reporting implementation should be added here
    case ZCL_CMD_CONFIG_REPORT:
      // zclSampleLight_ProcessInConfigReportCmd( pInMsg );
      break;

    case ZCL_CMD_CONFIG_REPORT_RSP:
      // zclSampleLight_ProcessInConfigReportRspCmd( pInMsg );
      break;

    case ZCL_CMD_READ_REPORT_CFG:
      // zclSampleLight_ProcessInReadReportCfgCmd( pInMsg );
      break;

    case ZCL_CMD_READ_REPORT_CFG_RSP:
      // zclSampleLight_ProcessInReadReportCfgRspCmd( pInMsg );
      break;

    case ZCL_CMD_REPORT:
      // zclSampleLight_ProcessInReportCmd( pInMsg );
      break;
#endif
    case ZCL_CMD_DEFAULT_RSP:
      zclSampleLight_ProcessInDefaultRspCmd( pInMsg );
      break;
#ifdef ZCL_DISCOVER
    case ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP:
      zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
      break;

    case ZCL_CMD_DISCOVER_CMDS_GEN_RSP:
      zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
      break;

    case ZCL_CMD_DISCOVER_ATTRS_RSP:
      zclSampleLight_ProcessInDiscAttrsRspCmd( pInMsg );
      break;

    case ZCL_CMD_DISCOVER_ATTRS_EXT_RSP:
      zclSampleLight_ProcessInDiscAttrsExtRspCmd( pInMsg );
      break;
#endif
    default:
      break;
  }

  if ( pInMsg->attrCmd )
    osal_mem_free( pInMsg->attrCmd );
}

#ifdef ZCL_READ
/*********************************************************************
 * @fn      zclSampleLight_ProcessInReadRspCmd
 *
 * @brief   Process the "Profile" Read Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg )
{
  zclReadRspCmd_t *readRspCmd;
  uint8 i;

  readRspCmd = (zclReadRspCmd_t *)pInMsg->attrCmd;
  for (i = 0; i < readRspCmd->numAttr; i++)
  {
    // Notify the originator of the results of the original read attributes
    // attempt and, for each successfull request, the value of the requested
    // attribute
  }

  return ( TRUE );
}
#endif // ZCL_READ

#ifdef ZCL_WRITE
/*********************************************************************
 * @fn      zclSampleLight_ProcessInWriteRspCmd
 *
 * @brief   Process the "Profile" Write Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg )
{
  zclWriteRspCmd_t *writeRspCmd;
  uint8 i;

  writeRspCmd = (zclWriteRspCmd_t *)pInMsg->attrCmd;
  for ( i = 0; i < writeRspCmd->numAttr; i++ )
  {
    // Notify the device of the results of the its original write attributes
    // command.
  }

  return ( TRUE );
}
#endif // ZCL_WRITE

/*********************************************************************
 * @fn      zclSampleLight_ProcessInDefaultRspCmd
 *
 * @brief   Process the "Profile" Default Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg )
{
  // zclDefaultRspCmd_t *defaultRspCmd = (zclDefaultRspCmd_t *)pInMsg->attrCmd;

  // Device is notified of the Default Response command.
  (void)pInMsg;

  return ( TRUE );
}

#ifdef ZCL_DISCOVER
/*********************************************************************
 * @fn      zclSampleLight_ProcessInDiscCmdsRspCmd
 *
 * @brief   Process the Discover Commands Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg )
{
  zclDiscoverCmdsCmdRsp_t *discoverRspCmd;
  uint8 i;

  discoverRspCmd = (zclDiscoverCmdsCmdRsp_t *)pInMsg->attrCmd;
  for ( i = 0; i < discoverRspCmd->numCmd; i++ )
  {
    // Device is notified of the result of its attribute discovery command.
  }

  return ( TRUE );
}

/*********************************************************************
 * @fn      zclSampleLight_ProcessInDiscAttrsRspCmd
 *
 * @brief   Process the "Profile" Discover Attributes Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg )
{
  zclDiscoverAttrsRspCmd_t *discoverRspCmd;
  uint8 i;

  discoverRspCmd = (zclDiscoverAttrsRspCmd_t *)pInMsg->attrCmd;
  for ( i = 0; i < discoverRspCmd->numAttr; i++ )
  {
    // Device is notified of the result of its attribute discovery command.
  }

  return ( TRUE );
}

/*********************************************************************
 * @fn      zclSampleLight_ProcessInDiscAttrsExtRspCmd
 *
 * @brief   Process the "Profile" Discover Attributes Extended Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg )
{
  zclDiscoverAttrsExtRsp_t *discoverRspCmd;
  uint8 i;

  discoverRspCmd = (zclDiscoverAttrsExtRsp_t *)pInMsg->attrCmd;
  for ( i = 0; i < discoverRspCmd->numAttr; i++ )
  {
    // Device is notified of the result of its attribute discovery command.
  }

  return ( TRUE );
}
#endif // ZCL_DISCOVER

#if ZCL_EZMODE
/*********************************************************************
 * @fn      zclSampleLight_ProcessZDOMsgs
 *
 * @brief   Called when this node receives a ZDO/ZDP response.
 *
 * @param   none
 *
 * @return  status
 */
static void zclSampleLight_ProcessZDOMsgs( zdoIncomingMsg_t *pMsg )
{
  zclEZMode_ActionData_t data;
  ZDO_MatchDescRsp_t *pMatchDescRsp;

  // Let EZ-Mode know of the Simple Descriptor Response
  if ( pMsg->clusterID == Match_Desc_rsp )
  {
    pMatchDescRsp = ZDO_ParseEPListRsp( pMsg );
    data.pMatchDescRsp = pMatchDescRsp;
    zcl_EZModeAction( EZMODE_ACTION_MATCH_DESC_RSP, &data );
    osal_mem_free( pMatchDescRsp );
  }
}

/*********************************************************************
 * @fn      zclSampleLight_EZModeCB
 *
 * @brief   The Application is informed of events. This can be used to show on the UI what is
*           going on during EZ-Mode steering/finding/binding.
 *
 * @param   state - an
 *
 * @return  none
 */
static void zclSampleLight_EZModeCB( zlcEZMode_State_t state, zclEZMode_CBData_t *pData )
{
#ifdef LCD_SUPPORTED
  char *pStr;
  uint8 err;
#endif

  // time to go into identify mode
  if ( state == EZMODE_STATE_IDENTIFYING )
  {
#ifdef LCD_SUPPORTED
    HalLcdWriteString( "EZMode", HAL_LCD_LINE_2 );
#endif

    zclSampleLight_IdentifyTime = ( EZMODE_TIME / 1000 );  // convert to seconds
    zclSampleLight_ProcessIdentifyTimeChange();
  }

  // autoclosing, show what happened (success, cancelled, etc...)
  if( state == EZMODE_STATE_AUTOCLOSE )
  {
#ifdef LCD_SUPPORTED
    pStr = NULL;
    err = pData->sAutoClose.err;
    if ( err == EZMODE_ERR_SUCCESS )
    {
      pStr = "EZMode: Success";
    }
    else if ( err == EZMODE_ERR_NOMATCH )
    {
      pStr = "EZMode: NoMatch"; // not a match made in heaven
    }
    if ( pStr )
    {
      if ( giLightScreenMode == LIGHT_MAINMODE )
      {
        HalLcdWriteString ( pStr, HAL_LCD_LINE_2 );
      }
    }
#endif
  }

  // finished, either show DstAddr/EP, or nothing (depending on success or not)
  if( state == EZMODE_STATE_FINISH )
  {
    // turn off identify mode
    zclSampleLight_IdentifyTime = 0;
    zclSampleLight_ProcessIdentifyTimeChange();

#ifdef LCD_SUPPORTED
    // if successful, inform user which nwkaddr/ep we bound to
    pStr = NULL;
    err = pData->sFinish.err;
    if( err == EZMODE_ERR_SUCCESS )
    {
      // already stated on autoclose
    }
    else if ( err == EZMODE_ERR_CANCELLED )
    {
      pStr = "EZMode: Cancel";
    }
    else if ( err == EZMODE_ERR_BAD_PARAMETER )
    {
      pStr = "EZMode: BadParm";
    }
    else if ( err == EZMODE_ERR_TIMEDOUT )
    {
      pStr = "EZMode: TimeOut";
    }
    if ( pStr )
    {
      if ( giLightScreenMode == LIGHT_MAINMODE )
      {
        HalLcdWriteString ( pStr, HAL_LCD_LINE_2 );
      }
    }
#endif
    // show main UI screen 3 seconds after binding
    osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_MAIN_SCREEN_EVT, 3000 );
  }
}
#endif // ZCL_EZMODE

/****************************************************************************
****************************************************************************/


  • For the application part, it's similar. You can merge your code into zcl_samplelight.c and also need to revise the hal_key.c/.h.
  • So now I've revised the hal_key.c. Below are my code revisions so far in Z-stack 3.0. However it keeps on giving me a linking error. Am I doing this wrong?

    0131.zcl_samplelight.h

    7573.zcl_samplelight.c
    /**************************************************************************************************
      Filename:       zcl_sampleLight.c
      Revised:        $Date: 2014-10-24 16:04:46 -0700 (Fri, 24 Oct 2014) $
      Revision:       $Revision: 40796 $
    
    
      Description:    Zigbee Cluster Library - sample light application.
    
    
      Copyright 2006-2014 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    /*********************************************************************
      This application implements a ZigBee Light, based on Z-Stack 3.0. It can be configured as an
      On/Off light or as a dimmable light, by undefining or defining ZCL_LEVEL_CTRL, respectively.
    
      This application is based on the common sample-application user interface. Please see the main
      comment in zcl_sampleapp_ui.c. The rest of this comment describes only the content specific for
      this sample applicetion.
      
      Application-specific UI peripherals being used:
    
      - LEDs:
        LED1 reflect the current light state (On / Off accordingly).
    
      Application-specific menu system:
    
        <TOGGLE LIGHT> Toggle the local light and display its status and level
          Press OK to toggle the local light on and off.
          This screen shows the following information
            Line1: (only populated if ZCL_LEVEL_CTRL is defined)
              LEVEL XXX - xxx is the current level of the light if the light state is ON, or the target level
                of the light when the light state is off. The target level is the level that the light will be
                set to when it is switched from off to on using the on or the toggle commands.
            Line2:
              LIGHT OFF / ON: shows the current state of the light.
          Note when ZCL_LEVEL_CTRL is enabled:
            - If the light state is ON and the light level is X, and then the light receives the OFF or TOGGLE 
              commands: The level will decrease gradually until it reaches 1, and only then the light state will
              be changed to OFF. The level then will be restored to X, with the state staying OFF. At this stage
              the light is not lighting, and the level represent the target level for the next ON or TOGGLE 
              commands.
            - If the light state is OFF and the light level is X, and then the light receives the ON or TOGGLE
              commands; The level will be set to 1, the light state will be set to ON, and then the level will
              increase gradually until it reaches level X.
            - Any level-setting command will affect the level directly, and may also affect the on/off state,
              depending on the command's arguments.       
    
    *********************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include "ZComDef.h"
    #include "OSAL.h"
    #include "AF.h"
    #include "ZDApp.h"
    #include "ZDObject.h"
    #include "MT_SYS.h"
    
    #include "nwk_util.h"
    
    #include "zcl.h"
    #include "zcl_general.h"
    #include "zcl_ha.h"
    #include "zcl_diagnostic.h"
    
    #include "zcl_samplelight.h"
       
    #include "bdb.h"
    #include "bdb_interface.h"
    
     //GP_UPDATE
    #include "gp_interface.h"
       
    #include "onboard.h"
    
    /* HAL */
    #include "hal_lcd.h"
    #include "hal_led.h"
    #include "hal_key.h"
    
    #include "NLMEDE.h"
    
    // Added to include TouchLink initiator functionality 
    #if defined ( BDB_TL_INITIATOR )
      #include "bdb_touchlink_initiator.h"
    #endif // BDB_TL_INITIATOR
    
    #if defined ( BDB_TL_TARGET )
      #include "bdb_touchlink_target.h"
    #endif // BDB_TL_TARGET
    
    #if defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET )
      #include "bdb_touchlink.h"
    #endif
    
    #include "zcl_sampleapps_ui.h"
    
    /*********************************************************************
     * MACROS
     */
    #define UI_STATE_TOGGLE_LIGHT 1 //UI_STATE_BACK_FROM_APP_MENU is item #0, so app item numbers should start from 1
    
    #define APP_TITLE "TI Sample Light"
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    uint8 zclSampleLightSeqNum;
    
    /*********************************************************************
     * GLOBAL FUNCTIONS
     */
    extern void TestingDecrypt(void);
    /*********************************************************************
     * LOCAL VARIABLES
     */
    afAddrType_t zclSampleLight_DstAddr;
    
    // Test Endpoint to allow SYS_APP_MSGs
    static endPointDesc_t sampleLight_TestEp =
    {
      SAMPLELIGHT_ENDPOINT,
      0,
      &zclSampleLight_TaskID,
      (SimpleDescriptionFormat_t *)NULL,  // No Simple description for this test endpoint
      (afNetworkLatencyReq_t)0            // No Network Latency req
    };
    
    #ifdef ZCL_LEVEL_CTRL
    uint8 zclSampleLight_WithOnOff;       // set to TRUE if state machine should set light on/off
    uint8 zclSampleLight_NewLevel;        // new level when done moving
    uint8 zclSampleLight_LevelChangeCmd; // current level change was triggered by an on/off command
    bool  zclSampleLight_NewLevelUp;      // is direction to new level up or down?
    int32 zclSampleLight_CurrentLevel32;  // current level, fixed point (e.g. 192.456)
    int32 zclSampleLight_Rate32;          // rate in units, fixed point (e.g. 16.123)
    uint8 zclSampleLight_LevelLastLevel;  // to save the Current Level before the light was turned OFF
    #endif
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static void zclSampleLight_HandleKeys( byte shift, byte keys );
    static void zclSampleLight_BasicResetCB( void );
    static void zclSampleLight_OnOffCB( uint8 cmd );
    //GP_UPDATE
    #if (ZG_BUILD_RTR_TYPE)
    static void gp_CommissioningMode(bool isEntering);
    static uint8 gp_ChangeChannelReq(void);
    #endif
    
    
    static void zclSampleLight_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg);
    
    
    #ifdef ZCL_LEVEL_CTRL
    static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd );
    static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd );
    static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd );
    static void zclSampleLight_LevelControlStopCB( void );
    static void zclSampleLight_DefaultMove( uint8 OnOff );
    static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel );
    static uint16 zclSampleLight_GetTime ( uint8 level, uint16 time );
    static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate );
    static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time );
    static void zclSampleLight_AdjustLightLevel( void );
    #endif
    
    // Functions to process ZCL Foundation incoming Command/Response messages
    static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *msg );
    #ifdef ZCL_READ
    static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    #ifdef ZCL_WRITE
    static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
    #ifdef ZCL_DISCOVER
    static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    
    void zclSampleLight_UiActionToggleLight(uint16 keys);
    void zclSampleLight_UiUpdateLcd(uint8 uiCurrentState, char * line[3]);
    void zclSampleLight_UpdateLedState(void);
    
    /*********************************************************************
     * CONSTANTS
     */
    const uiState_t zclSampleLight_UiStatesMain[] = 
    {
      /*  UI_STATE_BACK_FROM_APP_MENU  */   {UI_STATE_DEFAULT_MOVE,       UI_STATE_TOGGLE_LIGHT,  UI_KEY_SW_5_PRESSED, &UI_ActionBackFromAppMenu}, //do not change this line, except for the second item, which should point to the last entry in this menu
      /*  UI_STATE_TOGGLE_LIGHT        */   {UI_STATE_BACK_FROM_APP_MENU, UI_STATE_DEFAULT_MOVE,  UI_KEY_SW_5_PRESSED, &zclSampleLight_UiActionToggleLight},
    };
    
    #define LEVEL_CHANGED_BY_LEVEL_CMD  0
    #define LEVEL_CHANGED_BY_ON_CMD     1
    #define LEVEL_CHANGED_BY_OFF_CMD    2
    
    /*********************************************************************
     * STATUS STRINGS
     */
    #ifdef LCD_SUPPORTED
      const char sLightOn[]      = "   LIGHT ON     ";
      const char sLightOff[]     = "   LIGHT OFF    ";
      #ifdef ZCL_LEVEL_CTRL
        char sLightLevel[]        = "   LEVEL ###    "; // displays level 1-254
      #endif
    #endif
    
    /*********************************************************************
     * REFERENCED EXTERNALS
     */
    extern int16 zdpExternalStateTaskID;
    
    /*********************************************************************
     * ZCL General Profile Callback table
     */
    static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks =
    {
      zclSampleLight_BasicResetCB,            // Basic Cluster Reset command
      NULL,                                   // Identify Trigger Effect command
      zclSampleLight_OnOffCB,                 // On/Off cluster commands
      NULL,                                   // On/Off cluster enhanced command Off with Effect
      NULL,                                   // On/Off cluster enhanced command On with Recall Global Scene
      NULL,                                   // On/Off cluster enhanced command On with Timed Off
    #ifdef ZCL_LEVEL_CTRL
      zclSampleLight_LevelControlMoveToLevelCB, // Level Control Move to Level command
      zclSampleLight_LevelControlMoveCB,        // Level Control Move command
      zclSampleLight_LevelControlStepCB,        // Level Control Step command
      zclSampleLight_LevelControlStopCB,        // Level Control Stop command
    #endif
    #ifdef ZCL_GROUPS
      NULL,                                   // Group Response commands
    #endif
    #ifdef ZCL_SCENES
      NULL,                                  // Scene Store Request command
      NULL,                                  // Scene Recall Request command
      NULL,                                  // Scene Response command
    #endif
    #ifdef ZCL_ALARMS
      NULL,                                  // Alarm (Response) commands
    #endif
    #ifdef SE_UK_EXT
      NULL,                                  // Get Event Log command
      NULL,                                  // Publish Event Log command
    #endif
      NULL,                                  // RSSI Location command
      NULL                                   // RSSI Location Response command
    };
    
    /*********************************************************************
     * @fn          zclSampleLight_Init
     *
     * @brief       Initialization function for the zclGeneral layer.
     *
     * @param       none
     *
     * @return      none
     */
    #include <hal_adc.h>
    #include <OSAL_PwrMgr.h>
    
    
    
    
    
    
    
    
    
    void zclSampleLight_Init( byte task_id )
    {
      zclSampleLight_TaskID = task_id;
      
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10 );
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 10 );  
      osal_start_timerEx( zclSampleLight_TaskID, offline, 10 );
    
      // Set destination address to indirect
      zclSampleLight_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
      zclSampleLight_DstAddr.endPoint = 0;
      zclSampleLight_DstAddr.addr.shortAddr = 0;
    
      // Register the Simple Descriptor for this application
      bdb_RegisterSimpleDescriptor( &zclSampleLight_SimpleDesc );
    
      // Register the ZCL General Cluster Library callback functions
      zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );
    
      // Register the application's attribute list
      zclSampleLight_ResetAttributesToDefaultValues();
      zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, zclSampleLight_NumAttributes, zclSampleLight_Attrs );
    
    #ifdef ZCL_LEVEL_CTRL
      zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
    #endif
    
      // Register the Application to receive the unprocessed Foundation command/response messages
      zcl_registerForMsg( zclSampleLight_TaskID );
    
    #ifdef ZCL_DISCOVER
      // Register the application's command list
      zcl_registerCmdList( SAMPLELIGHT_ENDPOINT, zclCmdsArraySize, zclSampleLight_Cmds );
    #endif
    
      // Register for all key events - This app will handle all key events
      RegisterForKeys( zclSampleLight_TaskID );
      
      bdb_RegisterCommissioningStatusCB( zclSampleLight_ProcessCommissioningStatus );
      
      // Register for a test endpoint
      afRegister( &sampleLight_TestEp );
    
    #ifdef ZCL_DIAGNOSTIC
      // Register the application's callback function to read/write attribute data.
      // This is only required when the attribute data format is unknown to ZCL.
      zcl_registerReadWriteCB( SAMPLELIGHT_ENDPOINT, zclDiagnostic_ReadWriteAttrCB, NULL );
    
      if ( zclDiagnostic_InitStats() == ZSuccess )
      {
        // Here the user could start the timer to save Diagnostics to NV
      }
    #endif
      
    //GP_UPDATE  
    #if (ZG_BUILD_RTR_TYPE)  
      gp_RegisterCommissioningModeCB(gp_CommissioningMode);
      gp_RegisterGPChangeChannelReqCB(gp_ChangeChannelReq);
    #endif
      
      zdpExternalStateTaskID = zclSampleLight_TaskID;
    
      UI_Init(zclSampleLight_TaskID, SAMPLEAPP_LCD_AUTO_UPDATE_EVT, SAMPLEAPP_KEY_AUTO_REPEAT_EVT, &zclSampleLight_IdentifyTime, APP_TITLE, &zclSampleLight_UiUpdateLcd, zclSampleLight_UiStatesMain);
    
      UI_UpdateLcd();
      
      osal_nv_item_init(nv_test_id, 1, &direction);
      osal_nv_read(nv_test_id, 0, 1, &direction);
      
      P0SEL &= (~((BV(5))|(BV(6))));
      P0DIR |= ((BV(5))|(BV(6)));  
      P1DIR |= 0x01;
      pin=0;
      
      if(direction==0){
        enable = 1;
        phase = 0;  
      }
      else if(direction==1){
        enable = 1;
        phase = 1;
      }
      osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
    }
    
    /*********************************************************************
     * @fn          zclSample_event_loop
     *
     * @brief       Event Loop Processor for zclGeneral.
     *
     * @param       none
     *
     * @return      none
     */
    uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
    {
      if(DEV_NWK_BACKOFF){
        pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY;
        if(devState==DEV_NWK_BACKOFF){
          scan=1;
        }
      }
      
      if(disconnect==1 & (devState==DEV_NWK_DISC || devState==DEV_NWK_BACKOFF)){
        disconnect=0;
        osal_start_timerEx( zclSampleLight_TaskID, offline, 30000 );
      }
      
      if( events & offline )
      {
        ZDApp_SetRejoinBackoffDuration(86400000);
        ZDApp_SetRejoinScanDuration(10000);
        return (events ^ offline);
      }
      
      if( events & TURNOFF_MOTOR_EVT )
      {
        enable = 0;
        if(start==1){
          phase=0;
          start=0;
        }
        else if(zclSampleLight_OnOff==LIGHT_ON){
          phase = 1;
        }
        else if(zclSampleLight_OnOff==LIGHT_OFF){
          phase = 0;
        }
        return (events ^ TURNOFF_MOTOR_EVT);
      }
      
      if ( events & KEYHOLD_EVT)
      {
        if ( P2_0==1 )
        {
          if (KeyPressCnt>40){
            //uiActionResetToFactoryNew(keys);
            
            pin=1;
            for(int i=0; i<500; i++){
              Onboard_wait(10000);
            }
            
            SystemReset();
          }    
          else{     
            KeyPressCnt++;
            osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
          }
        }
        return ( events ^ KEYHOLD_EVT );
      }
      
      if( events & PERIODIC_EVT4 ){
        osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
        
        if(b==1){
          pin=1;
          b=0;
          osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 25 );
        }
        else if(b==0){
          pin=0;
          b=1;
          osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 2000 );
        }
        return (events ^ PERIODIC_EVT4);
      }
      
      if( events & PERIODIC_EVT )
      {
        HalAdcSetReference(HAL_ADC_REF_125V);
        adc_ain2=HalAdcRead(HAL_ADC_CHN_AIN7,HAL_ADC_RESOLUTION_10);
    
        if(adc_ain2<=155){           //155=2.6v   //177=3v   //188=3.3v  //160=2.5v
          osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 25 );
        }
        else if(adc_ain2>155){
          pin=0;
          osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
        }
    
        osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10000 );
        return (events ^ PERIODIC_EVT);
      }
      
      afIncomingMSGPacket_t *MSGpkt;
    
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclSampleLight_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case ZCL_INCOMING_MSG:
              // Incoming ZCL Foundation command/response messages
              zclSampleLight_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
              break;
    
            case KEY_CHANGE:
              zclSampleLight_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    
            case ZDO_STATE_CHANGE:
              UI_DeviceStateUpdated((devStates_t)(MSGpkt->hdr.status));
              
              //if ( zclSampleLight_NwkState == DEV_END_DEVICE )
              //{
                disconnect = 1;            
                ZDApp_SetRejoinBackoffDuration(5000);
                ZDApp_SetRejoinScanDuration(10000);
              //}
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
        }
    
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }
    
    #ifdef ZCL_LEVEL_CTRL
      if ( events & SAMPLELIGHT_LEVEL_CTRL_EVT )
      {
        zclSampleLight_AdjustLightLevel();
        return ( events ^ SAMPLELIGHT_LEVEL_CTRL_EVT );
      }
    #endif
    
    #if ZG_BUILD_ENDDEVICE_TYPE    
      if ( events & SAMPLEAPP_END_DEVICE_REJOIN_EVT )
      {
        bdb_ZedAttemptRecoverNwk();
        return ( events ^ SAMPLEAPP_END_DEVICE_REJOIN_EVT );
      }
    #endif
    
      if ( events & SAMPLEAPP_LCD_AUTO_UPDATE_EVT )
      {
        UI_UpdateLcd();
        return ( events ^ SAMPLEAPP_LCD_AUTO_UPDATE_EVT );
      }
    
      if ( events & SAMPLEAPP_KEY_AUTO_REPEAT_EVT )
      {
        UI_MainStateMachine(UI_KEY_AUTO_PRESSED);
        return ( events ^ SAMPLEAPP_KEY_AUTO_REPEAT_EVT );
      }
    
      // Discard unknown events
      return 0;
    }
    
    
    /*********************************************************************
     * @fn      zclSampleLight_HandleKeys
     *
     * @brief   Handles all key events for this device.
     *
     * @param   shift - true if in shift/alt.
     * @param   keys - bit field for key events. Valid entries:
     *                 HAL_KEY_SW_5
     *                 HAL_KEY_SW_4
     *                 HAL_KEY_SW_2
     *                 HAL_KEY_SW_1
     *
     * @return  none
     */
    static void zclSampleLight_HandleKeys( byte shift, byte keys )
    {
      UI_MainStateMachine(keys);
    }
    
    //GP_UPDATE
    #if (ZG_BUILD_RTR_TYPE)
    /*********************************************************************
     * @fn      gp_CommissioningMode
     *
     * @brief   Callback that notifies the application that gp Proxy is entering 
     *          into commissioning mode
     *
     * @param   isEntering - 
     *
     * @return  
     */
    static void gp_CommissioningMode(bool isEntering)
    {
      if(isEntering)
      {
        //Led on indicating enter commissioning mode
      }
      else
      {
        //Led off indicating enter commissioning mode
      }
    }
    
    
    
    //GP_UPDATE
    /*********************************************************************
     * @fn      gp_ChangeChannelReq
     *
     * @brief   Callback function to notify the application about a GP commissioning 
     * request that will change the current channel for at most 
     * gpBirectionalCommissioningChangeChannelTimeout ms
     *
     * @param   channel - Channel in which the commissioning will take place
     *
     * @return  TRUE to allow change channel, FALSE to do not allow
     */
    static uint8 gp_ChangeChannelReq(void)
    {
      bool allowChangeChannel = TRUE;
      
      //Check application state to decide if allow change channel or not
      
      return allowChangeChannel;
    }
    
    #endif
    
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessCommissioningStatus
     *
     * @brief   Callback in which the status of the commissioning process are reported
     *
     * @param   bdbCommissioningModeMsg - Context message of the status of a commissioning process
     *
     * @return  none
     */
    static void zclSampleLight_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg)
    {
      switch(bdbCommissioningModeMsg->bdbCommissioningMode)
      {
        case BDB_COMMISSIONING_FORMATION:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
          {
            //After formation, perform nwk steering again plus the remaining commissioning modes that has not been process yet
            bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING | bdbCommissioningModeMsg->bdbRemainingCommissioningModes);
          }
          else
          {
            //Want to try other channels?
            //try with bdb_setChannelAttribute
          }
        break;
        case BDB_COMMISSIONING_NWK_STEERING:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
          {
            //YOUR JOB:
            //We are on the nwk, what now?
          }
          else
          {
            //See the possible errors for nwk steering procedure
            //No suitable networks found
            //Want to try other channels?
            //try with bdb_setChannelAttribute
          }
        break;
        case BDB_COMMISSIONING_FINDING_BINDING:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
          {
            //YOUR JOB:
          }
          else
          {
            //YOUR JOB:
            //retry?, wait for user interaction?
          }
        break;
        case BDB_COMMISSIONING_INITIALIZATION:
          //Initialization notification can only be successful. Failure on initialization 
          //only happens for ZED and is notified as BDB_COMMISSIONING_PARENT_LOST notification
          
          //YOUR JOB:
          //We are on a network, what now?
          
        break;
    #if ZG_BUILD_ENDDEVICE_TYPE    
        case BDB_COMMISSIONING_PARENT_LOST:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_NETWORK_RESTORED)
          {
            //We did recover from losing parent
          }
          else
          {
            //Parent not found, attempt to rejoin again after a fixed delay
            osal_start_timerEx(zclSampleLight_TaskID, SAMPLEAPP_END_DEVICE_REJOIN_EVT, SAMPLEAPP_END_DEVICE_REJOIN_DELAY);
          }
        break;
    #endif 
      }
      
      UI_UpdateComissioningStatus(bdbCommissioningModeMsg);
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_BasicResetCB
     *
     * @brief   Callback from the ZCL General Cluster Library
     *          to set all the Basic Cluster attributes to default values.
     *
     * @param   none
     *
     * @return  none
     */
    static void zclSampleLight_BasicResetCB( void )
    {
      //Reset every attribute in all supported cluster to their default value.
    
      zclSampleLight_ResetAttributesToDefaultValues();
    
      zclSampleLight_UpdateLedState();
    
      // update the display
      UI_UpdateLcd( ); 
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_OnOffCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an On/Off Command for this application.
     *
     * @param   cmd - COMMAND_ON, COMMAND_OFF or COMMAND_TOGGLE
     *
     * @return  none
     */
    static void zclSampleLight_OnOffCB( uint8 cmd )
    {
      afIncomingMSGPacket_t *pPtr = zcl_getRawAFMsg();
    
      uint8 OnOff;
    
      zclSampleLight_DstAddr.addr.shortAddr = pPtr->srcAddr.addr.shortAddr;
    
    
      // Turn on the light
      if ( cmd == COMMAND_ON )
      {
        OnOff = LIGHT_ON;
      }
      // Turn off the light
      else if ( cmd == COMMAND_OFF )
      {
        OnOff = LIGHT_OFF;
      }
      // Toggle the light
      else if ( cmd == COMMAND_TOGGLE )
      {
    #ifdef ZCL_LEVEL_CTRL
        if (zclSampleLight_LevelRemainingTime > 0) 
        {
          if (zclSampleLight_NewLevelUp)
          {
            OnOff = LIGHT_OFF;
          }
          else
          {
            OnOff = LIGHT_ON;
          }
        }
        else
        {
          if (zclSampleLight_OnOff == LIGHT_ON)
          {
            OnOff = LIGHT_OFF;
          }
          else
          {
            OnOff = LIGHT_ON;
          }
        }
    #else
        if (zclSampleLight_OnOff == LIGHT_ON)
        {
          OnOff = LIGHT_OFF;
        }
        else
        {
          OnOff = LIGHT_ON;
        }
    #endif
      }
    
    #ifdef ZCL_LEVEL_CTRL
      zclSampleLight_LevelChangeCmd = (OnOff == LIGHT_ON ? LEVEL_CHANGED_BY_ON_CMD : LEVEL_CHANGED_BY_OFF_CMD);
    
      zclSampleLight_DefaultMove(OnOff);
    #else
      zclSampleLight_OnOff = OnOff;
    #endif
    
      zclSampleLight_UpdateLedState();
      
      // update the display
      UI_UpdateLcd( );
    }
    
    #ifdef ZCL_LEVEL_CTRL
    /*********************************************************************
     * @fn      zclSampleLight_TimeRateHelper
     *
     * @brief   Calculate time based on rate, and startup level state machine
     *
     * @param   newLevel - new level for current level
     *
     * @return  diff (directly), zclSampleLight_CurrentLevel32 and zclSampleLight_NewLevel, zclSampleLight_NewLevelUp
     */
    static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel )
    {
      uint32 diff;
      uint32 newLevel32;
    
      // remember current and new level
      zclSampleLight_NewLevel = newLevel;
      zclSampleLight_CurrentLevel32 = (uint32)1000 * zclSampleLight_LevelCurrentLevel;
    
      // calculate diff
      newLevel32 = (uint32)1000 * newLevel;
      if ( zclSampleLight_LevelCurrentLevel > newLevel )
      {
        diff = zclSampleLight_CurrentLevel32 - newLevel32;
        zclSampleLight_NewLevelUp = FALSE;  // moving down
      }
      else
      {
        diff = newLevel32 - zclSampleLight_CurrentLevel32;
        zclSampleLight_NewLevelUp = TRUE;   // moving up
      }
    
      return ( diff );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_MoveBasedOnRate
     *
     * @brief   Calculate time based on rate, and startup level state machine
     *
     * @param   newLevel - new level for current level
     * @param   rate16   - fixed point rate (e.g. 16.123)
     *
     * @return  none
     */
    static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate )
    {
      uint32 diff;
    
      // determine how much time (in 10ths of seconds) based on the difference and rate
      zclSampleLight_Rate32 = rate;
      diff = zclSampleLight_TimeRateHelper( newLevel );
      zclSampleLight_LevelRemainingTime = diff / rate;
      if ( !zclSampleLight_LevelRemainingTime )
      {
        zclSampleLight_LevelRemainingTime = 1;
      }
    
      osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_MoveBasedOnTime
     *
     * @brief   Calculate rate based on time, and startup level state machine
     *
     * @param   newLevel  - new level for current level
     * @param   time      - in 10ths of seconds
     *
     * @return  none
     */
    static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time )
    {
      uint16 diff;
    
      // determine rate (in units) based on difference and time
      diff = zclSampleLight_TimeRateHelper( newLevel );
      zclSampleLight_LevelRemainingTime = zclSampleLight_GetTime( newLevel, time );
      zclSampleLight_Rate32 = diff / time;
    
      osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_GetTime
     *
     * @brief   Determine amount of time that MoveXXX will take to complete.
     *
     * @param   level = new level to move to
     *          time  = 0xffff=default, or 0x0000-n amount of time in tenths of seconds.
     *
     * @return  none
     */
    static uint16 zclSampleLight_GetTime( uint8 newLevel, uint16 time )
    {
      // there is a hiearchy of the amount of time to use for transistioning
      // check each one in turn. If none of defaults are set, then use fastest
      // time possible.
      if ( time == 0xFFFF )
      {
        // use On or Off Transition Time if set (not 0xffff)
        if ( zclSampleLight_LevelCurrentLevel > newLevel )
        {
          time = zclSampleLight_LevelOffTransitionTime;
        }
        else
        {
          time = zclSampleLight_LevelOnTransitionTime;
        }
    
        // else use OnOffTransitionTime if set (not 0xffff)
        if ( time == 0xFFFF )
        {
          time = zclSampleLight_LevelOnOffTransitionTime;
        }
    
        // else as fast as possible
        if ( time == 0xFFFF )
        {
          time = 1;
        }
      }
    
      if ( time == 0 )
      {
        time = 1; // as fast as possible
      }
    
      return ( time );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_DefaultMove
     *
     * @brief   We were turned on/off. Use default time to move to on or off.
     *
     * @param   zclSampleLight_OnOff - must be set prior to calling this function.
     *
     * @return  none
     */
    static void zclSampleLight_DefaultMove( uint8 OnOff )
    {
      uint8  newLevel;
      uint32 rate;      // fixed point decimal (3 places, eg. 16.345)
      uint16 time;
    
      // if moving to on position, move to on level
      if ( OnOff )
      {
        if (zclSampleLight_OnOff == LIGHT_OFF)
        {
          zclSampleLight_LevelCurrentLevel = ATTR_LEVEL_MIN_LEVEL;
        }
        
        if ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT )
        {
          // The last Level (before going OFF) should be used)
          newLevel = zclSampleLight_LevelLastLevel;
        }
        else
        {
          newLevel = zclSampleLight_LevelOnLevel;
        }
    
        time = zclSampleLight_LevelOnTransitionTime;
    
      }
      else
      {
        newLevel = ATTR_LEVEL_MIN_LEVEL;
    
        time = zclSampleLight_LevelOffTransitionTime;
      }
    
      // else use OnOffTransitionTime if set (not 0xffff)
      if ( time == 0xFFFF )
      {
        time = zclSampleLight_LevelOnOffTransitionTime;
      }
    
      // else as fast as possible
      if ( time == 0xFFFF )
      {
        time = 1;
      }
    
      // calculate rate based on time (int 10ths) for full transition (1-254)
      rate = 255000 / time;    // units per tick, fixed point, 3 decimal places (e.g. 8500 = 8.5 units per tick)
    
      // start up state machine.
      zclSampleLight_WithOnOff = TRUE;
      zclSampleLight_MoveBasedOnRate( newLevel, rate );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_AdjustLightLevel
     *
     * @brief   Called each 10th of a second while state machine running
     *
     * @param   none
     *
     * @return  none
     */
    static void zclSampleLight_AdjustLightLevel( void )
    {
      // one tick (10th of a second) less
      if ( zclSampleLight_LevelRemainingTime )
      {
        --zclSampleLight_LevelRemainingTime;
      }
    
      // no time left, done
      if ( zclSampleLight_LevelRemainingTime == 0)
      {
        zclSampleLight_LevelCurrentLevel = zclSampleLight_NewLevel;
      }
    
      // still time left, keep increment/decrementing
      else
      {
        if ( zclSampleLight_NewLevelUp )
        {
          zclSampleLight_CurrentLevel32 += zclSampleLight_Rate32;
        }
        else
        {
          zclSampleLight_CurrentLevel32 -= zclSampleLight_Rate32;
        }
        zclSampleLight_LevelCurrentLevel = (uint8)( zclSampleLight_CurrentLevel32 / 1000 );
      }
    
      if (( zclSampleLight_LevelChangeCmd == LEVEL_CHANGED_BY_LEVEL_CMD ) && ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT ))
      {
        zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
      }
    
      // also affect on/off
      if ( zclSampleLight_WithOnOff )
      {
        if ( zclSampleLight_LevelCurrentLevel > ATTR_LEVEL_MIN_LEVEL )
        {
          zclSampleLight_OnOff = LIGHT_ON;
        }
        else
        {
          if (zclSampleLight_LevelChangeCmd != LEVEL_CHANGED_BY_ON_CMD)
          {
            zclSampleLight_OnOff = LIGHT_OFF;
          }
          else
          {
            zclSampleLight_OnOff = LIGHT_ON;
          }
          
          if (( zclSampleLight_LevelChangeCmd != LEVEL_CHANGED_BY_LEVEL_CMD ) && ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT ))
          {
            zclSampleLight_LevelCurrentLevel = zclSampleLight_LevelLastLevel;
          }
        }
      }
    
      zclSampleLight_UpdateLedState();
      
      // display light level as we go
      UI_UpdateLcd( );
    
      // keep ticking away
      if ( zclSampleLight_LevelRemainingTime )
      {
        osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
      }
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlMoveToLevelCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received a LevelControlMoveToLevel Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd )
    {
      zclSampleLight_LevelChangeCmd = LEVEL_CHANGED_BY_LEVEL_CMD;
    
      zclSampleLight_WithOnOff = pCmd->withOnOff;
      zclSampleLight_MoveBasedOnTime( pCmd->level, pCmd->transitionTime );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlMoveCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received a LevelControlMove Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd )
    {
      uint8 newLevel;
      uint32 rate;
    
      // convert rate from units per second to units per tick (10ths of seconds)
      // and move at that right up or down
      zclSampleLight_WithOnOff = pCmd->withOnOff;
    
      if ( pCmd->moveMode == LEVEL_MOVE_UP )
      {
        newLevel = ATTR_LEVEL_MAX_LEVEL;  // fully on
      }
      else
      {
        newLevel = ATTR_LEVEL_MIN_LEVEL; // fully off
      }
    
      zclSampleLight_LevelChangeCmd = LEVEL_CHANGED_BY_LEVEL_CMD;
    
      rate = (uint32)100 * pCmd->rate;
      zclSampleLight_MoveBasedOnRate( newLevel, rate );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlStepCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an On/Off Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd )
    {
      uint8 newLevel;
    
      // determine new level, but don't exceed boundaries
      if ( pCmd->stepMode == LEVEL_MOVE_UP )
      {
        if ( (uint16)zclSampleLight_LevelCurrentLevel + pCmd->amount > ATTR_LEVEL_MAX_LEVEL )
        {
          newLevel = ATTR_LEVEL_MAX_LEVEL;
        }
        else
        {
          newLevel = zclSampleLight_LevelCurrentLevel + pCmd->amount;
        }
      }
      else
      {
        if ( pCmd->amount >= zclSampleLight_LevelCurrentLevel )
        {
          newLevel = ATTR_LEVEL_MIN_LEVEL;
        }
        else
        {
          newLevel = zclSampleLight_LevelCurrentLevel - pCmd->amount;
        }
      }
      
      zclSampleLight_LevelChangeCmd = LEVEL_CHANGED_BY_LEVEL_CMD;
    
      // move to the new level
      zclSampleLight_WithOnOff = pCmd->withOnOff;
      zclSampleLight_MoveBasedOnTime( newLevel, pCmd->transitionTime );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlStopCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an Level Control Stop Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlStopCB( void )
    {
      // stop immediately
      osal_stop_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT );
      zclSampleLight_LevelRemainingTime = 0;
    }
    #endif
    
    /******************************************************************************
     *
     *  Functions for processing ZCL Foundation incoming Command/Response messages
     *
     *****************************************************************************/
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessIncomingMsg
     *
     * @brief   Process ZCL Foundation incoming message
     *
     * @param   pInMsg - pointer to the received message
     *
     * @return  none
     */
    static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
    {
      switch ( pInMsg->zclHdr.commandID )
      {
    #ifdef ZCL_READ
        case ZCL_CMD_READ_RSP:
          zclSampleLight_ProcessInReadRspCmd( pInMsg );
          break;
    #endif
    #ifdef ZCL_WRITE
        case ZCL_CMD_WRITE_RSP:
          zclSampleLight_ProcessInWriteRspCmd( pInMsg );
          break;
    #endif
        case ZCL_CMD_CONFIG_REPORT:
        case ZCL_CMD_CONFIG_REPORT_RSP:
        case ZCL_CMD_READ_REPORT_CFG:
        case ZCL_CMD_READ_REPORT_CFG_RSP:
        case ZCL_CMD_REPORT:
          //bdb_ProcessIncomingReportingMsg( pInMsg );
          break;
    
        case ZCL_CMD_DEFAULT_RSP:
          zclSampleLight_ProcessInDefaultRspCmd( pInMsg );
          break;
    #ifdef ZCL_DISCOVER
        case ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP:
          zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_CMDS_GEN_RSP:
          zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_RSP:
          zclSampleLight_ProcessInDiscAttrsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_EXT_RSP:
          zclSampleLight_ProcessInDiscAttrsExtRspCmd( pInMsg );
          break;
    #endif
        default:
          break;
      }
    
      if ( pInMsg->attrCmd )
        osal_mem_free( pInMsg->attrCmd );
    }
    
    #ifdef ZCL_READ
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInReadRspCmd
     *
     * @brief   Process the "Profile" Read Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclReadRspCmd_t *readRspCmd;
      uint8 i;
    
      readRspCmd = (zclReadRspCmd_t *)pInMsg->attrCmd;
      for (i = 0; i < readRspCmd->numAttr; i++)
      {
        // Notify the originator of the results of the original read attributes
        // attempt and, for each successfull request, the value of the requested
        // attribute
      }
    
      return ( TRUE );
    }
    #endif // ZCL_READ
    
    #ifdef ZCL_WRITE
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInWriteRspCmd
     *
     * @brief   Process the "Profile" Write Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclWriteRspCmd_t *writeRspCmd;
      uint8 i;
    
      writeRspCmd = (zclWriteRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < writeRspCmd->numAttr; i++ )
      {
        // Notify the device of the results of the its original write attributes
        // command.
      }
    
      return ( TRUE );
    }
    #endif // ZCL_WRITE
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDefaultRspCmd
     *
     * @brief   Process the "Profile" Default Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg )
    {
      // zclDefaultRspCmd_t *defaultRspCmd = (zclDefaultRspCmd_t *)pInMsg->attrCmd;
    
      // Device is notified of the Default Response command.
      (void)pInMsg;
    
      return ( TRUE );
    }
    
    #ifdef ZCL_DISCOVER
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDiscCmdsRspCmd
     *
     * @brief   Process the Discover Commands Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverCmdsCmdRsp_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverCmdsCmdRsp_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numCmd; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDiscAttrsRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverAttrsRspCmd_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverAttrsRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numAttr; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDiscAttrsExtRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Extended Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverAttrsExtRsp_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverAttrsExtRsp_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numAttr; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    #endif // ZCL_DISCOVER
    
    void zclSampleLight_UiActionToggleLight(uint16 keys)
    {
      zclSampleLight_OnOffCB(COMMAND_TOGGLE);
    }
    
    void zclSampleLight_UpdateLedState(void)
    {
      // set the LED1 based on light (on or off)
      if ( zclSampleLight_OnOff == LIGHT_ON )
      {
        HalLedSet ( UI_LED_APP, HAL_LED_MODE_ON );
      }
      else
      {
        HalLedSet ( UI_LED_APP, HAL_LED_MODE_OFF );
      }
    }
    
    void zclSampleLight_UiUpdateLcd(uint8 UiState, char * line[3])
    {
    #ifdef LCD_SUPPORTED
    #ifdef ZCL_LEVEL_CTRL
      zclHA_uint8toa( zclSampleLight_LevelCurrentLevel, &sLightLevel[9] );
      line[0] = (char *)sLightLevel;
    #endif // ZCL_LEVEL_CTRL
      line[1] = (char *)(zclSampleLight_OnOff ? sLightOn : sLightOff);
      line[2] = "< TOGGLE LIGHT >";
    #endif
    }
    
    /****************************************************************************
    ****************************************************************************/
    
    
    

    zcl_sampleapps_ui.c

  • What link error do you see?
  • I get the below error.

  • If you use KeyPressCnt in OSAL_SampleLight.c, you should extern KeyPressCnt in your OSAL_SampleLight.c.
  • I am confused. How exactly do I do that?
  • Where and how do you claim KeyPressCnt?
  • In zcl_samplelight.h as an integer value.

  • Can you attach your OSAL_SampleLight.c?
  • Here it is.

    OSAL_samplelight.c
    /**************************************************************************************************
      Filename:       OSAL_SampleLight.c
      Revised:        $Date: 2008-02-07 12:10:00 -0800 (Thu, 07 Feb 2008) $
      Revision:       $Revision: 16360 $
    
      Description:    This file contains all the settings and other functions
                      that the user should set and change.
    
    
      Copyright 2006-2007 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    
    #include "ZComDef.h"
    #include "hal_drivers.h"
    #include "OSAL.h"
    #include "OSAL_Tasks.h"
    
    #if defined ( MT_TASK )
      #include "MT.h"
      #include "MT_TASK.h"
    #endif
    
    #include "nwk.h"
    #include "APS.h"
    #include "ZDApp.h"
    
    #include "bdb_interface.h"
    #if (ZG_BUILD_RTR_TYPE)
      #include "gp_common.h"
    #endif
    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
      #include "ZDNwkMgr.h"
    #endif
    #if defined ( ZIGBEE_FRAGMENTATION )
      #include "aps_frag.h"
    #endif
    
    #if defined ( INTER_PAN )
      #include "stub_aps.h"
    #if defined ( BDB_TL_INITIATOR )
      #include "bdb_touchlink_initiator.h"
    #endif // BDB_TL_INITIATOR
    #if defined ( BDB_TL_TARGET )
      #include "bdb_touchlink_target.h"
    #endif // BDB_TL_TARGET
    #endif // INTER_PAN
    
    #include "zcl_samplelight.h"
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    // The order in this table must be identical to the task initialization calls below in osalInitTask.
    const pTaskEventHandlerFn tasksArr[] = {
      macEventLoop,
      nwk_event_loop,
    #if (ZG_BUILD_RTR_TYPE)
      gp_event_loop,
    #endif
      Hal_ProcessEvent,
    #if defined( MT_TASK )
      MT_ProcessEvent,
    #endif
      APS_event_loop,
    #if defined ( ZIGBEE_FRAGMENTATION )
      APSF_ProcessEvent,
    #endif
      ZDApp_event_loop,
    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
      ZDNwkMgr_event_loop,
    #endif
      //Added to include TouchLink functionality
      #if defined ( INTER_PAN )
        StubAPS_ProcessEvent,
      #endif
      // Added to include TouchLink initiator functionality
      #if defined ( BDB_TL_INITIATOR )
        touchLinkInitiator_event_loop,
      #endif
      // Added to include TouchLink target functionality
      #if defined ( BDB_TL_TARGET )
        touchLinkTarget_event_loop,
      #endif
      zcl_event_loop,
      bdb_event_loop,
      zclSampleLight_event_loop
    };
    
    const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
    uint16 *tasksEvents;
    
    /*********************************************************************
     * FUNCTIONS
     *********************************************************************/
    
    /*********************************************************************
     * @fn      osalInitTasks
     *
     * @brief   This function invokes the initialization function for each task.
     *
     * @param   void
     *
     * @return  none
     */
    void osalInitTasks( void )
    {
      uint8 taskID = 0;
    
      tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
      osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
    
      macTaskInit( taskID++ );
      nwk_init( taskID++ );
    #if (ZG_BUILD_RTR_TYPE)
      gp_Init( taskID++ );
    #endif
      Hal_Init( taskID++ );
    #if defined( MT_TASK )
      MT_TaskInit( taskID++ );
    #endif
      APS_Init( taskID++ );
    #if defined ( ZIGBEE_FRAGMENTATION )
      APSF_Init( taskID++ );
    #endif
      ZDApp_Init( taskID++ );
    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
      ZDNwkMgr_Init( taskID++ );
    #endif
      // Added to include TouchLink functionality 
      #if defined ( INTER_PAN )
        StubAPS_Init( taskID++ );
      #endif
      // Added to include TouchLink initiator functionality 
      #if defined( BDB_TL_INITIATOR )
        touchLinkInitiator_Init( taskID++ );
      #endif
      // Added to include TouchLink target functionality 
      #if defined ( BDB_TL_TARGET )
        touchLinkTarget_Init( taskID++ );
      #endif
      zcl_Init( taskID++ );
      bdb_Init( taskID++ );
      zclSampleLight_Init( taskID );
    }
    
    /*********************************************************************
    *********************************************************************/
    

  • I think you have to move "int KeyPressCnt=0;" from zcl_SampleLight.h to zcl_SampleLight.c and add "extern int KeyPressCnt;" in your zcl_sampleapps_ui.c
  • So I moved everything from zcl_samplelight.h back to zcl_samplelight.c. Then I used extern for everything in zcl_sampleapps_ui.c. However I get the below error on the image. How can I fix this?

    zcl_sampleapps_ui.txt

  • You cannot use Onboard_wait on line 938 of zcl_sampleapps_ui. It would block other task.
  • Thanks. That fixed the error. So in the old Z-stack, there was a function called "zclSampleLight_DisplayLight". What is the equivalent of that in Z-Stack 3.0?
  • It's UI_UpdateLcd.
  • Thanks. I also have a few more questions.

    4645.zcl_samplelight.c
    /**************************************************************************************************
      Filename:       zcl_sampleLight.c
      Revised:        $Date: 2014-10-24 16:04:46 -0700 (Fri, 24 Oct 2014) $
      Revision:       $Revision: 40796 $
    
    
      Description:    Zigbee Cluster Library - sample light application.
    
    
      Copyright 2006-2014 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    /*********************************************************************
      This application implements a ZigBee Light, based on Z-Stack 3.0. It can be configured as an
      On/Off light or as a dimmable light, by undefining or defining ZCL_LEVEL_CTRL, respectively.
    
      This application is based on the common sample-application user interface. Please see the main
      comment in zcl_sampleapp_ui.c. The rest of this comment describes only the content specific for
      this sample applicetion.
      
      Application-specific UI peripherals being used:
    
      - LEDs:
        LED1 reflect the current light state (On / Off accordingly).
    
      Application-specific menu system:
    
        <TOGGLE LIGHT> Toggle the local light and display its status and level
          Press OK to toggle the local light on and off.
          This screen shows the following information
            Line1: (only populated if ZCL_LEVEL_CTRL is defined)
              LEVEL XXX - xxx is the current level of the light if the light state is ON, or the target level
                of the light when the light state is off. The target level is the level that the light will be
                set to when it is switched from off to on using the on or the toggle commands.
            Line2:
              LIGHT OFF / ON: shows the current state of the light.
          Note when ZCL_LEVEL_CTRL is enabled:
            - If the light state is ON and the light level is X, and then the light receives the OFF or TOGGLE 
              commands: The level will decrease gradually until it reaches 1, and only then the light state will
              be changed to OFF. The level then will be restored to X, with the state staying OFF. At this stage
              the light is not lighting, and the level represent the target level for the next ON or TOGGLE 
              commands.
            - If the light state is OFF and the light level is X, and then the light receives the ON or TOGGLE
              commands; The level will be set to 1, the light state will be set to ON, and then the level will
              increase gradually until it reaches level X.
            - Any level-setting command will affect the level directly, and may also affect the on/off state,
              depending on the command's arguments.       
    
    *********************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include "ZComDef.h"
    #include "OSAL.h"
    #include "AF.h"
    #include "ZDApp.h"
    #include "ZDObject.h"
    #include "MT_SYS.h"
    
    #include "nwk_util.h"
    
    #include "zcl.h"
    #include "zcl_general.h"
    #include "zcl_ha.h"
    #include "zcl_diagnostic.h"
    
    #include "zcl_samplelight.h"
       
    #include "bdb.h"
    #include "bdb_interface.h"
    
     //GP_UPDATE
    #include "gp_interface.h"
       
    #include "onboard.h"
    
    /* HAL */
    #include "hal_lcd.h"
    #include "hal_led.h"
    #include "hal_key.h"
    
    #include "NLMEDE.h"
    
    // Added to include TouchLink initiator functionality 
    #if defined ( BDB_TL_INITIATOR )
      #include "bdb_touchlink_initiator.h"
    #endif // BDB_TL_INITIATOR
    
    #if defined ( BDB_TL_TARGET )
      #include "bdb_touchlink_target.h"
    #endif // BDB_TL_TARGET
    
    #if defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET )
      #include "bdb_touchlink.h"
    #endif
    
    #include "zcl_sampleapps_ui.h"
    
    /*********************************************************************
     * MACROS
     */
    #define UI_STATE_TOGGLE_LIGHT 1 //UI_STATE_BACK_FROM_APP_MENU is item #0, so app item numbers should start from 1
    
    #define APP_TITLE "TI Sample Light"
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    byte zclSampleLight_TaskID;
    uint8 zclSampleLightSeqNum;
    
    /*********************************************************************
     * GLOBAL FUNCTIONS
     */
    extern void TestingDecrypt(void);
    /*********************************************************************
     * LOCAL VARIABLES
     */
    afAddrType_t zclSampleLight_DstAddr;
    
    // Test Endpoint to allow SYS_APP_MSGs
    static endPointDesc_t sampleLight_TestEp =
    {
      SAMPLELIGHT_ENDPOINT,
      0,
      &zclSampleLight_TaskID,
      (SimpleDescriptionFormat_t *)NULL,  // No Simple description for this test endpoint
      (afNetworkLatencyReq_t)0            // No Network Latency req
    };
    
    #ifdef ZCL_LEVEL_CTRL
    uint8 zclSampleLight_WithOnOff;       // set to TRUE if state machine should set light on/off
    uint8 zclSampleLight_NewLevel;        // new level when done moving
    uint8 zclSampleLight_LevelChangeCmd; // current level change was triggered by an on/off command
    bool  zclSampleLight_NewLevelUp;      // is direction to new level up or down?
    int32 zclSampleLight_CurrentLevel32;  // current level, fixed point (e.g. 192.456)
    int32 zclSampleLight_Rate32;          // rate in units, fixed point (e.g. 16.123)
    uint8 zclSampleLight_LevelLastLevel;  // to save the Current Level before the light was turned OFF
    #endif
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static void zclSampleLight_HandleKeys( byte shift, byte keys );
    static void zclSampleLight_BasicResetCB( void );
    static void zclSampleLight_OnOffCB( uint8 cmd );
    //GP_UPDATE
    #if (ZG_BUILD_RTR_TYPE)
    static void gp_CommissioningMode(bool isEntering);
    static uint8 gp_ChangeChannelReq(void);
    #endif
    
    
    static void zclSampleLight_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg);
    
    
    #ifdef ZCL_LEVEL_CTRL
    static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd );
    static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd );
    static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd );
    static void zclSampleLight_LevelControlStopCB( void );
    static void zclSampleLight_DefaultMove( uint8 OnOff );
    static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel );
    static uint16 zclSampleLight_GetTime ( uint8 level, uint16 time );
    static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate );
    static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time );
    static void zclSampleLight_AdjustLightLevel( void );
    #endif
    
    // Functions to process ZCL Foundation incoming Command/Response messages
    static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *msg );
    #ifdef ZCL_READ
    static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    #ifdef ZCL_WRITE
    static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
    #ifdef ZCL_DISCOVER
    static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    
    void zclSampleLight_UiActionToggleLight(uint16 keys);
    void zclSampleLight_UiUpdateLcd(uint8 uiCurrentState, char * line[3]);
    void zclSampleLight_UpdateLedState(void);
    
    /*********************************************************************
     * CONSTANTS
     */
    const uiState_t zclSampleLight_UiStatesMain[] = 
    {
      /*  UI_STATE_BACK_FROM_APP_MENU  */   {UI_STATE_DEFAULT_MOVE,       UI_STATE_TOGGLE_LIGHT,  UI_KEY_SW_5_PRESSED, &UI_ActionBackFromAppMenu}, //do not change this line, except for the second item, which should point to the last entry in this menu
      /*  UI_STATE_TOGGLE_LIGHT        */   {UI_STATE_BACK_FROM_APP_MENU, UI_STATE_DEFAULT_MOVE,  UI_KEY_SW_5_PRESSED, &zclSampleLight_UiActionToggleLight},
    };
    
    #define LEVEL_CHANGED_BY_LEVEL_CMD  0
    #define LEVEL_CHANGED_BY_ON_CMD     1
    #define LEVEL_CHANGED_BY_OFF_CMD    2
    
    /*********************************************************************
     * STATUS STRINGS
     */
    #ifdef LCD_SUPPORTED
      const char sLightOn[]      = "   LIGHT ON     ";
      const char sLightOff[]     = "   LIGHT OFF    ";
      #ifdef ZCL_LEVEL_CTRL
        char sLightLevel[]        = "   LEVEL ###    "; // displays level 1-254
      #endif
    #endif
    
    /*********************************************************************
     * REFERENCED EXTERNALS
     */
    extern int16 zdpExternalStateTaskID;
    
    /*********************************************************************
     * ZCL General Profile Callback table
     */
    static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks =
    {
      zclSampleLight_BasicResetCB,            // Basic Cluster Reset command
      NULL,                                   // Identify Trigger Effect command
      zclSampleLight_OnOffCB,                 // On/Off cluster commands
      NULL,                                   // On/Off cluster enhanced command Off with Effect
      NULL,                                   // On/Off cluster enhanced command On with Recall Global Scene
      NULL,                                   // On/Off cluster enhanced command On with Timed Off
    #ifdef ZCL_LEVEL_CTRL
      zclSampleLight_LevelControlMoveToLevelCB, // Level Control Move to Level command
      zclSampleLight_LevelControlMoveCB,        // Level Control Move command
      zclSampleLight_LevelControlStepCB,        // Level Control Step command
      zclSampleLight_LevelControlStopCB,        // Level Control Stop command
    #endif
    #ifdef ZCL_GROUPS
      NULL,                                   // Group Response commands
    #endif
    #ifdef ZCL_SCENES
      NULL,                                  // Scene Store Request command
      NULL,                                  // Scene Recall Request command
      NULL,                                  // Scene Response command
    #endif
    #ifdef ZCL_ALARMS
      NULL,                                  // Alarm (Response) commands
    #endif
    #ifdef SE_UK_EXT
      NULL,                                  // Get Event Log command
      NULL,                                  // Publish Event Log command
    #endif
      NULL,                                  // RSSI Location command
      NULL                                   // RSSI Location Response command
    };
    
    /*********************************************************************
     * @fn          zclSampleLight_Init
     *
     * @brief       Initialization function for the zclGeneral layer.
     *
     * @param       none
     *
     * @return      none
     */
    #include <hal_adc.h>
    #include <OSAL_PwrMgr.h>
    
    #define enable P0_6
    #define phase P0_5
    #define pin P1_4
      
    #define PERIODIC_EVT 0x4000
    #define PERIODIC_EVT4 0x0020
    #define offline 0x0010
    #define TURNOFF_MOTOR_EVT 0x0400
    #define KEYHOLD_EVT  0x0100
      
    uint8 direction;
    uint16 nv_test_id=0x0401;
    
    uint16 adc_ain2=0; 
    int KeyPressCnt=0;
    //int seven = 1;  
    int scan=0;
    int disconnect = 0;
    int b=1;
    int start=1;
    
    void zclSampleLight_Init( byte task_id )
    {
      zclSampleLight_TaskID = task_id;
      
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10 );
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 10 );  
      osal_start_timerEx( zclSampleLight_TaskID, offline, 10 );
    
      // Set destination address to indirect
      zclSampleLight_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
      zclSampleLight_DstAddr.endPoint = 0;
      zclSampleLight_DstAddr.addr.shortAddr = 0;
    
      // Register the Simple Descriptor for this application
      bdb_RegisterSimpleDescriptor( &zclSampleLight_SimpleDesc );
    
      // Register the ZCL General Cluster Library callback functions
      zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );
    
      // Register the application's attribute list
      zclSampleLight_ResetAttributesToDefaultValues();
      zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, zclSampleLight_NumAttributes, zclSampleLight_Attrs );
    
    #ifdef ZCL_LEVEL_CTRL
      zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
    #endif
    
      // Register the Application to receive the unprocessed Foundation command/response messages
      zcl_registerForMsg( zclSampleLight_TaskID );
    
    #ifdef ZCL_DISCOVER
      // Register the application's command list
      zcl_registerCmdList( SAMPLELIGHT_ENDPOINT, zclCmdsArraySize, zclSampleLight_Cmds );
    #endif
    
      // Register for all key events - This app will handle all key events
      RegisterForKeys( zclSampleLight_TaskID );
      
      bdb_RegisterCommissioningStatusCB( zclSampleLight_ProcessCommissioningStatus );
      
      // Register for a test endpoint
      afRegister( &sampleLight_TestEp );
    
    #ifdef ZCL_DIAGNOSTIC
      // Register the application's callback function to read/write attribute data.
      // This is only required when the attribute data format is unknown to ZCL.
      zcl_registerReadWriteCB( SAMPLELIGHT_ENDPOINT, zclDiagnostic_ReadWriteAttrCB, NULL );
    
      if ( zclDiagnostic_InitStats() == ZSuccess )
      {
        // Here the user could start the timer to save Diagnostics to NV
      }
    #endif
      
    //GP_UPDATE  
    #if (ZG_BUILD_RTR_TYPE)  
      gp_RegisterCommissioningModeCB(gp_CommissioningMode);
      gp_RegisterGPChangeChannelReqCB(gp_ChangeChannelReq);
    #endif
      
      zdpExternalStateTaskID = zclSampleLight_TaskID;
    
      UI_Init(zclSampleLight_TaskID, SAMPLEAPP_LCD_AUTO_UPDATE_EVT, SAMPLEAPP_KEY_AUTO_REPEAT_EVT, &zclSampleLight_IdentifyTime, APP_TITLE, &zclSampleLight_UiUpdateLcd, zclSampleLight_UiStatesMain);
    
      UI_UpdateLcd();
      
      osal_nv_item_init(nv_test_id, 1, &direction);
      osal_nv_read(nv_test_id, 0, 1, &direction);
      
      UI_DeviceStateUpdated((devStates_t)(MSGpkt->hdr.status));
      
      P0SEL &= (~((BV(5))|(BV(6))));
      P0DIR |= ((BV(5))|(BV(6)));  
      P1DIR |= 0x01;
      pin=0;
      
      if(direction==0){
        enable = 1;
        phase = 0;  
      }
      else if(direction==1){
        enable = 1;
        phase = 1;
      }
      osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
    }
    
    /*********************************************************************
     * @fn          zclSample_event_loop
     *
     * @brief       Event Loop Processor for zclGeneral.
     *
     * @param       none
     *
     * @return      none
     */
    uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
    {
      if(DEV_NWK_BACKOFF){
        pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY;
        if(devState==DEV_NWK_BACKOFF){
          scan=1;
        }
      }
      
      if(disconnect==1 & (devState==DEV_NWK_DISC || devState==DEV_NWK_BACKOFF)){
        disconnect=0;
        osal_start_timerEx( zclSampleLight_TaskID, offline, 30000 );
      }
      
      if( events & offline )
      {
        ZDApp_SetRejoinBackoffDuration(86400000);
        ZDApp_SetRejoinScanDuration(10000);
        return (events ^ offline);
      }
      
      if( events & TURNOFF_MOTOR_EVT )
      {
        enable = 0;
        if(start==1){
          phase=0;
          start=0;
        }
        else if(zclSampleLight_OnOff==LIGHT_ON){
          phase = 1;
        }
        else if(zclSampleLight_OnOff==LIGHT_OFF){
          phase = 0;
        }
        return (events ^ TURNOFF_MOTOR_EVT);
      }
      
      if ( events & KEYHOLD_EVT)
      {
        if ( P2_0==1 )
        {
          if (KeyPressCnt>40){
            uiActionResetToFactoryNew(keys);
            
            pin=1;
            for(int i=0; i<500; i++){
              Onboard_wait(10000);
            }
            
            SystemReset();
          }    
          else{     
            KeyPressCnt++;
            osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
          }
        }
        return ( events ^ KEYHOLD_EVT );
      }
      
      if( events & PERIODIC_EVT4 ){
        osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
        
        if(b==1){
          pin=1;
          b=0;
          osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 25 );
        }
        else if(b==0){
          pin=0;
          b=1;
          osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 2000 );
        }
        return (events ^ PERIODIC_EVT4);
      }
      
      if( events & PERIODIC_EVT )
      {
        HalAdcSetReference(HAL_ADC_REF_125V);
        adc_ain2=HalAdcRead(HAL_ADC_CHN_AIN7,HAL_ADC_RESOLUTION_10);
    
        if(adc_ain2<=155){           //155=2.6v   //177=3v   //188=3.3v  //160=2.5v
          osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 25 );
        }
        else if(adc_ain2>155){
          pin=0;
          osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
        }
    
        osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10000 );
        return (events ^ PERIODIC_EVT);
      }
      
      afIncomingMSGPacket_t *MSGpkt;
    
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclSampleLight_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case ZCL_INCOMING_MSG:
              // Incoming ZCL Foundation command/response messages
              zclSampleLight_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
              break;
    
            case KEY_CHANGE:
              zclSampleLight_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    
            case ZDO_STATE_CHANGE:
              UI_DeviceStateUpdated((devStates_t)(MSGpkt->hdr.status));
              
              //if ( zclSampleLight_NwkState == DEV_END_DEVICE )
              //{
                disconnect = 1;            
                ZDApp_SetRejoinBackoffDuration(5000);
                ZDApp_SetRejoinScanDuration(10000);
              //}
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
        }
    
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }
    
    #ifdef ZCL_LEVEL_CTRL
      if ( events & SAMPLELIGHT_LEVEL_CTRL_EVT )
      {
        zclSampleLight_AdjustLightLevel();
        return ( events ^ SAMPLELIGHT_LEVEL_CTRL_EVT );
      }
    #endif
    
    #if ZG_BUILD_ENDDEVICE_TYPE    
      if ( events & SAMPLEAPP_END_DEVICE_REJOIN_EVT )
      {
        bdb_ZedAttemptRecoverNwk();
        return ( events ^ SAMPLEAPP_END_DEVICE_REJOIN_EVT );
      }
    #endif
    
      if ( events & SAMPLEAPP_LCD_AUTO_UPDATE_EVT )
      {
        UI_UpdateLcd();
        return ( events ^ SAMPLEAPP_LCD_AUTO_UPDATE_EVT );
      }
    
      if ( events & SAMPLEAPP_KEY_AUTO_REPEAT_EVT )
      {
        UI_MainStateMachine(UI_KEY_AUTO_PRESSED);
        return ( events ^ SAMPLEAPP_KEY_AUTO_REPEAT_EVT );
      }
    
      // Discard unknown events
      return 0;
    }
    
    
    /*********************************************************************
     * @fn      zclSampleLight_HandleKeys
     *
     * @brief   Handles all key events for this device.
     *
     * @param   shift - true if in shift/alt.
     * @param   keys - bit field for key events. Valid entries:
     *                 HAL_KEY_SW_5
     *                 HAL_KEY_SW_4
     *                 HAL_KEY_SW_2
     *                 HAL_KEY_SW_1
     *
     * @return  none
     */
    static void zclSampleLight_HandleKeys( byte shift, byte keys )
    {
      UI_MainStateMachine(keys);
    }
    
    //GP_UPDATE
    #if (ZG_BUILD_RTR_TYPE)
    /*********************************************************************
     * @fn      gp_CommissioningMode
     *
     * @brief   Callback that notifies the application that gp Proxy is entering 
     *          into commissioning mode
     *
     * @param   isEntering - 
     *
     * @return  
     */
    static void gp_CommissioningMode(bool isEntering)
    {
      if(isEntering)
      {
        //Led on indicating enter commissioning mode
      }
      else
      {
        //Led off indicating enter commissioning mode
      }
    }
    
    
    
    //GP_UPDATE
    /*********************************************************************
     * @fn      gp_ChangeChannelReq
     *
     * @brief   Callback function to notify the application about a GP commissioning 
     * request that will change the current channel for at most 
     * gpBirectionalCommissioningChangeChannelTimeout ms
     *
     * @param   channel - Channel in which the commissioning will take place
     *
     * @return  TRUE to allow change channel, FALSE to do not allow
     */
    static uint8 gp_ChangeChannelReq(void)
    {
      bool allowChangeChannel = TRUE;
      
      //Check application state to decide if allow change channel or not
      
      return allowChangeChannel;
    }
    
    #endif
    
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessCommissioningStatus
     *
     * @brief   Callback in which the status of the commissioning process are reported
     *
     * @param   bdbCommissioningModeMsg - Context message of the status of a commissioning process
     *
     * @return  none
     */
    static void zclSampleLight_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg)
    {
      switch(bdbCommissioningModeMsg->bdbCommissioningMode)
      {
        case BDB_COMMISSIONING_FORMATION:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
          {
            //After formation, perform nwk steering again plus the remaining commissioning modes that has not been process yet
            bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING | bdbCommissioningModeMsg->bdbRemainingCommissioningModes);
          }
          else
          {
            //Want to try other channels?
            //try with bdb_setChannelAttribute
          }
        break;
        case BDB_COMMISSIONING_NWK_STEERING:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
          {
            //YOUR JOB:
            //We are on the nwk, what now?
          }
          else
          {
            //See the possible errors for nwk steering procedure
            //No suitable networks found
            //Want to try other channels?
            //try with bdb_setChannelAttribute
          }
        break;
        case BDB_COMMISSIONING_FINDING_BINDING:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
          {
            //YOUR JOB:
          }
          else
          {
            //YOUR JOB:
            //retry?, wait for user interaction?
          }
        break;
        case BDB_COMMISSIONING_INITIALIZATION:
          //Initialization notification can only be successful. Failure on initialization 
          //only happens for ZED and is notified as BDB_COMMISSIONING_PARENT_LOST notification
          
          //YOUR JOB:
          //We are on a network, what now?
          
        break;
    #if ZG_BUILD_ENDDEVICE_TYPE    
        case BDB_COMMISSIONING_PARENT_LOST:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_NETWORK_RESTORED)
          {
            //We did recover from losing parent
          }
          else
          {
            //Parent not found, attempt to rejoin again after a fixed delay
            osal_start_timerEx(zclSampleLight_TaskID, SAMPLEAPP_END_DEVICE_REJOIN_EVT, SAMPLEAPP_END_DEVICE_REJOIN_DELAY);
          }
        break;
    #endif 
      }
      
      UI_UpdateComissioningStatus(bdbCommissioningModeMsg);
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_BasicResetCB
     *
     * @brief   Callback from the ZCL General Cluster Library
     *          to set all the Basic Cluster attributes to default values.
     *
     * @param   none
     *
     * @return  none
     */
    static void zclSampleLight_BasicResetCB( void )
    {
      //Reset every attribute in all supported cluster to their default value.
    
      zclSampleLight_ResetAttributesToDefaultValues();
    
      zclSampleLight_UpdateLedState();
    
      // update the display
      UI_UpdateLcd( ); 
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_OnOffCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an On/Off Command for this application.
     *
     * @param   cmd - COMMAND_ON, COMMAND_OFF or COMMAND_TOGGLE
     *
     * @return  none
     */
    static void zclSampleLight_OnOffCB( uint8 cmd )
    {
      afIncomingMSGPacket_t *pPtr = zcl_getRawAFMsg();
    
      uint8 OnOff;
    
      zclSampleLight_DstAddr.addr.shortAddr = pPtr->srcAddr.addr.shortAddr;
    
    
      // Turn on the light
      if ( cmd == COMMAND_ON )
      {
        OnOff = LIGHT_ON;
      }
      // Turn off the light
      else if ( cmd == COMMAND_OFF )
      {
        OnOff = LIGHT_OFF;
      }
      // Toggle the light
      else if ( cmd == COMMAND_TOGGLE )
      {
    #ifdef ZCL_LEVEL_CTRL
        if (zclSampleLight_LevelRemainingTime > 0) 
        {
          if (zclSampleLight_NewLevelUp)
          {
            OnOff = LIGHT_OFF;
          }
          else
          {
            OnOff = LIGHT_ON;
          }
        }
        else
        {
          if (zclSampleLight_OnOff == LIGHT_ON)
          {
            OnOff = LIGHT_OFF;
          }
          else
          {
            OnOff = LIGHT_ON;
          }
        }
    #else
        if (zclSampleLight_OnOff == LIGHT_ON)
        {
          OnOff = LIGHT_OFF;
        }
        else
        {
          OnOff = LIGHT_ON;
        }
    #endif
      }
    
    #ifdef ZCL_LEVEL_CTRL
      zclSampleLight_LevelChangeCmd = (OnOff == LIGHT_ON ? LEVEL_CHANGED_BY_ON_CMD : LEVEL_CHANGED_BY_OFF_CMD);
    
      zclSampleLight_DefaultMove(OnOff);
    #else
      zclSampleLight_OnOff = OnOff;
    #endif
    
      zclSampleLight_UpdateLedState();
      
      // update the display
      UI_UpdateLcd( );
    }
    
    #ifdef ZCL_LEVEL_CTRL
    /*********************************************************************
     * @fn      zclSampleLight_TimeRateHelper
     *
     * @brief   Calculate time based on rate, and startup level state machine
     *
     * @param   newLevel - new level for current level
     *
     * @return  diff (directly), zclSampleLight_CurrentLevel32 and zclSampleLight_NewLevel, zclSampleLight_NewLevelUp
     */
    static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel )
    {
      uint32 diff;
      uint32 newLevel32;
    
      // remember current and new level
      zclSampleLight_NewLevel = newLevel;
      zclSampleLight_CurrentLevel32 = (uint32)1000 * zclSampleLight_LevelCurrentLevel;
    
      // calculate diff
      newLevel32 = (uint32)1000 * newLevel;
      if ( zclSampleLight_LevelCurrentLevel > newLevel )
      {
        diff = zclSampleLight_CurrentLevel32 - newLevel32;
        zclSampleLight_NewLevelUp = FALSE;  // moving down
      }
      else
      {
        diff = newLevel32 - zclSampleLight_CurrentLevel32;
        zclSampleLight_NewLevelUp = TRUE;   // moving up
      }
    
      return ( diff );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_MoveBasedOnRate
     *
     * @brief   Calculate time based on rate, and startup level state machine
     *
     * @param   newLevel - new level for current level
     * @param   rate16   - fixed point rate (e.g. 16.123)
     *
     * @return  none
     */
    static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate )
    {
      uint32 diff;
    
      // determine how much time (in 10ths of seconds) based on the difference and rate
      zclSampleLight_Rate32 = rate;
      diff = zclSampleLight_TimeRateHelper( newLevel );
      zclSampleLight_LevelRemainingTime = diff / rate;
      if ( !zclSampleLight_LevelRemainingTime )
      {
        zclSampleLight_LevelRemainingTime = 1;
      }
    
      osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_MoveBasedOnTime
     *
     * @brief   Calculate rate based on time, and startup level state machine
     *
     * @param   newLevel  - new level for current level
     * @param   time      - in 10ths of seconds
     *
     * @return  none
     */
    static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time )
    {
      uint16 diff;
    
      // determine rate (in units) based on difference and time
      diff = zclSampleLight_TimeRateHelper( newLevel );
      zclSampleLight_LevelRemainingTime = zclSampleLight_GetTime( newLevel, time );
      zclSampleLight_Rate32 = diff / time;
    
      osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_GetTime
     *
     * @brief   Determine amount of time that MoveXXX will take to complete.
     *
     * @param   level = new level to move to
     *          time  = 0xffff=default, or 0x0000-n amount of time in tenths of seconds.
     *
     * @return  none
     */
    static uint16 zclSampleLight_GetTime( uint8 newLevel, uint16 time )
    {
      // there is a hiearchy of the amount of time to use for transistioning
      // check each one in turn. If none of defaults are set, then use fastest
      // time possible.
      if ( time == 0xFFFF )
      {
        // use On or Off Transition Time if set (not 0xffff)
        if ( zclSampleLight_LevelCurrentLevel > newLevel )
        {
          time = zclSampleLight_LevelOffTransitionTime;
        }
        else
        {
          time = zclSampleLight_LevelOnTransitionTime;
        }
    
        // else use OnOffTransitionTime if set (not 0xffff)
        if ( time == 0xFFFF )
        {
          time = zclSampleLight_LevelOnOffTransitionTime;
        }
    
        // else as fast as possible
        if ( time == 0xFFFF )
        {
          time = 1;
        }
      }
    
      if ( time == 0 )
      {
        time = 1; // as fast as possible
      }
    
      return ( time );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_DefaultMove
     *
     * @brief   We were turned on/off. Use default time to move to on or off.
     *
     * @param   zclSampleLight_OnOff - must be set prior to calling this function.
     *
     * @return  none
     */
    static void zclSampleLight_DefaultMove( uint8 OnOff )
    {
      uint8  newLevel;
      uint32 rate;      // fixed point decimal (3 places, eg. 16.345)
      uint16 time;
    
      // if moving to on position, move to on level
      if ( OnOff )
      {
        if (zclSampleLight_OnOff == LIGHT_OFF)
        {
          zclSampleLight_LevelCurrentLevel = ATTR_LEVEL_MIN_LEVEL;
        }
        
        if ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT )
        {
          // The last Level (before going OFF) should be used)
          newLevel = zclSampleLight_LevelLastLevel;
        }
        else
        {
          newLevel = zclSampleLight_LevelOnLevel;
        }
    
        time = zclSampleLight_LevelOnTransitionTime;
    
      }
      else
      {
        newLevel = ATTR_LEVEL_MIN_LEVEL;
    
        time = zclSampleLight_LevelOffTransitionTime;
      }
    
      // else use OnOffTransitionTime if set (not 0xffff)
      if ( time == 0xFFFF )
      {
        time = zclSampleLight_LevelOnOffTransitionTime;
      }
    
      // else as fast as possible
      if ( time == 0xFFFF )
      {
        time = 1;
      }
    
      // calculate rate based on time (int 10ths) for full transition (1-254)
      rate = 255000 / time;    // units per tick, fixed point, 3 decimal places (e.g. 8500 = 8.5 units per tick)
    
      // start up state machine.
      zclSampleLight_WithOnOff = TRUE;
      zclSampleLight_MoveBasedOnRate( newLevel, rate );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_AdjustLightLevel
     *
     * @brief   Called each 10th of a second while state machine running
     *
     * @param   none
     *
     * @return  none
     */
    static void zclSampleLight_AdjustLightLevel( void )
    {
      // one tick (10th of a second) less
      if ( zclSampleLight_LevelRemainingTime )
      {
        --zclSampleLight_LevelRemainingTime;
      }
    
      // no time left, done
      if ( zclSampleLight_LevelRemainingTime == 0)
      {
        zclSampleLight_LevelCurrentLevel = zclSampleLight_NewLevel;
      }
    
      // still time left, keep increment/decrementing
      else
      {
        if ( zclSampleLight_NewLevelUp )
        {
          zclSampleLight_CurrentLevel32 += zclSampleLight_Rate32;
        }
        else
        {
          zclSampleLight_CurrentLevel32 -= zclSampleLight_Rate32;
        }
        zclSampleLight_LevelCurrentLevel = (uint8)( zclSampleLight_CurrentLevel32 / 1000 );
      }
    
      if (( zclSampleLight_LevelChangeCmd == LEVEL_CHANGED_BY_LEVEL_CMD ) && ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT ))
      {
        zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
      }
    
      // also affect on/off
      if ( zclSampleLight_WithOnOff )
      {
        if ( zclSampleLight_LevelCurrentLevel > ATTR_LEVEL_MIN_LEVEL )
        {
          zclSampleLight_OnOff = LIGHT_ON;
        }
        else
        {
          if (zclSampleLight_LevelChangeCmd != LEVEL_CHANGED_BY_ON_CMD)
          {
            zclSampleLight_OnOff = LIGHT_OFF;
          }
          else
          {
            zclSampleLight_OnOff = LIGHT_ON;
          }
          
          if (( zclSampleLight_LevelChangeCmd != LEVEL_CHANGED_BY_LEVEL_CMD ) && ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT ))
          {
            zclSampleLight_LevelCurrentLevel = zclSampleLight_LevelLastLevel;
          }
        }
      }
    
      zclSampleLight_UpdateLedState();
      
      // display light level as we go
      UI_UpdateLcd( );
    
      // keep ticking away
      if ( zclSampleLight_LevelRemainingTime )
      {
        osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
      }
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlMoveToLevelCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received a LevelControlMoveToLevel Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd )
    {
      zclSampleLight_LevelChangeCmd = LEVEL_CHANGED_BY_LEVEL_CMD;
    
      zclSampleLight_WithOnOff = pCmd->withOnOff;
      zclSampleLight_MoveBasedOnTime( pCmd->level, pCmd->transitionTime );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlMoveCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received a LevelControlMove Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd )
    {
      uint8 newLevel;
      uint32 rate;
    
      // convert rate from units per second to units per tick (10ths of seconds)
      // and move at that right up or down
      zclSampleLight_WithOnOff = pCmd->withOnOff;
    
      if ( pCmd->moveMode == LEVEL_MOVE_UP )
      {
        newLevel = ATTR_LEVEL_MAX_LEVEL;  // fully on
      }
      else
      {
        newLevel = ATTR_LEVEL_MIN_LEVEL; // fully off
      }
    
      zclSampleLight_LevelChangeCmd = LEVEL_CHANGED_BY_LEVEL_CMD;
    
      rate = (uint32)100 * pCmd->rate;
      zclSampleLight_MoveBasedOnRate( newLevel, rate );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlStepCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an On/Off Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd )
    {
      uint8 newLevel;
    
      // determine new level, but don't exceed boundaries
      if ( pCmd->stepMode == LEVEL_MOVE_UP )
      {
        if ( (uint16)zclSampleLight_LevelCurrentLevel + pCmd->amount > ATTR_LEVEL_MAX_LEVEL )
        {
          newLevel = ATTR_LEVEL_MAX_LEVEL;
        }
        else
        {
          newLevel = zclSampleLight_LevelCurrentLevel + pCmd->amount;
        }
      }
      else
      {
        if ( pCmd->amount >= zclSampleLight_LevelCurrentLevel )
        {
          newLevel = ATTR_LEVEL_MIN_LEVEL;
        }
        else
        {
          newLevel = zclSampleLight_LevelCurrentLevel - pCmd->amount;
        }
      }
      
      zclSampleLight_LevelChangeCmd = LEVEL_CHANGED_BY_LEVEL_CMD;
    
      // move to the new level
      zclSampleLight_WithOnOff = pCmd->withOnOff;
      zclSampleLight_MoveBasedOnTime( newLevel, pCmd->transitionTime );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_LevelControlStopCB
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an Level Control Stop Command for this application.
     *
     * @param   pCmd - ZigBee command parameters
     *
     * @return  none
     */
    static void zclSampleLight_LevelControlStopCB( void )
    {
      // stop immediately
      osal_stop_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT );
      zclSampleLight_LevelRemainingTime = 0;
    }
    #endif
    
    /******************************************************************************
     *
     *  Functions for processing ZCL Foundation incoming Command/Response messages
     *
     *****************************************************************************/
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessIncomingMsg
     *
     * @brief   Process ZCL Foundation incoming message
     *
     * @param   pInMsg - pointer to the received message
     *
     * @return  none
     */
    static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
    {
      switch ( pInMsg->zclHdr.commandID )
      {
    #ifdef ZCL_READ
        case ZCL_CMD_READ_RSP:
          zclSampleLight_ProcessInReadRspCmd( pInMsg );
          break;
    #endif
    #ifdef ZCL_WRITE
        case ZCL_CMD_WRITE_RSP:
          zclSampleLight_ProcessInWriteRspCmd( pInMsg );
          break;
    #endif
        case ZCL_CMD_CONFIG_REPORT:
        case ZCL_CMD_CONFIG_REPORT_RSP:
        case ZCL_CMD_READ_REPORT_CFG:
        case ZCL_CMD_READ_REPORT_CFG_RSP:
        case ZCL_CMD_REPORT:
          //bdb_ProcessIncomingReportingMsg( pInMsg );
          break;
    
        case ZCL_CMD_DEFAULT_RSP:
          zclSampleLight_ProcessInDefaultRspCmd( pInMsg );
          break;
    #ifdef ZCL_DISCOVER
        case ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP:
          zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_CMDS_GEN_RSP:
          zclSampleLight_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_RSP:
          zclSampleLight_ProcessInDiscAttrsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_EXT_RSP:
          zclSampleLight_ProcessInDiscAttrsExtRspCmd( pInMsg );
          break;
    #endif
        default:
          break;
      }
    
      if ( pInMsg->attrCmd )
        osal_mem_free( pInMsg->attrCmd );
    }
    
    #ifdef ZCL_READ
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInReadRspCmd
     *
     * @brief   Process the "Profile" Read Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclReadRspCmd_t *readRspCmd;
      uint8 i;
    
      readRspCmd = (zclReadRspCmd_t *)pInMsg->attrCmd;
      for (i = 0; i < readRspCmd->numAttr; i++)
      {
        // Notify the originator of the results of the original read attributes
        // attempt and, for each successfull request, the value of the requested
        // attribute
      }
    
      return ( TRUE );
    }
    #endif // ZCL_READ
    
    #ifdef ZCL_WRITE
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInWriteRspCmd
     *
     * @brief   Process the "Profile" Write Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclWriteRspCmd_t *writeRspCmd;
      uint8 i;
    
      writeRspCmd = (zclWriteRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < writeRspCmd->numAttr; i++ )
      {
        // Notify the device of the results of the its original write attributes
        // command.
      }
    
      return ( TRUE );
    }
    #endif // ZCL_WRITE
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDefaultRspCmd
     *
     * @brief   Process the "Profile" Default Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg )
    {
      // zclDefaultRspCmd_t *defaultRspCmd = (zclDefaultRspCmd_t *)pInMsg->attrCmd;
    
      // Device is notified of the Default Response command.
      (void)pInMsg;
    
      return ( TRUE );
    }
    
    #ifdef ZCL_DISCOVER
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDiscCmdsRspCmd
     *
     * @brief   Process the Discover Commands Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverCmdsCmdRsp_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverCmdsCmdRsp_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numCmd; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDiscAttrsRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverAttrsRspCmd_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverAttrsRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numAttr; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    
    /*********************************************************************
     * @fn      zclSampleLight_ProcessInDiscAttrsExtRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Extended Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverAttrsExtRsp_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverAttrsExtRsp_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numAttr; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    #endif // ZCL_DISCOVER
    
    void zclSampleLight_UiActionToggleLight(uint16 keys)
    {
      zclSampleLight_OnOffCB(COMMAND_TOGGLE);
    }
    
    void zclSampleLight_UpdateLedState(void)
    {
      // set the LED1 based on light (on or off)
      if ( zclSampleLight_OnOff == LIGHT_ON )
      {
        HalLedSet ( UI_LED_APP, HAL_LED_MODE_ON );
      }
      else
      {
        HalLedSet ( UI_LED_APP, HAL_LED_MODE_OFF );
      }
    }
    
    void zclSampleLight_UiUpdateLcd(uint8 UiState, char * line[3])
    {
    #ifdef LCD_SUPPORTED
    #ifdef ZCL_LEVEL_CTRL
      zclHA_uint8toa( zclSampleLight_LevelCurrentLevel, &sLightLevel[9] );
      line[0] = (char *)sLightLevel;
    #endif // ZCL_LEVEL_CTRL
      line[1] = (char *)(zclSampleLight_OnOff ? sLightOn : sLightOff);
      line[2] = "< TOGGLE LIGHT >";
    #endif
    }
    
    /****************************************************************************
    ****************************************************************************/
    
    
    

    1. How can I get the the uiActionResetToFactoryNew() function to work as shown in the image below?

    2. How can I get the the UI_DeviceStateUpdated() function to work as shown in the image below?

  • 1. You should change "static void uiActionResetToFactoryNew(uint16 keys);" to "void uiActionResetToFactoryNew(uint16 keys);" in zcl_sampleapps_ui.c and add "extern void uiActionResetToFactoryNew(uint16 keys);" in zcl_sampleLight.c to use it.
    2. You have to add "extern void UI_DeviceStateUpdated(devStates_t NwkState);" in zcl_sampleLight.c to use it.
    These are very fundamental of C programming and I suggest you to enhance your programming skill.
  • Thanks. This helps a lot.
  • You are welcome.
  • Hi,

    I wanted to ask how it would be possible to get the end device to start the joining process with Z-stack 3.0. Because whenever I power the CC2530 on, it doesn't seem to start joining.
  • Hi,

    You need to start BDB commissioning for an end device to the network joining process. Are you using SmartRF05 + CC2530EM? You can refer to the Quick Start Guide (section 7) of Z-Stack 3.0 Sample Application User's Guide. Look for the API bdb_StartCommissioning() throughout the sample applications for more usage examples.
  • I use just a regular CC2530 board module. How can I get the CC2530 to automatically start trying to join a network without having to press any buttons?
  • Do you call bdb_StartCommissioning() automatically when device starts from power on?
  • How do I do that?
  • You can start a timer event that would trigger the event two seconds later in zclSampleLight_Init and in the event you can call the following bdb_StartCommissioning to start it.

    bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |
    BDB_COMMISSIONING_MODE_NWK_STEERING |
    BDB_COMMISSIONING_MODE_FINDING_BINDING |
    BDB_COMMISSIONING_MODE_INITIATOR_TL );
  • Why does it have to be 2 seconds later? Why not immediately after power up?
  • You can try to do it immediately.
  • Thanks. The joining process now works. I also wanted to ask, when adding the HAL_KEY_SW_X code, do I only add it in "UI_MainStateMachine"? What about "uiActionConfigureEnables", "uiActionConfigureEnables", "uiActionProcessPrepareInstallCode", and "uiActionProcessConfigurePanId" which also contain code about HAL_KEY_SW_X?
  • Try to read Z-Stack 3.0 Developer's Guide and Z-Stack 3.0 Sample Application User's Guide in document folder.
  • Sorry, but I am still unsure.

  • unsure what?
  • So if I configure a button to do something in "UI_MainStateMachine" only and not in "uiActionConfigureEnables", "uiActionConfigureEnables", "uiActionProcessPrepareInstallCode", or "uiActionProcessConfigurePanId", when I press that button, will it perform the action that was configured only in "UI_MainStateMachine"?
  • I couldn't understand your question.
  • Basically, all I'm trying to do is have it so when I trigger "UI_KEY_SW_2_PRESSED" then something will happen. I am just confused whether or not I have to add my code in the functions "uiActionConfigureEnables", "uiActionConfigureEnables", "uiActionProcessPrepareInstallCode", and "uiActionProcessConfigurePanId" in addition to UI_MainStateMachine. I see that HandleKeys only refers to UI_MainStateMachine, so if I want to add code for when I trigger "UI_KEY_SW_2_PRESSED", do I only add it in UI_MainStateMachine in order for it to work?
  • I think it is OK to add it in UI_MainStateMachine to make it work.
  • Thanks. That is working now. So I've been testing and I found a couple of issues.

    1. When I add the below code, I noticed the CC2530 only tries to search for a network for 4 seconds and then stops. It does not attempt to search for a network again. I have DREJOIN_SCAN=900000 which is way more than 4 seconds. How can I fix this?

    bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |
    BDB_COMMISSIONING_MODE_NWK_STEERING |
    BDB_COMMISSIONING_MODE_FINDING_BINDING |
    BDB_COMMISSIONING_MODE_INITIATOR_TL );

    2. I also noticed that when the CC2530 is able to connect to a network within 4 seconds, it works fine, but when I re-power the CC2530, it does not rejoin the network. I have NV_RESTORE enabled. How can this be fixed?

  • 1. You have to add code to restart bdb_StartCommissioning in "case BDB_COMMISSIONING_NWK_STEERING:" of zclSampleLight_ProcessCommissioningStatus.
    2. I suggest you to set breakpoint inZDOInitDeviceEx and trace why it doesn't start to rejoin network when NV_RESTORE is enabled.
  • 1. I just put in the below in that function. However when I set -DREJOIN_SCAN=10000, it never stops scanning. How do I fix this?

    bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |
    BDB_COMMISSIONING_MODE_NWK_STEERING |
    BDB_COMMISSIONING_MODE_FINDING_BINDING |
    BDB_COMMISSIONING_MODE_INITIATOR_TL );
  • You can implement a count in "case BDB_COMMISSIONING_NWK_STEERING:" of zclSampleLight_ProcessCommissioningStatus to stop it when count hits a threshold.
  • Is it possible to have the CC2530 search for a network until the DREJOIN_SCAN is over? Why does it only scan for 4 seconds and then stop instead of the full time specified in DREJOIN_SCAN?

  • REJOIN_SCAN is for another purpose so you cannot use it here.
  • I am a bit confused? So why exactly can't the below code scan for a network for the full scan time specified in DREJOIN_SCAN? In the old Z-stack, I used code below this one to scan for a network and it scanned until it reached the full time of DREJOIN_SCAN.

    bdb_StartCommissioning( BDB_COMMISSIONING_MODE_NWK_FORMATION |
    BDB_COMMISSIONING_MODE_NWK_STEERING |
    BDB_COMMISSIONING_MODE_FINDING_BINDING |
    BDB_COMMISSIONING_MODE_INITIATOR_TL );

    ZDApp_ChangeState(DEV_NWK_DISC);
    ZDApp_StartJoiningCycle();
    osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );

  • REJOIN_SCAN and REJOIN_BACKOFF is used for controlling device had joined a network but lost connection with its parent node. bdb_StartCommissioning is used for device trying to join Zigbee network first time so you cannot mess them up.
  • Does uiProcessPermitJoin set the BDB Commisioning duration?
  • BDB commissioning is defined by BDBC_MIN_COMMISSIONING_TIME which is "#define BDBC_MIN_COMMISSIONING_TIME 180 // 180 seconds" in bdb_interface.h
  • I've noticed that a strange signal is turning on and off constantly in the below picture alongside with the polling. I don't think it's an LED since I defined LED FALSE in hal config. What is causing this and how can I stop it?

  • Check if you have a periodic event keeps waking up MCU.
  • I had 1 timer and I disabled it, but it didn't fix the problem.
  • It looks like a regular pattern so I can only suggest you to double check if there is periodic event running accidentally.
  • A few minutes later it stops on its own and doesn't reappear. Only when i power the CC2530 on, does it do that for the first few minutes.