Hi,
I have a problem where in SampleLight, once a button is pressed on P1.7, the power consumption is high and stays high as long as the button is still pressed. I currently have P1.7 set to Rising Edge. How do I fix it so that when P1.7 is pressed and held, there isn't any power consumption?
/*********************************************************************
* INCLUDES
*/
#include "ZComDef.h"
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "MT_SYS.h"
#include "nwk_util.h"
#include "zcl.h"
#include "zcl_general.h"
#include "zcl_ha.h"
#include "zcl_ezmode.h"
#include "zcl_diagnostic.h"
#include "zcl_samplelight.h"
#include "onboard.h"
/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#if ( defined (ZGP_DEVICE_TARGET) || defined (ZGP_DEVICE_TARGETPLUS) \
|| defined (ZGP_DEVICE_COMBO) || defined (ZGP_DEVICE_COMBO_MIN) )
#include "zgp_translationtable.h"
#if (SUPPORTED_S_FEATURE(SUPP_ZGP_FEATURE_TRANSLATION_TABLE))
#define ZGP_AUTO_TT
#endif
#endif
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
#include "math.h"
#include "hal_timer.h"
#endif
#include "NLMEDE.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
#if (defined HAL_BOARD_ZLIGHT)
#define LEVEL_MAX 0xFE
#define LEVEL_MIN 0x0
#define GAMMA_VALUE 2
#define PWM_FULL_DUTY_CYCLE 1000
#elif (defined HAL_PWM)
#define LEVEL_MAX 0xFE
#define LEVEL_MIN 0x0
#define GAMMA_VALUE 2
#define PWM_FULL_DUTY_CYCLE 100
#endif
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
byte zclSampleLight_TaskID;
uint8 zclSampleLightSeqNum;
/*********************************************************************
* GLOBAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
afAddrType_t zclSampleLight_DstAddr;
#ifdef ZCL_EZMODE
static void zclSampleLight_ProcessZDOMsgs( zdoIncomingMsg_t *pMsg );
static void zclSampleLight_EZModeCB( zlcEZMode_State_t state, zclEZMode_CBData_t *pData );
// register EZ-Mode with task information (timeout events, callback, etc...)
static const zclEZMode_RegisterData_t zclSampleLight_RegisterEZModeData =
{
&zclSampleLight_TaskID,
SAMPLELIGHT_EZMODE_NEXTSTATE_EVT,
SAMPLELIGHT_EZMODE_TIMEOUT_EVT,
&zclSampleLightSeqNum,
zclSampleLight_EZModeCB
};
#else
uint16 bindingInClusters[] =
{
ZCL_CLUSTER_ID_GEN_ON_OFF
#ifdef ZCL_LEVEL_CTRL
, ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL
#endif
};
#define ZCLSAMPLELIGHT_BINDINGLIST (sizeof(bindingInClusters) / sizeof(bindingInClusters[0]))
#endif // ZCL_EZMODE
// Test Endpoint to allow SYS_APP_MSGs
static endPointDesc_t sampleLight_TestEp =
{
SAMPLELIGHT_ENDPOINT,
&zclSampleLight_TaskID,
(SimpleDescriptionFormat_t *)NULL, // No Simple description for this test endpoint
(afNetworkLatencyReq_t)0 // No Network Latency req
};
uint8 giLightScreenMode = LIGHT_MAINMODE; // display the main screen mode first
uint8 gPermitDuration = 0; // permit joining default to disabled
devStates_t zclSampleLight_NwkState = DEV_INIT;
#if ZCL_LEVEL_CTRL
uint8 zclSampleLight_WithOnOff; // set to TRUE if state machine should set light on/off
uint8 zclSampleLight_NewLevel; // new level when done moving
bool zclSampleLight_NewLevelUp; // is direction to new level up or down?
int32 zclSampleLight_CurrentLevel32; // current level, fixed point (e.g. 192.456)
int32 zclSampleLight_Rate32; // rate in units, fixed point (e.g. 16.123)
uint8 zclSampleLight_LevelLastLevel; // to save the Current Level before the light was turned OFF
#endif
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void zclSampleLight_HandleKeys( byte shift, byte keys );
static void zclSampleLight_BasicResetCB( void );
static void zclSampleLight_IdentifyCB( zclIdentify_t *pCmd );
static void zclSampleLight_IdentifyQueryRspCB( zclIdentifyQueryRsp_t *pRsp );
static void zclSampleLight_OnOffCB( uint8 cmd );
static void zclSampleLight_ProcessIdentifyTimeChange( void );
#ifdef ZCL_LEVEL_CTRL
static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd );
static void zclSampleLight_LevelControlMoveCB( zclLCMove_t *pCmd );
static void zclSampleLight_LevelControlStepCB( zclLCStep_t *pCmd );
static void zclSampleLight_LevelControlStopCB( void );
static void zclSampleLight_DefaultMove( void );
static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel );
static uint16 zclSampleLight_GetTime ( uint8 level, uint16 time );
static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate );
static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time );
static void zclSampleLight_AdjustLightLevel( void );
#endif
// app display functions
static void zclSampleLight_LcdDisplayUpdate( void );
#ifdef LCD_SUPPORTED
static void zclSampleLight_LcdDisplayMainMode( void );
static void zclSampleLight_LcdDisplayHelpMode( void );
#endif
static void zclSampleLight_DisplayLight( void );
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
void zclSampleLight_UpdateLampLevel( uint8 level );
#endif
// Functions to process ZCL Foundation incoming Command/Response messages
static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *msg );
#ifdef ZCL_READ
static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
#endif
#ifdef ZCL_WRITE
static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
#endif
static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
#ifdef ZCL_DISCOVER
static uint8 zclSampleLight_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg );
static uint8 zclSampleLight_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg );
static uint8 zclSampleLight_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg );
#endif
/*********************************************************************
* STATUS STRINGS
*/
#ifdef LCD_SUPPORTED
const char sDeviceName[] = " Sample Light";
const char sClearLine[] = " ";
const char sSwLight[] = "SW1: ToggleLight"; // 16 chars max
const char sSwEZMode[] = "SW2: EZ-Mode";
char sSwHelp[] = "SW5: Help "; // last character is * if NWK open
const char sLightOn[] = " LIGHT ON ";
const char sLightOff[] = " LIGHT OFF";
#if ZCL_LEVEL_CTRL
char sLightLevel[] = " LEVEL ###"; // displays level 1-254
#endif
#endif
/*********************************************************************
* ZCL General Profile Callback table
*/
static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks =
{
zclSampleLight_BasicResetCB, // Basic Cluster Reset command
zclSampleLight_IdentifyCB, // Identify command
#ifdef ZCL_EZMODE
NULL, // Identify EZ-Mode Invoke command
NULL, // Identify Update Commission State command
#endif
NULL, // Identify Trigger Effect command
zclSampleLight_IdentifyQueryRspCB, // Identify Query Response command
zclSampleLight_OnOffCB, // On/Off cluster commands
NULL, // On/Off cluster enhanced command Off with Effect
NULL, // On/Off cluster enhanced command On with Recall Global Scene
NULL, // On/Off cluster enhanced command On with Timed Off
#ifdef ZCL_LEVEL_CTRL
zclSampleLight_LevelControlMoveToLevelCB, // Level Control Move to Level command
zclSampleLight_LevelControlMoveCB, // Level Control Move command
zclSampleLight_LevelControlStepCB, // Level Control Step command
zclSampleLight_LevelControlStopCB, // Level Control Stop command
#endif
#ifdef ZCL_GROUPS
NULL, // Group Response commands
#endif
#ifdef ZCL_SCENES
NULL, // Scene Store Request command
NULL, // Scene Recall Request command
NULL, // Scene Response command
#endif
#ifdef ZCL_ALARMS
NULL, // Alarm (Response) commands
#endif
#ifdef SE_UK_EXT
NULL, // Get Event Log command
NULL, // Publish Event Log command
#endif
NULL, // RSSI Location command
NULL // RSSI Location Response command
};
/*********************************************************************
* @fn zclSampleLight_Init
*
* @brief Initialization function for the zclGeneral layer.
*
* @param none
*
* @return none
*/
#define enable P0_6
#define phase P0_5
#define pin P1_4
#define time 110
static int no = 0;
#define PERIODIC_EVT 0x4000
#define PERIODIC_EVT2 0x0001
#define PERIODIC_EVT3 0x0002
#define PERIODIC_EVT4 0x0005
#define TURNOFF_MOTOR_EVT 0x0400
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 );
osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3, 10 );
osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 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
P0SEL &= (~((BV(5))|(BV(6))));
P0DIR |= ((BV(5))|(BV(6)));
P1SEL &= (~(BV(7)));
P1DIR |= ((BV(7)));
P1_7=0;
P2SEL &= (~(BV(0)));
P2DIR |= (BV(0));
P2_0=0;
P1DIR |= 0x01;
//P1DIR |= 0x13;
enable=0;
phase=0;
pin=0;
no = 1;
zclSampleLight_OnOff = LIGHT_ON;
zclReportCmd_t rptcmd;
rptcmd.numAttr = 1;
rptcmd.attrList[0].attrID = ATTRID_ON_OFF;
rptcmd.attrList[0].dataType = ZCL_DATATYPE_BOOLEAN;
rptcmd.attrList[0].attrData = (uint8*)&zclSampleLight_OnOff;
// Set destination address to indirect
zclSampleLight_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
zclSampleLight_DstAddr.addr.shortAddr = 0;
zclSampleLight_DstAddr.endPoint=1;
zcl_SendReportCmd(SAMPLELIGHT_ENDPOINT,&zclSampleLight_DstAddr, ZCL_CLUSTER_ID_GEN_ON_OFF, &rptcmd, ZCL_FRAME_CLIENT_SERVER_DIR, false, 0 );
ZDApp_ChangeState(DEV_NWK_DISC);
// Restart scan for rejoin
ZDApp_StartJoiningCycle();
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>
#include <OSAL_PwrMgr.h>
#define KEYHOLD_EVT 0x0100 //define event for key hold
int KeyPressCnt=0;
uint8 ret;
uint16 adc_ain2;
int n=1;
int g=0;
int k=0;
int p=0;
uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
{
if(DEV_NWK_BACKOFF){
pwrmgr_attribute.pwrmgr_device = PWRMGR_BATTERY;
if(devState==DEV_NWK_BACKOFF && devState!=DEV_END_DEVICE & zgDefaultRejoinScan>=5000){
g=1;
}
else{
k=0;
pin=0;
g=0;
//osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT );
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3 );
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
}
}
if( events & TURNOFF_MOTOR_EVT )
{
enable = 0;
phase = 0;
p=0;
return (events ^ TURNOFF_MOTOR_EVT);
}
if ( events & KEYHOLD_EVT)
{
if ( P2_0==1 )
{
if (KeyPressCnt>40){
KeyPressCnt=0;
extern void ZDApp_ResetTimerStart( uint16 delay );
zgWriteStartupOptions(ZG_STARTUP_SET, (ZCD_STARTOPT_DEFAULT_NETWORK_STATE | ZCD_STARTOPT_DEFAULT_CONFIG_STATE) );
pin=1;
for(int i=0; i<500; i++){
Onboard_wait(10000);
}
//SystemResetSoft();
//ZDApp_ResetTimerStart(2000);
/* ZDApp_ChangeState(DEV_NWK_DISC);
ZDApp_StartJoiningCycle();
osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );
g=1;*/
}
else{
KeyPressCnt++;
osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
}
}
return ( events ^ KEYHOLD_EVT );
}
if( events & PERIODIC_EVT3 ){
pin=1;
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3 );
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4, 500 );
return (events ^ PERIODIC_EVT3);
}
if( events & PERIODIC_EVT4 ){
pin=0;
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3 );
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3, 500 );
return (events ^ PERIODIC_EVT4);
}
if( events & PERIODIC_EVT )
{
HalAdcSetReference(HAL_ADC_REF_125V);
adc_ain2=HalAdcRead(HAL_ADC_CHN_AIN1,HAL_ADC_RESOLUTION_10);
if(adc_ain2<172 & adc_ain2>120 & P2_0==0){ //172=2.75v //177=3v //188=3.3v //160=2.5v
if(k==0 & p==0){
k=1;
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3 );
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
osal_start_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3, 500 );
}
}else if(adc_ain2>=172 & adc_ain2>120){
k=0;
pin=0;
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT3 );
osal_stop_timerEx( zclSampleLight_TaskID, PERIODIC_EVT4 );
}
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
*/
int tell=0;
static void zclSampleLight_HandleKeys( byte shift, byte keys )
{
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 );
if ( keys & HAL_KEY_SW_2 )
{
enable = 0;
phase = 0;
p=0;
}
if ( keys & HAL_KEY_SW_1 )
{
if(g==1){
ZDApp_ChangeState(DEV_NWK_DISC);
ZDApp_StartJoiningCycle();
osal_start_timerEx( ZDAppTaskID, ZDO_REJOIN_BACKOFF, zgDefaultRejoinScan );
g=0;
}
while(P1_7==1){
if(no==0){
enable = 1;
phase = 1;
p=0;
}
else if(no==1){
enable = 1;
phase = 0;
p=0;
}
}
p=1;
KeyPressCnt=0;
osal_start_timerEx( zclSampleLight_TaskID, KEYHOLD_EVT, 100);
zclSampleLight_OnOff = zclSampleLight_OnOff ? LIGHT_OFF : LIGHT_ON;
for(int i=0; i<30; i++){
Onboard_wait(10000);
}
}
/*if ( keys & HAL_KEY_SW_2 )
{
#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 );
}
#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
}
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
osal_start_timerEx( zclSampleLight_TaskID, TURNOFF_MOTOR_EVT, 5000);
zclReportCmd_t rptcmd;
rptcmd.numAttr = 1;
rptcmd.attrList[0].attrID = ATTRID_ON_OFF;
rptcmd.attrList[0].dataType = ZCL_DATATYPE_BOOLEAN;
rptcmd.attrList[0].attrData = (uint8*)&zclSampleLight_OnOff;
// Set destination address to indirect
zclSampleLight_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
zclSampleLight_DstAddr.addr.shortAddr = 0;
zclSampleLight_DstAddr.endPoint=1;
zcl_SendReportCmd(SAMPLELIGHT_ENDPOINT,&zclSampleLight_DstAddr, ZCL_CLUSTER_ID_GEN_ON_OFF, &rptcmd, ZCL_FRAME_CLIENT_SERVER_DIR, false, 0 );
zclSampleLight_DisplayLight();
}
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
/*********************************************************************
* @fn zclSampleLight_UpdateLampLevel
*
* @brief Update lamp level output with gamma compensation
*
* @param level
*
* @return none
*/
void zclSampleLight_UpdateLampLevel( uint8 level )
{
uint16 gammaCorrectedLevel;
// gamma correct the level
gammaCorrectedLevel = (uint16) ( pow( ( (float)level / LEVEL_MAX ), (float)GAMMA_VALUE ) * (float)LEVEL_MAX);
halTimer1SetChannelDuty(WHITE_LED, (uint16)(((uint32)gammaCorrectedLevel*PWM_FULL_DUTY_CYCLE)/LEVEL_MAX) );
}
#endif
/*********************************************************************
* @fn zclSampleLight_DisplayLight
*
* @brief Displays current state of light on LED and also on main display if supported.
*
* @param none
*
* @return none
*/
static void zclSampleLight_DisplayLight( void )
{
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 );
if ( zclSampleLight_OnOff == LIGHT_ON & no == 0 )
{
enable = 1;
phase = 1;
no = 1;
}
else if ( zclSampleLight_OnOff == LIGHT_OFF & no == 1 )
{
enable = 1;
phase = 0;
no = 0;
}
#ifdef LCD_SUPPORTED
if (giLightScreenMode == LIGHT_MAINMODE)
{
#ifdef ZCL_LEVEL_CTRL
// display current light level
if ( ( zclSampleLight_LevelCurrentLevel == ATTR_LEVEL_MIN_LEVEL ) &&
( zclSampleLight_OnOff == LIGHT_OFF ) )
{
HalLcdWriteString( (char *)sLightOff, HAL_LCD_LINE_2 );
}
else if ( ( zclSampleLight_LevelCurrentLevel >= ATTR_LEVEL_MAX_LEVEL ) ||
( zclSampleLight_LevelCurrentLevel == zclSampleLight_LevelOnLevel ) ||
( ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT ) &&
( zclSampleLight_LevelCurrentLevel == zclSampleLight_LevelLastLevel ) ) )
{
HalLcdWriteString( (char *)sLightOn, HAL_LCD_LINE_2 );
}
else // " LEVEL ###"
{
zclHA_uint8toa( zclSampleLight_LevelCurrentLevel, &sLightLevel[10] );
HalLcdWriteString( (char *)sLightLevel, HAL_LCD_LINE_2 );
}
#else
if ( zclSampleLight_OnOff )
{
HalLcdWriteString( (char *)sLightOn, HAL_LCD_LINE_2 );
}
else
{
HalLcdWriteString( (char *)sLightOff, HAL_LCD_LINE_2 );
}
#endif // ZCL_LEVEL_CTRL
}
#endif // LCD_SUPPORTED
}
#ifdef LCD_SUPPORTED
/*********************************************************************
* @fn zclSampleLight_LcdDisplayMainMode
*
* @brief Called to display the main screen on the LCD.
*
* @param none
*
* @return none
*/
static void zclSampleLight_LcdDisplayMainMode( void )
{
// display line 1 to indicate NWK status
if ( zclSampleLight_NwkState == DEV_ZB_COORD )
{
zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZC );
}
else if ( zclSampleLight_NwkState == DEV_ROUTER )
{
zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZR );
}
else if ( zclSampleLight_NwkState == DEV_END_DEVICE )
{
zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZED );
}
// end of line 3 displays permit join status (*)
if ( gPermitDuration )
{
sSwHelp[15] = '*';
}
else
{
sSwHelp[15] = ' ';
}
HalLcdWriteString( (char *)sSwHelp, HAL_LCD_LINE_3 );
}
/*********************************************************************
* @fn zclSampleLight_LcdDisplayHelpMode
*
* @brief Called to display the SW options on the LCD.
*
* @param none
*
* @return none
*/
static void zclSampleLight_LcdDisplayHelpMode( void )
{
HalLcdWriteString( (char *)sSwLight, HAL_LCD_LINE_1 );
HalLcdWriteString( (char *)sSwEZMode, HAL_LCD_LINE_2 );
HalLcdWriteString( (char *)sSwHelp, HAL_LCD_LINE_3 );
}
#endif // LCD_SUPPORTED
/*********************************************************************
* @fn zclSampleLight_ProcessIdentifyTimeChange
*
* @brief Called to process any change to the IdentifyTime attribute.
*
* @param none
*
* @return none
*/
static void zclSampleLight_ProcessIdentifyTimeChange( void )
{
if ( zclSampleLight_IdentifyTime > 0 )
{
osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT, 1000 );
HalLedBlink ( HAL_LED_4, 0xFF, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME );
}
else
{
#ifdef ZCL_EZMODE
if ( zclSampleLight_IdentifyCommissionState & EZMODE_COMMISSION_OPERATIONAL )
{
HalLedSet ( HAL_LED_4, HAL_LED_MODE_ON );
}
else
{
HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
}
#endif
osal_stop_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT );
}
}
/*********************************************************************
* @fn zclSampleLight_BasicResetCB
*
* @brief Callback from the ZCL General Cluster Library
* to set all the Basic Cluster attributes to default values.
*
* @param none
*
* @return none
*/
static void zclSampleLight_BasicResetCB( void )
{
NLME_LeaveReq_t leaveReq;
// Set every field to 0
osal_memset( &leaveReq, 0, sizeof( NLME_LeaveReq_t ) );
// This will enable the device to rejoin the network after reset.
leaveReq.rejoin = TRUE;
// Set the NV startup option to force a "new" join.
zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
// Leave the network, and reset afterwards
if ( NLME_LeaveReq( &leaveReq ) != ZSuccess )
{
// Couldn't send out leave; prepare to reset anyway
ZDApp_LeaveReset( FALSE );
}
}
/*********************************************************************
* @fn zclSampleLight_IdentifyCB
*
* @brief Callback from the ZCL General Cluster Library when
* it received an Identity Command for this application.
*
* @param srcAddr - source address and endpoint of the response message
* @param identifyTime - the number of seconds to identify yourself
*
* @return none
*/
static void zclSampleLight_IdentifyCB( zclIdentify_t *pCmd )
{
zclSampleLight_IdentifyTime = pCmd->identifyTime;
zclSampleLight_ProcessIdentifyTimeChange();
}
/*********************************************************************
* @fn zclSampleLight_IdentifyQueryRspCB
*
* @brief Callback from the ZCL General Cluster Library when
* it received an Identity Query Response Command for this application.
*
* @param srcAddr - requestor's address
* @param timeout - number of seconds to identify yourself (valid for query response)
*
* @return none
*/
static void zclSampleLight_IdentifyQueryRspCB( zclIdentifyQueryRsp_t *pRsp )
{
(void)pRsp;
#ifdef ZCL_EZMODE
{
zclEZMode_ActionData_t data;
data.pIdentifyQueryRsp = pRsp;
zcl_EZModeAction ( EZMODE_ACTION_IDENTIFY_QUERY_RSP, &data );
}
#endif
}
/*********************************************************************
* @fn zclSampleLight_OnOffCB
*
* @brief Callback from the ZCL General Cluster Library when
* it received an On/Off Command for this application.
*
* @param cmd - COMMAND_ON, COMMAND_OFF or COMMAND_TOGGLE
*
* @return none
*/
static void zclSampleLight_OnOffCB( uint8 cmd )
{
afIncomingMSGPacket_t *pPtr = zcl_getRawAFMsg();
zclSampleLight_DstAddr.addr.shortAddr = pPtr->srcAddr.addr.shortAddr;
// Turn on the light
if ( cmd == COMMAND_ON )
{
zclSampleLight_OnOff = LIGHT_ON;
}
// Turn off the light
else if ( cmd == COMMAND_OFF )
{
zclSampleLight_OnOff = LIGHT_OFF;
}
// Toggle the light
else if ( cmd == COMMAND_TOGGLE )
{
if ( zclSampleLight_OnOff == LIGHT_OFF )
{
zclSampleLight_OnOff = LIGHT_ON;
}
else
{
zclSampleLight_OnOff = LIGHT_OFF;
}
}
#if ZCL_LEVEL_CTRL
zclSampleLight_DefaultMove( );
#endif
// update the display
zclSampleLight_LcdDisplayUpdate( );
}
#ifdef ZCL_LEVEL_CTRL
/*********************************************************************
* @fn zclSampleLight_TimeRateHelper
*
* @brief Calculate time based on rate, and startup level state machine
*
* @param newLevel - new level for current level
*
* @return diff (directly), zclSampleLight_CurrentLevel32 and zclSampleLight_NewLevel, zclSampleLight_NewLevelUp
*/
static uint32 zclSampleLight_TimeRateHelper( uint8 newLevel )
{
uint32 diff;
uint32 newLevel32;
// remember current and new level
zclSampleLight_NewLevel = newLevel;
zclSampleLight_CurrentLevel32 = (uint32)1000 * zclSampleLight_LevelCurrentLevel;
// calculate diff
newLevel32 = (uint32)1000 * newLevel;
if ( zclSampleLight_LevelCurrentLevel > newLevel )
{
diff = zclSampleLight_CurrentLevel32 - newLevel32;
zclSampleLight_NewLevelUp = FALSE; // moving down
}
else
{
diff = newLevel32 - zclSampleLight_CurrentLevel32;
zclSampleLight_NewLevelUp = TRUE; // moving up
}
return ( diff );
}
/*********************************************************************
* @fn zclSampleLight_MoveBasedOnRate
*
* @brief Calculate time based on rate, and startup level state machine
*
* @param newLevel - new level for current level
* @param rate16 - fixed point rate (e.g. 16.123)
*
* @return none
*/
static void zclSampleLight_MoveBasedOnRate( uint8 newLevel, uint32 rate )
{
uint32 diff;
// determine how much time (in 10ths of seconds) based on the difference and rate
zclSampleLight_Rate32 = rate;
diff = zclSampleLight_TimeRateHelper( newLevel );
zclSampleLight_LevelRemainingTime = diff / rate;
if ( !zclSampleLight_LevelRemainingTime )
{
zclSampleLight_LevelRemainingTime = 1;
}
osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
}
/*********************************************************************
* @fn zclSampleLight_MoveBasedOnTime
*
* @brief Calculate rate based on time, and startup level state machine
*
* @param newLevel - new level for current level
* @param time - in 10ths of seconds
*
* @return none
*/
static void zclSampleLight_MoveBasedOnTime( uint8 newLevel, uint16 time )
{
uint16 diff;
// determine rate (in units) based on difference and time
diff = zclSampleLight_TimeRateHelper( newLevel );
zclSampleLight_LevelRemainingTime = zclSampleLight_GetTime( newLevel, time );
zclSampleLight_Rate32 = diff / time;
osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
}
/*********************************************************************
* @fn zclSampleLight_GetTime
*
* @brief Determine amount of time that MoveXXX will take to complete.
*
* @param level = new level to move to
* time = 0xffff=default, or 0x0000-n amount of time in tenths of seconds.
*
* @return none
*/
static uint16 zclSampleLight_GetTime( uint8 level, uint16 time )
{
// there is a hiearchy of the amount of time to use for transistioning
// check each one in turn. If none of defaults are set, then use fastest
// time possible.
if ( time == 0xFFFF )
{
// use On or Off Transition Time if set (not 0xffff)
if ( zclSampleLight_OnOff == LIGHT_ON )
{
time = zclSampleLight_LevelOffTransitionTime;
}
else
{
time = zclSampleLight_LevelOnTransitionTime;
}
// else use OnOffTransitionTime if set (not 0xffff)
if ( time == 0xFFFF )
{
time = zclSampleLight_LevelOnOffTransitionTime;
}
// else as fast as possible
if ( time == 0xFFFF )
{
time = 1;
}
}
if ( !time )
{
time = 1; // as fast as possible
}
return ( time );
}
/*********************************************************************
* @fn zclSampleLight_DefaultMove
*
* @brief We were turned on/off. Use default time to move to on or off.
*
* @param zclSampleLight_OnOff - must be set prior to calling this function.
*
* @return none
*/
static void zclSampleLight_DefaultMove( void )
{
uint8 newLevel;
uint32 rate; // fixed point decimal (3 places, eg. 16.345)
uint16 time;
// if moving to on position, move to on level
if ( zclSampleLight_OnOff )
{
if ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT )
{
// The last Level (before going OFF) should be used)
newLevel = zclSampleLight_LevelLastLevel;
}
else
{
newLevel = zclSampleLight_LevelOnLevel;
}
time = zclSampleLight_LevelOnTransitionTime;
}
else
{
newLevel = ATTR_LEVEL_MIN_LEVEL;
if ( zclSampleLight_LevelOnLevel == ATTR_LEVEL_ON_LEVEL_NO_EFFECT )
{
// Save the current Level before going OFF to use it when the light turns ON
// it should be back to this level
zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
}
time = zclSampleLight_LevelOffTransitionTime;
}
// else use OnOffTransitionTime if set (not 0xffff)
if ( time == 0xFFFF )
{
time = zclSampleLight_LevelOnOffTransitionTime;
}
// else as fast as possible
if ( time == 0xFFFF )
{
time = 1;
}
// calculate rate based on time (int 10ths) for full transition (1-254)
rate = 255000 / time; // units per tick, fixed point, 3 decimal places (e.g. 8500 = 8.5 units per tick)
// start up state machine.
zclSampleLight_WithOnOff = TRUE;
zclSampleLight_MoveBasedOnRate( newLevel, rate );
}
/*********************************************************************
* @fn zclSampleLight_AdjustLightLevel
*
* @brief Called each 10th of a second while state machine running
*
* @param none
*
* @return none
*/
static void zclSampleLight_AdjustLightLevel( void )
{
// one tick (10th of a second) less
if ( zclSampleLight_LevelRemainingTime )
{
--zclSampleLight_LevelRemainingTime;
}
// no time left, done
if ( zclSampleLight_LevelRemainingTime == 0)
{
zclSampleLight_LevelCurrentLevel = zclSampleLight_NewLevel;
}
// still time left, keep increment/decrementing
else
{
if ( zclSampleLight_NewLevelUp )
{
zclSampleLight_CurrentLevel32 += zclSampleLight_Rate32;
}
else
{
zclSampleLight_CurrentLevel32 -= zclSampleLight_Rate32;
}
zclSampleLight_LevelCurrentLevel = (uint8)( zclSampleLight_CurrentLevel32 / 1000 );
}
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
zclSampleLight_UpdateLampLevel(zclSampleLight_LevelCurrentLevel);
#endif
// also affect on/off
if ( zclSampleLight_WithOnOff )
{
if ( zclSampleLight_LevelCurrentLevel > ATTR_LEVEL_MIN_LEVEL )
{
zclSampleLight_OnOff = LIGHT_ON;
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
ENABLE_LAMP;
#endif
}
else
{
zclSampleLight_OnOff = LIGHT_OFF;
#if (defined HAL_BOARD_ZLIGHT) || (defined HAL_PWM)
DISABLE_LAMP;
#endif
}
}
// display light level as we go
zclSampleLight_DisplayLight( );
// keep ticking away
if ( zclSampleLight_LevelRemainingTime )
{
osal_start_timerEx( zclSampleLight_TaskID, SAMPLELIGHT_LEVEL_CTRL_EVT, 100 );
}
}
/*********************************************************************
* @fn zclSampleLight_LevelControlMoveToLevelCB
*
* @brief Callback from the ZCL General Cluster Library when
* it received a LevelControlMoveToLevel Command for this application.
*
* @param pCmd - ZigBee command parameters
*
* @return none
*/
static void zclSampleLight_LevelControlMoveToLevelCB( zclLCMoveToLevel_t *pCmd )
{
zclSampleLight_WithOnOff = pCmd->withOnOff;
zclSampleLight_MoveBasedOnTime( pCmd->level, pCmd->transitionTime );
}
/*********************************************************************
* @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
/****************************************************************************
****************************************************************************/
/**************************************************************************************************
* 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_1_PORT P2
#define HAL_KEY_SW_1_BIT BV(0)
#define HAL_KEY_SW_1_SEL P2SEL
#define HAL_KEY_SW_1_DIR P2DIR
/* edge interrupt */
#define HAL_KEY_SW_1_EDGEBIT BV(3)
#define HAL_KEY_SW_1_EDGE HAL_KEY_RISING_EDGE
/* SW_6 interrupts */
#define HAL_KEY_SW_1_IEN IEN2 /* CPU interrupt mask register */
#define HAL_KEY_SW_1_IENBIT BV(1) /* Mask bit for all of Port_0 */
#define HAL_KEY_SW_1_ICTL P2IEN /* Port Interrupt Control register */
#define HAL_KEY_SW_1_ICTLBIT BV(0) /* P0IEN - P0.1 enable/disable bit */
#define HAL_KEY_SW_1_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 */
////////////////////////////////////////////////////////////////////////
#define port P1_7
/**************************************************************************************************
* 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_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_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 */
/* 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_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
/* Interrupt configuration:
* - Enable interrupt generation at the port
* - Enable CPU interrupt
* - Clear any pending interrupt
*/
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);
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);
/* 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_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_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 */
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_1;
}
if (port==1)
{
keys |= HAL_KEY_SW_2;
}
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 (HAL_PUSH_BUTTON1())
{
keys |= HAL_KEY_SW_1;
}
if (port==1)
{
keys |= HAL_KEY_SW_2;
}
/* 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_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_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 (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_2_PXIFG & HAL_KEY_SW_2_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_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_1_PXIFG & HAL_KEY_SW_1_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_SW_1_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 */
