User Tools

Site Tools


lib:simpliciti:example

SimpliciTI program example for WSN430

Introduction

This simple program shows how to implement communication thanks to SimpliciTI. In this program we establish a peer to peer communication between two end devices : a sender and a listener. These devices are going to exchange frames containing a led number to turn on and a transmitted frame id, in order to demonstrate the communication.

Description

The sender periodically sends a frame that includes a table of 2 elements called msg. The first element is the led number to toggle. In this case it is always the green led. The second one is a number representing the sent frame id. Thus each time the sender sends a frame, this counter is incremented.

The listener is waiting in an infinite loop for incoming frame. As soon as it receives a frame, a callback function is launch that will toggle the green led of the listener device, if the message is valid. As acknowledgement, the listener sends a frame to the sender containing a led number (the red) to turn on and a transmitted frame id.

The sender is also always checking for incoming frame, and when it receives a valid frame from the listener, it calls a callback function checking the message and toggling the red led.

SimpliciTI APIs usage

The first function to be invoked is the BSP_Init(), to initialize the specific target platform.

Then the SMPL_Init(sRxCallback) API initializes the radio and the SimpliciTI protocol stack. The sRxCallback() is the user callback function.

These two first steps are done in the sender device program code, as well as in the listener device one.

At this step, the sender tries to initiate the communication by executing periodically the SimpliciTI API : SMPL_Link(). Once the listener is ready to communicate, it runs the SimpliciTI API : SMPL_LinkListen(). In case of success, the two devices are linked.

The last APIs used is this example are SMPL_Send() and SMPL_Receive(), to send/receive to/from a specified device frames.

Compiling and executing the example

This example is located /Projects/Examples/WSN430 folder. It is composed of two main folders, the first one for the sender device files (/sender), and the second one for the listener device files (/listener). To compile this example you just have to go into them, and executing the make command.

Note that SimpliciTI device addresses are very important, to enable them to communicate. Theses addresses are defined in the devices makefile, with the following command and address for instance: SMPL_NWK_CONFIG += -DTHIS_DEVICE_ADDRESS=“{0x79, 0x56, 0x34, 0x13}”.

Example code

Sender code (main LinkTo.c)

#include "bsp.h"
#include "mrfi.h"
#include "nwk_types.h"
#include "nwk_api.h"
#include "bsp_leds.h"
#include "bsp_buttons.h"
 
//#include "app_remap_led.h"
 
static void linkTo(void);
 
void toggleLED(uint8_t);
 
static uint8_t  sTxTid, sRxTid;
static linkID_t sLinkID1;
 
/* application Rx frame handler. */
static uint8_t sRxCallback(linkID_t);
 
#define SPIN_ABOUT_A_SECOND  NWK_DELAY(100)
 
void main (void)
{
  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 */
 
  /* This call will fail because the join will fail since there is no Access Point 
   * in this scenario. But we don't care -- just use the default link token later. 
   * We supply a callback pointer to handle the message returned by the peer. 
   */
 
  SMPL_Init(sRxCallback);
 
 
  /* turn on LEDs alternatively */
  toggleLED(1);
  toggleLED(2);
  toggleLED(3);
  NWK_DELAY(200);
  int i,j;
  for (i = 6; --i >= 0; ) {
    for (j = 1; j<=3 ; j++) {
      toggleLED(j);
      NWK_DELAY(20);
    }
  }
 
 
  /* never coming back... */
  linkTo();
 
  /* but in case we do... */
  while (1) ;
}
 
static void linkTo()
{
  uint8_t  msg[2], delay = 0;
 
  while (SMPL_SUCCESS != SMPL_Link(&sLinkID1))
  {
    /* blink red LED, until we link successfully */
    toggleLED(1);
    NWK_DELAY(100);//SPIN_ABOUT_A_SECOND;
  }
 
  /* we're linked. turn off LEDs. Received messages will toggle the green LED. */
  if (BSP_LED2_IS_ON())
  {
    toggleLED(1);
  }
 
  if (BSP_LED1_IS_ON())
  {
    toggleLED(2);
  }
 
  if (BSP_LED1_IS_ON())
  {
    toggleLED(3);
  }
 
  /* turn on RX. default is RX off. */
  SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
 
  /* put LED to toggle in the message */
  msg[0] = 2;  /* toggle green */
  while (1)
  {
    SPIN_ABOUT_A_SECOND;
    if (delay > 0x00)
    {
      SPIN_ABOUT_A_SECOND;
    }
    if (delay > 0x01)
    {
      SPIN_ABOUT_A_SECOND;
    }
    if (delay > 0x02)
    {
      SPIN_ABOUT_A_SECOND;
    }
 
    /* delay longer and longer -- then start over */
    delay = (delay+1) & 0x03;
    /* put the sequence ID in the message */
    msg[1] = ++sTxTid;
    SMPL_Send(sLinkID1, msg, sizeof(msg));
  }
}
 
 
void toggleLED(uint8_t which)
{
  switch(which)
   {
    case 1 :
      BSP_TOGGLE_LED1();
      break;
    case 2 :
      BSP_TOGGLE_LED2();
      break;
    case 3 :
      BSP_TOGGLE_LED3();
      break;
   }
  return;
}
 
 
/* handle received frames. */
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 == 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+1);
       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;
}

Listener code (main LinkListen.c)

#include "bsp.h"
#include "mrfi.h"
#include "nwk_types.h"
#include "nwk_api.h"
#include "bsp_leds.h"
#include "bsp_buttons.h"
 
//#include "app_remap_led.h"
 
static void linkFrom(void);
 
void toggleLED(uint8_t);
 
static          uint8_t  sRxTid;
static          linkID_t sLinkID2;
static volatile uint8_t  sSemaphore;
 
/* Rx callback handler */
static uint8_t sRxCallback(linkID_t);
 
int main (void)
{
  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 */
 
  /* This call will fail because the join will fail since there is no Access Point
   * in this scenario. But we don't care -- just use the default link token later.
   * We supply a callback pointer to handle the message returned by the peer.
   */
  SMPL_Init(sRxCallback);
 
  /* turn on LEDs. */
  toggleLED(2);
  NWK_DELAY(500);
  int i;
  for (i = 10; --i >= 0; ) {
    toggleLED(1);
    toggleLED(2);
    NWK_DELAY(10);
  }
  toggleLED(2);
 
 
  /* never coming back... */
  linkFrom();
 
  /* but in case we do... */
  while (1) ;
}
 
static void linkFrom()
{
  uint8_t     msg[2], tid = 0;
 
  /* Turn off one LED so we can tell the device is now listening.
   * Received messages will toggle the other LED.
   */
  //toggleLED(1);
 
  /* listen for link forever... */
  while (1)
    {
      if (SMPL_SUCCESS == SMPL_LinkListen(&sLinkID2))
	{
	  break;
	}
      /* Implement fail-to-link policy here. otherwise, listen again. */
    }
  /* we're linked. turn off red LED. Received messages will toggle the green LED. */
  if (BSP_LED2_IS_ON())
    {
      toggleLED(2);
    }
 
  if (BSP_LED1_IS_ON())
    {
      toggleLED(1);
    }
 
  /* turn on LED1 on the peer in response to receiving a frame. */
  *msg = 0x01;  /* toggle red led */
 
  /* turn on RX. default is RX off. */
  SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_RXON, 0);
 
   while (1)
   {
     /* Wait for a frame to be received. The Rx handler, which is running in
      * ISR thread, will post to this semaphore allowing the application to
      * send the reply message in the user thread.
      */
     if (sSemaphore)
     {
       *(msg+1) = ++tid;
       SMPL_Send(sLinkID2, msg, 2);
 
       /* Reset semaphore. This is not properly protected and there is a race
        * here. In theory we could miss a message. Good enough for a demo, though.
        */
       sSemaphore = 0;
     }
   }
}
 
 
void toggleLED(uint8_t which)
{
  switch(which)
   {
    case 1 :
      BSP_TOGGLE_LED1();
      break;
    case 2 :
      BSP_TOGGLE_LED2();
      break;
    case 3 :
      BSP_TOGGLE_LED3();
      break;
   }
  return;
}
 
 
/* 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 */
           toggleLED(*msg);
           sRxTid = tid;
         }
       }
       else
       {
         /* wrap case... */
         if (sRxTid)
         {
           /* we're good. toggle LED */
           toggleLED(*msg);
           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;
}
lib/simpliciti/example.txt · Last modified: 2018/04/13 14:47 (external edit)