RadioCountToLeds

This program sends the value of a counter on one component over the radio to another component for display on its LEDs.

/**
 * Implementation of the RadioCountToLeds application.  RadioCountToLeds periodically
 * increments a counter and broadcasts the value of the counter on the radio.
 * A RadioCountToLeds node that hears a broadcast displays the bottom three bits
 * of the value it has received. This application is a useful test to show that
 * basic communication, and timers work.
 *
 */

// Interface for Counter Broadcaster
type ICountBroadcast is interface (
		out any broadcastSend ;
		in integer button ;
		in bool timerRecv ;
)

// Counter Broadcaster component
component CountBroadcast presents ICountBroadcast {

	count = 0
	test = true
	constructor() {
	}

	behaviour {	

			//wait for a button press to start sending
			if(test) then {
				receive tick1 from button
				test := false
			}

			setTimer(timerRecv , 0.25 , false)
			receive tick from timerRecv

			count := count + 1 

			send any(count) on broadcastSend
	}
} 

/***************************************************************************/

//Interface for Counter Receiver
type ICountReceiver is interface (
		in RadioPacket broadcastRecv
)

//Counter Receiver Component
component CountRecv presents ICountReceiver {

	constructor() {
	}

	behaviour {

		// wait for packet from Radio
		receive packet from broadcastRecv

		project packet.payload as reading onto
			integer	: {
				if (reading & 4) == 4 then {
					setRedLedPower(true)
		      	} else {
					setRedLedPower(false)
				}

		        if (reading & 2) == 2 then {
					setBlueLedPower(true)
		      	} else {
					setBlueLedPower(false)
				}

		      	if (reading & 1) == 1 then {
					setGreenLedPower(true)
		      	} else {
					setGreenLedPower(false)
				}

			}
			default : { printString( "???" ) }
	}
}

/***************************************************************************/
//Create the components
tbc = new CountBroadcast()
trc = new CountRecv()

//Connect the channels
connect tbc.button to buttonSensor.output
connect tbc.broadcastSend to radio.broadcastSend
connect trc.broadcastRecv to radio.received

The corresponding nesC program for TinyOS is shown below.

#ifndef RADIO_COUNT_TO_LEDS_H
#define RADIO_COUNT_TO_LEDS_H

typedef nx_struct radio_count_msg {
  nx_uint16_t counter;
} radio_count_msg_t;

enum {
  AM_RADIO_COUNT_MSG = 6,
};
#endif

/*******************************/
#include "RadioCountToLeds.h"

configuration RadioCountToLedsAppC {}
implementation {
  components MainC, RadioCountToLedsC as App, LedsC;
  components new AMSenderC(AM_RADIO_COUNT_MSG);
  components new AMReceiverC(AM_RADIO_COUNT_MSG);
  components new TimerMilliC();
  components ActiveMessageC;
  
  App.Boot -> MainC.Boot;
  
  App.Receive -> AMReceiverC;
  App.AMSend -> AMSenderC;
  App.AMControl -> ActiveMessageC;
  App.Leds -> LedsC;
  App.MilliTimer -> TimerMilliC;
  App.Packet -> AMSenderC;
}

/*******************************/

#include "Timer.h"
#include "RadioCountToLeds.h"

module RadioCountToLedsC @safe() {
  uses {
    interface Leds;
    interface Boot;
    interface Receive;
    interface AMSend;
    interface Timer as MilliTimer;
    interface SplitControl as AMControl;
    interface Packet;
  }
}
implementation {

  message_t packet;

  bool locked;
  uint16_t counter = 0;
  
  event void Boot.booted() {
    call AMControl.start();
  }

  event void AMControl.startDone(error_t err) {
    if (err == SUCCESS) {
      call MilliTimer.startPeriodic(250);
    }
    else {
      call AMControl.start();
    }
  }

  event void AMControl.stopDone(error_t err) {
    // do nothing
  }
  
  event void MilliTimer.fired() {
    counter++;
    dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter);
    if (locked) {
      return;
    }
    else {
      radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t));
      if (rcm == NULL) {
	return;
      }

      rcm->counter = counter;
      if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) {
	dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n", counter);	
	locked = TRUE;
      }
    }
  }

  event message_t* Receive.receive(message_t* bufPtr, 
				   void* payload, uint8_t len) {
    dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len);
    if (len != sizeof(radio_count_msg_t)) {return bufPtr;}
    else {
      radio_count_msg_t* rcm = (radio_count_msg_t*)payload;
      if (rcm->counter & 0x1) {
	call Leds.led0On();
      }
      else {
	call Leds.led0Off();
      }
      if (rcm->counter & 0x2) {
	call Leds.led1On();
      }
      else {
	call Leds.led1Off();
      }
      if (rcm->counter & 0x4) {
	call Leds.led2On();
      }
      else {
	call Leds.led2Off();
      }
      return bufPtr;
    }
  }

  event void AMSend.sendDone(message_t* bufPtr, error_t error) {
    if (&packet == bufPtr) {
      locked = FALSE;
    }
  }

}