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: Make motor run until HAL_KEY_SW_1 is pressed

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

Hello,

How can I program the CC2530 to make a motor run forever until HAL_KEY_SW_1 is presssed. I have it so that I press HAL_KEY_SW_6 (in HandleKeys) to start to motor. Below is my code so far in SampleLight, but the CC2530 is skipping over the while loop. My program is supposed to say that if HAL_KEY_SW_1 isn't pressed, run the motor until the button is pressed. Why doesn't it work?

static void zclSampleLight_DisplayLight( void )
{
// set the LED1 based on light (on or off)
if ( zclSampleLight_OnOff == LIGHT_ON & no == 0 )
{
while(!HAL_KEY_SW_1){
DATA_PIN = 0;
forward = 0;
backward = 1;

for(int i=0; i<time; i++){
Onboard_wait(10000);
}
}

forward = 0;
backward = 0;
DATA_PIN = 1;

no = 1;
}

  • You cannot put a while loop in Z-Stack otherwise it would block everything.
  • How would the code be written then? How can I have it so that the motor will run until HAL_KEY_SW_1 is pressed?
  • So I typed the code in HandleKeys so the buttons stop the motor when they are pressed (shown below), but how can I have it so that the motor can also be stopped when a timer runs out? For example: I press HAL_KEY_SW_6 to start the motor and the motor will stop after 5 seconds automatically or unless I press HAL_KEY_SW_1 first.

    static void zclSampleLight_HandleKeys( byte shift, byte keys )
    {
    if ( (keys & HAL_KEY_SW_1) || (keys & HAL_KEY_SW_2) ){
    forward = 0;
    backward = 0;
    DATA_PIN = 1;
    }
  • Besides add code to stop motor when pressing SW1. When you start motor after pressing SW6, you can start a timer event that comes 5 seconds later to stop motor.
  • How do I write the code for the timer event?
  • You can use the following pseudo code to start motor and schedule a timer event to stop motor 5 seconds later when SW1 is triggered.
    static void zclSampleLight_HandleKeys( byte shift, byte keys )
    {
    if ( (keys & HAL_KEY_SW_1) ){
    //Start motor here
    ...
    //Start timer event
    osal_start_timerEx(...., 5000);
    }
  • Right now my code looks like the below and I want to know what parameters to put inside of osal_start_timerEx() and what is the rest of the code for this timer? The timer is the code I don't know how to do.

    if ( keys & HAL_KEY_SW_6)

     {    

       KeyPressCnt=0;  //for factory reset

       osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100); //for factory reset

       zclSampleLight_OnOff = zclSampleLight_OnOff ? LIGHT_OFF : LIGHT_ON;  //Tells which way motor should run in zcl_DisplayLight

       osal_start_timerEx( x, x, 5000);  //What parameters do I use for this timer that stops the motor automatically after 5 seconds? Also what more code do I need to put?

     }

  • It is like how you start timer KEYHOLD_EVT and how you process it in event loop.
  • But I am not holding down the button. I only press it. So how is it the same?
  • Since you don't hold the button, you can do it in "if ( (keys & HAL_KEY_SW_1) ){..." of zclSampleLight_HandleKeys and no need to start KEYHOLD_EVT.
  • So what do I put for osal_start_timerEx( x, x, 5000); ?
  • It's like osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR__EVT, 5000);
  • So what value should TURNOFF_MOTOR__EVT be?

    /*********************************************************************
     * 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
     */
    //uint16 adc_ain2 = 0;
    
    
    #define DATA_PIN P0_5
    #define forward P1_2
    #define backward P0_6
    
    #define time 5000//110
    
    static int no = 0;
    
    #define PERIODIC_EVT 0x4000
    #define PERIODIC_EVT2 0x0001
    
    void zclSampleLight_Init( byte task_id )
    {
      zclSampleLight_TaskID = task_id;
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10 );
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT2, 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
      
      zclSampleLight_OnOff = LIGHT_ON;
      P0DIR |= 0x20;
      
      P1SEL &= ~BV(2);
      P1DIR |= BV(2);
      
      P0SEL &= ~BV(6);
      P0DIR |= BV(6);
      //P1DIR |= 0x3f;
      
        DATA_PIN = 0;
        forward = 1;
        backward = 0;
    
        for(int i=0; i<110; i++){
          Onboard_wait(10000);
        }       
        
        forward = 0;
        backward = 0;    
        DATA_PIN = 1;
        
        no = 1;  
        
        ZDApp_ChangeState(DEV_NWK_DISC);
        // Restart scan for rejoin
        ZDApp_StartJoiningCycle();
        osal_stop_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF );
        osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );
    }
    
    /*********************************************************************
     * @fn          zclSample_event_loop
     *
     * @brief       Event Loop Processor for zclGeneral.
     *
     * @param       none
     *
     * @return      none
     */
    #include <hal_adc.h>
    
    #define KEYHOLD_EVT  0x0100    //define event for key hold
    int KeyPressCnt=0; 
    
    uint16 adc_ain2=0; 
    
    #define HAL_ADC_REF_125V    0x00    /* Internal 1.25V Reference */
    #define HAL_ADC_DEC_064     0x00    /* Decimate by 64 : 8-bit resolution */
    #define HAL_ADC_DEC_128     0x10    /* Decimate by 128 : 10-bit resolution */
    #define HAL_ADC_DEC_512     0x30    /* Decimate by 512 : 14-bit resolution */
    #define HAL_ADC_CHN_VDD3    0x0f    /* Input channel: VDD/3 */
    #define HAL_ADC_CHN_TEMP    0x0e    /* Temperature sensor */
    uint16 value_bat;
    uint32        next;
    halIntState_t intState;
    uint8 ret;
    
    #include <OSAL_PwrMgr.h>
    
    uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
    {
      if ( events & KEYHOLD_EVT )
      {
        if ( P2_0==1 )
        {
          if (KeyPressCnt>10){
            KeyPressCnt=0;
            extern void ZDApp_ResetTimerStart( uint16 delay );
            zgWriteStartupOptions(ZG_STARTUP_SET, (ZCD_STARTOPT_DEFAULT_NETWORK_STATE | ZCD_STARTOPT_DEFAULT_CONFIG_STATE) );
            ZDApp_ResetTimerStart(2000);
          }    
          else{
            KeyPressCnt++;
            osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100); 
            ret=osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100); 
          }
        }
        return ( events ^ KEYHOLD_EVT );
      }
      
      //////////////////////////////////////////////////////
      
      if( events & PERIODIC_EVT2 )
      {
        //CODE HERE
    
    #if (defined HAL_BOARD_ZLIGHT)
    
        zclSampleLight_BasicResetCB();
    
    #else
    
        giLightScreenMode = LIGHT_MAINMODE;
    
    #ifdef ZCL_EZMODE
        {
          // 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 );
    
          // Hold off interrupts.
          HAL_ENTER_CRITICAL_SECTION( intState );
    
          // Get next time-out
          next = osal_next_timeout();
    
          // Re-enable interrupts.
          HAL_EXIT_CRITICAL_SECTION( intState );
    
          // Put the processor into sleep mode
          OSAL_SET_CPU_INTO_SLEEP( 7200000 );
        }
    
    #else // NOT EZ-Mode
        {
          zAddrType_t dstAddr;
          HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
    
          // Initiate an End Device Bind Request, this bind request will
          // only use a cluster list that is important to binding.
          dstAddr.addrMode = afAddr16Bit;
          dstAddr.addr.shortAddr = 0;   // Coordinator makes the match
          ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),
                               SAMPLELIGHT_ENDPOINT,
                               ZCL_HA_PROFILE_ID,
                               ZCLSAMPLELIGHT_BINDINGLIST, bindingInClusters,
                               0, NULL,   // No Outgoing clusters to bind
                               TRUE );
        }
    #endif // ZCL_EZMODE
    #endif // HAL_BOARD_ZLIGHT
      
        
        osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT2, 5000 );
        return (events ^ PERIODIC_EVT2);
      }
      
      //////////////////////////////////////////////////////////  
      
      if( events & PERIODIC_EVT )
      {
        //Do things that need periodic processing here!
        /* Clear ADC interrupt flag */
        ADCIF = 0;
        ADCCON3 = (HAL_ADC_REF_125V| HAL_ADC_DEC_128 | HAL_ADC_CHN_VDD3);
        /* Wait for the conversion to finish */
        while ( !ADCIF ); 
        /* Get the result */
        value_bat = ADCL;
        value_bat |= ((uint16) ADCH) << 8;
        /*
        * value now contains measurement of Vdd/3
        * 0 indicates 0V and 32767 indicates 1.25V
        * voltage = (value*3*1.25)/32767 volts
        * we will multiply by this by 10 to allow units of 0.1 volts
        */
        value_bat = value_bat >> 6; // divide first by 2^6
        value_bat = (uint16)(value_bat * 37.5);
        value_bat = value_bat >> 9; // ...and later by 2^9...to prevent overflow during multiplication
        
        if(value_bat<=25){
          P0_4=1;    
        }
        else if(value_bat>25){
          P0_4=0;    
        }
    
        osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 5000 );
        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) )
                {
                  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_1) || (keys & HAL_KEY_SW_2) ){
        forward = 0;
        backward = 0;
        DATA_PIN = 1;
      }
      
      if ( keys & HAL_KEY_SW_6)
      {
        KeyPressCnt=0;
        osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
        
        giLightScreenMode = LIGHT_MAINMODE;
    
        // toggle local light immediately
        zclSampleLight_OnOff = zclSampleLight_OnOff ? LIGHT_OFF : LIGHT_ON;
    #ifdef ZCL_LEVEL_CTRL
        zclSampleLight_LevelCurrentLevel = zclSampleLight_OnOff ? zclSampleLight_LevelOnLevel : ATTR_LEVEL_MIN_LEVEL;
    #endif
        
        /*for(int i=0; i<10; i++){
          Onboard_wait(10000);
        } */   
      }
    
      
      
    
      /*if ( keys & HAL_KEY_SW_3 )
      {
        NLME_SendNetworkStatus( zclSampleLight_DstAddr.addr.shortAddr,
                           NLME_GetShortAddr(), NWKSTAT_NONTREE_LINK_FAILURE, FALSE );
      }
    
      if ( keys & HAL_KEY_SW_4 )
      {
        giLightScreenMode = LIGHT_MAINMODE;
    
        if ( ( zclSampleLight_NwkState == DEV_ZB_COORD ) ||
              ( zclSampleLight_NwkState == DEV_ROUTER ) )
        {
          zAddrType_t tmpAddr;
    
          tmpAddr.addrMode = Addr16Bit;
          tmpAddr.addr.shortAddr = NLME_GetShortAddr();
    
          // toggle permit join
          gPermitDuration = gPermitDuration ? 0 : 0xff;
    
          // Trust Center significance is always true
          ZDP_MgmtPermitJoinReq( &tmpAddr, gPermitDuration, TRUE, FALSE );
        }
      }
    
      // Shift F5 does a Basic Reset (factory defaults)
      if ( shift && ( keys & HAL_KEY_SW_5 ) )
      {
        zclSampleLight_BasicResetCB();
      }
      else if ( keys & HAL_KEY_SW_5 )
      {
        giLightScreenMode = giLightScreenMode ? LIGHT_MAINMODE : LIGHT_HELPMODE;
      }*/
    
      // 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
    
      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 )
    {
      // set the LED1 based on light (on or off)
      if ( zclSampleLight_OnOff == LIGHT_ON & no == 0 )
      {
        DATA_PIN = 0;
        forward = 0;
        backward = 1;
        
        /*for(int i=0; i<time; i++){
          Onboard_wait(10000);
        }  
    
        forward = 0;
        backward = 0;
        DATA_PIN = 1;*/
        
        no = 1;
      }
      else if ( zclSampleLight_OnOff == LIGHT_OFF & no == 1 )
      {
        DATA_PIN = 0;
        forward = 1;
        backward = 0;
    
        /*for(int i=0; i<time; i++){
          Onboard_wait(10000);
        }         
        forward = 0;
        backward = 0;
        DATA_PIN = 1;*/
        
        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 );
    }
    
    /*********************************************************************
     * @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;
    }
    #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
    
    /****************************************************************************
    ****************************************************************************/
    
    

  • #define TURNOFF_MOTOR__EVT 0x0200

    uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
    {
    ...
    if( events & TURNOFF_MOTOR__EVT )
    {
    //Turn off motor here!
    ...

    return (events ^ TURNOFF_MOTOR__EVT);
    }
    ...
    }
  • I placed the below code in the event loop and osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR__EVT, 5000); in HandlKeys, but the motor stops instantly as soon as I press the button. Why isn't the motor given time to move and then stop? I set a breakpoint in the below code and everytime I press HAL_KEY_SW_6, the breakpoint is always hit immediately, meaning that the motor stops when I press the button. How can this be fixed?

    if( events & TURNOFF_MOTOR__EVT )
    {
    forward = 0;
    backward = 0;
    DATA_PIN = 1;

    return (events ^ TURNOFF_MOTOR__EVT);
    }
  • If you add events to your watch window, what value of events do you see?
  • I mainly get the value 37376, but ocassionaly I get some other values like 54016 and 512.
  • Try to use "#define TURNOFF_MOTOR__EVT 0x0400" instead of "#define TURNOFF_MOTOR__EVT 0x0200" to test again.
  • Unfortunately that didn't work. The breakpoint was never hit and the code didn't stop the motor.
  • Can you tell me the value of events?
  • I get 1024.
  • I get 1024
  • I get the value of 1024
  • Can you attach your latest code?
  • Here is the code:

    /*********************************************************************
     * 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
     */
    //uint16 adc_ain2 = 0;
    
    
    #define DATA_PIN P0_5
    #define forward P1_2
    #define backward P0_6
    
    #define time 5000//110
    
    static int no = 0;
    
    #define PERIODIC_EVT 0x4000
    #define PERIODIC_EVT2 0x0001
    
    void zclSampleLight_Init( byte task_id )
    {
      zclSampleLight_TaskID = task_id;
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 10 );
      osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT2, 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
      
      zclSampleLight_OnOff = LIGHT_ON;
      P0DIR |= 0x20;
      
      P1SEL &= ~BV(2);
      P1DIR |= BV(2);
      
      P0SEL &= ~BV(6);
      P0DIR |= BV(6);
      //P1DIR |= 0x3f;
      
        DATA_PIN = 0;
        forward = 1;
        backward = 0;
    
        for(int i=0; i<110; i++){
          Onboard_wait(10000);
        }       
        
        forward = 0;
        backward = 0;    
        DATA_PIN = 1;
        
        no = 1;  
        
        ZDApp_ChangeState(DEV_NWK_DISC);
        // Restart scan for rejoin
        ZDApp_StartJoiningCycle();
        osal_stop_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF );
        osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );
    }
    
    /*********************************************************************
     * @fn          zclSample_event_loop
     *
     * @brief       Event Loop Processor for zclGeneral.
     *
     * @param       none
     *
     * @return      none
     */
    #include <hal_adc.h>
    
    #define KEYHOLD_EVT  0x0100    //define event for key hold
    int KeyPressCnt=0; 
    
    uint16 adc_ain2=0; 
    
    #define HAL_ADC_REF_125V    0x00    /* Internal 1.25V Reference */
    #define HAL_ADC_DEC_064     0x00    /* Decimate by 64 : 8-bit resolution */
    #define HAL_ADC_DEC_128     0x10    /* Decimate by 128 : 10-bit resolution */
    #define HAL_ADC_DEC_512     0x30    /* Decimate by 512 : 14-bit resolution */
    #define HAL_ADC_CHN_VDD3    0x0f    /* Input channel: VDD/3 */
    #define HAL_ADC_CHN_TEMP    0x0e    /* Temperature sensor */
    uint16 value_bat;
    uint32        next;
    halIntState_t intState;
    uint8 ret;
    
    #define TURNOFF_MOTOR__EVT 0x0400
    
    uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
    {
      if( events & TURNOFF_MOTOR__EVT )
      {
        forward = 0;
        backward = 0;
        DATA_PIN = 1;
        
        return (events ^ TURNOFF_MOTOR__EVT);
      } 
      
      if ( events & KEYHOLD_EVT )
      {
        if ( P2_0==1 )
        {
          if (KeyPressCnt>10){
            KeyPressCnt=0;
            extern void ZDApp_ResetTimerStart( uint16 delay );
            zgWriteStartupOptions(ZG_STARTUP_SET, (ZCD_STARTOPT_DEFAULT_NETWORK_STATE | ZCD_STARTOPT_DEFAULT_CONFIG_STATE) );
            //ZDApp_ResetTimerStart(2000);
            SystemResetSoft();
          }    
          else{
            KeyPressCnt++;
            osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100); 
            ret=osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100); 
          }
        }
        return ( events ^ KEYHOLD_EVT );
      }
      
      //////////////////////////////////////////////////////
      
      if( events & PERIODIC_EVT2 )
      {
        //CODE HERE
    
    #if (defined HAL_BOARD_ZLIGHT)
    
        zclSampleLight_BasicResetCB();
    
    #else
    
        giLightScreenMode = LIGHT_MAINMODE;
    
    #ifdef ZCL_EZMODE
        {
          // 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 );
    
          // Hold off interrupts.
          HAL_ENTER_CRITICAL_SECTION( intState );
    
          // Get next time-out
          next = osal_next_timeout();
    
          // Re-enable interrupts.
          HAL_EXIT_CRITICAL_SECTION( intState );
    
          // Put the processor into sleep mode
          OSAL_SET_CPU_INTO_SLEEP( 7200000 );
        }
    
    #else // NOT EZ-Mode
        {
          zAddrType_t dstAddr;
          HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
    
          // Initiate an End Device Bind Request, this bind request will
          // only use a cluster list that is important to binding.
          dstAddr.addrMode = afAddr16Bit;
          dstAddr.addr.shortAddr = 0;   // Coordinator makes the match
          ZDP_EndDeviceBindReq( &dstAddr, NLME_GetShortAddr(),
                               SAMPLELIGHT_ENDPOINT,
                               ZCL_HA_PROFILE_ID,
                               ZCLSAMPLELIGHT_BINDINGLIST, bindingInClusters,
                               0, NULL,   // No Outgoing clusters to bind
                               TRUE );
        }
    #endif // ZCL_EZMODE
    #endif // HAL_BOARD_ZLIGHT
      
        
        osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT2, 5000 );
        return (events ^ PERIODIC_EVT2);
      }
      
      //////////////////////////////////////////////////////////  
      
      if( events & PERIODIC_EVT )
      {
        //Do things that need periodic processing here!
        /* Clear ADC interrupt flag */
        ADCIF = 0;
        ADCCON3 = (HAL_ADC_REF_125V| HAL_ADC_DEC_128 | HAL_ADC_CHN_VDD3);
        /* Wait for the conversion to finish */
        while ( !ADCIF ); 
        /* Get the result */
        value_bat = ADCL;
        value_bat |= ((uint16) ADCH) << 8;
        /*
        * value now contains measurement of Vdd/3
        * 0 indicates 0V and 32767 indicates 1.25V
        * voltage = (value*3*1.25)/32767 volts
        * we will multiply by this by 10 to allow units of 0.1 volts
        */
        value_bat = value_bat >> 6; // divide first by 2^6
        value_bat = (uint16)(value_bat * 37.5);
        value_bat = value_bat >> 9; // ...and later by 2^9...to prevent overflow during multiplication
        
        if(value_bat<=25){
          P0_4=1;    
        }
        else if(value_bat>25){
          P0_4=0;    
        }
    
        osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT, 5000 );
        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) )
                {
                  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_1) || (keys & HAL_KEY_SW_2) ){
        forward = 0;
        backward = 0;
        DATA_PIN = 1;
      }
      
      if ( keys & HAL_KEY_SW_6)
      {
        osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR__EVT, 5000);
        KeyPressCnt=0;
        osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
        
        giLightScreenMode = LIGHT_MAINMODE;
    
        // toggle local light immediately
        zclSampleLight_OnOff = zclSampleLight_OnOff ? LIGHT_OFF : LIGHT_ON;
    #ifdef ZCL_LEVEL_CTRL
        zclSampleLight_LevelCurrentLevel = zclSampleLight_OnOff ? zclSampleLight_LevelOnLevel : ATTR_LEVEL_MIN_LEVEL;
    #endif
        
        /*for(int i=0; i<10; i++){
          Onboard_wait(10000);
        } */   
      }
    
      
      
    
      /*if ( keys & HAL_KEY_SW_3 )
      {
        NLME_SendNetworkStatus( zclSampleLight_DstAddr.addr.shortAddr,
                           NLME_GetShortAddr(), NWKSTAT_NONTREE_LINK_FAILURE, FALSE );
      }
    
      if ( keys & HAL_KEY_SW_4 )
      {
        giLightScreenMode = LIGHT_MAINMODE;
    
        if ( ( zclSampleLight_NwkState == DEV_ZB_COORD ) ||
              ( zclSampleLight_NwkState == DEV_ROUTER ) )
        {
          zAddrType_t tmpAddr;
    
          tmpAddr.addrMode = Addr16Bit;
          tmpAddr.addr.shortAddr = NLME_GetShortAddr();
    
          // toggle permit join
          gPermitDuration = gPermitDuration ? 0 : 0xff;
    
          // Trust Center significance is always true
          ZDP_MgmtPermitJoinReq( &tmpAddr, gPermitDuration, TRUE, FALSE );
        }
      }
    
      // Shift F5 does a Basic Reset (factory defaults)
      if ( shift && ( keys & HAL_KEY_SW_5 ) )
      {
        zclSampleLight_BasicResetCB();
      }
      else if ( keys & HAL_KEY_SW_5 )
      {
        giLightScreenMode = giLightScreenMode ? LIGHT_MAINMODE : LIGHT_HELPMODE;
      }*/
    
      // 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
    
      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 )
    {
      // set the LED1 based on light (on or off)
      if ( zclSampleLight_OnOff == LIGHT_ON & no == 0 )
      {
        DATA_PIN = 0;
        forward = 0;
        backward = 1;
        
        /*for(int i=0; i<time; i++){
          Onboard_wait(10000);
        }  
    
        forward = 0;
        backward = 0;
        DATA_PIN = 1;*/
        
        no = 1;
      }
      else if ( zclSampleLight_OnOff == LIGHT_OFF & no == 1 )
      {
        DATA_PIN = 0;
        forward = 1;
        backward = 0;
    
        /*for(int i=0; i<time; i++){
          Onboard_wait(10000);
        }         
        forward = 0;
        backward = 0;
        DATA_PIN = 1;*/
        
        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 );
    }
    
    /*********************************************************************
     * @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;
    }
    #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
    
    /****************************************************************************
    ****************************************************************************/
    
    

  • Check if "if ( keys & HAL_KEY_SW_6)" is triggered continuously.
  • I checked and it is not.
  • Check if there is anywhere define event code as 0x0400 which is overlap to TURNOFF_MOTOR__EVT.
  • I couldn't find anything else that uses 0x0400.
  • Can you elaborate your problem again? Is the problem that the motor stops instantly as soon as I press the button SW6?
  • The goal is to get the motor to stop after 5 seconds if neither HAL_KEY_SW_1 or HAL_KEY_SW_2 are pressed. The code your provided me to make the motor stop after 5 seconds doesn't work.
  • Set a breakpoint inside "if ( (keys & HAL_KEY_SW_1) || (keys & HAL_KEY_SW_2) ){...}" of zclSampleLight_HandleKeys to see if it hits when you trigger SW6.
  • I did and SW6 doesn't trigger the breakpoint in there.
  • If you also set breakpoint inside "if( events & TURNOFF_MOTOR__EVT ){..}", does it hit immediately when you trigger SW6?
  • If TURNOFF_MOTOR__EVT 0x0200, then yes, but if TURNOFF_MOTOR__EVT 0x0400, then the breakpoint never hits.
  • If you keep TURNOFF_MOTOR__EVT 0x0400 and check return value of "osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR__EVT, 5000);", what do you see on the return value?
  • How can I check the return value? Also, just checking, is the below code correct?

    In event loop:
    #define TURNOFF_MOTOR_EVT 0x0400
    uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
    {
    if( events & TURNOFF_MOTOR_EVT )
    {
    forward = 0;
    backward = 0;
    DATA_PIN = 1;

    return (events ^ TURNOFF_MOTOR_EVT);
    }


    In HandleKeys:
    static void zclSampleLight_HandleKeys( byte shift, byte keys )
    {
    if ( (keys & HAL_KEY_SW_1) || (keys & HAL_KEY_SW_2) ){
    forward = 0;
    backward = 0;
    DATA_PIN = 1;
    }

    if ( keys & HAL_KEY_SW_6)
    {
    osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
    KeyPressCnt=0;
    osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
    }
  • I see no problem in the code. I remember I had shown you how to check return value of osal_start_timerEx. Anyway, you have to claim a global variable like the followings to get it:

    uint8 ret;
    ...
    ret=osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
  • I get a value of '\0' (0x00).
  • It means event is scheduled correctly. Doesn't it hit "if( events & TURNOFF_MOTOR_EVT ){...}" 5 seconds later?
  • I went back a few steps and fixed some problems and now it works. Thanks. However, sometimes, when I press HAL_KEY_SW_6 to start the button, the motor immediately stops. Why is this so and how can it be fixed? (FYI, most of the time it works)
  • Try to add the following red line to stop previous scheduled TURNOFF_MOTOR_EVT before you start a new one.

    if ( keys & HAL_KEY_SW_6)
    {
    osal_stop_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT);
    osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
    KeyPressCnt=0;
    osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
    }

  • I tried that and it didn't fix the problem unfortunately. I don't believe the problem is about stopping the previous TURNOFF_MOTOR_EVT because the previous one already stopped the motor after 5 seconds. It's just that the 2nd time I press the button, the motor immediately stops instead of waiting 5 seconds. So what do you suggest?
  • Set a breakpoint inside "if ( (keys & HAL_KEY_SW_1) || (keys & HAL_KEY_SW_2) ){..}" and see if it hits when it stops immediately.
  • It does. Why is this so? How can this be fixed?
  • Apparently this is from HAL_KEY_SW_7 (I changed it from 2 to 7). Below is the code. What may be wrong in with HAL_KEY_SW_7?

    /**************************************************************************************************
     *                                            INCLUDES
     **************************************************************************************************/
    #include "hal_mcu.h"
    #include "hal_defs.h"
    #include "hal_types.h"
    #include "hal_board.h"
    #include "hal_drivers.h"
    #include "hal_adc.h"
    #include "hal_key.h"
    #include "osal.h"
    
    #if (defined HAL_KEY) && (HAL_KEY == TRUE)
    
    /**************************************************************************************************
     *                                              MACROS
     **************************************************************************************************/
    
    /**************************************************************************************************
     *                                            CONSTANTS
     **************************************************************************************************/
    #define HAL_KEY_RISING_EDGE   0
    #define HAL_KEY_FALLING_EDGE  1
    
    #define HAL_KEY_DEBOUNCE_VALUE  25
    
    /* CPU port interrupt */
    #define HAL_KEY_CPU_PORT_0_IF P0IF
    #define HAL_KEY_CPU_PORT_1_IF P1IF
    #define HAL_KEY_CPU_PORT_2_IF P2IF
    
    /* SW_6 is at P0.1 */
    #define HAL_KEY_SW_6_PORT   P2
    #define HAL_KEY_SW_6_BIT    BV(0)
    #define HAL_KEY_SW_6_SEL    P2SEL
    #define HAL_KEY_SW_6_DIR    P2DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_6_EDGEBIT  BV(3)
    #define HAL_KEY_SW_6_EDGE     HAL_KEY_RISING_EDGE
    
    
    /* SW_6 interrupts */
    #define HAL_KEY_SW_6_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_6_IENBIT   BV(1) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_6_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_6_ICTLBIT  BV(0) /* P0IEN - P0.1 enable/disable bit */
    #define HAL_KEY_SW_6_PXIFG    P2IFG /* Interrupt flag at source */
    ///////////////////////////////////////////////////////////////////////////
    
    #define HAL_KEY_SW_1_PORT P1
    #define HAL_KEY_SW_1_BIT BV(7)
    #define HAL_KEY_SW_1_SEL P1SEL
    #define HAL_KEY_SW_1_DIR P1DIR
    
    #define HAL_KEY_SW_1_EDGEBIT BV(2)
    #define HAL_KEY_SW_1_EDGE HAL_KEY_RISING_EDGE
    
    #define HAL_KEY_SW_1_IEN IEN2 
    #define HAL_KEY_SW_1_IENBIT BV(4) 
    #define HAL_KEY_SW_1_ICTL P1IEN 
    #define HAL_KEY_SW_1_ICTLBIT BV(7) 
    #define HAL_KEY_SW_1_PXIFG P1IFG
    
    ///////////////////////////////////////////////////////////////////////////
    
    /*#define HAL_KEY_SW_2_PORT P1
    #define HAL_KEY_SW_2_BIT BV(6)
    #define HAL_KEY_SW_2_SEL P1SEL
    #define HAL_KEY_SW_2_DIR P1DIR
    
    #define HAL_KEY_SW_2_EDGEBIT BV(2)
    #define HAL_KEY_SW_2_EDGE HAL_KEY_RISING_EDGE
    
    #define HAL_KEY_SW_2_IEN IEN2 
    #define HAL_KEY_SW_2_IENBIT BV(4) 
    #define HAL_KEY_SW_2_ICTL P1IEN 
    #define HAL_KEY_SW_2_ICTLBIT BV(6) 
    #define HAL_KEY_SW_2_PXIFG P1IFG */
    
    /* SW_7 is at P1.6 */
    #define HAL_KEY_SW_7_PORT   P1
    #define HAL_KEY_SW_7_BIT    BV(6)
    #define HAL_KEY_SW_7_SEL    P1SEL
    #define HAL_KEY_SW_7_DIR    P1DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_7_EDGEBIT  BV(2)
    #define HAL_KEY_SW_7_EDGE     HAL_KEY_FALLING_EDGE
    
    /* SW_7 interrupts */
    #define HAL_KEY_SW_7_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_7_IENBIT   BV(4) /* Mask bit for all of Port_1 */
    #define HAL_KEY_SW_7_ICTL     P1IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_7_ICTLBIT  BV(6) /* P0IEN - P1.6 enable/disable bit */
    #define HAL_KEY_SW_7_PXIFG    P1IFG /* Interrupt flag at source */
    
    
    
    #define port P1_7
    #define port2 P1_6
    
    
    /**************************************************************************************************
     *                                            TYPEDEFS
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     *                                        GLOBAL VARIABLES
     **************************************************************************************************/
    static uint8 halKeySavedKeys;     /* used to store previous key state in polling mode */
    static halKeyCBack_t pHalKeyProcessFunction;
    static uint8 HalKeyConfigured;
    bool Hal_KeyIntEnable;            /* interrupt enable/disable flag */
    
    /**************************************************************************************************
     *                                        FUNCTIONS - Local
     **************************************************************************************************/
    void halProcessKeyInterrupt(void);
    
    
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - API
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     * @fn      HalKeyInit
     *
     * @brief   Initilize Key Service
     *
     * @param   none
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyInit( void )
    {
      /* Initialize previous key to 0 */
      halKeySavedKeys = 0;
    
      HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
      
      HAL_KEY_SW_1_SEL &= ~(HAL_KEY_SW_1_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_1_DIR &= ~(HAL_KEY_SW_1_BIT);    /* Set pin direction to Input */
      
      HAL_KEY_SW_7_SEL &= ~(HAL_KEY_SW_7_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_7_DIR &= ~(HAL_KEY_SW_7_BIT);    /* Set pin direction to Input */
    
    
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyConfig
     *
     * @brief   Configure the Key serivce
     *
     * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
     *          cback - pointer to the CallBack function
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
    
      /* Register the callback fucntion */
      pHalKeyProcessFunction = cback;
    
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
        /* Rising/Falling edge configuratinn */
    
        PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_6_EDGEBIT;
      #endif
        
        PICTL &= ~(HAL_KEY_SW_1_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_1_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_1_EDGEBIT;
      #endif
        
        PICTL &= ~(HAL_KEY_SW_7_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_7_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_7_EDGEBIT;
      #endif
    
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;
        HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT);
        
        HAL_KEY_SW_1_ICTL |= HAL_KEY_SW_1_ICTLBIT;
        HAL_KEY_SW_1_IEN |= HAL_KEY_SW_1_IENBIT;
        HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT);
        
        HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT;
        HAL_KEY_SW_7_IEN |= HAL_KEY_SW_7_IENBIT;
        HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT);
    
    
    
        /* Rising/Falling edge configuratinn */
    
    
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
    
    
    
        /* Do this only after the hal_key is configured - to work with sleep stuff */
        if (HalKeyConfigured == TRUE)
        {
          osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);  /* Cancel polling if active */
        }
      }
      else    /* Interrupts NOT enabled */
      {
        HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */
        
        HAL_KEY_SW_1_ICTL &= ~(HAL_KEY_SW_1_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_1_IEN &= ~(HAL_KEY_SW_1_IENBIT);   /* Clear interrupt enable bit */
        
        HAL_KEY_SW_7_ICTL &= ~(HAL_KEY_SW_7_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_7_IEN &= ~(HAL_KEY_SW_7_IENBIT);   /* Clear interrupt enable bit */
    
    
        osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyRead
     *
     * @brief   Read the current value of a key
     *
     * @param   None
     *
     * @return  keys - current keys status
     **************************************************************************************************/
    uint8 HalKeyRead ( void )
    {
      uint8 keys = 0;
    
      if (P2_0==1/*HAL_PUSH_BUTTON1()*/)
      {
        keys |= HAL_KEY_SW_6;
      }
      
      if (port==1)
      {
        keys |= HAL_KEY_SW_1;
      }
      
      if (port2==1)
      {
        keys |= HAL_KEY_SW_7;
      }
    
    
      return keys;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyPoll
     *
     * @brief   Called by hal_driver to poll the keys
     *
     * @param   None
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyPoll (void)
    {
      uint8 keys = 0;
    
      /* If interrupts are not enabled, previous key status and current key status
       * are compared to find out if a key has changed status.
       */
      if (!Hal_KeyIntEnable)
      {
        if (keys == halKeySavedKeys)
        {
          /* Exit - since no keys have changed */
          return;
        }
        /* Store the current keys for comparation next time */
        halKeySavedKeys = keys;
      }
      else
      {
        /* Key interrupt handled here */
      }
    
      if (P2_0==1/*HAL_PUSH_BUTTON1()*/)
      {
        keys |= HAL_KEY_SW_6;
      }
      
      if (port==1)
      {
        keys |= HAL_KEY_SW_1;
      }
      
      if (port2==1)
      {
        keys |= HAL_KEY_SW_7;
      }
    
      /* Invoke Callback if new keys were depressed */
      if (keys && (pHalKeyProcessFunction))
      {
        (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
      }
    }
    
    /**************************************************************************************************
     * @fn      halGetJoyKeyInput
     *
     * @brief   Map the ADC value to its corresponding key.
     *
     * @param   None
     *
     * @return  keys - current joy key status
     **************************************************************************************************/
    
    
    
    
    
    
    /**************************************************************************************************
     * @fn      halProcessKeyInterrupt
     *
     * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
     *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
      
      if (HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
      
      if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
    
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    }
    
    /**************************************************************************************************
     * @fn      HalKeyEnterSleep
     *
     * @brief  - Get called to enter sleep mode
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void HalKeyEnterSleep ( void )
    {
    }
    
    /**************************************************************************************************
     * @fn      HalKeyExitSleep
     *
     * @brief   - Get called when sleep is over
     *
     * @param
     *
     * @return  - return saved keys
     **************************************************************************************************/
    uint8 HalKeyExitSleep ( void )
    {
      /* Wake up and read keys */
      return ( HalKeyRead () );
    }
    
    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/
    
    /**************************************************************************************************
     * @fn      halKeyPort0Isr
     *
     * @brief   Port0 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    
    HAL_ISR_FUNCTION( halKeyPort1Isr, P1INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT)
      {
        halProcessKeyInterrupt();
      }
      
      if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      HAL_KEY_SW_1_PXIFG = 0;
      HAL_KEY_SW_7_PXIFG = 0;
      
      HAL_KEY_CPU_PORT_1_IF = 0;
      
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    /**************************************************************************************************
     * @fn      halKeyPort2Isr
     *
     * @brief   Port2 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    
    HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      HAL_KEY_SW_6_PXIFG = 0;
      
      HAL_KEY_CPU_PORT_2_IF = 0;
      
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    
    
    
    #else
    
    
    void HalKeyInit(void){}
    void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){}
    uint8 HalKeyRead(void){ return 0;}
    void HalKeyPoll(void){}
    
    #endif /* HAL_KEY */

  • You should check your hal_key.c to see why it sends HAL_KEY_SW_1 or HAL_KEY_SW_2 without triggering them.
  • I keep on getting an error about the HAL_KEY_SW_2_BIT that is configured to P1.7. It says "interger conversion resulted in truncation". What is wrong with the bit and I've done some testing and found out that if I change this to any other value like 0, HAL_KEY_SW_2 doesn't do halProcessKeyInterrupt(), but however HAL_KEY_SW_6 doesn't hit the breakpoint on the below code. So there must be a direct relationship between the bit value of HAL_KEY_SW_2 and HAL_KEY_SW_6 that is causing the problem, but I don't know why this is. What do you think may be the problem? What value should the bit be?

    if ( (keys & HAL_KEY_SW_2) || (keys & HAL_KEY_SW_7) )
    {
    forward = 0;
    backward = 0;
    DATA_PIN = 1;
    }

    /**************************************************************************************************
     *                                            INCLUDES
     **************************************************************************************************/
    #include "hal_mcu.h"
    #include "hal_defs.h"
    #include "hal_types.h"
    #include "hal_board.h"
    #include "hal_drivers.h"
    #include "hal_adc.h"
    #include "hal_key.h"
    #include "osal.h"
    
    #if (defined HAL_KEY) && (HAL_KEY == TRUE)
    
    /**************************************************************************************************
     *                                              MACROS
     **************************************************************************************************/
    
    /**************************************************************************************************
     *                                            CONSTANTS
     **************************************************************************************************/
    #define HAL_KEY_RISING_EDGE   0
    #define HAL_KEY_FALLING_EDGE  1
    
    #define HAL_KEY_DEBOUNCE_VALUE  25
    
    /* CPU port interrupt */
    #define HAL_KEY_CPU_PORT_0_IF P0IF
    #define HAL_KEY_CPU_PORT_1_IF P1IF
    #define HAL_KEY_CPU_PORT_2_IF P2IF
    
    ////////////////////////////////////////////////////////////////////////
    
    /* SW_6 is at P0.1 */
    #define HAL_KEY_SW_6_PORT   P2
    #define HAL_KEY_SW_6_BIT    BV(0)
    #define HAL_KEY_SW_6_SEL    P2SEL
    #define HAL_KEY_SW_6_DIR    P2DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_6_EDGEBIT  BV(3)
    #define HAL_KEY_SW_6_EDGE     HAL_KEY_RISING_EDGE
    
    
    /* SW_6 interrupts */
    #define HAL_KEY_SW_6_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_6_IENBIT   BV(1) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_6_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_6_ICTLBIT  BV(0) /* P0IEN - P0.1 enable/disable bit */
    #define HAL_KEY_SW_6_PXIFG    P2IFG /* Interrupt flag at source */
    
    ////////////////////////////////////////////////////////////////////////
    
    /* SW_2 is at P1.7 */
    #define HAL_KEY_SW_2_PORT   P1
    #define HAL_KEY_SW_2_BIT    BV(7)
    #define HAL_KEY_SW_2_SEL    P1SEL
    #define HAL_KEY_SW_2_DIR    P1DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_2_EDGEBIT  BV(2)
    #define HAL_KEY_SW_2_EDGE     HAL_KEY_RISING_EDGE
    
    /* SW_2 interrupts */
    #define HAL_KEY_SW_2_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_2_IENBIT   BV(4) /* Mask bit for all of Port_1 */
    #define HAL_KEY_SW_2_ICTL     P1IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_2_ICTLBIT  BV(7) /* P0IEN - P1.6 enable/disable bit */
    #define HAL_KEY_SW_2_PXIFG    P1IFG /* Interrupt flag at source */
    
    ////////////////////////////////////////////////////////////////////////
    
    /* SW_7 is at P1.6 */
    #define HAL_KEY_SW_7_PORT   P1
    #define HAL_KEY_SW_7_BIT    BV(6)
    #define HAL_KEY_SW_7_SEL    P1SEL
    #define HAL_KEY_SW_7_DIR    P1DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_7_EDGEBIT  BV(2)
    #define HAL_KEY_SW_7_EDGE     HAL_KEY_RISING_EDGE
    
    /* SW_7 interrupts */
    #define HAL_KEY_SW_7_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_SW_7_IENBIT   BV(4) /* Mask bit for all of Port_1 */
    #define HAL_KEY_SW_7_ICTL     P1IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_7_ICTLBIT  BV(6) /* P0IEN - P1.6 enable/disable bit */
    #define HAL_KEY_SW_7_PXIFG    P1IFG /* Interrupt flag at source */
    
    ////////////////////////////////////////////////////////////////////////
    
    /* Joy stick move at P2.0 */
    #define HAL_KEY_JOY_MOVE_PORT   P2
    #define HAL_KEY_JOY_MOVE_BIT    BV(0)
    #define HAL_KEY_JOY_MOVE_SEL    P2SEL
    #define HAL_KEY_JOY_MOVE_DIR    P2DIR
    
    /* edge interrupt */
    #define HAL_KEY_JOY_MOVE_EDGEBIT  BV(3)
    #define HAL_KEY_JOY_MOVE_EDGE     HAL_KEY_FALLING_EDGE
    
    /* Joy move interrupts */
    #define HAL_KEY_JOY_MOVE_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_JOY_MOVE_IENBIT   BV(1) /* Mask bit for all of Port_2 */
    #define HAL_KEY_JOY_MOVE_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_JOY_MOVE_ICTLBIT  BV(0) /* P2IENL - P2.0<->P2.3 enable/disable bit */
    #define HAL_KEY_JOY_MOVE_PXIFG    P2IFG /* Interrupt flag at source */
    
    #define HAL_KEY_JOY_CHN   HAL_ADC_CHANNEL_6
    
    
    /**************************************************************************************************
     *                                            TYPEDEFS
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     *                                        GLOBAL VARIABLES
     **************************************************************************************************/
    static uint8 halKeySavedKeys;     /* used to store previous key state in polling mode */
    static halKeyCBack_t pHalKeyProcessFunction;
    static uint8 HalKeyConfigured;
    bool Hal_KeyIntEnable;            /* interrupt enable/disable flag */
    
    /**************************************************************************************************
     *                                        FUNCTIONS - Local
     **************************************************************************************************/
    void halProcessKeyInterrupt(void);
    uint8 halGetJoyKeyInput(void);
    
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - API
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     * @fn      HalKeyInit
     *
     * @brief   Initilize Key Service
     *
     * @param   none
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyInit( void )
    {
      /* Initialize previous key to 0 */
      halKeySavedKeys = 0;
    
      HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
        
      HAL_KEY_SW_2_SEL &= ~(HAL_KEY_SW_2_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_2_DIR &= ~(HAL_KEY_SW_2_BIT);    /* Set pin direction to Input */
    
      HAL_KEY_SW_7_SEL &= ~(HAL_KEY_SW_7_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_7_DIR &= ~(HAL_KEY_SW_7_BIT);    /* Set pin direction to Input */
    
      HAL_KEY_JOY_MOVE_SEL &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */
      HAL_KEY_JOY_MOVE_DIR &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */
    
    
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyConfig
     *
     * @brief   Configure the Key serivce
     *
     * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
     *          cback - pointer to the CallBack function
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
    
      /* Register the callback fucntion */
      pHalKeyProcessFunction = cback;
    
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
        /* Rising/Falling edge configuratinn */
    
        PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_6_EDGEBIT;
      #endif
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;
        HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT);
        
        PICTL &= ~(HAL_KEY_SW_2_EDGEBIT);    /* Clear the edge bit SW_7*/
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_2_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_2_EDGEBIT;
      #endif
    
    
        /* Interrupt configuration: SW_7
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_SW_2_ICTL |= HAL_KEY_SW_2_ICTLBIT;
        HAL_KEY_SW_2_IEN |= HAL_KEY_SW_2_IENBIT;
        HAL_KEY_SW_2_PXIFG = ~(HAL_KEY_SW_2_BIT);
        
    
        PICTL &= ~(HAL_KEY_SW_7_EDGEBIT);    /* Clear the edge bit SW_7*/
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_7_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_7_EDGEBIT;
      #endif
    
    
        /* Interrupt configuration: SW_7
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT;
        HAL_KEY_SW_7_IEN |= HAL_KEY_SW_7_IENBIT;
        HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT);
    
    
        /* Rising/Falling edge configuratinn */
    
        HAL_KEY_JOY_MOVE_ICTL &= ~(HAL_KEY_JOY_MOVE_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE)
        HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_EDGEBIT;
      #endif
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_ICTLBIT;
        HAL_KEY_JOY_MOVE_IEN |= HAL_KEY_JOY_MOVE_IENBIT;
        HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT);
    
    
        /* Do this only after the hal_key is configured - to work with sleep stuff */
        if (HalKeyConfigured == TRUE)
        {
          osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);  /* Cancel polling if active */
        }
      }
      else    /* Interrupts NOT enabled */
      {
        HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */
        
        HAL_KEY_SW_2_ICTL &= ~(HAL_KEY_SW_2_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_2_IEN &= ~(HAL_KEY_SW_2_IENBIT);   /* Clear interrupt enable bit */
        
        HAL_KEY_SW_7_ICTL &= ~(HAL_KEY_SW_7_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_7_IEN &= ~(HAL_KEY_SW_7_IENBIT);   /* Clear interrupt enable bit */
    
        osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyRead
     *
     * @brief   Read the current value of a key
     *
     * @param   None
     *
     * @return  keys - current keys status
     **************************************************************************************************/
    uint8 HalKeyRead ( void )
    {
      uint8 keys = 0;
    
      if (HAL_PUSH_BUTTON1())
      {
        keys |= HAL_KEY_SW_6;
      }
    
      if (P1_7==0)
      {
        keys |= HAL_KEY_SW_2;
      }
      
      if (P1_6==0)
      {
        keys |= HAL_KEY_SW_7;
      }
    
      if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT))  /* Key is active low */
      {
        keys |= halGetJoyKeyInput();
      }
    
      return keys;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyPoll
     *
     * @brief   Called by hal_driver to poll the keys
     *
     * @param   None
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyPoll (void)
    {
      uint8 keys = 0;
    
      if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT))  /* Key is active HIGH */
      {
        keys = halGetJoyKeyInput();
      }
    
      /* If interrupts are not enabled, previous key status and current key status
       * are compared to find out if a key has changed status.
       */
      if (!Hal_KeyIntEnable)
      {
        if (keys == halKeySavedKeys)
        {
          /* Exit - since no keys have changed */
          return;
        }
        /* Store the current keys for comparation next time */
        halKeySavedKeys = keys;
      }
      else
      {
        /* Key interrupt handled here */
      }
    
      if (HAL_PUSH_BUTTON1())
      {
        keys |= HAL_KEY_SW_6;
      }
      
      if (P1_7==0)
      {
        keys |= HAL_KEY_SW_2;
      }
    
      if (P1_6==0)
      {
        keys |= HAL_KEY_SW_7;
      }
      
      /* Invoke Callback if new keys were depressed */
      if (keys && (pHalKeyProcessFunction))
      {
        (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
      }
    }
    
    /**************************************************************************************************
     * @fn      halGetJoyKeyInput
     *
     * @brief   Map the ADC value to its corresponding key.
     *
     * @param   None
     *
     * @return  keys - current joy key status
     **************************************************************************************************/
    uint8 halGetJoyKeyInput(void)
    {
      /* The joystick control is encoded as an analog voltage.
       * Read the JOY_LEVEL analog value and map it to joy movement.
       */
      uint8 adc;
      uint8 ksave0 = 0;
      uint8 ksave1;
    
      /* Keep on reading the ADC until two consecutive key decisions are the same. */
      do
      {
        ksave1 = ksave0;    /* save previouse key reading */
    
        adc = HalAdcRead (HAL_KEY_JOY_CHN, HAL_ADC_RESOLUTION_8);
    
        if ((adc >= 2) && (adc <= 38))
        {
           ksave0 |= HAL_KEY_UP;
        }
        else if ((adc >= 74) && (adc <= 88))
        {
          ksave0 |= HAL_KEY_RIGHT;
        }
        else if ((adc >= 60) && (adc <= 73))
        {
          ksave0 |= HAL_KEY_LEFT;
        }
        else if ((adc >= 39) && (adc <= 59))
        {
          ksave0 |= HAL_KEY_DOWN;
        }
        else if ((adc >= 89) && (adc <= 100))
        {
          ksave0 |= HAL_KEY_CENTER;
        }
      } while (ksave0 != ksave1);
    
      return ksave0;
    }
    
    
    
    
    
    /**************************************************************************************************
     * @fn      halProcessKeyInterrupt
     *
     * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
     *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
      
      if (HAL_KEY_SW_2_PXIFG & HAL_KEY_SW_2_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_2_PXIFG = ~(HAL_KEY_SW_2_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    }
    
    /**************************************************************************************************
     * @fn      HalKeyEnterSleep
     *
     * @brief  - Get called to enter sleep mode
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void HalKeyEnterSleep ( void )
    {
    }
    
    /**************************************************************************************************
     * @fn      HalKeyExitSleep
     *
     * @brief   - Get called when sleep is over
     *
     * @param
     *
     * @return  - return saved keys
     **************************************************************************************************/
    uint8 HalKeyExitSleep ( void )
    {
      /* Wake up and read keys */
      return ( HalKeyRead () );
    }
    
    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/
    
    /**************************************************************************************************
     * @fn      halKeyPort0Isr
     *
     * @brief   Port0 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    /*HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      
        //Clear the CPU interrupt flag for Port_0
        //PxIFG has to be cleared before PxIF
      
      HAL_KEY_SW_6_PXIFG = 0;
      HAL_KEY_CPU_PORT_0_IF = 0;
      
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }*/
    
    /**************************************************************************************************
     * @fn      halKeyPort1Isr
     *
     * @brief   Port1 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort1Isr, P1INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_SW_2_PXIFG & HAL_KEY_SW_2_BIT)
      {
        halProcessKeyInterrupt();
      }
      if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      HAL_KEY_SW_2_PXIFG = 0;
      HAL_KEY_SW_7_PXIFG = 0;
      HAL_KEY_CPU_PORT_1_IF = 0;
      
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    /**************************************************************************************************
     * @fn      halKeyPort2Isr
     *
     * @brief   Port2 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR )
    {
      HAL_ENTER_ISR();
      
      if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)
      {
        halProcessKeyInterrupt();
      }
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      /*
        Clear the CPU interrupt flag for Port_2
        PxIFG has to be cleared before PxIF
        Notes: P2_1 and P2_2 are debug lines.
      */
      HAL_KEY_JOY_MOVE_PXIFG = 0;
      HAL_KEY_SW_6_PXIFG = 0;
      HAL_KEY_CPU_PORT_2_IF = 0;
    
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    #else
    
    
    void HalKeyInit(void){}
    void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){}
    uint8 HalKeyRead(void){ return 0;}
    void HalKeyPoll(void){}
    
    #endif /* HAL_KEY */

  • Set a breakpoint in the following two red lines to check if they hit.

     if (P1_7==0)

     {

       keys |= HAL_KEY_SW_2;

     }

     if (P1_6==0)

     {

       keys |= HAL_KEY_SW_7;

     }

  • I did and sometimes keys |= HAL_KEY_SW_2 is hit, but it isn't always hit unlike keys |= HAL_KEY_SW_6. The breakpoint at keys |= HAL_KEY_SW_7 is never hit.