📄 coordmain.c
字号:
SM_SEND_IDLE= 0,
SM_SEND_UPDATE,
SM_SEND_WAIT
} SM_SEND_STATE;
SM_SEND_STATE sendState;
#define MAX_SEND_RETRY_COUNT (3)
void ComSend(void);
void ComReceive(void);
unsigned char sendRetryCount;
// State machine and retry counter for responding to
// request for data
#if defined (I_AM_END_DEVICE)
#define MAX_UPDATE_WAIT (TICK_SECOND*1)
// how often we should check coordinator for messages
#define MAX_QUERY_TIME (TICK_SECOND/4)
#define MAX_SAUPDATE_TIME (TICK_SECOND/3)
void RFD_Request_Messages(void);
#endif
typedef enum _COMSTATE
{
COM_NORMAL,
COM_QUERY,
} COMSTATE;
static COMSTATE ComState;
static SHORT_ADDR rfd_sa;
static BYTE rfd_sa_received_flag;
static BYTE contacted_coordinator_flag;
TICK lastCoordQueryTick; //used by RFD
TICK lastShortAddrUpdate; //used by RFD
//initialize the Communication app
static void ComInit(void){
char c;
#ifdef I_AM_COORDINATOR
rfd_sa.Val = 0; // we do not know the RFD's short address yet
rfd_sa_received_flag = 0;
#else
// as RFD, have not contacted cooordinator yet.
contacted_coordinator_flag = 0;
#endif
ComState = COM_NORMAL;
overrun_flag = 0;
bufptr = 1; //index into active buffer, 1st two bytes reserved
ebufptr = 1; //follows bufptr
echoptr = 1; //echo'ed char pointer, 1st two bytes reserved
buf_flag = 0; //selects active input buffer
ebuf_flag = 0; //selects active echo buffer
send_buffer_flag = 0;
//enable RCIF interrupt, assume USART port already configured
// clear any characters in the input buffer
while (RCIF) {
c = RCREG;
}
#if defined(DUPLEX) || defined(I_AM_END_DEVICE)
RCIE = 1; //enable RCIF interrupt
#else
// this must the coordinator and in half-duplex mode, disable input
CREN = 0;
#endif
#ifndef I_AM_END_DEVICE
hCoord = APLOpenEP( EP_COORD ); // open zigbee endpoint
#else
hRfd = APLOpenEP( EP_RFD ); // open zigbee endpoint
#endif
sendState = SM_SEND_IDLE;
ConsolePutROMString((ROM char *)"Wireless Com Port Demo\r\n");
#if defined(STREAMING_DATA)
ConsolePutROMString((ROM char *)" Streaming data enabled, only send when buffer full\r\n");
#else
ConsolePutROMString((ROM char *)" Streaming data disabled, send on buffer full or carriage return\r\n");
#endif
#if defined(DUPLEX)
ConsolePutROMString((ROM char *)"DUPLEX enabled, begin typing text after binding....\n\r");
#else
#ifndef I_AM_END_DEVICE
ConsolePutROMString((ROM char *)"DUPLEX disabled, waiting for input....\n\r");
#else
ConsolePutROMString((ROM char *)"DUPLEX disabled, begin typing text after binding....\n\r");
#endif
#endif
lastCoordQueryTick = TickGet();
lastShortAddrUpdate = TickGet();
}
// this function handles echoing of received characters to
// to the console. Once a complete line is received, it is
// is then sent to the remote node.
// if this is an RFD, then we have to periodically
// request messages from the cooordinator
static void ComApp(void){
char c;
// After APLTask() is called, MUST check for
// input before attempting to send
ComReceive();
#ifdef I_AM_END_DEVICE
RFD_Send_ShortAddr();
#endif
#ifdef I_AM_COORDINATOR
if (rfd_sa_received_flag) {
Coord_Send_ShortAddr_Ack();
}
#endif
switch(ComState){
case COM_NORMAL:
if (overrun_flag) {
ConsolePutROMString((ROM char *)"Overrun, buffer lost\r\n");
overrun_flag = 0;
}
//first echo any typed characters
c = 0xff;
while (echoptr != ebufptr) {
if (!ebuf_flag) c = buf_2[echoptr];
else c = buf_1[echoptr];
if (c == '\r') {
ConsolePut(c);
ConsolePut((BYTE)'\n');
} else ConsolePut((BYTE) c);
echoptr++;
CLRWDT();
}
// if send state is not idle yet, we can't send
if (sendState != SM_SEND_IDLE) {
ComSend();// finish the last send
} else {
if (send_buffer_flag) {
// got an entire string, send it
#ifdef I_AM_COORDINATOR
//I am coordinator
sendState = SM_SEND_UPDATE;
sendRetryCount = MAX_SEND_RETRY_COUNT;
ComSend();
#else
//I am an RFD
sendState = SM_SEND_UPDATE;
sendRetryCount = MAX_SEND_RETRY_COUNT;
ComSend();
#endif
echoptr = 1;
ebufptr = 1;
send_buffer_flag = 0;
ebuf_flag = !ebuf_flag; //change buffers
} else {
#if defined (I_AM_END_DEVICE) && defined DUPLEX && !defined MY_RX_IS_ALWAYS_ON_OR_SYNCED_WITH_BEACON
//only have to query if end device
if ( TickGetDiff(TickGet(), lastCoordQueryTick) > MAX_QUERY_TIME) {
ComState = COM_QUERY;
}
#endif
}
}
break;
case COM_QUERY: //used only by end devices
#if defined(I_AM_END_DEVICE)
// only check for messages if duplex communication allowed
RFD_Request_Messages();
lastCoordQueryTick = TickGet();
#endif
ComState = COM_NORMAL;
break;
}
}
//this just sends the received line to the remote node
void ComSend(void) {
TRANS_ID transID;
BYTE *dataPtr;
BYTE cid;
BYTE ep;
SHORT_ADDR dest_sa;
#ifndef I_AM_END_DEVICE
cid = MSSTATE_COORDOUT_CLUSTER_ID;
ep = EP_COORD;
APLSetEP(hCoord);
#else
cid = MSSTATE_RFDOUT_CLUSTER_ID;
ep = EP_RFD;
APLSetEP(hRfd);
#endif
switch(sendState){
case SM_SEND_IDLE:
break;
case SM_SEND_UPDATE:
if ( APLIsPutReady() ) {
if (!ebuf_flag) dataPtr = (BYTE *) buf_2;
else dataPtr = (BYTE *)buf_1;
// Write ZigBee string length
*(dataPtr) = (echoptr-1);
#ifdef I_AM_END_DEVICE
dest_sa.Val = 0;
//send direct, we know the short address
APLSendKVPDirect( transID, MY_PROFILE_ID, cid, EP_RFD,
dest_sa, EP_COORD, // dest EP and short addr
(echoptr), dataPtr, GENERATE_TRANS_ID,
TRANS_SET, TRANS_ZSTRING, AN_ATTRIBUTE,DEFAULT_RADIUS,ROUTE_DISCOVERY_SUPPRESS );
#else
// coordinator
if (rfd_sa.Val != 0) {
// only send if we know the destination short address
APLSendKVPDirect( transID, MY_PROFILE_ID, cid, EP_COORD,
rfd_sa,EP_RFD,
(echoptr), dataPtr, GENERATE_TRANS_ID,
TRANS_SET, TRANS_ZSTRING, AN_ATTRIBUTE,DEFAULT_RADIUS,ROUTE_DISCOVERY_SUPPRESS );
}
#endif
#ifndef I_AM_END_DEVICE
sendState = SM_SEND_IDLE;
APLRemoveFrame();
#else
sendRetryCount--;
sendState = SM_SEND_WAIT;
#endif
}
break;
case SM_SEND_WAIT:
if ( APLIsConfirmed() )
{
sendState = SM_SEND_IDLE;
APLRemoveFrame();
}
else if ( APLIsTimedOut() )
{
// Remove previous frame from queue
APLRemoveFrame();
if ( sendRetryCount == 0 ){
sendState = SM_SEND_IDLE;
ConsolePutROMString((ROM char *)"*****String Send Failed\r\n");
}
else {
sendState = SM_SEND_UPDATE;
ConsolePutROMString((ROM char *)"*****Retrying String Send Failed\r\n");
}
}
break;
}
}
// this just checks for any messages that have been received
void ComReceive(void){
WORD_VAL attribID;
TRANS_ID transID;
BYTE transTag;
BYTE strLen;
BYTE c;
BYTE cid;
#ifndef I_AM_END_DEVICE
cid = MSSTATE_RFDOUT_CLUSTER_ID;
APLSetEP(hCoord);
#else
cid = MSSTATE_COORDOUT_CLUSTER_ID;
APLSetEP(hRfd);
#endif
if ( APLIsGetReady() ) {
BYTE transTagType;
BYTE transTagData;
//checking cluster ID is really only necessary if you
// have multiple input clusters
if (APLGetClusterID() == cid) {
// Get KVP detail.
transID = APLGet();
transTag = APLGet();
attribID.byte.LSB = APLGet();
attribID.byte.MSB = APLGet();
#if defined (I_AM_END_DEVICE)
// have received a message from the coordinator!
contacted_coordinator_flag = 1;
#endif
// ConsolePutROMString((ROM char *)"In Com Receive\r\n");
if (D1) D1=0;
else D1 = 1; //toggle LED everytime we get message from a remote unit
// Decode the transaction type and data type fields from
// the transcaction tag for faster access
transTagType = transTag & TRANS_COMMAND_TYPE_MASK;
transTagData = transTag & TRANS_DATA_TYPE_MASK;
if(transTagType == TRANS_SET) {
if(transTagData == TRANS_ZSTRING){
// First byte is ZigBee string length, get it
strLen = APLGet();
//simple sanity check on payload length
if (strLen < 118) {
// Write the whole string + CR+LF to the console
while(strLen--) {
c = APLGet();
ConsolePut(c);
if (c == '\r')ConsolePut('\n');
}
}
}
else if(transTagData == TRANS_UINT16) {
#ifdef I_AM_COORDINATOR
// get the short address value
rfd_sa.byte.LSB = APLGet();
rfd_sa.byte.MSB = APLGet();
sprintf(tmpbuf,(ROM char *)"Received RFD short address: %4x\n\r",rfd_sa.Val);
ConsolePutString((BYTE *)tmpbuf);
rfd_sa_received_flag = 1;
#else
// this is dummy data back from the coordinator acknowledging receipt
// we can ignore
#endif
}
}
else {
ConsolePutROMString((ROM char *)"Unknown received msg type\r\n");
}
} else {
ConsolePutROMString((ROM char *)"Unknown CLUSTER ID received, discarding\r\n");
}
// After processing, you must discard current data packet.
APLDiscardRx();
}
}
#if defined (I_AM_COORDINATOR)
// this is a user level acknowledge
static void Coord_Send_ShortAddr_Ack(void) {
BYTE mybuf[2];
SHORT_ADDR dest_sa;
TRANS_ID transID;
dest_sa.Val = 0;
if ( APLIsPutReady() ) {
ConsolePutROMString((ROM char *)"*****Sending Short Address Acknowledge\r\n");
// this data is ignored by RFD
*((BYTE *)mybuf) = 0;
*((BYTE *)mybuf+1) = 0;
APLSendKVPDirect( transID, MY_PROFILE_ID, MSSTATE_COORDOUT_CLUSTER_ID, EP_COORD,
rfd_sa, EP_RFD, // dest EP and short addr
2, mybuf, GENERATE_TRANS_ID,
TRANS_SET, TRANS_UINT16, AN_ATTRIBUTE,DEFAULT_RADIUS,ROUTE_DISCOVERY_SUPPRESS );
rfd_sa_received_flag = 0;
APLRemoveFrame();
}
}
#endif
#if defined (I_AM_END_DEVICE)
// this is used to send our short address to the endpoint
// on the coordinator so that they know where we live
static void RFD_Send_ShortAddr(void){
BYTE mybuf[2];
SHORT_ADDR dest_sa;
TRANS_ID transID;
if (!contacted_coordinator_flag) {
if ((TickGetDiff(TickGet(), lastShortAddrUpdate) > MAX_SAUPDATE_TIME)){
dest_sa.Val = 0;
if ( APLIsPutReady() ) {
ConsolePutROMString((ROM char *)"*****Sending Short Address\r\n");
*((BYTE *)mybuf) = macInfo.shortAddr.byte.LSB;
*((BYTE *)mybuf+1) = macInfo.shortAddr.byte.MSB;
// we will request an ack for this
APLSendKVPDirect( transID, MY_PROFILE_ID, MSSTATE_RFDOUT_CLUSTER_ID, EP_RFD,
dest_sa, EP_COORD, // dest EP and short addr
2, mybuf, GENERATE_TRANS_ID,
TRANS_SET, TRANS_UINT16, AN_ATTRIBUTE,DEFAULT_RADIUS,ROUTE_DISCOVERY_SUPPRESS );
APLRemoveFrame();// don't wait for ACK
lastShortAddrUpdate = TickGet();
}
}
}
}
//RFD has to explicity request messages from coordinator
// when this returns true we will keep on processing
// don't bother waiting for response or ack'ing, just send it
// since we resend in a short time anyway
void RFD_Request_Messages(void){
APLSetEP(hRfd);
// request messages from coord
if (APLIsPutReady() ) {
APLRequestMessages();
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -