📄 coordmain.c
字号:
/*********************************************************************
Coordinator/RFD node based on Demo Coordinator App from Microchip
Implements an endpoint on the coordinator that accepts
serial input from the console and sends this
endpoints on remote nodes.
This file also contains the main() code for the RFD nodes
as well.
Both coordinator and RFD nodes accept data from the serial
port and send it to each other (RFD nodes to coordinator,
coordinator to all bound RFD nodes).
R.B.Reese (reese@ece.msstate.edu), July 2005
********************************************************************/
// Uncomment ENABLE_DEBUG line to enable debug mode for this file.
// Or you may also globally enable debug by defining this macro
// in zigbee.h file or from compiler command-line.
#ifndef ENABLE_DEBUG
//#define ENABLE_DEBUG
#endif
#include <string.h>
#include "zigbee.h" // Zigbee defs
#if defined(MCHP_C18)
#include <stdio.h>
#endif
#include "config.h"
#include "msstate.h"
#include "sralloc.h"
#include "Console.h"
#include "bugfix.h"
#include "board.h"
#ifndef I_AM_END_DEVICE
#include "coord.h"
#else
#include "rfd.h"
#endif
// When to update lamp status.
#define MAX_LAMP_UPDATE_PERIOD (1*TICK_SECOND)
// This defines how LEDs will be blinked when unexpected RESET is detected.
#define FATAL_ERROR_BLINK_PERIOD (TICK_SECOND/2)
#if defined(ENABLE_DEBUG)
#define BUILD_MODE " (Debug Build)"
#else
#define BUILD_MODE " (Non-debug Build)"
#endif
// Various informational messages as part of configuration process.
ROM char * const startUpMsg = " SerialCoord/RFD V3 Demo, 28 Sep 2005\r\n";
ROM char * const menuMsg = "1. Join Network\r\n. Enter Application\n\r Enter (1,2,3): ";
ROM char * const resetMsg = "******Unexpected reset occurred.******\r\n";
ROM char * const nextChannelMsg = "Now operating in next channel...\r\n";
ROM char * const brownOutMsg = "\r\nBrown Out reset\r\n";
ROM char * const powerOnMsg = "\r\nPower On reset\r\n";
ROM char * const illegalState = "\r\nIllegal State, resetting\r\n";
ROM char * const bindingTableCleared = "Neighbor/Binding Table cleared, reseting network\n\r";
ROM char * const queryTimeout = "Query timeout to all nodes. Resetting network\n\r";
#include "app.h"
APPFLAGS appFlags;
// Private helper functions
static void InitializeBoard(void);
#define MAX_CLEARBIND_TIME (TICK_SECOND*10)
static void ComApp(void);
static void ComInit(void);
#ifndef I_AM_END_DEVICE
extern BYTE selective_join;
#endif
//these are input buffers and flags for the application code
#define INPUT_BUF_SIZE 40
volatile char buf_1[INPUT_BUF_SIZE], buf_2[INPUT_BUF_SIZE];
volatile unsigned char ebufptr,bufptr;
volatile unsigned char buf_flag, send_buffer_flag, overrun_flag;
volatile unsigned char echoptr, ebuf_flag, last_char;
void main(void){
BYTE c, exit_flag;
// To keep track of time.
TICK lastTick;
TICK S2High; //use for clearing binding table
APP_STATE smApp;
// Enable watchdog
ENABLE_WDT();
// Clear all flags in the begining.
appFlags.Val = 0x00;
// Initialize the board hardware.
InitializeBoard();
// 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;
// Display message on terminal.
ConsolePutROMString(resetMsg);
// Prepare for alternating flashing LED sequence.
D1 = 0;
D2 = 1;
TickInit(); //start TICK timer
DISABLE_WDT();
// On this error, blink LEDs.
while(1)
{
lastTick = TickGet();
while (TickGetDiff(TickGet(), lastTick) < (TICK_SECOND>>1)) {
TickUpdate(); //update tick count
}
D1 ^= 1;
D2 ^= 1;
}
}
if (!POR && !BOR) {
ConsolePutROMString(powerOnMsg);
POR = 1; BOR = 1;
CLRWDT();
}
if (POR && !BOR) {
ConsolePutROMString(brownOutMsg);
BOR = 1;
CLRWDT();
}
ConsolePutROMString(startUpMsg);
PrintStackConfig();
exit_flag = 0;
do {
ConsolePutROMString(menuMsg);
DISABLE_WDT();
while (!RCIF);
c = RCREG;
ConsolePut(c);
ConsolePut('\r'); ConsolePut('\n');
ENABLE_WDT();
if (c == '1') {
// join Network
appFlags.bits.bInConfigMode = TRUE;
InitializeNetwork();
ConsolePutROMString((ROM char *)"Network Started\r\n");
while( !ConsoleIsPutReady() ) { CLRWDT(); };
RESET();
}else if (c == '2') {
exit_flag = 1;
ConsolePutROMString((ROM char *)"Starting App\r\n");
}
}
while (!exit_flag);
InitRxAlive();
InitializeNetwork();
lastTick = TickGet();
smApp = SM_APP_NORMAL_START;
while( 1 ) {
// Toggle RA4 to indicate how long we execute this loop
LATA4 ^= 1;
// Keep watchdog happy
CLRWDT();
// This is the main stack task, responsible for Zigbee stack related functionality.
// This function must be called before all Zigbee tasks.
// Actual application task functions can be called in any order.
APLTask();
KeepRxAlive();
// all network initialization work of this state machine done
// in InitializeNetwork
switch(smApp) {
case SM_APP_NORMAL_START:
smApp = SM_APP_NORMAL_RUN;
break;
// this application does nothing except route
case SM_APP_NORMAL_RUN:
smApp = SM_APP_IDLE;
break;
case SM_APP_IDLE:
// sleep or do other work
smApp = SM_APP_NORMAL_RUN;
break;
}
}
}
static void InitializeBoard(void)
{
// This is a RS232 console - you may replace it with any console you like.
ConsoleInit();
// 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;
}
#if defined(MCHP_C18)
#pragma interruptlow LowISR
void LowISR(void)
#elif defined(HITECH_C18)
void interrupt low_priority LowISR(void)
#else
void LowISR(void)
#endif
{
return;
}
// NOTE: Several PICs, including the PIC18F4620 revision A3 have a RETFIE FAST/MOVFF bug
// The interruptlow keyword is used to work around the bug when using C18
// To work around the bug on PICC-18, configure the compiler to Compile for ICD
#if defined(MCHP_C18)
#pragma interruptlow HighISR save=section(".tmpdata"),section("MATH_DATA"),PROD
void HighISR(void)
#elif defined(HITECH_C18)
void interrupt HighISR(void)
#else
void HighISR(void)
#endif
{
// This is a quick way to display MAC TX/RX status on RD1 LED.
// TMR0IF is also used by TickUpdate, so we will let it clear the flag.
// D2 turned on during transmission
if ( TMR0IF ) D2 = 0;
// Must call this so that MAC module can determine if a transmission is in progress or not.
APL_ISR();
// Must call this so that tick manager can update its tick count.
TickUpdate();
// Is this a interrupt-on-change interrupt?
if ( RBIF == 1 )
{
// Clear mismatch condition and flag
if ( S2 == 0 )
appFlags.bits.S2Toggled = TRUE;
if ( S3 == 0 )
appFlags.bits.S3Toggled = TRUE;
// Clear mis-match condition and reset the interrupt flag
LATB = PORTB;
RBIF = 0;
}
// this handles the serial data input capture
// two buffers are used, when a complete line is
// recieved, it switchs to the alternate buffer
// while the the line is sent to the remote unit(s)
if (RCIF && RCIE) {
// get character from serial port
last_char = RCREG;
// save character
if (!buf_flag) buf_2[bufptr] = last_char;
else buf_1[bufptr] = last_char;
bufptr++; //increment buffer pointer
//ebufptr is normally a copy of bufptr except when
// trying to send the last buffer. send_buffer_flag freezes
// the ebufptr until the last buffer is sent
if (!send_buffer_flag) ebufptr = bufptr; //echo bufptr
#if defined(STREAMING_DATA)
//don't send until buffer fills
if (bufptr == INPUT_BUF_SIZE )
#else
//send when buffer fill or carriage return
if ((bufptr == INPUT_BUF_SIZE) || last_char == '\r' )
#endif
{
if (send_buffer_flag) {
overrun_flag = 1;
// discard buffer by resetting pointer
bufptr = 1;
} else {
send_buffer_flag = 1; //use this to freeze ebufptr until buffer is echoed
bufptr = 1;
// toggler buffer flag
buf_flag = !buf_flag;
}
}
}
}
#if defined(MCHP_C18)
#pragma code highVector=0x08
void HighVector (void)
{
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
#endif
#if defined(MCHP_C18)
#pragma code lowhVector=0x18
void LowVector (void)
{
_asm goto LowISR _endasm
}
#pragma code /* return to default code section */
#endif
// Callback to application to notify of a frame transmission.
void AppMACFrameTransmitted(void){
// Turn on LED to indicate activity. TMR0IF interrupt will turn it off.
// See interrupt handler.
D2 = 1;
}
// Callback to application to notify of a frame reception
void AppMACFrameReceived(void)
{
// Turn on LED to indicate activity. TMR0IF interrupt will turn it off.
// See interrupt handler.
D2 = 1;
}
// Callback to application to notify of an ack timeout
void AppMACFrameTimeOutOccurred(void)
{
}
// Callback to application to notify that a route discovery attempt failed.
extern void AppRouteDiscoveryFailed( SHORT_ADDR shortAddr )
{
}
//The functions that actually do the work of this application in terms
// of reading console input and then sending it to a remote node
// are below here
#ifndef I_AM_END_DEVICE
EP_HANDLE hCoord;
#else
EP_HANDLE hRfd;
#endif
//state machine for sending data
typedef enum _SM_SEND_STATE
{
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)
void RFD_Request_Messages(void);
#endif
typedef enum _COMSTATE
{
COM_NORMAL,
COM_QUERY,
} COMSTATE;
static COMSTATE ComState;
TICK lastCoordQueryTick; //used by RFD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -