[Tinyos-2-commits] CVS: tinyos-2.x/doc/html/tutorial lesson16.html, NONE, 1.1 index.html, 1.6, 1.7 lesson15.html, 1.7, 1.8 lesson8.html, 1.6, 1.7

Kevin Klues klueska at users.sourceforge.net
Mon Sep 3 15:38:44 PDT 2007


Update of /cvsroot/tinyos/tinyos-2.x/doc/html/tutorial
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv4861/tutorial

Modified Files:
	index.html lesson15.html lesson8.html 
Added Files:
	lesson16.html 
Log Message:
Small modifications to lesson 15 and 8, and new checkin of lesson 16

--- NEW FILE: lesson16.html ---
<html>
    <head>
      <title>TinyOS Tutorial Lesson 16: Writing Low Power Sensing Applications</title>
      <link href="../../stylesheets/tutorial.css" rel="stylesheet" Type="text/css">
  </head>
  <body>
    
    <div class="title">Lesson 16: Writing Low Power Sensing Applications</div>
    <div class="subtitle">Last updated August 31st, 2007</div>
    
    <p>
    This lesson demonstrates how to write low power sensing applications in TinyOS.  At 
    	any given moment, the power consumption of a wireless sensor node is a function of its
    	microcontroller power state, whether the radio, flash, and sensor peripherals are on, 
    	and what operations active peripherals are performing.  This tutorial shows you 
    	how to best utilize the features provided by TinyOS to keep the power consumption
    	of applications that use these devices to a minumum.
    	</p>
    
    <h1>Overview</h1>
    <p>
    Energy management is a critical concern in wireless sensor networks.  Without it, 
    the lifetime of a wireless sensor node is limited to just a few short weeks or even 
    days, depending on the type of application it is running and the size of batteries 
    it is using.  With proper energy management, the same node, running the 
    same application, can be made to last for months or years on the same set of batteries.
    </p>
    <p>
    Ideally, one would want all energy management to be handled transparently by the
    operating system, relieving application developers from having to deal with this 
    burden themselves.  While attempts have been made in the past to provide such
    capabilities, most operating systems today still just provide the necessary primitives for 
    performing energy management -- the logic of when and how to do so is left completely up 
    to the application.
    </p>
    <p>
	TinyOS provides a novel method of performing energy management directly 
	within the OS. The method it uses is as efficient as it is elegant.  Developers 
	no longer have to struggle with code that explicitly manages the power state for any of the
	peripheral devices that it uses.  To get a better idea of the complexity involved in 
	doing something as simple as periodically taking a set of sensor readings 
	and logging them to flash in the most energy efficient manner possible, take a look 
	at the pseudo code found below.
	</p>
	<pre>   
Every Sample Period:
  Turn on SPI bus              
  Turn on flash chip           
  Turn on voltage reference    
  Turn on I2C bus              
  Log prior readings           
  Start humidity sample        
  Wait 5ms for log             
  Turn off flash chip          
  Turn off SPI bus             
  Wait 12ms for vref          
  Turn on ADC
  Start total solar sample
  Wait 2ms for total solar
  Start photo active sample
  Wait 2ms for photo active
  Turn off ADC
  Turn off vref
  Wait 34ms for humidity
  Start temperature sample
  Wait 220ms for temperature
  Turn off I2C bus
	</pre>
	<p>
	With the methods provided by TinyOS, hand-tuned application code that looks like that 
	can be transformed into this:
	</p>
	<pre>    
Every Sample Period:
  Log prior readings
  Sample photo active
  Sample total solar
  Sample temperature
  Sample humidity 
	</pre>
    	<p>
    	The pseudo code shown above is for concurrently sampling all of the 
    	the onboard sensors found on the latest revision of the tmote sky sensor nodes.
    Experiments have shown that using the methods provided by TinyOS, this application 
    comes within 1.6% of the energy efficiency of the hand-tuned implementation -- 
    even at sampling rates as fast as 1 sample per second.  For more information
    on these experiments and the method TinyOS uses to actually manage energy
    so efficiently, please refer to the paper found 
    <a href="http://sing.stanford.edu/klueska/Black_Site/Publications_files/klues07icem.pdf">
    here.</a> 
    	</p>
    	<!---
    	<center>
    	<img src="img/tmote_current.png" width=66% ></img>
	</center>
	-->
	<p>
	The rest of this tutorial is dedicated to teaching you how to write applications
	that allow TinyOS to manage energy for you in the most efficient manner possible.  
	As a rule, TinyOS can manage energy more efficiently when I/O requests are submitted
	by an application in parallel.  Submitting them serially may result in energy
	wasted by unnecessarily turning devices on and off more frequently than required. 
	</p>
	<h1>
	Peripheral Energy Management
	</h1>
	<p>
	Compare the following two code snippets:
	</p>
<table>
 <tr><td><b>Parallel</b></td><td width=10></td><td><b>Serial</b></td></tr>
 <tr><td valign=top>
<pre>
event void Boot.booted() {
  call Timer.startPeriodic(SAMPLE_PERIOD);
}

event void Timer.fired() {
  call LogWrite.append(current_entry, sizeof(log_entry_t));

  current_entry_num = !current_entry_num;
  current_entry = &(entry[current_entry_num]);
  current_entry->entry_num = ++log_entry_num;
  
  call Humidity.read();
  call Temperature.read();
  call Photo.read();
  call Radiation.read();
}
  
event void Humidity.readDone(error_t result, uint16_t val) {
  if(result == SUCCESS) {
   current_entry->hum = val;
  }
  else current_entry->hum  = 0xFFFF;
}
  
event void Temperature.readDone(error_t result, uint16_t val) {     
  if(result == SUCCESS) {
    current_entry->temp = val; 
  }
  else current_entry->temp = 0xFFFF;
}
  
event void Photo.readDone(error_t result, uint16_t val) {
  if(result == SUCCESS) {
    current_entry->photo = val;
  }
  else current_entry->photo = 0xFFFF;
 }
  
event void Radiation.readDone(error_t result, uint16_t val) {
  if(result == SUCCESS) {
    current_entry->rad = val;
  }
  else current_entry->rad = 0xFFFF;
}

event void LogWrite.appendDone(void* buf, 
                               storage_len_t len, 
                               bool recordsLost, 
                               error_t error) {
  if (error == SUCCESS) 
    call Leds.led2Toggle();
}
</pre>
</td>
<td></td>
<td valign=top>
<pre>
event void Boot.booted() {
  call Timer.startPeriodic(SAMPLE_PERIOD);
}

event void Timer.fired() {
  call Humidity.read();
}
  
event void Humidity.readDone(error_t result, uint16_t val) {
  if(result == SUCCESS) {
    entry->rad = val;
  }
  else current_entry->rad = 0xFFFF;
  call Temperature.read();
}
  
event void Temperature.readDone(error_t result, uint16_t val) {     
  if(result == SUCCESS) {
    entry->rad = val;
  }
  else current_entry->rad = 0xFFFF;
  call Photo.read();
}
  
event void Photo.readDone(error_t result, uint16_t val) {
  if(result == SUCCESS) {
    entry->rad = val;
  }
  else current_entry->rad = 0xFFFF;
  call Radiation.read();
}
  
event void Radiation.readDone(error_t result, uint16_t val) {
  if(result == SUCCESS) {
    entry->rad = val;
  }
  else current_entry->rad = 0xFFFF;
  call LogWrite.append(entry, sizeof(log_entry_t));
}

event void LogWrite.appendDone(void* buf, 
                               storage_len_t len, 
                               bool recordsLost, 
                               error_t error) {
  if (error == SUCCESS) 
    call Leds.led2Toggle();
}





  </pre>
  </td>
  </tr>
  </table>
  <p>
  In the parallel case, logging to flash and requesting samples from each sensor is 
  all done within the body of the <code>Timer.fired()</code> event.  In the serial case, 
  a chain of events is triggered by first calling <code>Humidity.read()</code> in
  <code>Timer.fired()</code>, sampling each subsequent sensor in the body of the previous 
  <code>readDone()</code> event, and ending with all sensor readings 
  being logged to flash.
  </p>
  <p>
  By logging to flash and sampling all sensors within the body of a single event, the OS
  has the opportunity to schedule each operation as it sees fit.  Performing each operation
  after the completion of the previous one gives the OS no such opportunity.  The only 
  downside of the parallel approach is that the application must manually manage a double 
  buffer so that the values written to flash are not overwritten before they are logged. To save
  the most energy, however, the parallel version should always be used. 
  Keep in mind that in both cases, the developer must also make sure that the sampling 
  interval is longer than the time it takes to gather all sensor readings.  If it is not, 
  data corruption will inevitably occur.
  </p>
  <h1>
  Radio Power Management
  </h1>
  <p>
  By default, TinyOS provides low power radio operation through a technique known as
  <i>Low-Power Listening</i>.  In low-power listening, a node turns on
  its radio just long enough to detect a carrier on the channel. 
  If it detects a carrier, then it keeps the radio on long enough to detect a packet.  
  Because the LPL check period is much longer than a packet, a transmitter must send 
  its first packet enough times for a receiver to have  a chance to hear it. The
  transmitter stops sending once it receives a link-layer acknowledgment or a timeout 
  of twice the check period. When a node receives a packet, it stays awake long
  enough to receive a second packet. Therefore, a packet burst amortizes the wakeup 
  cost of the first packet over the follow-up packets. It is therefore more energy
  efficient to send packets in bursts when using low-power listening than sending individual 
  packets at some fixed constant rate.  Keep this in mind when developing applications
  that require low power operation.
  </p>
  <p>
  Controlling the operation of low-power listening in TinyOS is provided through the 
  use of the <code>LowPowerListening</code> interface.  Currently, this interface
  is only supported for the cc1000 and cc2420 radios.  In the future we hope to 
  support other radio platforms as well.
  </p>
  <pre>
interface LowPowerListening {
  /**
   * Set this this node's radio sleep interval, in milliseconds.
   * Once every interval, the node will sleep and perform an Rx check 
   * on the radio.  Setting the sleep interval to 0 will keep the radio
   * always on.
   *
   * This is the equivalent of setting the local duty cycle rate.
   *
   * @param sleepIntervalMs the length of this node's Rx check interval, in [ms]
   */
  command void setLocalSleepInterval(uint16_t sleepIntervalMs);
  
  /**
   * @return the local node's sleep interval, in [ms]
   */
  command uint16_t getLocalSleepInterval();
  
  /**
   * Set this node's radio duty cycle rate, in units of [percentage*100].
   * For example, to get a 0.05% duty cycle,
   *   call LowPowerListening.setDutyCycle(5);
   *
   * For a 100% duty cycle (always on),
   *   call LowPowerListening.setDutyCycle(10000);
   *
   * This is the equivalent of setting the local sleep interval explicitly.
   * 
   * @param dutyCycle The duty cycle percentage, in units of [percentage*100]
   */
  command void setLocalDutyCycle(uint16_t dutyCycle);
  
  /**
   * @return this node's radio duty cycle rate, in units of [percentage*100]
   */
  command uint16_t getLocalDutyCycle();
  
  /**
   * Configure this outgoing message so it can be transmitted to a neighbor mote
   * with the specified Rx sleep interval.
   * @param msg Pointer to the message that will be sent
   * @param sleepInterval The receiving node's sleep interval, in [ms]
   */
  command void setRxSleepInterval(message_t *msg, uint16_t sleepIntervalMs);
  
  /**
   * @return the destination node's sleep interval configured in this message
   */
  command uint16_t getRxSleepInterval(message_t *msg);
  
  /**
   * Configure this outgoing message so it can be transmitted to a neighbor mote
   * with the specified Rx duty cycle rate.
   * Duty cycle is in units of [percentage*100], i.e. 0.25% duty cycle = 25.
   * 
   * @param msg Pointer to the message that will be sent
   * @param dutyCycle The duty cycle of the receiving mote, in units of 
   *     [percentage*100]
   */
  command void setRxDutyCycle(message_t *msg, uint16_t dutyCycle);
  
  /**
   * @return the destination node's duty cycle configured in this message
   *     in units of [percentage*100]
   */
  command uint16_t getRxDutyCycle(message_t *msg);
  
  /**
   * Convert a duty cycle, in units of [percentage*100], to
   * the sleep interval of the mote in milliseconds
   * @param dutyCycle The duty cycle in units of [percentage*100]
   * @return The equivalent sleep interval, in units of [ms]
   */
  command uint16_t dutyCycleToSleepInterval(uint16_t dutyCycle);
  
  /**
   * Convert a sleep interval, in units of [ms], to a duty cycle
   * in units of [percentage*100]
   * @param sleepInterval The sleep interval in units of [ms]
   * @return The duty cycle in units of [percentage*100]
   */
  command uint16_t sleepIntervalToDutyCycle(uint16_t sleepInterval);
  
}</pre>
<p>
This interface is located in <code>tos/interfaces</code> in the standard TinyOS tree.  Take a
look at the comments for each command to familiarize yourself with how this interface can be used.
</p>
<p>
Using this interface typically involves first setting a nodes local duty cycle within the 
<code>Boot.booted()</code> event of the top level application.  For each packet the application 
wishes to send, the duty cycle of its destination is then specified as metadata so that the 
correct number of preambles can be prepended to it.  The code snippet found below demonstrates 
this usage pattern:
</p>
<pre>
event void Boot.booted() {
  call LPL.setLocalSleepInterval(LPL_INTERVAL);
  call AMControl.start();
}

event void AMControl.startDone(error_t e) {
  if(e != SUCCESS)
    call AMControl.start();
}
  
...

void sendMsg() {
  call LPL.setRxSleepInterval(&msg, LPL_INTERVAL);
  if(call Send.send(dest_addr, &msg, sizeof(my_msg_t)) != SUCCESS)
    post retrySendTask();
}</pre>

The <code>AMControl</code> interface is provided by <code>ActiveMessageC</code>, and is 
used, among other things, to enable the operation of low-power listening for the radio.  
Once <code>AMControl.start()</code> has completed successfully, the radio begins to duty cycle
itself as specified by the parameter to the <code>setLocalSleepInterval()</code> command.  Calling 
<code>setRxSleepInterval()</code> with a specific sleep interval then allows the correct number of preambles to be sent
for the message specified in its parameter list.

<h1>
Microcontroller Power Management
</h1>
<p>
Microcontrollers often have several power states, with varying power draws, 
wakeup latencies, and peripheral support. The microcontroller should always be 
in the lowest possible power state that can satisfy application requirements. 
Determining this state accurately requires knowing a great deal about the power 
state of many subsystems and their peripherals. Additionally, state transitions 
are common. Every time a microcontroller handles an interrupt, it moves from a low 
power state to an active state, and whenever the TinyOS scheduler finds the task 
queue empty it returns the microcontroller to a low power state. TinyOS uses 
three mechanisms to decide what low power state it puts a microcontroller into: 
status and control registers, a dirty bit, and a power state override.  
Please refer to <a href=../tep112.html>TEP 112</a> for more information.
</p>
</p>
As a developer, you will not have to worry about MCU power managment at all in 
most situations.  TinyOS handles everything for you automatically.  At times,
however, you may want to use the provided power state override functionality.
Take a look at <code>tos/chips/atm128/timer/HplAtm128Timer0AsyncP.nc</code> if
you are interested in seeing an example of where this override functionality is used.  
</p>

<h1>
Low Power Sensing Application
</h1>
A fully functional low-power sensing application that combines each of the techniques 
found in this tutorial can be found in <code>apps/tutorials/LowPowerSensing</code>.  This
application has been tested on telosb and mica2 platforms, but should be usable
on others without modification.  Take a look at the README file found in the top level directory
for more information.

<a name=#related_docs>
<h1>Related Documentation</h1>
</a>
<ul>
<li> <a href="../tep103.html">TEP 103: Permanent Data Storage (Flash)</a>
<li> <a href="../tep105.html">TEP 105: Low Power Listening</a>
<li> <a href="../tep108.html">TEP 108: Resource Arbitration</a>
<li> <a href="../tep109.html">TEP 109: Sensors and Sensor Boards</a>
<li> <a href="../tep112.html">TEP 112: Microcontroller Power Management</a>
<li> <a href="../tep114.html">TEP 114: SIDs: Source and Sink Independent Drivers</a>
<li> <a href="../tep115.html">TEP 115: Power Management of Non-Virtualised Devices</a>
<li> <a href="http://sing.stanford.edu/klueska/Black_Site/Publications_files/klues07icem.pdf">
Integrating Concurrency Control and Energy Management in Device Drivers</a>
</ul>

<!-- Begin footer -->
<br>
<hr>
<center>
<p>&lt;&nbsp;<b><a href="lesson15.html">Previous Lesson</a></b> |&nbsp; <b><a
 href="index.html">Top</a></b> &nbsp;|&nbsp;
</center>

</body>
</html>

Index: index.html
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/doc/html/tutorial/index.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** index.html	20 Aug 2007 06:15:14 -0000	1.6
--- index.html	3 Sep 2007 22:38:41 -0000	1.7
***************
*** 9,15 ****
  
        <div class="title">TinyOS 2.0 Tutorials </div>
!       <div class="subtitle">Last updated 30 Oct 2006</div>
! 
  
        These brief tutorials are intended to get you started with TinyOS. They show
        you the basics of writing, compiling, and installing TinyOS applications.
--- 9,15 ----
  
        <div class="title">TinyOS 2.0 Tutorials </div>
!       <div class="subtitle">Last updated 30 Aug 2007</div>
  
+ 	  <p>
        These brief tutorials are intended to get you started with TinyOS. They show
        you the basics of writing, compiling, and installing TinyOS applications.
***************
*** 17,22 ****
        sensing, and storage. The later tutorials go a little deeper into some of
        the more advanced areas of TinyOS, such as handling interrupts,
!       power management, and how platforms are organized. For the beta2 release,
!       only tutorials 1-5 are ready.
        
        <h1><a href="lesson1.html">Lesson 1: TinyOS</a></h1>
--- 17,22 ----
        sensing, and storage. The later tutorials go a little deeper into some of
        the more advanced areas of TinyOS, such as handling interrupts,
!       power management, and how platforms are organized.
!       </p>
        
        <h1><a href="lesson1.html">Lesson 1: TinyOS</a></h1>
***************
*** 136,139 ****
--- 136,148 ----
  </dd>
  
+ <h1><a href="lesson16.html">Lesson 16: Writing Low Power Sensing Applications</a></h1>
+ <dd>
+     This lesson demonstrates how to write low power sensing applications in TinyOS.  At 
+     	any given moment, the power consumption of a wireless sensor node is a function of its
+     	microcontroller power state, whether the radio, flash, and sensor peripherals are on, 
+     	and what operations active peripherals are performing.  This tutorial shows you 
+     	how to best utilize the features provided by TinyOS to keep the power consumption 
+     	of applications that use these devices to a minumum.
+ </dd>
  </body>
  </html>

Index: lesson15.html
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/doc/html/tutorial/lesson15.html,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** lesson15.html	20 Aug 2007 17:40:30 -0000	1.7
--- lesson15.html	3 Sep 2007 22:38:41 -0000	1.8
***************
*** 95,99 ****
      calls to <code>printf</code> before flushing them.  This means that while
      the buffer is being flushed, any calls to <code>printf</code> will fail.
!     In the future, we plan to implement a doubled buffer approach so that
      strings can continue to be buffered at the same time they are being printed.
      </p>
--- 95,99 ----
      calls to <code>printf</code> before flushing them.  This means that while
      the buffer is being flushed, any calls to <code>printf</code> will fail.
!     In the future, we plan to implement a double buffered approach so that
      strings can continue to be buffered at the same time they are being printed.
      </p>
***************
*** 134,138 ****
      <p>
      If you are not using cvs, you will also have to apply the patch
!     found <a href=http://www.stanford.edu/~klueska/tinyos-2.0-printf.patch>here</a>
      in order to allow the <code>printf</code> library to compile correctly for
      atmega128x based platforms (i.e. mica2, micaz):
--- 134,138 ----
      <p>
      If you are not using cvs, you will also have to apply the patch
!     found <a href=http://sing.stanford.edu/klueska/tinyos-2.0-printf.patch>here</a>
      in order to allow the <code>printf</code> library to compile correctly for
      atmega128x based platforms (i.e. mica2, micaz):
***************
*** 301,310 ****
      If you actually read the line printed above it you can see why.  The buffer
      used to store TinyOS <code>printf</code> messages before they are flushed
!     is limited to a total of 250 bytes.  If you try and print more characters than
      this before flushing, then only the first 250 characters will actually be printed.
!     As of now, this buffer size is fixed and can't be changed.  In the future we
!     hope to allow developers to specify custom buffer sizes at the time that
!     they include the PrintfC component in their configuration file.
      </p>
      <p>
      Once the the <code>Printf</code> service has been stopped, the
--- 301,311 ----
      If you actually read the line printed above it you can see why.  The buffer
      used to store TinyOS <code>printf</code> messages before they are flushed
!     is by default limited to 250 bytes.  If you try and print more characters than
      this before flushing, then only the first 250 characters will actually be printed.
!     This buffer size is configurable, however, by specifying the proper CFLAGS option
!     in your Makefile.
      </p>
+     <pre>
+ CFLAGS += -DPRINTF_BUFFER_SIZE=XXX</pre>
      <p>
      Once the the <code>Printf</code> service has been stopped, the
***************
*** 332,340 ****
      </p>
      <ol>
-       <li>The buffer used by the <code>printf</code> library is limited to 250 bytes.
-           Do NOT try and increase this value.  It is unclear why, but at present,
-           larger buffer sizes result in messages being cut short when printed over the
-           serial line.  Tracking down
-           the source of this problem is on our list of things to do.</li>
        <li>In order to use the <code>printf</code> library, the <code>tos/lib/printf</code>
            directory must be in your include path.  The easiest way to include it is
--- 333,336 ----
***************
*** 342,346 ****
            level application:
            <pre>
! CFLAGS += -I$(TOSDIR)/lib/printf</pre></li>
        <li>You MUST be sure to #include <code>"printf.h"</code> header file in
            every component in which you would like to call the <code>printf()</code>
--- 338,346 ----
            level application:
            <pre>
! CFLAGS += -I$(TOSDIR)/lib/printf</pre>
!           Remember that changing the <code>printf</code> buffer size is done similarly:
!           <pre>
! CFLAGS += -DPRINTF_BUFFER_SIZE=XXX</pre>
!       </li>
        <li>You MUST be sure to #include <code>"printf.h"</code> header file in
            every component in which you would like to call the <code>printf()</code>

Index: lesson8.html
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/doc/html/tutorial/lesson8.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** lesson8.html	13 Jul 2007 23:43:17 -0000	1.6
--- lesson8.html	3 Sep 2007 22:38:41 -0000	1.7
***************
*** 346,350 ****
  
  <p>
! While the power managers presented in this tutorial are powerful components for providing power management of shared resources, they are not the only power management mechanisms provided by TinyOS.  Microcontroller power management is also preformed as outlined in TEP115.  Whenever the task queue empties, the lowest power state that the microcontroller is capapble of dropping to is automatically calculated and then switched to.  In this way, the user is not burdened with explicity controlling these power states.  The cc1000 and cc2420 radio implementations also provide "Low Power Listening" (LPL) interfaces for controlling their duty cycles.  Although the LPL interface used by each radio stack differs somewhat, they are both able to provide energy savings not achieveable through other means.  The LPL implementation for the cc2420 can be found under <tt>tinyos-2.x/tos/chips/cc2420</tt> and the LPL implementation for the cc1000 can be found under <tt>tinyos-2.x/tos/chips/cc1000</tt>.  As these interfaces begin to mature and merge into one, this tutorial will be updated appropriately to accomodate the change.
  </p>
  
--- 346,351 ----
  
  <p>
! While the power managers presented in this tutorial are powerful components for providing power management of shared resources, they are not the only power management mechanisms provided by TinyOS.  Microcontroller power management is also preformed as outlined in TEP115.  Whenever the task queue empties, the lowest power state that the microcontroller is capable of dropping to is automatically calculated and then switched to.  In this way, the user is not burdened with explicity controlling these power states.  The cc1000 and cc2420 radio implementations also provide "Low Power Listening" (LPL) interfaces for controlling their duty cycles.  The LPL implementation for the cc2420 can be found under <tt>tinyos-2.x/tos/chips/cc2420</tt> and the LPL implementation for the cc1000 can be found under <tt>tinyos-2.x/tos/chips/cc1000</tt>.  Take a look 
! at <a href=lesson16.html>lesson 16</a> to see how this interface is used.
  </p>
  



More information about the Tinyos-2-commits mailing list