Exemplo n.º 1
0
/* handle received messages */
uint8_t rxCallback(linkID_t port) {
   uint8_t len;
   packet_t thePacket;

   /* is the callback for the link ID we want to handle? */
   if (port == myLinkID) {
      if ((SMPL_SUCCESS == SMPL_Receive(myLinkID, (uint8_t *) &thePacket, 
            &len)) && len) {
         uint8_t plen = thePacket.dlen + HEADER_SIZE;
         uint8_t *packet_ptr = (uint8_t *) &thePacket;
         if (thePacket.dev_id != BS_ID)
            return 1;

         if (plen <= len) {
            // add to the queue
            uint8_t i;
            for (i = 0; i < plen; i++)
               rq_push(packet_ptr[i]);
            newRepPacket++;
         }

         // drop frame. we're done with it. 
         return 1;
      }
   }

   /* keep frame for later handling */
   return 0;
}
Exemplo n.º 2
0
void main(void)
{
	BSP_Init(); // Initialisation de la librairie BSP
	NWK_DELAY(500);
	
	SMPL_Init(&RxCallBack); // Initialisation de la librairie simpliciTI
	SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
	SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0); // Activation de la radio pour permettre la réception des messages
	
	COM_Init(); // Initialisation du port COM
		
	while (1)
	{
		if(broadSem)
		{
			memset(msg, 0, sizeof(msg));
			if ((SMPL_Receive(SMPL_LINKID_USER_UUD, msg, &msgLen)) == SMPL_SUCCESS) // Cette fonction permet de stocker les messages reçu par un périphérique en spécifiant son linkID
			{
				sigInfo.lid = SMPL_LINKID_USER_UUD; // Permet d'indiquer les informations de quel périphérique sont demandées
				SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SIGINFO, &sigInfo); // On récupère les informations sur la force de connexion dans la structure sigInfo
			  	msg[5] = 'S';
			  	msg[6] = sigInfo.sigInfo.rssi+128;
			  	msg[7] = 'L';
			  	msg[8] = sigInfo.sigInfo.lqi;
			  	msg[9] = 0xFF;
				broadSem--;
				TXString(msg, sizeof(msg));
			}
		}
	}
}
Exemplo n.º 3
0
/* handle received messages */
static uint8_t sRxCallback(linkID_t port)
{
  uint8_t msg[2], len, tid;

  /* is the callback for the link ID we want to handle? */
  if (port == sLinkID2)
  {
    /* yes. go get the frame. we know this call will succeed. */
     if ((SMPL_SUCCESS == SMPL_Receive(sLinkID2, msg, &len)) && len)
     {
       /* Check the application sequence number to detect
        * late or missing frames...
        */
       tid = *(msg+1);
       if (tid)
       {
         if (tid > sRxTid)
         {
           /* we're good. toggle LED */
	   if ((*msg) == 0)
	   {
	     LedToggle(&led_red);
	   }
	   else
	   {
	     LedToggle(&led_green);
	   }
           sRxTid = tid;
         }
       }
       else
       {
         /* wrap case... */
         if (sRxTid)
         {
           /* we're good. toggle LED */
           if ((*msg) == 0)
	   {
	     LedToggle(&led_red);
	   }
	   else
	   {
	     LedToggle(&led_green);
	   }
           sRxTid = tid;
         }
       }
       /* Post to the semaphore to let application know so it sends
        * the reply
        */
       sSemaphore = 1;
       /* drop frame. we're done with it. */
       return 1;
     }
  }
  /* keep frame for later handling */
  return 0;
}
// *************************************************************************************************
// @fn          simpliciti_main_sync
// @brief       Send ready-to-receive packets in regular intervals. Listen shortly for host reply.
//				Decode received host command and trigger action.
// @param       none
// @return      none
// *************************************************************************************************
void simpliciti_main_sync(void)
{
    uint8_t len, i;
    uint8_t ed_data[2];

    while (1)
    {
        // Sleep 0.5sec between ready-to-receive packets
        // SimpliciTI has no low power delay function, so we have to use ours
        Timer0_A4_Delay(CONV_MS_TO_TICKS(500));

        // Get radio ready. Radio wakes up in IDLE state.
        SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

        // Send 2 byte long ready-to-receive packet to stimulate host reply
        ed_data[0] = SYNC_ED_TYPE_R2R;
        ed_data[1] = 0xCB;
        SMPL_SendOpt(sLinkID1, ed_data, 2, SMPL_TXOPTION_NONE);

        // Wait shortly for host reply
        SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
        NWK_DELAY(10);

        // Check if a command packet was received
        while (SMPL_Receive(sLinkID1, simpliciti_data, &len) == SMPL_SUCCESS)
        {
            // Decode received data
            if (len > 0)
            {
                // Use callback function in application to decode data and react
                simpliciti_sync_decode_ap_cmd_callback();

                // Get reply data and send out reply packet burst (19 bytes each)
                for (i = 0; i < simpliciti_reply_count; i++)
                {
                    NWK_DELAY(10);
                    simpliciti_sync_get_data_callback(i);
                    SMPL_SendOpt(sLinkID1, simpliciti_data, BM_SYNC_DATA_LENGTH, SMPL_TXOPTION_NONE);
                }
            }
        }

        // Put radio back to sleep
        SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

        // Service watchdog
        WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL;

        // Exit when flag bit SIMPLICITI_TRIGGER_STOP is set
        if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP))
        {
            // Clean up SimpliciTI stack to enable restarting
            sInit_done = 0;
            break;
        }
    }
}
Exemplo n.º 5
0
/* handle received frames. */
static uint8_t sRxCallback(linkID_t port)
{
  uint8_t msg[10], len, tid;
  memset(msg, 0, 10);

  /* is the callback for the link ID we want to handle? */
  if (port == sLinkID1)
  {
    /* yes. go get the frame. we know this call will succeed. */
     if ((SMPL_SUCCESS == SMPL_Receive(sLinkID1, msg, &len)) && len)
     {
       /* Check the application sequence number to detect
        * late or missing frames... 
        */
       tid = *(msg+9);
       if (tid)
       {
         if (tid > sRxTid)
         {
           /* we're good. toggle LED in the message */
           toggleLED(*msg);
           sRxTid = tid;
         }
       }
       else
       {
         /* the wrap case... */
         if (sRxTid)
         {
           /* we're good. toggle LED in the message */
           toggleLED(*msg);
           sRxTid = tid;
         }
       }
       /* drop frame. we're done with it. */
       return 1;
     }
  }
  /* keep frame for later handling. */
  return 0;
}
Exemplo n.º 6
0
void unsyncRepere()
{
	uint8_t msgTemp[10] = {0,0,0,0,0,0,0,0,0,0};
	uint8_t msgLen = 0;
	
	SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0); // Activation de la radio pour permettre la réception des messages
	NWK_DELAY(10);
	while((SMPL_Receive(SMPL_LINKID_USER_UUD, msgTemp, &msgLen)) == SMPL_SUCCESS) // Boucle de désynchronisation des repères
	{
		BSP_TOGGLE_LED2();
		NWK_DELAY(10);
	}
	if(BSP_LED2_IS_ON())
		BSP_TOGGLE_LED2();
	
	TACCR0 = 2280;                            // ~ 0.2sec - 10 msec
    TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
    __bis_SR_register(LPM3_bits + GIE);
    TACCR0 = 2400;                            // ~ 0.2sec
    TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
    
    SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXIDLE, 0); // Désactivation de la réception des messages
}
//*****************************************************************************
//
// Handle frames received from the radio.
//
//*****************************************************************************
static uint8_t
RxCallback(linkID_t port)
{
    uint8_t pcMsg[2], ucLen, ucTid;
    smplStatus_t eRetcode;

    //
    // Is the callback for the link ID we want to handle?
    //
    if (port == sLinkID)
    {
        //
        // Yes - go and get the frame. We know this call will succeed.
        //
        eRetcode = SMPL_Receive(sLinkID, pcMsg, &ucLen);

        if ((eRetcode == SMPL_SUCCESS) && ucLen)
        {
            //
            // Update our receive counter.
            //
            g_ulRxCount++;

            //
            // Check the application sequence number to detect late or missing
            // frames.
            //
            ucTid = *(pcMsg+1);
            if (ucTid)
            {
                if (ucTid > g_ucRxTid)
                {
                    //
                    // Things are fine so toggle the requested LED.  Note that
                    // we send a message to the main loop to do this for us
                    // since redrawing the widget on the screen is a
                    // time-consuming operation that we don't want to do in
                    // interrupt context.
                    //
                    HWREGBITW(&g_ulCommandFlags, ((*pcMsg == 1) ?
                              COMMAND_LED1_TOGGLE : COMMAND_LED2_TOGGLE)) = 1;
                    g_ucRxTid = ucTid;
                }
            }
            else
            {
                //
                // The sequence number has wrapped.
                //
                if (g_ucRxTid)
                {
                    //
                    // Send a message to the main loop asking it to toggle the
                    // "LED" on the display.
                    //
                    HWREGBITW(&g_ulCommandFlags, ((*pcMsg == 1) ?
                              COMMAND_LED1_TOGGLE : COMMAND_LED2_TOGGLE)) = 1;
                    g_ucRxTid = ucTid;
                }
            }

            //
            // If we're operating as the listener, we need to reply with another
            // packet so tell the main loop to do this for us.
            //
            if(g_ulMode == MODE_LISTENER)
            {
                HWREGBITW(&g_ulCommandFlags, COMMAND_SEND_REPLY) = 1;
            }

            //
            // We've finished processing this frame.
            //
            return(1);
        }
    }

    //
    // Tell SimpliciTI to keep frame for later handling.
    //
    return(0);
}
//*****************************************************************************
//
// Main application entry function.
//
//*****************************************************************************
int
main(void)
{
    tBoolean bRetcode;
    bspIState_t intState;
    uint8_t ucLastChannel;

    //
    // Set the system clock to run at 50MHz from the PLL
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // NB: We don't call PinoutSet() in this testcase since the EM header
    // expansion board doesn't currently have an I2C ID EEPROM.  If we did
    // call PinoutSet() this would configure all the EPI pins for SDRAM and
    // we don't want to do this.
    //
    g_eDaughterType = DAUGHTER_NONE;

    //
    // Enable peripherals required to drive the LCD.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);

    //
    // Configure SysTick for a 10Hz interrupt.
    //
    ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / TICKS_PER_SECOND);
    ROM_SysTickEnable();
    ROM_SysTickIntEnable();

    //
    // Initialize the display driver.
    //
    Kitronix320x240x16_SSD2119Init();

    //
    // Initialize the touch screen driver.
    //
    TouchScreenInit();

    //
    // Set the touch screen event handler.
    //
    TouchScreenCallbackSet(WidgetPointerMessage);

    //
    // Add the compile-time defined widgets to the widget tree.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sHeading);

    //
    // Initialize the status string.
    //
    UpdateStatus(true, "Initializing...");

    //
    // Paint the widget tree to make sure they all appear on the display.
    //
    WidgetPaint(WIDGET_ROOT);

    //
    // Initialize the SimpliciTI BSP.
    //
    BSP_Init();

    //
    // Set the SimpliciTI device address using the current Ethernet MAC address
    // to ensure something like uniqueness.
    //
    bRetcode = SetSimpliciTIAddress();

    //
    // Did we have a problem with the address?
    //
    if(!bRetcode)
    {
        //
        // Yes - make sure the display is updated then hang the app.
        //
        WidgetMessageQueueProcess();
        while(1)
        {
            //
            // MAC address is not set so hang the app.
            //
        }
    }

    //
    // Turn on both our LEDs
    //
    SetLED(1, true);
    SetLED(2, true);

    UpdateStatus(true, "Waiting for a device...");

    //
    // Initialize the SimpliciTI stack and register our receive callback.
    //
    SMPL_Init(ReceiveCallback);

    //
    // Tell the user what's up.
    //
    UpdateStatus(true, "Access point active.");

    //
    // Do nothing after this - the SimpliciTI stack code handles all the
    // access point function required.
    //
    while(1)
    {
        //
        // Wait for the Join semaphore to be set by the receipt of a Join
        // frame from a device that supports an end device.
        //
        // An external method could be used as well. A button press could be
        // connected to an ISR and the ISR could set a semaphore that is
        // checked by a function call here, or a command shell running in
        // support of a serial connection could set a semaphore that is
        // checked by a function call.
        //
        if (g_ucJoinSem && (g_ucNumCurrentPeers < NUM_CONNECTIONS))
        {
            //
            // Listen for a new incoming connection.
            //
            while (1)
            {
                if (SMPL_SUCCESS == SMPL_LinkListen(&g_sLID[g_ucNumCurrentPeers]))
                {
                    //
                    // The connection attempt succeeded so break out of the
                    // loop.
                    //
                    break;
                }

                //
                // Process our widget message queue.
                //
                WidgetMessageQueueProcess();

                //
                // A "real" application would implement its fail-to-link
                // policy here.  We go back and listen again.
                //
            }

            //
            // Increment our peer counter.
            //
            g_ucNumCurrentPeers++;

            //
            // Decrement the join semaphore.
            //
            BSP_ENTER_CRITICAL_SECTION(intState);
            g_ucJoinSem--;
            BSP_EXIT_CRITICAL_SECTION(intState);

            //
            // Tell the user how many devices we are now connected to.
            //
            UpdateStatus(false, "%d devices connected.", g_ucNumCurrentPeers);
        }

        //
        // Have we received a frame on one of the ED connections? We don't use
        // a critical section here since it doesn't really matter much if we
        // miss a poll.
        //
        if (g_ucPeerFrameSem)
        {
            uint8_t     pucMsg[MAX_APP_PAYLOAD], ucLen, ucLoop;

            /* process all frames waiting */
            for (ucLoop = 0; ucLoop < g_ucNumCurrentPeers; ucLoop++)
            {
                //
                // Receive the message.
                //
                if (SMPL_SUCCESS == SMPL_Receive(g_sLID[ucLoop], pucMsg,
                                                 &ucLen))
                {
                    //
                    // ...and pass it to the function that processes it.
                    //
                    ProcessMessage(g_sLID[ucLoop], pucMsg, ucLen);

                    //
                    // Decrement our frame semaphore.
                    //
                    BSP_ENTER_CRITICAL_SECTION(intState);
                    g_ucPeerFrameSem--;
                    BSP_EXIT_CRITICAL_SECTION(intState);
                }
            }
        }

        //
        // Have we been asked to change channel?
        //
        ucLastChannel = g_ucChannel;
        if (g_bChangeChannel)
        {
            //
            // Yes - go ahead and change to the next radio channel.
            //
            g_bChangeChannel = false;
            ChangeChannel();
        }
        else
        {
            //
            // No - check to see if we need to automatically change channel
            // due to interference on the current one.
            //
            CheckChangeChannel();
        }

        //
        // If the channel changed, update the display.
        //
        if(g_ucChannel != ucLastChannel)
        {
            UpdateStatus(false, "Changed to channel %d.", g_ucChannel);
        }

        //
        // If required, blink the "LEDs" to indicate we are waiting for a
        // message following a channel change.
        //
        BSP_ENTER_CRITICAL_SECTION(intState);
        if (g_ulBlinky)
        {
            if (++g_ulBlinky >= 0xF)
            {
                g_ulBlinky = 1;
                ToggleLED(1);
                ToggleLED(2);
            }
        }
        BSP_EXIT_CRITICAL_SECTION(intState);

        //
        // Process our widget message queue.
        //
        WidgetMessageQueueProcess();
    }
}
void main1 (void)
{
  /* holds length of current message */
  uint8_t len; 
  
  /* the link token */
  linkID_t LinkID = 0;
  
  /* the transmit and receive buffers */
  uint8_t rx[MAX_APP_PAYLOAD], tx[MAX_APP_PAYLOAD];

  /* holds led indicator time out counts */
  uint16_t led_tmr;
  
  int8_t rssi_value;
  

  BSP_Init( );

  SMPL_Init( NULL );
  
  uart_intfc_init( );

  /* turn on the radio so we are always able to receive data asynchronously */
  SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, NULL );
  
  /* turn on LED. */
  BSP_TURN_ON_LED1( );

#ifdef  LINK_TO
  {
    uint8_t cnt = 0;
    tx_send_wait( "Linking to...\r\n", 15 );
    while (SMPL_SUCCESS != SMPL_Link(&LinkID))
      if( cnt++ == 0 )
      {
        /* blink LED until we link successfully */
        BSP_TOGGLE_LED1( );
      }
  }
#else // ifdef LINK_LISTEN
  tx_send_wait( "Listening for Link...\r\n", 23 );
  while (SMPL_SUCCESS != SMPL_LinkListen(&LinkID))
  {
    /* blink LED until we link successfully */
    BSP_TOGGLE_LED1( );
  }
#endif

  tx_send_wait( "Link Established!\r\nReady...\r\n", 29 );
  
  /* turn off the led */
  BSP_TURN_OFF_LED1( );
  
  main_loop:
    /* Check to see if we received any characters from the other radio
     * and if we have send them out the uart and reset indicator timeout.
     * Prioritize on radio received links as that buffer is the most time
     * critical with respect to the UART buffers.
     */
    if( SMPL_Receive( LinkID, tx, &len ) == SMPL_SUCCESS )
    {
      /* blocking call but should be ok if both ends have same uart buad rate */
      //tx_send_wait( tx, len );
      led_tmr = INDICATOR_TIME_OUT;   /* update activity time out */
      
      
      /*
      int8_t dbm;
      SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RSSI, (void *)&dbm);
      sSample= dbm;
      tx_send_wait(&char2send, 1 );//input only (unsigned char)
      tx_send_wait("\n", 1 );*/
      
      
      unsigned char Test2;
      //unsigned char Test;
      rssi_value = 0 ;
      
       ioctlRadioSiginfo_t sigInfo1;
       sigInfo1.lid=LinkID; 
       smplStatus_t SMPL_SUCCESS = SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SIGINFO, (void *)&sigInfo1);
    
      //if( SMPL_SUCCESS == SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RSSI,(void*)&rssi_value) )
      {
        
   
        //transmitData( i, (signed char)sigInfo.sigInfo.rssi, (char*)msg );
        
        //MRFI_Rssi()
        //Test2=RSSI;
        //Test=rssi_value;
        //int8_t i =-127;
        //int i =-127;
        unsigned char rssi_tmp[10];
        int8_t rssi_int = sigInfo1.sigInfo.rssi;
        itoa(rssi_int,rssi_tmp);
        //tx_send_wait("This is Test :", sizeof("This is Test :") );
        //tx_send_wait(&Test2, strlen(&Test2));
        tx_send_wait(&rssi_tmp, strlen(rssi_tmp));
        //tx_send_wait("\r\n", sizeof("\r\n") );
        
        int8_t mk=0x01,bitshift=0;
              
        tx_send_wait("=",1);  
        
        for (bitshift=0;bitshift<8;bitshift++)
        {
          if( (mk<<bitshift) & rssi_int ) 
            tx_send_wait("1",1);
          else
            tx_send_wait("0",1);
          //tx_send_wait("x",1);
          MRFI_DelayMs( 5 );
        }
        tx_send_wait("\r\n", sizeof("\r\n") );
        
        
         
        
        /*        
        tx_send_wait("This is Test2 :", sizeof("This is Test2 :") );
        tx_send_wait( &Test2, sizeof(Test2) );
        tx_send_wait("\n", sizeof("\n") );
        */
      }
      
    }

    FHSS_ACTIVE( if( nwk_pllBackgrounder( false ) != false ) );
    {
      /* check to see if the host has sent any characters and if it has
      * then send them over the radio link and reset indicator timeout.
      */
      len = rx_receive( rx, MAX_APP_PAYLOAD );
      if( len != 0 )
      {
        while( SMPL_Send( LinkID, rx, len ) != SMPL_SUCCESS )
          ;
        /*
        if( SMPL_SUCCESS == SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RSSI,&rssi_value ) ){
          SMPL_Send( LinkID, &rssi_value, sizeof(rssi_value) );
        }*/
        led_tmr = INDICATOR_TIME_OUT;   /* update activity time out */
        
        /* By forcing a minimum delay between transmissions we guarantee
        * a window for receiving packets.  This is necessary as the radio
        * link is half duplex while the UART is full duplex.  Without this
        * delay mechanism, packets can get lost as both ends may attempt to
        * transmit at the same time which the CCA algorithm fails to handle.
        */
        MRFI_DelayMs( 5 );
      }
    }
    
    /* manage led indicator */
    if( led_tmr != 0 )
    {
      led_tmr--;
      BSP_TURN_ON_LED1( );
    }
    else
      BSP_TURN_OFF_LED1( );

    
    goto main_loop; /* do it again and again and again and ... */
    

}
//*****************************************************************************
//
// This function listens for a link request from another SimpliciTI device.
//
//*****************************************************************************
tBoolean
LinkFrom(void)
{
    linkID_t linkID1;
    uint8_t  pucMsg[MAX_APP_PAYLOAD], ucLen, ucLtid;
    unsigned long ulCount;
    smplStatus_t eRetcode;

    //
    // Tell the user what we're doing.
    //
    UpdateStatus(false, "Listening for link...");

    //
    // Keep the compiler happy.
    //
    eRetcode = SMPL_TIMEOUT;

    //
    // Turn on LED 1 to indicate that we are listening.
    //
    SetLED(1, true);

    //
    // Listen for link for 10 seconds or so.  This logic may fail if you
    // happen to have sat around for about 13.6 years between starting the
    // example and pressing the mode selection button.  I suspect I will be
    // forgiven for this.
    //
    ulCount = g_ulSysTickCount + (LINK_TIMEOUT_SECONDS * TICKS_PER_SECOND);
    while (ulCount > g_ulSysTickCount)
    {
        //
        // Process our message queue to keep the widget library happy.
        //
        WidgetMessageQueueProcess();

        //
        // Listen for a link.  This call takes quite some time to return.
        //
        eRetcode = SMPL_LinkListen(&linkID1);

        //
        // Was the link successful?
        //
        if (SMPL_SUCCESS == eRetcode)
        {
            //
            // Yes - drop out of the loop.
            //
            break;
        }
    }

    //
    // Did we link successfully?
    //
    if(eRetcode != SMPL_SUCCESS)
    {
        //
        // No - Tell the user what happened and return an error.
        //
        UpdateStatus(false, "Failed to link!");
        return(false);
    }

    //
    // Turn off LED 1 to indicate that our listen succeeded.
    //
    UpdateStatus(false, "Link succeeded.");
    SetLED(1, false);

    //
    // Clear our message counter.
    //
    ulCount = 0;

    //
    // Enter an infinite loop polling for messages.
    //
    while (1)
    {
        //
        // Turn the radio off and pretend to sleep for a second or so.
        //
        SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
        SPIN_ABOUT_A_SECOND;  /* emulate MCU sleeping */

        //
        // Turn the radio back on again.
        //
        SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

        //
        // Were any messages "received"?
        //
        // The receive call results in polling the Access Point.  The success
        // case occurs when a payload is actually returned.  When there is no
        // frame waiting for the device a frame with no payload is returned by
        // the Access Point.  Note that this loop will retrieve any and all
        // frames that are waiting for this device on the specified link ID.
        // This call will also return frames that were received directly.  It
        // is possible to get frames that were repeated either from the initial
        // transmission from the peer or via a Range Extender.  This is why we
        // implement the TID check.
        //
        do
        {
            //
            // Receive whatever the AP has for us.
            //
            eRetcode = SMPL_Receive(linkID1, pucMsg, &ucLen);

            //
            // Did we get a real frame?
            //
            if((eRetcode == SMPL_SUCCESS) && ucLen)
            {
                //
                // Tell the user what's going on.
                //
                UpdateStatus(false, "Received msg %d", ++ulCount);

                //
                // Process our message queue to keep the widget library happy.
                //
                WidgetMessageQueueProcess();

                //
                // Check the application sequence number to detect late or missing
                // frames.
                //
                ucLtid = *(pucMsg+1);
                if (ucLtid)
                {
                    //
                    // If the current TID is non-zero and the last one we saw was
                    // less than this one assume we've received the 'next' one.
                    //
                    if (g_ucTid < ucLtid)
                    {
                        //
                        // 'Next' frame.  We may have missed some but we don't
                        // care.
                        //
                        if ((*pucMsg == 1) || (*pucMsg == 2))
                        {
                            //
                            // We're good. Toggle the requested LED.
                            //
                            ToggleLED(*pucMsg);
                        }

                        //
                        // Remember the last TID.
                        //
                        g_ucTid = ucLtid;
                    }

                    //
                    // If current TID is non-zero and less than or equal to the last
                    // one we saw assume we received a duplicate.  Just ignore it.
                    //
                }
                else
                {
                    //
                    // Current TID is zero so the count wrapped or we just started.
                    // Let's just accept it and start over.
                    //
                    if ((*pucMsg == 1) || (*pucMsg == 2))
                    {
                        //
                        // We're good. Toggle the requested LED.
                        //
                        ToggleLED(*pucMsg);
                    }

                    //
                    // Remember the last TID.
                    //
                    g_ucTid = ucLtid;
                }
            }
        } while ((eRetcode == SMPL_SUCCESS) & ucLen);
    }
}
void main (void)
{
  addr_t lAddr;
  bspIState_t intState;
  char *Flash_Addr;                         // Initialize radio address location
  Flash_Addr = (char *)0x10F0;

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  // delay loop to ensure proper startup before SimpliciTI increases DCO
  // This is typically tailored to the power supply used, and in this case
  // is overkill for safety due to wide distribution.
  __delay_cycles(65000);

  if( CALBC1_8MHZ == 0xFF && CALDCO_8MHZ == 0xFF )// Do not run if cal values
  {
    P1DIR |= 0x03;
    BSP_TURN_ON_LED1();
    BSP_TURN_OFF_LED2();
    while(1)
    {
      __delay_cycles(65000);
      BSP_TOGGLE_LED2();
      BSP_TOGGLE_LED1();
    }
  }

  BSP_Init();

  if( Flash_Addr[0] == 0xFF &&
      Flash_Addr[1] == 0xFF &&
      Flash_Addr[2] == 0xFF &&
      Flash_Addr[3] == 0xFF )
    {
      createRandomAddress();                // Create Random device address at
    }                                       // initial startup if missing
  lAddr.addr[0]=Flash_Addr[0];
  lAddr.addr[1]=Flash_Addr[1];
  lAddr.addr[2]=Flash_Addr[2];
  lAddr.addr[3]=Flash_Addr[3];

  //SMPL_Init();
  SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr);

  MCU_Init();
  //Transmit splash screen and network init notification
  TXString( (char*)splash, sizeof splash);
  TXString( "\r\nInitializing Network....", 26 );

  SMPL_Init(sCB);

  // network initialized
  TXString( "Done\r\n", 6);

  // main work loop
  while(1)
  {
    // Wait for the Join semaphore to be set by the receipt of a Join frame from a
    // device that supports and End Device.

    if (sJoinSem && (sNumCurrentPeers < NUM_CONNECTIONS))
    {
      // listen for a new connection
      SMPL_LinkListen(&sLID[sNumCurrentPeers]);
      sNumCurrentPeers++;
      BSP_ENTER_CRITICAL_SECTION(intState);
      if (sJoinSem)
      {
        sJoinSem--;
      }
      BSP_EXIT_CRITICAL_SECTION(intState);
    }

    // if it is time to measure our own temperature...
    if(sSelfMeasureSem)
    {
//    	TXString("\r\n...", 5);
      BSP_TOGGLE_LED1();
      sSelfMeasureSem = 0;
    }

    // Have we received a frame on one of the ED connections?
    // No critical section -- it doesn't really matter much if we miss a poll
    if (sPeerFrameSem)
    {
    	  uint8_t  msg[MESSAGE_LENGTH], len, i;

      // process all frames waiting
      for (i=0; i<sNumCurrentPeers; ++i)
      {
        if (SMPL_Receive(sLID[i], msg, &len) == SMPL_SUCCESS)
        {
          ioctlRadioSiginfo_t sigInfo;
          sigInfo.lid = sLID[i];
          SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SIGINFO, (void *)&sigInfo);
          transmitData( i, (signed char)sigInfo.sigInfo.rssi, (char*)msg );
          BSP_TURN_ON_LED2();               // Toggle LED2 when received packet
          BSP_ENTER_CRITICAL_SECTION(intState);
          sPeerFrameSem--;
          BSP_EXIT_CRITICAL_SECTION(intState);
          __delay_cycles(10000);
          BSP_TURN_OFF_LED2();
        }
      }
    }
  }
}
Exemplo n.º 12
0
static void linkTo()
{
  uint8_t     msg[2];
  uint8_t     button, misses, done;

  /* Keep trying to link... */
  while (SMPL_SUCCESS != SMPL_Link(&sLinkID1))
  {
    toggleLED(1);
    toggleLED(2);
    SPIN_ABOUT_A_SECOND;
  }

  /* Turn off LEDs. */
  if (BSP_LED2_IS_ON())
  {
    toggleLED(2);
  }
  if (BSP_LED1_IS_ON())
  {
    toggleLED(1);
  }

  /* sleep until button press... */
  SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

  while (1)
  {
    button = 0;
    /* Send a message when either button pressed */
    if (BSP_BUTTON1())
    {
      SPIN_ABOUT_A_QUARTER_SECOND;  /* debounce... */
      /* Message to toggle LED 1. */
      button = 1;
    }
    else if (BSP_BUTTON2())
    {
      SPIN_ABOUT_A_QUARTER_SECOND;  /* debounce... */
      /* Message to toggle LED 2. */
      button = 2;
    }
    if (button)
    {
      /* get radio ready...awakens in idle state */
      SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

      /* Set TID and designate which LED to toggle */
      msg[1] = ++sTid;
      msg[0] = (button == 1) ? 1 : 2;
      done = 0;
      while (!done)
      {
        for (misses=0; misses < MISSES_IN_A_ROW; ++misses)
        {
          if (SMPL_SUCCESS == SMPL_Send(sLinkID1, msg, sizeof(msg)))
          {
#if defined( FREQUENCY_AGILITY )
            /* If macro is defined we're supporting Frequency Agility. In this case
             * the peer will acknowledge the message sent. It is the only way we can
             * tell if we are on the right channel. Wait for ack.
             */
            {
              bspIState_t intState;

              SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
              NWK_REPLY_DELAY();
              SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXIDLE, 0);

              if (!sPeerFrameSem)
              {
                /* Try again if we havn't received anything. */
                continue;
              }
              else
              {
                uint8_t len;

                BSP_ENTER_CRITICAL_SECTION(intState);
                sPeerFrameSem--;
                BSP_EXIT_CRITICAL_SECTION(intState);

                /* We got something. Go get it. */
                SMPL_Receive(sLinkID1, msg, &len);
                if (len && (*msg & NWK_APP_REPLY_BIT))
                {
                  toggleLED(*msg & ~NWK_APP_REPLY_BIT);
                  break;
                }
              }
            }
#else
            /* Not supporting Frequency agility. Just break out since there
             * will be no ack.
             */
            break;
#endif
          }
        }
        if (misses == MISSES_IN_A_ROW)
        {
          /* This can only happen if we are supporting Frequency Agility and we
           * appear not to have received an acknowledge. Do a scan.
           */
          ioctlScanChan_t scan;
          freqEntry_t     freq[NWK_FREQ_TBL_SIZE];

          scan.freq = freq;
          SMPL_Ioctl(IOCTL_OBJ_FREQ, IOCTL_ACT_SCAN, &scan);
          /* If we now know the channel (number == 1) change to it. In any case
           * try it all again. If we changed channels we should get an ack now.
           */
          if (1 == scan.numChan)
          {
            SMPL_Ioctl(IOCTL_OBJ_FREQ, IOCTL_ACT_SET, freq);
          }
        }
        else
        {
          /* Got the ack. We're done. */
          done = 1;
        }
      }

      /* radio back to sleep */
      SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
    }
  }
}
Exemplo n.º 13
0
// *************************************************************************************************
// @fn          simpliciti_main_tx_only
// @brief       Get data through callback. Transfer data when external trigger is set.
// @param       none
// @return      none
// *************************************************************************************************
void simpliciti_main_tx_only(void)
{
	uint8_t len, i;
	uint8_t ed_data[2];

	while(1)
	{
		// Get end device data from callback function 
		simpliciti_get_ed_data_callback();

		// Get radio ready. Wakes up in IDLE state.
		if(getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA) || 
		   getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA)) {

			SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);

			// Send data when flag bit SIMPLICITI_TRIGGER_SEND_DATA is set
			if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA)) 
			{
			  // Acceleration / button events packets are 4 bytes long
              SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, SMPL_TXOPTION_NONE);
			  //SMPL_SendOpt(sLinkID1, simpliciti_data, simpliciti_payload_length, simpliciti_options);
              // reset options to default
              //simpliciti_options =  SMPL_TXOPTION_NONE;
			  clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_DATA);
			}
			// Receive data when flag bit SIMPLICITI_TRIGGER_RECEIVE_DATA is set
			if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA)) {
				// Send 2 byte long ready-to-receive packet to stimulate host reply
				clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVE_DATA);

				// clean up tha buffer first
				simpliciti_data[0] = 0x00;
				simpliciti_data[1] = 0x00;
				simpliciti_data[3] = 0x00;
				simpliciti_data[4] = 0x00;

				// generate a ready to receive packet
				ed_data[0] = SYNC_ED_TYPE_R2R;
				ed_data[1] = 0xCB;

				SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);

				// we try to receive 9 times by sending a R2R packet
				for (i = 0; i < 10; i++) {
					SMPL_SendOpt(sLinkID1, ed_data, 2, SMPL_TXOPTION_NONE);

					//WDTCTL = WDTPW + WDTHOLD;

					// Wait shortly for host reply
					NWK_DELAY(10);

					while (SMPL_Receive(sLinkID1, simpliciti_data, &len) == SMPL_SUCCESS) 
					{
						if (len > 0)
						{
							// Decode received data
							if(simpliciti_get_rvc_callback(len))
							{
								// stop retry loop
								i = 10;
								break;
							}
						}
					}
                    Timer0_A4_Delay(CONV_MS_TO_TICKS(500));
				}
			}

			// Put radio back to SLEEP state
			SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
		}
		// Exit when flag bit SIMPLICITI_TRIGGER_STOP is set
		if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP)) 
		{
			// Clean up SimpliciTI stack to enable restarting
			sInit_done = 0;
			break;
		}
	}
}
Exemplo n.º 14
0
static void monitorForBadNews()
{
	uint8_t i, msg[1], len;

	/* Turn off LEDs. Check for bad news will toggle one LED. 
	 * The other LED will toggle when bad news message is sent.
	 */
	toggleLED(2);
	toggleLED(1);

	/* frequency hopping doesn't support sleeping just yet */
#ifndef FREQUENCY_HOPPING
	/* start the radio off sleeping */
	SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
#endif

	while (1)
	{
		/* spoof MCU sleeping... */
		for (i=0; i<CHECK_RATE; ++i)
		{
			SPIN_ABOUT_A_SECOND; /* manages FHSS implicitly */
		}

		toggleLED(1);
		/* check "sensor" to see if we need to send an alert */
		if (BSP_BUTTON1() || BSP_BUTTON2())
		{
			/* sensor activated. start babbling. */
			start2Babble();
		}

		/* frequency hopping doesn't support sleeping just yet */
#ifndef FREQUENCY_HOPPING
		/* wake up radio. we need it to listen for others babbling. */
		SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
		/* turn on RX. default is RX off. */
		SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
#endif

		/* stay on "long enough" to see if someone else is babbling */
		SPIN_ABOUT_A_QUARTER_SECOND;

		/* frequency hopping doesn't support sleeping just yet */
#ifndef FREQUENCY_HOPPING
		/* we're done with radio. shut it down */
		SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);
#endif

		/* got message? */
		if (SMPL_SUCCESS == SMPL_Receive(SMPL_LINKID_USER_UUD, msg, &len))
		{
			/* got something. is it bad news? */
		if (len && (msg[0] == BAD_NEWS))
		{
			/* Yep. start babbling. If there is a filtering token make
			 * sure the token matches the expected value.
			 */
			start2Babble();
		}
		}
	}
}
// AP main routine
void simpliciti_main(void)
{
  bspIState_t intState;
  uint8_t j;
  uint8_t len;
  uint32_t led_toggle = 0;
  uint8_t   pwr;

  // Init variables  
  simpliciti_flag = SIMPLICITI_STATUS_LINKING;

  // Init SimpliciTI
  SMPL_Init(sCB);
  
  // Set output power to +1.1dBm (868MHz) / +1.3dBm (915MHz)
  pwr = IOCTL_LEVEL_2;
  SMPL_Ioctl(IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SETPWR, &pwr);
  
   // LED off
  BSP_TURN_OFF_LED1();
    
  /* main work loop */
  while (1)
  {
    // Wait for the Join semaphore to be set by the receipt of a Join frame from a
    //device that supports an End Device.
    if (sJoinSem && !sNumCurrentPeers)
    {
      /* listen for a new connection */
      while (1)
      {
        if (SMPL_SUCCESS == SMPL_LinkListen(&linkID0))
        {
          // We have a connection
          simpliciti_flag = SIMPLICITI_STATUS_LINKED;
          BSP_TURN_ON_LED1();
          break;
        }
        /* Implement fail-to-link policy here. otherwise, listen again. */
      }

      sNumCurrentPeers++;

      BSP_ENTER_CRITICAL_SECTION(intState);
      sJoinSem--;
      BSP_EXIT_CRITICAL_SECTION(intState);
    }

    /* Have we received a frame on one of the ED connections?
     * No critical section -- it doesn't really matter much if we miss a poll
     */
    if (sPeerFrameSem)
    {
      // Continuously try to receive end device packets
      if (SMPL_SUCCESS == SMPL_Receive(linkID0, ed_data, &len))
      {
        // Acceleration / ppt data packets are 4 byte long
        if (len == 4)
        {
          BSP_TOGGLE_LED1();
          memcpy(simpliciti_data, ed_data, 4);
          setFlag(simpliciti_flag, SIMPLICITI_TRIGGER_RECEIVED_DATA);

#ifdef EMBEDDED_UART        
          uart_analyze_packet(simpliciti_data[0],simpliciti_data[1],simpliciti_data[2],simpliciti_data[3]);
#endif              
        }        
        // Sync packets are either R2R (2 byte) or data (19 byte) long
        else if ((len == 2) || (len == 19))
        {
          // Indicate received packet
          BSP_TOGGLE_LED1();

          // Decode end device packet
          switch (ed_data[0])
          {
              case SYNC_ED_TYPE_R2R: 
                                    // Send reply
                                    if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_CMD))
                                    {
                                      // Clear flag
                                      clearFlag(simpliciti_flag, SIMPLICITI_TRIGGER_SEND_CMD);
                                      // Command data was set by USB buffer previously
                                      len = BM_SYNC_DATA_LENGTH;
                                    }
                                    else // No command currently available
                                    {
                                      simpliciti_data[0] = SYNC_AP_CMD_NOP;
                                      simpliciti_data[1] = 0x55;
                                      len = 2;
                                    }
                
                                    // Send reply packet to end device
                                    SMPL_Send(linkID0, simpliciti_data, len);
                                    break;
                                 
            case SYNC_ED_TYPE_MEMORY: 
            case SYNC_ED_TYPE_STATUS:
                                    // If buffer is empty, copy received end device data to intermediate buffer
                                    if (!simpliciti_sync_buffer_status)
                                    {
                                      for (j=0; j<BM_SYNC_DATA_LENGTH; j++) simpliciti_data[j] = ed_data[j];
                                      simpliciti_sync_buffer_status = 1;
                                    }
                                    // Set buffer status to full
                                    break;

          }
        }
      }
    }
    
    // Exit function if SIMPLICITI_TRIGGER_STOP flag bit is set in USB driver    
    if (getFlag(simpliciti_flag, SIMPLICITI_TRIGGER_STOP)) 
    {
      // Immediately turn off RF interrupt
      IEN2 &= ~BIT0;
      RFIM = 0;
      RFIF = 0;
      // Clean up after SimpliciTI and enable restarting the stack
      linkID0 = 0;
      sNumCurrentPeers = 0;
      sJoinSem = 0;
      sPeerFrameSem = 0;
      sInit_done = 0;
      // LED off
      BSP_TURN_OFF_LED1();
      return;
    }
    
    // Blink slowly to indicate that access point is on
    if (!sNumCurrentPeers)
    {
      if (led_toggle++>150000)
      {
        BSP_TOGGLE_LED1();
        led_toggle = 0;
      }
    }
  }
}
//*****************************************************************************
//
// This is the main monitoring function for the applicaiton. It "sleeps" for
// 5 seconds or so then checks to see if there are any alerts being broadcast.
// If not, it toggles a LED and goes back to "sleep".  If an alert is received
// it switches into "babbling" mode where it retransmits the alert every 100mS
// to propagate the alert through the network.
//
// This function does not return.
//
//*****************************************************************************
void
MonitorForBadNews(void)
{
    uint8_t pucMsg[1], ucLen;
    unsigned long ulLoop;

    //
    // Turn off LEDs. Check for bad news will toggle one LED.  The other LED will
    // toggle when bad news message is sent.
    //
    SetLED(2, false);
    SetLED(1, false);

    //
    // Start with radio sleeping.
    //
    SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

    while (1)
    {
        //
        // Spoof MCU sleeping...
        //
        for (ulLoop = 0; ulLoop < CHECK_RATE; ulLoop++)
        {
            SPIN_ABOUT_A_SECOND;
        }

        ToggleLED(1);

        //
        // Check the "sensor" to see if we need to send an alert.
        //
        if (g_bAlarmRaised)
        {
            //
            // The sensor has been activated. Start babbling.  This function
            // will not return.
            //
            Start2Babble();
        }

        //
        // Wake up the radio and receiver so that we can listen for others
        // babbling.
        //
        SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_AWAKE, 0);
        SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);

        //
        // Stay on "long enough" to see if someone else is babbling
        //
        SPIN_ABOUT_A_QUARTER_SECOND;

        //
        // We're done with the radio so shut it down.
        //
        SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, 0);

        //
        // Did we receive a message while the radio was on?
        //
        if (SMPL_SUCCESS == SMPL_Receive(SMPL_LINKID_USER_UUD, pucMsg, &ucLen))
        {
            //
            // Did we receive something and, if so, is it bad news?
            //
            if (ucLen && (pucMsg[0] == BAD_NEWS))
            {
                //
                // Bad news has been received so start babbling to pass the
                // alert on to the other devices in the network.
                //
                UpdateStatus(true, "Alarm received!");
                Start2Babble();
            }
        }
    }
}
void main (void)
{
  bspIState_t intState;

#ifdef FREQUENCY_AGILITY
  memset(sSample, 0x0, sizeof(sSample));
#endif

  BSP_Init();

  /* If an on-the-fly device address is generated it must be done before the
   * call to SMPL_Init(). If the address is set here the ROM value will not
   * be used. If SMPL_Init() runs before this IOCTL is used the IOCTL call
   * will not take effect. One shot only. The IOCTL call below is conformal.
   */
#ifdef I_WANT_TO_CHANGE_DEFAULT_ROM_DEVICE_ADDRESS_PSEUDO_CODE
  {
    addr_t lAddr;

    createRandomAddress(&lAddr);
    SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr);
  }
#endif /* I_WANT_TO_CHANGE_DEFAULT_ROM_DEVICE_ADDRESS_PSEUDO_CODE */

  SMPL_Init(sCB);

  /* green and red LEDs on solid to indicate waiting for a Join. */
  if (!BSP_LED2_IS_ON())
  {
    toggleLED(2);
  }
  if (!BSP_LED1_IS_ON())
  {
    toggleLED(1);
  }

  /* main work loop */
  while (1)
  {
    /* manage FHSS schedule if FHSS is active */
    FHSS_ACTIVE( nwk_pllBackgrounder( false ) );
    
    /* Wait for the Join semaphore to be set by the receipt of a Join frame from a
     * device that supports an End Device.
     *
     * An external method could be used as well. A button press could be connected
     * to an ISR and the ISR could set a semaphore that is checked by a function
     * call here, or a command shell running in support of a serial connection
     * could set a semaphore that is checked by a function call.
     */
    if (sJoinSem && (sNumCurrentPeers < NUM_CONNECTIONS))
    {
      /* listen for a new connection */
      while (1)
      { /* SMPL_LinkListen will call nwk_PllBackgrounder for us if FHSS active */
        if (SMPL_SUCCESS == SMPL_LinkListen(&sLID[sNumCurrentPeers]))
        {
          break;
        }
        /* Implement fail-to-link policy here. otherwise, listen again. */
      }

      sNumCurrentPeers++;

      BSP_ENTER_CRITICAL_SECTION(intState);
      sJoinSem--;
      BSP_EXIT_CRITICAL_SECTION(intState);
    }

    /* Have we received a frame on one of the ED connections?
     * No critical section -- it doesn't really matter much if we miss a poll
     */
    if (sPeerFrameSem)
    {
      uint8_t     msg[MAX_APP_PAYLOAD], len, i;

      /* process all frames waiting */
      for (i=0; i<sNumCurrentPeers; ++i)
      {
        if (SMPL_SUCCESS == SMPL_Receive(sLID[i], msg, &len))
        {
          processMessage(sLID[i], msg, len);

          BSP_ENTER_CRITICAL_SECTION(intState);
          sPeerFrameSem--;
          BSP_EXIT_CRITICAL_SECTION(intState);
        }
      }
    }
    if (BSP_BUTTON1())
    {
      SPIN_ABOUT_A_QUARTER_SECOND;  /* debounce */
      changeChannel();
    }
    else
    {
      checkChangeChannel();
    }
    BSP_ENTER_CRITICAL_SECTION(intState);
    if (sBlinky)
    {
      if (++sBlinky >= 0xF)
      {
        sBlinky = 1;
        toggleLED(1);
        toggleLED(2);
      }
    }
    BSP_EXIT_CRITICAL_SECTION(intState);
  }

}