📄 hcswitchc.c
字号:
MESSAGE_INDICATION = 0;
// This is to check some errant/programming mistakes.
if ( TO == 0 )
{
// Clear watchdog to set TO bit.
CLRWDT();
// Clear flags so that we can detect it next time.
STKPTR &= 0x3F;
RCON |= 0x1F;
// Disable all interrupts
INTCON = 0;
// Prepare for alternating flashing LED sequence.
BIND_INDICATION = 0;
MESSAGE_INDICATION = 1;
// On this error, blink LEDs.
while(1)
{
CLRWDT();
// This is to make sure that we don't waste battery.
// At least one LED is always ON so saving would not be
// that much - actual application may do something different.
SLEEP();
NOP();
BIND_INDICATION ^= 1;
MESSAGE_INDICATION ^= 1;
}
}
// Initialize the MAC address
p = (BYTE *)&macInfo.longAddr;
*p++ = MAC_LONG_ADDR_BYTE0;
*p++ = MAC_LONG_ADDR_BYTE1;
*p++ = MAC_LONG_ADDR_BYTE2;
*p++ = MAC_LONG_ADDR_BYTE3;
*p++ = MAC_LONG_ADDR_BYTE4;
*p++ = MAC_LONG_ADDR_BYTE5;
*p++ = MAC_LONG_ADDR_BYTE6;
*p = MAC_LONG_ADDR_BYTE7;
// Now that we have complete board id, save the info into nonvolatile memory.
PutMACAddress(&macInfo.longAddr);
// Now ask the Stack to set our address in the transceiver.
APLUpdateAddressInfo();
}
//------------------------------------------------------------------------------
// InitializeBoard
//------------------------------------------------------------------------------
static void InitializeBoard(void)
{
#ifdef ENABLE_DEBUG
// This is a RS232 console - you may replace it with any console you like.
ConsoleInit();
#endif
// Switches S2 and S3 are on RB5 and RB4 respectively. We want interrupt-on-change
INTCON = 0x00;
// There is no external pull-up resistors on S2 and S3. We will use internal pull-ups.
// The CC2420 provides SFD (Start of Frame Detect) signal on RB2. We are using
// the falling edge of that signal to generate INT2
// Enable PORTB internal pullups, INT2 on falling edge
INTCON2 = 0x00;
// Enable INT2 interrupt - SFD from CC2420 or IRQ from ZMD44101
INTCON3 = 0xD0;
// CC2420 I/O assignments with respect to PIC:
// RB0 <- FIFO (Input)
// RB1 <- CCA (Input - Not used in this version of stack)
// RB2 <- SFD (Input - Generates interrupt on falling edge)
// RB3 <- FIFOP (Input - Used to detect overflow)
// RC0 -> CSn (Output - to select CC2420 SPI slave)
// RC1 -> VREG_EN (Output - to enable CC2420 voltage regulator)
// RC2 -> RESETn (Output - to reset CC2420)
// RC3 - > SCK (Output - SPI Clock to CC2420)
// RC4 <- SO (Input - SPI data from CC2420)
// RC5 -> SI (Output - SPI data to CC2420)
// Make PORTB as input - this is the RESET default
TRISB = 0xff;
// Set PORTC control signal direction and initial states
// Start with CC2420 disabled and not selected
LATC = 0xfd;
// Set the SPI module for use by Stack
TRISC = 0xD0;
// Set the SPI module
SSPSTAT = 0xC0;
SSPCON1 = 0x20;
// D1 and D2 are on RA0 and RA1 respectively, and CS of TC77 is on RA2.
// Make PORTA as digital I/O.
// The TC77 temp sensor CS is on RA2.
ADCON1 = 0x0F;
// Deselect TC77 (RA2)
LATA = 0x04;
// Make RA0, RA1, RA2 and RA4 as outputs.
TRISA = 0xE0;
// Set up the interrupt to read in a data packet.
// set to capture on rising edge
CCP2CON = 0b00000101;
// set high priority for RX packet detection
CCP2IP = 1;
CCP2IF = 0;
CCP2IE = 1;
}
//******************************************************************************
// Binding Task
//******************************************************************************
static BOOL BindingTask( void )
{
static SM_BIND smBind = SM_BIND_INIT;
APLSetEP( ZDOEndpointHandle );
switch (smBind)
{
case SM_BIND_INIT:
if (SendEndDeviceBindReq())
{
smBind = SM_BIND_CHECK_RESPONSE;
}
else
{
DEBUG_OUT( "Could not bind request\r\n" );
return TRUE;
}
break;
case SM_BIND_CHECK_RESPONSE:
if (endDeviceBindInfo.flags.bits.bResponseReceived)
{
if (endDeviceBindInfo.flags.bits.bBindSuccessful)
{
appFlags.Val ^= TOGGLE_BOUND_FLAG;
BIND_INDICATION = appFlags.bits.bIsNotBound;
DEBUG_OUT( "End Device Bind/Unbind successful!\r\n" );
smBind = SM_BIND_INIT;
return TRUE;
}
else
{
DEBUG_OUT( "End Device Bind/Unbind unsuccessful.\r\n" );
smBind = SM_BIND_INIT;
return TRUE;
}
}
else if (TickGetDiff(TickGet(), endDeviceBindInfo.requestStart) >= BIND_WAIT_DURATION)
{
DEBUG_OUT( "No one is answering our bind request\r\n" );
smBind = SM_BIND_INIT;
return TRUE;
}
break;
}
return FALSE;
}
//******************************************************************************
// Light Switch Functions
//******************************************************************************
#define MAX_SW_RETRY_COUNT 3
#define RESPONSE_WAIT_DURATION (5*TICK_SECOND)
// ZigBee provides the following high-level acknowledges. They can be enabled
// independently of each other.
// NOTE - these acknowledges will not work when using indirect messages and
// bindings, as in this demo. The ZigBee Alliance is aware of the issue with
// the specification. To use APS and Application Framework acknowledges, you
// must restructure the HCSwitchC and HCLight code to use direct messaging.
// See the HCRouter project for how to discover a device's short address.
// Uncomment the following if you want to get an APS acknowledge that the light
// received the light message.
//#define GET_APS_ACK
// Uncomment the following if you want the light to generate an Application
// Framework-level response when it receives the light message.
// NOTE - the HCLight demo does not currently support this response, due to
// the limitation described above.
//#define GET_AF_RESPONSE
//------------------------------------------------------------------------------
// LightSwitchInit
//------------------------------------------------------------------------------
static void LightSwitchInit(void)
{
hLightSwitch = APLOpenEP( EP_SWITCH );
}
//------------------------------------------------------------------------------
// LightSwitchTask
//------------------------------------------------------------------------------
static BOOL LightSwitchTask( void )
{
#ifdef GET_AF_RESPONSE
WORD_VAL attribID;
BYTE dataTypeAndCommand;
BYTE errorCode;
static TICK messageTimeSent;
#else
#ifdef GET_APS_ACK
static TICK messageTimeSent;
#endif
#endif
static BYTE messageTryCount;
static SM_SWITCH smSwitch = SM_SWITCH_INIT;
static BYTE switchRetryCount;
BYTE switchValue;
TRANS_ID transID;
APLSetEP( hLightSwitch );
switch( smSwitch )
{
case SM_SWITCH_INIT:
// The switch has been pressed .
messageTryCount = 5;
switchRetryCount = MAX_SW_RETRY_COUNT;
smSwitch = SM_SWITCH_UPDATE;
break;
case SM_SWITCH_UPDATE:
if ( APLIsPutReady() )
{
DEBUG_OUT( "Sending switch value...\r\n" );
// We could do this a couple of ways. Since we have momentary switches,
// we'll make the lamp toggle rather than set it to a particular value.
// Note that the Switching Load Controller has to be able to handle any of
// the three valid values we can send it, so we can do whatever is easiest
// for us.
switchValue = LIGHT_TOGGLE;
#ifdef GET_AF_RESPONSE
#ifdef GET_APS_ACK
APLSendKVPIndirectWithACK( transID, MY_PROFILE_ID, OnOffSRC_CLUSTER,
EP_SWITCH, 1, &switchValue, GENERATE_TRANS_ID, TRANS_SET_ACK,
OnOffSRC_OnOff_DATATYPE, OnOffSRC_OnOff, DEFAULT_RADIUS, ROUTE_DISCOVERY_SUPPRESS );
#else
APLSendKVPIndirect( transID, MY_PROFILE_ID, OnOffSRC_CLUSTER,
EP_SWITCH, 1, &switchValue, GENERATE_TRANS_ID, TRANS_SET_ACK,
OnOffSRC_OnOff_DATATYPE, OnOffSRC_OnOff, DEFAULT_RADIUS, ROUTE_DISCOVERY_SUPPRESS );
#endif
#else
#ifdef GET_APS_ACK
APLSendKVPIndirectWithACK( transID, MY_PROFILE_ID, OnOffSRC_CLUSTER,
EP_SWITCH, 1, &switchValue, GENERATE_TRANS_ID, TRANS_SET,
OnOffSRC_OnOff_DATATYPE, OnOffSRC_OnOff, DEFAULT_RADIUS, ROUTE_DISCOVERY_SUPPRESS );
#else
APLSendKVPIndirect( transID, MY_PROFILE_ID, OnOffSRC_CLUSTER,
EP_SWITCH, 1, &switchValue, GENERATE_TRANS_ID, TRANS_SET,
OnOffSRC_OnOff_DATATYPE, OnOffSRC_OnOff, DEFAULT_RADIUS, ROUTE_DISCOVERY_SUPPRESS );
#endif
#endif
if (transID == TRANS_ID_INVALID)
{
messageTryCount --;
DEBUG_OUT( "Error sending switch message\r\n" );
if ( APSDE_DATA_confirm() == NO_BOUND_DEVICE)
{
DEBUG_OUT( "No bound device\r\n" );
smSwitch = SM_SWITCH_INIT;
return TRUE;
}
else if (messageTryCount == 0)
{
smSwitch = SM_SWITCH_INIT;
return TRUE;
}
}
else
{
#if defined (GET_APS_ACK) || defined (GET_AF_RESPONSE)
messageTimeSent = TickGet();
#endif
switchRetryCount--;
smSwitch = SM_SWITCH_MAC_WAIT;
}
}
else
{
DEBUG_OUT( "We cannot send switch message\r\n" );
}
break;
case SM_SWITCH_MAC_WAIT:
if ( APLIsConfirmed() )
{
// We have MAC acknowledge for our message, so we know the
// lamp device's MAC has received the message. Remove the frame
// from the list of frames waiting for acknowledge.
DEBUG_OUT( "Switch MAC acknowledge received.\r\n" );
APLRemoveFrame();
// If we're waiting for another acknowlegde, set the state
// machine to wait for that level. Otherwise, we're done. Note
// that we have to check for the APS level first, then we can
// check for the application framework level.
#ifdef GET_APS_ACK
smSwitch = SM_SWITCH_APS_WAIT;
#else
#ifdef GET_AF_RESPONSE
smSwitch = SM_SWITCH_AF_WAIT;
#else
smSwitch = SM_SWITCH_INIT;
return TRUE;
#endif
#endif
}
else if ( APLIsTimedOut() )
{
// We timed out before receiving an acknowledge of our message.
// Remove the frame from the list of frames waiting for
// acknowledge, and see if we should try again.
APLRemoveFrame();
if ( switchRetryCount == 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -