]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - doc/html/tep109.html
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / doc / html / tep109.html
index dad85f80919885ffe913a1c68f4ae742b08371c9..56b758c178bcb27b6bde2b724929fac11e1419ef 100644 (file)
@@ -4,8 +4,8 @@
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
-<title>Sensor Boards</title>
-<meta name="author" content="David Gay, Phil Levis, Wei Hong, and Joe Polastre" />
+<title>Sensors and Sensor Boards</title>
+<meta name="author" content="David Gay, Philip Levis, Wei Hong, Joe Polastre, and Gilman Tolle" />
 <style type="text/css">
 
 /*
@@ -41,11 +41,6 @@ blockquote.epigraph {
 dd {
   margin-bottom: 0.5em }
 
-/* Uncomment (& remove this text!) to get bold-faced definition list terms
-dt {
-  font-weight: bold }
-*/
-
 div.abstract {
   margin: 2em 5em }
 
@@ -283,8 +278,8 @@ ul.auto-toc {
 </style>
 </head>
 <body>
-<div class="document" id="sensor-boards">
-<h1 class="title">Sensor Boards</h1>
+<div class="document" id="sensors-and-sensor-boards">
+<h1 class="title">Sensors and Sensor Boards</h1>
 <table class="docinfo" frame="void" rules="none">
 <col class="docinfo-name" />
 <col class="docinfo-content" />
@@ -296,19 +291,11 @@ ul.auto-toc {
 <tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
 </tr>
 <tr><th class="docinfo-name">Status:</th>
-<td>Draft</td></tr>
+<td>Final</td></tr>
 <tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
 </tr>
 <tr><th class="docinfo-name">Author:</th>
-<td>David Gay, Phil Levis, Wei Hong, and Joe Polastre</td></tr>
-<tr class="field"><th class="docinfo-name">Draft-Created:</th><td class="field-body">19-Apr-2005</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Version:</th><td class="field-body">1.1.2.1</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Modified:</th><td class="field-body">2005-10-31</td>
-</tr>
-<tr class="field"><th class="docinfo-name">Draft-Discuss:</th><td class="field-body">TinyOS Developer List &lt;tinyos-devel at mail.millennium.berkeley.edu&gt;</td>
-</tr>
+<td>David Gay, Philip Levis, Wei Hong, Joe Polastre, and Gilman Tolle</td></tr>
 </tbody>
 </table>
 <div class="note">
@@ -320,262 +307,309 @@ TEP 1.</p>
 </div>
 <div class="section">
 <h1><a id="abstract" name="abstract">Abstract</a></h1>
-<p>This memo documents how sensor boards are organized in TinyOS, and the
-general principles followed by the components that provide access to
-its sensors.</p>
-</div>
-<div class="section">
-<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
-<p>This document defines the default organization of a sensor board in
-TinyOS. There likely will be sensor boards that cannot conform
-to this specification, but following as closely to its spirit as possible
-will simplify generic applications that use a range of sensor boards.</p>
-<p>This document assumes that sensors return uninterpreted 16-bit values, and,
-optionally uninterpreted, arbitrary-size calibration data. Conversion of
-sensor values to something with actual physical meaning is beyond the
-scope of this document.</p>
+<p>This memo documents how sensor drivers are organized in TinyOS and how
+sets of sensor drivers are combined into sensor boards and sensor
+platforms, along with general principles followed by the components
+that provide access to sensors.</p>
 </div>
 <div class="section">
-<h1><a id="directory-organization" name="directory-organization">2. Directory Organization</a></h1>
+<h1><a id="principles" name="principles">1. Principles</a></h1>
+<p>This section describes the basic organization principles for sensor
+drivers in TinyOS.</p>
+<p>For background, a sensor can be attached to the microcontroller on a
+TinyOS platform through a few different types of connections:</p>
+<blockquote>
 <ul class="simple">
-<li>A sensor board MUST have a unique name, composed of letters, numbers
-and underscores. Case is significant, but two sensor boards MUST
-differ in more than case. This is necessary to support platforms where
-filename case differences are not significant. We will use SBOARD to
-denote the sensor board name in the rest of this document.</li>
-<li>Each sensor board MUST have its own directory named SBOARD; default TinyOS
-sensor boards are placed in tinyos-2.x/tos/sensorboards, but
-sensor board directories can be placed anywhere as long as the nesC compiler
-receives a <cite>-I</cite> directive pointing to the sensor board's directory.</li>
-<li>Each sensor board directory MUST contain a <cite>.sensor</cite> file. This file
-is a perl script which contains any additional compiler settings needed for
-this sensor board (this file will be empty in many cases).</li>
-<li>If the sensor board wishes to define any C types or constants, it SHOULD
-place these in a file named SBOARD.h in the sensor board's directory.</li>
-<li>The sensor board directory SHOULD contain sensor board components
-for accessing each sensor on the sensor board. The conventions for these
-components are detailed in Section 3.</li>
-<li>A sensor board MAY include additional components providing alternative or
-higher-level interfaces to the sensors (e.g., for TinyDB). These components
-are beyond the scope of this document.</li>
-<li>Finally, the sensor board MAY contain any number of components,
-interfaces, C files, etc for internal use. To avoid name collisions, all
-externally visible names (interface types, components, C constants and
-types) used for internal purposes SHOULD be prefixed with SBOARD. All such
-components should end in P.</li>
+<li>Included within the microcontroller itself</li>
+<li>Connected to general-purpose IO pins for level/edge detection</li>
+<li>Connected to an ADC in the microcontroller for voltage sampling</li>
+<li>Connected to general-purpose IO pins for digital communication</li>
+<li>Connected through a standard digital bus protocol (1-Wire, I2C, SPI)</li>
 </ul>
-<p>A simple example: the basic sensor board is named <cite>basicsb</cite>, it's directory
-is <cite>tinyos-2.x/tos/sensorboards/basicsb</cite>. It has no <cite>basicsb.h</cite> file and
-its <cite>.sensor</cite> file is empty. It has two components, <cite>PhotoC</cite> and <cite>TempC</cite>
-representing its light and temperature sensors.</p>
+</blockquote>
+<p>Physically, these connections can also be decoupled by attaching the
+sensors to a <cite>sensor board</cite>, which can be removed from the TinyOS
+platform, and could attach to multiple different TinyOS platforms.</p>
+<p>The capabilities of a physical sensor are made available to a TinyOS
+application through a <cite>sensor driver</cite>.</p>
+<p>According to the HAA <a class="citation-reference" href="#tep2" id="id1" name="id1">[TEP2]</a>, TinyOS devices SHOULD provide both
+simple hardware-independent interfaces for common-case use (HIL) and
+rich hardware-dependent interfaces for special-case use (HAL). Sensor
+drivers SHOULD follow this spirit as well.</p>
+<p>TinyOS 2.x represents each sensor as an individual component. This
+allows the compilation process to minimize the amount of code
+included. A sensor board containing multiple sensors SHOULD be
+represented as a collection of components, one for each sensor,
+contained within a sensor board directory.</p>
+<p>Sensors, being physical devices that can be shared, can benefit from
+virtualization and arbitration. This document describes a design
+pattern for sensor virtualization that SHOULD be followed by sensor
+drivers.</p>
+<p>The same physical sensor can be attached to multiple different TinyOS
+platforms, through platform-dependent interconnections. The common
+logic of sensor driver SHOULD be factored into chip-dependent,
+platform-independent components, and those components SHOULD be bound
+to the hardware resources on a platform by platform-dependent
+components, and to the hardware resources on a sensor board by
+sensorboard-dependent components.</p>
+<p>A physical sensor has a general class and a specific set of
+performance characteristics, captured by the make and model of the
+sensor itself. The naming of the sensor driver components SHOULD
+reflect the specifc name of the sensor, and MAY provide a component
+with a generic name for application authors who only care about the
+general class of the sensor.</p>
+<p>This document requires that sensor components specify the range (in
+bits) of values returned by sensor drivers, but takes no position on
+the meaning of these values. They MAY be raw uninterpreted values or
+they MAY have some physical meaning. If a driver returns uninterpreted
+values, the driver MAY provide additional interfaces that would allow
+higher-level clients to obtain information (e.g. calibration
+coefficients) needed to properly interpret the value.</p>
 </div>
 <div class="section">
-<h1><a id="sensor-board-components" name="sensor-board-components">3. Sensor Board Components</a></h1>
-<p>We have not yet selected any naming conventions for sensor board
-components. Please select reasonable namesldots</p>
-<p>A sensor board component MUST provide:</p>
+<h1><a id="sensor-hil-components" name="sensor-hil-components">2. Sensor HIL Components</a></h1>
+<p>A sensor HIL component MUST provide:</p>
 <ul class="simple">
-<li>An <cite>Init</cite> interface.</li>
-<li>A <cite>StdControl</cite> or <cite>SplitControl</cite> interface for power management.</li>
-<li>A non-empty set of <cite>AcquireData</cite> interfaces for sampling.</li>
+<li>One or more SID interfaces <a class="citation-reference" href="#tep114" id="id2" name="id2">[TEP114]</a>, for reading data.</li>
 </ul>
-<p>A sensor board component MAY provide:</p>
+<p>A sensor HIL component MAY provide:</p>
 <ul class="simple">
-<li>Some <cite>CalibrationData</cite> interfaces for obtaining calibration data.
-A calibration interface for a sensor accessed via interface X should
-be called XCalibration.</li>
-<li>Some <cite>AcquireDataNow</cite> and <cite>AcquireDataBuffered</cite> interfaces, for high-speed
-or low-latency data acquisition.</li>
-<li>Any other appropriate interface.</li>
+<li>One or more SID interfaces <a class="citation-reference" href="#tep114" id="id3" name="id3">[TEP114]</a>, for reading or
+writing calibration coefficients or control registers.</li>
 </ul>
-<p>The <cite>CalibrationData</cite> interface is shown below, while <cite>AcquireData</cite>,
-<cite>AcquireDataNow</cite> and <cite>AcquireDataBuffered</cite> are in TEP 101. The
-<cite>AcquireData</cite> interface returns uinterpreted 16-bit data. This might
-represent an A/D conversion result, a counter, etc. The optional
-calibration interface returns uninterpreted, arbitrary-size data.</p>
-<p>A sensor board component SHOULD be as lightweight as possible - it should
-just provide basic access to the physical sensors and SHOULD NOT attempt to do
-calibration, signal processing, etc. If such functionality is desired, it
-SHOULD be provided in separate components.</p>
-<div class="line-block">
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">CalibrationData</span> <span class="pre">{</span></tt></div>
-<div class="line-block">
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">/*</span> <span class="pre">Collect</span> <span class="pre">uninterpreted</span> <span class="pre">calibration</span> <span class="pre">data</span> <span class="pre">from</span> <span class="pre">a</span> <span class="pre">sensor</span> <span class="pre">*/</span></tt></div>
-<div class="line"><br /></div>
-<div class="line"><tt class="docutils literal"><span class="pre">/**</span> <span class="pre">Request</span> <span class="pre">calibration</span> <span class="pre">data</span></tt></div>
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">*</span>&nbsp; <span class="pre">&#64;return</span> <span class="pre">SUCCESS</span> <span class="pre">if</span> <span class="pre">request</span> <span class="pre">accepted,</span> <span class="pre">FAIL</span> <span class="pre">if</span> <span class="pre">it</span> <span class="pre">is</span> <span class="pre">refused</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">*</span>&nbsp;&nbsp;&nbsp; <span class="pre">data</span> <span class="pre">error</span> <span class="pre">will</span> <span class="pre">be</span> <span class="pre">signaled</span> <span class="pre">if</span> <span class="pre">SUCCESS</span> <span class="pre">is</span> <span class="pre">returned</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">*/</span></tt></div>
-</div>
-<div class="line"><tt class="docutils literal"><span class="pre">command</span> <span class="pre">result_t</span> <span class="pre">get();</span></tt></div>
-<div class="line"><br /></div>
-</div>
-<div class="line"><tt class="docutils literal"><span class="pre">/**</span> <span class="pre">Returns</span> <span class="pre">calibration</span> <span class="pre">data</span></tt></div>
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">*</span> <span class="pre">&#64;param</span> <span class="pre">x</span> <span class="pre">Pointer</span> <span class="pre">to</span> <span class="pre">(uinterpreted)</span> <span class="pre">calibration</span> <span class="pre">data.</span> <span class="pre">This</span> <span class="pre">data</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">*</span>&nbsp;&nbsp; <span class="pre">must</span> <span class="pre">not</span> <span class="pre">be</span> <span class="pre">modified.</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">*</span> <span class="pre">&#64;param</span> <span class="pre">len</span> <span class="pre">Length</span> <span class="pre">of</span> <span class="pre">calibration</span> <span class="pre">data</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">*</span> <span class="pre">&#64;return</span> <span class="pre">Ignored.</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">*/</span></tt></div>
-</div>
-<div class="line"><tt class="docutils literal"><span class="pre">event</span> <span class="pre">result_t</span> <span class="pre">data(const</span> <span class="pre">void</span> <span class="pre">*x,</span> <span class="pre">uint8_t</span> <span class="pre">len);</span></tt></div>
-</div>
-</div>
-<div class="line"><tt class="docutils literal"><span class="pre">}</span></tt></div>
+<p>A sensor device driver SHOULD be a generic component that virtualizes
+access to the sensor. A sensor device driver can provide such
+virtualization for itself by defining a nesC generic client
+component. When a client component is being used, a call to a
+top-level SID interface SHOULD be delayed when the device is busy,
+rather than failing. Using one of the system arbiters can make the
+implementation of this requirement easier to accomplish.</p>
+<p>For example:</p>
+<pre class="literal-block">
+generic configuration SensirionSht11C() {
+  provides interface Read&lt;uint16_t&gt; as Temperature;
+  provides interface ReadStream&lt;uint16_t&gt; as TemperatureStream;
+  provides interface DeviceMetadata as TemperatureDeviceMetadata;
+
+  provides interface Read&lt;uint16_t&gt; as Humidity;
+  provides interface ReadStream&lt;uint16_t&gt; as HumidityStream;
+  provides interface DeviceMetadata as HumidityDeviceMetadata;
+}
+implementation {
+  // connect to the ADC HIL, GPIO HAL, or sensor's HAL
+}
+</pre>
+<p>When a HIL component is being used, the sensor MUST initialize itself,
+either by including the <cite>MainC</cite> component and wiring to the
+<cite>SoftwareInit</cite> interface, or by allowing a lower-level component (like
+an ADC) to initialize itself.</p>
+<p>In addition, the HIL sensor driver MUST start the physical sensor
+automatically. For sensors without a constant power draw, the sensor
+MAY be started once at boot time by wiring to the <cite>MainC.Boot</cite>
+interface. Sensors that draw appreciable power MUST be started in
+response to a call to one of the top-level SID interfaces, and stopped
+some time after that call completes. Using one of the power-management
+components described in <a class="citation-reference" href="#tep115" id="id4" name="id4">[TEP115]</a> can make this implementation easier.</p>
+<p>Generally, simple types are made up of octets. However, sensor values
+often have levels of precision besides a multiple of 8. To account for
+such cases, each device MUST specify the precision of each one of its
+interfaces by providing the DeviceMetadata interface:</p>
+<pre class="literal-block">
+interface DeviceMetadata {
+  command uint8_t getSignificantBits();
+}
+</pre>
+<p>The name of the instance of DeviceMetadata MUST clearly indicate which
+interface it corresponds to.</p>
+<p>The getSignificantBits() call MUST return the number of significant
+bits in the reading. For example, a sensor reading taken from a 12-bit
+ADC would typically return the value 12 (it might return less if, e.g.,
+physical constraints limit the maximum A/D result to 10-bits).</p>
+<p>Sensor driver components SHOULD be named according to the make and
+model of the sensing device being presented. Using specific names
+gives the developer the option to bind to a particular sensor, which
+provides compile-time detection of missing sensors. However, wrapper
+components using &quot;common&quot; names MAY also be provided by the driver
+author, to support application developers who are only concerned with
+the particular type of the sensor and not its make, model, or detailed
+performance characteristics.</p>
+<p>A &quot;common&quot; naming layer atop a HIL might look like this:</p>
+<pre class="literal-block">
+generic configuration TemperatureC() {
+  provides interface Read&lt;uint16_t&gt;;
+  provides interface ReadStream&lt;uint16_t&gt;;
+  provides interface DeviceMetadata;
+}
+implementation {
+  components new SensirionSht11C();
+  Read = SensirionSht11C.Temperature;
+  ReadStream = SensirionSht11C.TemperatureStream;
+  DeviceMetadata = SensirionSht11C.TemperatureDeviceMetadata;
+}
+
+generic configuration HumidityC() {
+  provides interface Read&lt;uint16_t&gt;;
+  provides interface ReadStream&lt;uint16_t&gt;;
+  provides interface DeviceMetadata;
+}
+implementation {
+  components new SensirionSht11C();
+  Read = SensirionSht11C.Humidity;
+  ReadStream = SensirionSht11C.HumidityStream;
+  DeviceMetadata = SensirionSht11C.HumidityDeviceMetadata;
+}
+</pre>
 </div>
-<p>Some common setups for sensor board components are:</p>
+<div class="section">
+<h1><a id="sensor-hal-components" name="sensor-hal-components">3. Sensor HAL Components</a></h1>
+<p>Sensors with a richer interface than would be supported by the SID
+interfaces MAY provide a HAL component in addition to a HIL
+component.</p>
+<p>A sensor HAL component MUST provide:</p>
 <ul class="simple">
-<li>A single <cite>AcquireData</cite> interface. This is probably the most common case,
-where a single component corresponds to a single physical sensor, e.g., for
-light, temperature, pressure and there is no expectation of high sample
-rates.</li>
-<li>Multiple <cite>AcquireData</cite> interfaces. Some sensors might be strongly
-related, e.g., the axes of an accelerometer.  A single component could then
-provide a sensor interface for each axis. For instance, a 2-axis
-accelerometer which can be sampled at high speed, and which has some
-calibration data might be declared with:</li>
+<li>A SID-based interface or a specific hardware-dependent interface
+with commands for sampling and controlling the sensor device.</li>
 </ul>
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">configuration</span> <span class="pre">Accelerometer2D</span> <span class="pre">{</span></tt></div>
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">provides</span> <span class="pre">{</span></tt></div>
-<div class="line-block">
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">StdControl</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">AcquireData</span> <span class="pre">as</span> <span class="pre">AccelX;</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">AcquireDataNow</span> <span class="pre">as</span> <span class="pre">AccelXSingle;</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">AcquireDataBuffered</span> <span class="pre">as</span> <span class="pre">AccelXMultiple;</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">CalibrationData</span> <span class="pre">as</span> <span class="pre">AccelXCalibration;</span></tt></div>
-<div class="line"><br /></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">AcquireData</span> <span class="pre">as</span> <span class="pre">AccelY;</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">AcquireDataNow</span> <span class="pre">as</span> <span class="pre">AccelYSingle;</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">AcquireDataBuffered</span> <span class="pre">as</span> <span class="pre">AccelYMultiple;</span></tt></div>
-<div class="line"><tt class="docutils literal"><span class="pre">interface</span> <span class="pre">CalibrationData</span> <span class="pre">as</span> <span class="pre">AccelYCalibration;</span></tt></div>
-</div>
-<div class="line"><tt class="docutils literal"><span class="pre">}</span></tt></div>
-</div>
-<div class="line"><tt class="docutils literal"><span class="pre">}</span></tt></div>
-</div>
+<p>A sensor HAL component MAY need to provide:</p>
 <ul class="simple">
-<li>A parameterised <cite>AcquireData</cite> interface. If a sensor board has multiple
-similar sensors, it may make sense to provide a single component to access
-all of these, using a parameterised <cite>AcquireData</cite> interface. For instance,
-a general purpose sensor board with multiple A/D channels might provide an
-<cite>AcquireData</cite> interface parameterised by the A/D channel id.</li>
-<li>In all of these examples, if high-speed sampling makes sensor for the
-sensor (e.g., a microphone), and the sensor is connected in a way that
-supports high-frequency and/or low-latency access (e.g., via an
-on-microcontroller A/D converter), the component should offer
-<cite>AcquireDataNow</cite> and <cite>AcquireDataBuffered</cite> interfaces.</li>
+<li>A <cite>StdControl</cite> or <cite>SplitControl</cite> interface for manual power
+management by the user, following the conventions described in
+<a class="citation-reference" href="#tep115" id="id5" name="id5">[TEP115]</a>.</li>
+<li>A <cite>Resource</cite> interface for requesting access to the device and
+possibly performing automated power management, following
+the conventions described in <a class="citation-reference" href="#tep108" id="id6" name="id6">[TEP108]</a> and <a class="citation-reference" href="#tep115" id="id7" name="id7">[TEP115]</a>.</li>
+<li>Any other interfaces needed to control the device, e.g., to
+read or write calibration coefficients.</li>
 </ul>
-<p>Sensor board components MUST respect the following conventions
-on the use of the <cite>Init</cite>, <cite>StdControl</cite>,  and <cite>SplitControl</cite>
-interfaces.  These are given assuming <cite>StdControl</cite> is used, but the
-behaviour with <cite>SplitControl</cite> is identical except that <cite>start</cite> and <cite>stop</cite>
-are not considered complete until the <cite>startDone</cite> and <cite>stopDone</cite> events are
-signaled. The conventions are:</p>
-<ol class="arabic">
-<li><p class="first"><cite>Init.init</cite>: must be called at mote boot time.</p>
+<p>For example:</p>
+<pre class="literal-block">
+configuration SensirionSht11DeviceC {
+  provides interface Resource[ uint8_t client ];
+  provides interface SensirionSht11[ uint8_t client ];
+}
+implementation {
+  // connect to the sensor's platform-dependent HPL here
+}
+</pre>
+</div>
+<div class="section">
+<h1><a id="sensor-component-organization-and-compiler-interaction-guidelines" name="sensor-component-organization-and-compiler-interaction-guidelines">4. Sensor Component Organization and Compiler Interaction Guidelines</a></h1>
+<p>Sensors are associated either with a particular sensor board or with a
+particular platform. Both sensors and sensor boards MUST have unique
+names. Case is significant, but two sensor (or sensor board) names
+MUST differ in more than case. This is necessary to support platforms
+where filename case differences are not significant.</p>
+<p>Each sensor board MUST have its own directory whose name is the sensor
+board's unique name (referred to as &lt;sensorboard&gt; in the rest of this
+section). Default TinyOS 2.x sensor boards are placed in
+<tt class="docutils literal"><span class="pre">tos/sensorboards/&lt;sensorboard&gt;</span></tt>, but sensor board directories can be
+placed anywhere as long as the nesC compiler receives a <tt class="docutils literal"><span class="pre">-I</span></tt> directive
+pointing to the sensor board's directory. Each sensor board directory
+MUST contain a <tt class="docutils literal"><span class="pre">.sensor</span></tt> file (described below). If the
+sensor board wishes to define any C types or constants, it SHOULD
+place these in a file named <tt class="docutils literal"><span class="pre">&lt;sensorboard&gt;.h</span></tt> in the sensor board's
+directory.</p>
+<p>A sensor board MAY contain components that override the default TinyOS
+<em>demo sensors</em>. This allows the sensor board to easily be used with
+TinyOS sample applications that use the demo sensors. If a sensor
+board wishes to override the default demo sensor:</p>
+<ul>
+<li><p class="first">It MUST provide a generic component named <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt> with the
+following signature:</p>
+<pre class="literal-block">
+provides interface Read&lt;uint16_t&gt;;
+provides interface DeviceMetadata;
+</pre>
 </li>
-<li><dl class="first docutils">
-<dt><cite>StdControl.start</cite>: ensure the sensor corresponding to this component is</dt>
-<dd><p class="first">ready for use. For instance, this should power-up the sensor if
-necessary. The application can call <cite>getData</cite> once <cite>StdControl.start</cite>
-completes.</p>
-<p class="last">If a sensor takes a while to power-up, the sensor board implementer can
-either use a <cite>SplitControl</cite> interface and signal <cite>startDone</cite>
-when the sensor is ready for use, or delay <cite>dataReady</cite> events
-until the sensor is ready. The former choice is preferable.</p>
-</dd>
-</dl>
+<li><p class="first">It MAY provide a generic component named <tt class="docutils literal"><span class="pre">DemoSensorNowC</span></tt> with the
+following signature:</p>
+<pre class="literal-block">
+provides interface ReadNow&lt;uint16_t&gt;;
+provides interface DeviceMetadata;
+</pre>
+<p>This component SHOULD sample the same sensor as <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt>.</p>
 </li>
-<li><p class="first"><cite>StdControl.stop</cite>: put the sensor in a low-power mode.
-<cite>StdControl.start</cite> must be called before any further readings
-are taken. The behaviour of calls to <cite>StdControl.stop</cite> during
-sampling (i.e., when an <cite>dataReady</cite> event is going to be
-signaled) is undefined.</p>
+<li><p class="first">It MAY provide a generic component named <tt class="docutils literal"><span class="pre">DemoSensorStreamC</span></tt> with the
+following signature:</p>
+<pre class="literal-block">
+provides interface ReadStream&lt;uint16_t&gt;;
+provides interface DeviceMetadata;
+</pre>
+<p>This component SHOULD sample the same sensor as <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt>.</p>
 </li>
-</ol>
-</div>
+</ul>
+<p>These components MUST be an alias for one of the sensor board's usual
+sensors, though they change the precision of the sensor if necessary.
+For instance, if <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt> is an alias for a 20-bit sensor that
+provides a <tt class="docutils literal"><span class="pre">Read&lt;uint32_t&gt;</span></tt> interface, <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt> would still
+provide <tt class="docutils literal"><span class="pre">Read&lt;uint16_t&gt;</span></tt> and would include code to reduce the
+precision of the aliased sensor.</p>
 <div class="section">
-<h1><a id="sensor-file" name="sensor-file"><cite>.sensor</cite> File</a></h1>
-<p>This file is a perl script which gets executed as part of the <cite>ncc</cite>
-nesC compiler frontend. It can add or modify any compile-time options
-necessary for a particular sensor board. It MAY modify the following perl
-variables, and MUST NOT modify any others:</p>
+<h2><a id="compiler-interaction" name="compiler-interaction">4.1 Compiler Interaction</a></h2>
+<p>When the <tt class="docutils literal"><span class="pre">ncc</span></tt> nesC compiler frontend is passed a <tt class="docutils literal"><span class="pre">-board=X</span></tt> option,
+it executes the <tt class="docutils literal"><span class="pre">.sensor</span></tt> file found in the sensor board directory
+<tt class="docutils literal"><span class="pre">X</span></tt>.  This file is a perl script which can add or modify any
+compile-time options necessary for the sensor board. It MAY modify the
+following perl variables, and MUST NOT modify any others:</p>
 <ul class="simple">
-<li>&#64;new_args: This is the array of arguments which will be
-passed to nescc. For instance, you might add an include directive
-to &#64;new_args with push &#64;new_args, <cite>-Isomedir</cite></li>
-<li>&#64;commonboards: This can be set to a list of sensor board names which
-should be added to the include path list. These sensor boards must be
-in tinyos-2.x/tos/sensorboards.</li>
+<li><tt class="docutils literal"><span class="pre">&#64;includes</span></tt>: This array contains the TinyOS search path, i.e., the
+directories which will be passed to nescc (the TinyOS-agnostic nesC
+compiler) as <tt class="docutils literal"><span class="pre">-I</span></tt> arguments. You MUST add to <tt class="docutils literal"><span class="pre">&#64;includes</span></tt> any
+directories needed to compile this sensor board's components.  For
+instance, if your sensor boards depends on support code found in
+<tt class="docutils literal"><span class="pre">tos/chips/sht11</span></tt>, you would add <tt class="docutils literal"><span class="pre">&quot;%T/chips/sht11&quot;</span></tt> to <tt class="docutils literal"><span class="pre">&#64;includes</span></tt>.</li>
+<li><tt class="docutils literal"><span class="pre">&#64;new_args</span></tt>: This is the array of arguments which will be passed to
+nescc. You MUST add any arguments other than <tt class="docutils literal"><span class="pre">-I</span></tt> that are necessary
+to compile your sensor board components to <tt class="docutils literal"><span class="pre">&#64;new_args</span></tt>.</li>
 </ul>
+<p>If a sensor is associated with a platform <cite>P</cite> rather than a sensor
+board, then that platform MUST ensure that, when compiling for
+platform <cite>P</cite>, all directories needed to compile that sensor's
+component are added to the TinyOS search path (see <a class="citation-reference" href="#tep131" id="id8" name="id8">[TEP131]</a> for
+information on how to set up a TinyOS platform).</p>
 </div>
 <div class="section">
-<h1><a id="example-mts3x0" name="example-mts3x0">Example: mts3x0</a></h1>
-<p>The mica sensor board (mts300/mts310) has five sensors (and one actuator,
-the sounder) -- the accelerometer and magnetometer are only present on
-the mts310:</p>
-<table border="1" class="docutils">
-<colgroup>
-</colgroup>
-<tbody valign="top">
-</tbody>
-</table>
-<div class="line-block">
-<div class="line">Name          | Component | Sensor Interfaces | Other Interfaces |</div>
-</div>
-<p>+===============+===========+===================+==================+</p>
-<div class="line-block">
-<div class="line">Accelerometer | AccelC    | AccelX            |                  |</div>
-</div>
-<div class="line-block">
-<div class="line">|           | AccelY            |                  |</div>
-</div>
-<div class="line-block">
-<div class="line">Magnetometer  | MagC      | MagX              | MagSetting       |</div>
-</div>
-<div class="line-block">
-<div class="line">|           | MagY              |                  |</div>
-</div>
-<div class="line-block">
-<div class="line">Microphone    | MicC      | MicADC            | Mic              |</div>
-</div>
-<div class="line-block">
-<div class="line">|           |                   | MicInterrupt     |</div>
-</div>
-<div class="line-block">
-<div class="line">Light         | PhotoC    | PhotoADC          |                  |</div>
-</div>
-<div class="line-block">
-<div class="line">Temperature   | TempC     | TempADC           |                  |</div>
+<h2><a id="sensor-components" name="sensor-components">4.2 Sensor Components</a></h2>
+<p>A particular sensor is typically supported by many components,
+including the HIL and HAL components from Sections 2 and 3, A/D
+conversion components (for analog sensors), digital bus components
+(e.g., SPI, for digital sensors), system services (timers, resource
+and power management, ...), glue components (to connect sensors,
+sensor boards and platforms), etc.  These components can be divided
+into three classes: sensorboard-dependent, platform-dependent and
+platform-independent. The sensorboard and platform MUST ensure
+(Section 4.1) that all these components can be found at compile-time.</p>
+<p>Because the same physical sensor can be used on many platforms or
+sensor boards, and attached in many different ways, to maximize code
+reuse the organization of sensor drivers SHOULD reflect the
+distinction between sensor and sensor interconnect. The sensor
+components SHOULD be platform-independent, while the sensor
+interconnect components are typically sensorboard or
+platform-dependent. However, some sensors (e.g. analong sensors) will
+not have a sufficiently large amount of platform-independent logic to
+justify creating platform-independent components.</p>
+<p>The following guidelines specify how to organize sensor and sensor
+interconnect components within TinyOS's directory hierarchy. These
+guidelines are only relevant to components that are part of the core
+source tree. The string <tt class="docutils literal"><span class="pre">&lt;sensor&gt;</span></tt> SHOULD reflect the make and model
+of the sensor device.</p>
+<ul class="simple">
+<li>Platform-independent sensor components that exist as part of a
+larger chip, like a MCU internal voltage sensor, SHOULD be placed in
+a subdirectory of the chip's directory
+<tt class="docutils literal"><span class="pre">tos/&lt;chip&gt;/sensors/&lt;sensor&gt;</span></tt>.</li>
+<li>Other platform-independent sensor components SHOULD be placed
+in <tt class="docutils literal"><span class="pre">tos/chips/&lt;sensor&gt;</span></tt>.</li>
+<li>Sensorboard-dependent sensor and sensor interconnect components
+SHOULD be placed either in the <tt class="docutils literal"><span class="pre">&lt;sensorboard&gt;</span></tt> directory or in a
+<tt class="docutils literal"><span class="pre">&lt;sensorboard&gt;/chips/&lt;sensor&gt;</span></tt> directory.</li>
+<li>Platform-dependent sensor and sensor interconnect components SHOULD
+be placed in <tt class="docutils literal"><span class="pre">tos/&lt;platform&gt;/chips/&lt;sensor&gt;</span></tt>.</li>
+</ul>
 </div>
-<table border="1" class="docutils">
-<colgroup>
-</colgroup>
-<tbody valign="top">
-</tbody>
-</table>
-<p>Each physical sensor is represented by a separate component. Specific
-sensors that have more than one axis of measurement (AccelC and MagC)
-provide more than one <cite>AcquireData</cite> interface on a single component. Some
-sensors, such as the magnetometer and microphone, have additional
-functionality provided through sensor-specific interfaces.</p>
-<p>Although light and temperature are represented by separate components, in
-reality they share a single microcontroller pin. The two components PhotoC
-and TempC sit on top of the PhotoTempP component, which controls access to
-the shared pin, and orchestrates which sensor is currently connected to
-it. From a programmer's perspective, they appear as individual sensors,
-even though their underlying implementation is a bit more complex.</p>
-<p>The board's mts3x0.h file contains private configuration data
-(pin usage, ADC ports, etc).</p>
-<p>The mica sensor board has an empty .sensor file.</p>
 </div>
 <div class="section">
-<h1><a id="author-s-address" name="author-s-address">6. Author's Address</a></h1>
+<h1><a id="authors-addresses" name="authors-addresses">5. Authors' Addresses</a></h1>
 <div class="line-block">
 <div class="line">David Gay</div>
 <div class="line">2150 Shattuck Ave, Suite 1300</div>
@@ -587,8 +621,9 @@ even though their underlying implementation is a bit more complex.</p>
 <div class="line">email - <a class="reference" href="mailto:david.e.gay&#64;intel.com">david.e.gay&#64;intel.com</a></div>
 <div class="line"><br /></div>
 <div class="line">Wei Hong</div>
-<div class="line">Arched Rock</div>
-<div class="line">Berkeley, CA 94704</div>
+<div class="line">Arch Rock</div>
+<div class="line">657 Mission St. Suite 600</div>
+<div class="line">San Francisco, CA 94105</div>
 <div class="line"><br /></div>
 <div class="line">email - <a class="reference" href="mailto:wei.hong&#64;gmail.com">wei.hong&#64;gmail.com</a></div>
 <div class="line"><br /></div>
@@ -608,6 +643,559 @@ even though their underlying implementation is a bit more complex.</p>
 <div class="line">Berkeley, CA 94720</div>
 <div class="line"><br /></div>
 <div class="line">email - <a class="reference" href="mailto:polastre&#64;cs.berkeley.edu">polastre&#64;cs.berkeley.edu</a></div>
+<div class="line"><br /></div>
+<div class="line">Gilman Tolle</div>
+<div class="line">Arch Rock</div>
+<div class="line">657 Mission St. Suite 600</div>
+<div class="line">San Francisco, CA 94105</div>
+<div class="line"><br /></div>
+<div class="line">email - <a class="reference" href="mailto:gtolle&#64;archrock.com">gtolle&#64;archrock.com</a></div>
+</div>
+</div>
+<div class="section">
+<h1><a id="citations" name="citations">6. Citations</a></h1>
+<table class="docutils citation" frame="void" id="tep2" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id1" name="tep2">[TEP2]</a></td><td>TEP 2: Hardware Abstraction Architecture</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="tep108" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id6" name="tep108">[TEP108]</a></td><td>TEP 108: Resource Arbitration</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="tep114" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="tep114">[TEP114]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> TEP 114: SIDs: Source and Sink Indepedent Drivers</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="tep115" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a name="tep115">[TEP115]</a></td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id5">2</a>, <a class="fn-backref" href="#id7">3</a>)</em> TEP 115: Power Management of Non-Virtualized Devices</td></tr>
+</tbody>
+</table>
+<table class="docutils citation" frame="void" id="tep131" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id8" name="tep131">[TEP131]</a></td><td>TEP 131: Creating a New Platform for TinyOS 2.x</td></tr>
+</tbody>
+</table>
+</div>
+<div class="section">
+<h1><a id="appendix-a-sensor-driver-examples" name="appendix-a-sensor-driver-examples">Appendix A: Sensor Driver Examples</a></h1>
+<div class="section">
+<h2><a id="analog-adc-connected-sensor" name="analog-adc-connected-sensor">1. Analog ADC-Connected Sensor</a></h2>
+<p>The Analog sensor requires two components</p>
+<ul class="simple">
+<li>a component to present the sensor itself (HamamatsuS1087ParC)</li>
+<li>a component to select the appropriate hardware resources, such as
+ADC port 4, reference voltage 1.5V, and a slow sample and hold time
+(HamamatsuS1087ParP).</li>
+</ul>
+<p>The AdcReadClientC component and underlying machinery handles all of
+the arbitration and access to the ADC.</p>
+<pre class="literal-block">
+tos/platforms/telosa/chips/s1087/HamamatsuS1087ParC.nc
+
+// HIL for the HamamatsuS1087 analog photodiode sensor
+generic configuration HamamatsuS1087ParC() {
+  provides interface Read&lt;uint16_t&gt;;
+  provides interface ReadStream&lt;uint16_t&gt;;
+  provides interface DeviceMetadata;
+}
+implementation {
+  // Create a new A/D client and connect it to the Hamamatsu S1087 A/D
+  // parameters
+  components new AdcReadClientC();
+  Read = AdcReadClientC;
+
+  components new AdcReadStreamClientC();
+  ReadStream = AdcReadStreamClientC;
+
+  components HamamatsuS1087ParP;
+  DeviceMetadata = HamamatsuS1087ParP;
+  AdcReadClientC.AdcConfigure -&gt; HamamatsuS1087ParP;
+  AdcReadStreamClientC.AdcConfigure -&gt; HamamatsuS1087ParP;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/s1087/HamamatsuS1087ParP.nc
+
+#include &quot;Msp430Adc12.h&quot;
+
+// A/D parameters for the Hamamatsu - see the MSP430 A/D converter manual,
+// Hamamatsu specification, Telos hardware schematic and TinyOS MSP430
+// A/D converter component specifications for the explanation of these
+// parameters
+module HamamatsuS1087ParP {
+  provides interface AdcConfigure&lt;const msp430adc12_channel_config_t*&gt;;
+  provides interface DeviceMetadata;
+}
+implementation {
+  msp430adc12_channel_config_t config = {
+    inch: INPUT_CHANNEL_A4,
+    sref: REFERENCE_VREFplus_AVss,
+    ref2_5v: REFVOLT_LEVEL_1_5,
+    adc12ssel: SHT_SOURCE_ACLK,
+    adc12div: SHT_CLOCK_DIV_1,
+    sht: SAMPLE_HOLD_4_CYCLES,
+    sampcon_ssel: SAMPCON_SOURCE_SMCLK,
+    sampcon_id: SAMPCON_CLOCK_DIV_1
+  };
+
+  async command const msp430adc12_channel_config_t* AdcConfigure.getConfiguration() {
+    return &amp;config;
+  }
+
+  command uint8_t DeviceMetadata.getSignificantBits() { return 12; }
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="binary-pin-connected-sensor" name="binary-pin-connected-sensor">2. Binary Pin-Connected Sensor</a></h2>
+<p>The Binary sensor gets a bit more complex, because it has three
+components:</p>
+<ul class="simple">
+<li>one to present the sensor (UserButtonC)</li>
+<li>one to execute the driver logic (UserButtonLogicP)</li>
+<li>one to select the appropriate hardware resources, such as MSP430
+Port 27 (HplUserButtonC).</li>
+</ul>
+<p>Note that the presentation of this sensor is not arbitrated because
+none of the operations are split-phase.</p>
+<pre class="literal-block">
+tos/platforms/telosa/UserButtonC.nc
+
+// HIL for the user button sensor on Telos-family motes
+configuration UserButtonC {
+  provides interface Get&lt;bool&gt;; // Get button status
+  provides interface Notify&lt;bool&gt;; // Get button-press notifications
+  provides interface DeviceMetadata;
+}
+implementation {
+
+  // Simply connect the button logic to the button HPL
+  components UserButtonLogicP;
+  Get = UserButtonLogicP;
+  Notify = UserButtonLogicP;
+  DeviceMetadata = UserButtonLogicP;
+
+  components HplUserButtonC;
+  UserButtonLogicP.GpioInterrupt -&gt; HplUserButtonC.GpioInterrupt;
+  UserButtonLogicP.GeneralIO -&gt; HplUserButtonC.GeneralIO;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/UserButtonLogicP.nc
+
+// Transform the low-level (GeneralIO and GpioInterrupt) interface to the
+// button to high-level SID interfaces
+module UserButtonLogicP {
+  provides interface Get&lt;bool&gt;;
+  provides interface Notify&lt;bool&gt;;
+  provides interface DeviceMetadata;
+
+  uses interface GeneralIO;
+  uses interface GpioInterrupt;
+}
+implementation {
+  norace bool m_pinHigh;
+
+  task void sendEvent();
+
+  command bool Get.get() { return call GeneralIO.get(); }
+
+  command error_t Notify.enable() {
+    call GeneralIO.makeInput();
+
+    // If the pin is high, we need to trigger on falling edge interrupt, and
+    // vice-versa
+    if ( call GeneralIO.get() ) {
+      m_pinHigh = TRUE;
+      return call GpioInterrupt.enableFallingEdge();
+    } else {
+      m_pinHigh = FALSE;
+      return call GpioInterrupt.enableRisingEdge();
+    }
+  }
+
+  command error_t Notify.disable() {
+    return call GpioInterrupt.disable();
+  }
+
+  // Button changed, signal user (in a task) and update interrupt detection
+  async event void GpioInterrupt.fired() {
+    call GpioInterrupt.disable();
+
+    m_pinHigh = !m_pinHigh;
+
+    post sendEvent();
+  }
+
+  task void sendEvent() {
+    bool pinHigh;
+    pinHigh = m_pinHigh;
+
+    signal Notify.notify( pinHigh );
+
+    if ( pinHigh ) {
+      call GpioInterrupt.enableFallingEdge();
+    } else {
+      call GpioInterrupt.enableRisingEdge();
+    }
+  }
+
+  command uint8_t DeviceMetadata.getSignificantBits() { return 1; }
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/HplUserButtonC.nc
+
+// HPL for the user button sensor on Telos-family motes - just provides
+// access to the I/O and interrupt control for the pin to which the
+// button is connected
+configuration HplUserButtonC {
+  provides interface GeneralIO;
+  provides interface GpioInterrupt;
+}
+implementation {
+
+  components HplMsp430GeneralIOC as GeneralIOC;
+
+  components new Msp430GpioC() as UserButtonC;
+  UserButtonC -&gt; GeneralIOC.Port27;
+  GeneralIO = UserButtonC;
+
+  components HplMsp430InterruptC as InterruptC;
+
+  components new Msp430InterruptC() as InterruptUserButtonC;
+  InterruptUserButtonC.HplInterrupt -&gt; InterruptC.Port27;
+  GpioInterrupt = InterruptUserButtonC.Interrupt;
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="digital-bus-connected-sensor" name="digital-bus-connected-sensor">3. Digital Bus-Connected Sensor</a></h2>
+<p>The Digital sensor is the most complex out of the set, and includes
+six components:</p>
+<ul class="simple">
+<li>one to present the sensor (SensirionSht11C)</li>
+<li>one to request arbitrated access and to transform the sensor HAL
+into the sensor HIL (SensirionSht11P)</li>
+<li>one to present the sensor HAL (HalSensirionSht11C)</li>
+<li>one to perform the driver logic needed to support the HAL, which
+twiddles pins according to a sensor-specific protocol
+(SensirionSht11LogicP).</li>
+<li>one to select the appropriate hardware resources, such as the clock,
+data, and power pins, and to provide an arbiter for the sensor
+(HplSensirionSht11C).</li>
+<li>one to perform the power control logic needed to support the power
+manager associated with the arbiter (HplSensirionSht11P).</li>
+</ul>
+<p>This bus-connected sensor is overly complex because it does not rely
+on a shared framework of bus manipulation components. A sensor built
+on top of the I2C or SPI bus would likely require fewer components.</p>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/SensirionSht11C.nc
+
+// HIL interface to Sensirion SHT11 temperature and humidity sensor
+generic configuration SensirionSht11C() {
+  provides interface Read&lt;uint16_t&gt; as Temperature;
+  provides interface DeviceMetadata as TemperatureDeviceMetadata;
+  provides interface Read&lt;uint16_t&gt; as Humidity;
+  provides interface DeviceMetadata as HumidityDeviceMetadata;
+}
+implementation {
+  // Instantiate the module providing the HIL interfaces
+  components new SensirionSht11ReaderP();
+
+  Temperature = SensirionSht11ReaderP.Temperature;
+  TemperatureDeviceMetadata = SensirionSht11ReaderP.TemperatureDeviceMetadata;
+  Humidity = SensirionSht11ReaderP.Humidity;
+  HumidityDeviceMetadata = SensirionSht11ReaderP.HumidityDeviceMetadata;
+
+  // And connect it to the HAL component for the Sensirion SHT11
+  components HalSensirionSht11C;
+
+  enum { TEMP_KEY = unique(&quot;Sht11.Resource&quot;) };
+  enum { HUM_KEY = unique(&quot;Sht11.Resource&quot;) };
+
+  SensirionSht11ReaderP.TempResource -&gt; HalSensirionSht11C.Resource[ TEMP_KEY ];
+  SensirionSht11ReaderP.Sht11Temp -&gt; HalSensirionSht11C.SensirionSht11[ TEMP_KEY ];
+  SensirionSht11ReaderP.HumResource -&gt; HalSensirionSht11C.Resource[ HUM_KEY ];
+  SensirionSht11ReaderP.Sht11Hum -&gt; HalSensirionSht11C.SensirionSht11[ HUM_KEY ];
+}
+</pre>
+<pre class="literal-block">
+tos/chips/sht11/SensirionSht11ReaderP.nc
+
+// Convert Sensirion SHT11 HAL to HIL interfaces for a single
+// client, performing automatic resource arbitration
+generic module SensirionSht11ReaderP() {
+  provides interface Read&lt;uint16_t&gt; as Temperature;
+  provides interface DeviceMetadata as TemperatureDeviceMetadata;
+  provides interface Read&lt;uint16_t&gt; as Humidity;
+  provides interface DeviceMetadata as HumidityDeviceMetadata;
+
+  // Using separate resource interfaces for temperature and humidity allows
+  // temperature and humidity measurements to be requested simultaneously
+  // (if a single Resource interface was used, a request for temperature would
+  // prevent any humidity requests until the temperature measurement was complete)
+  uses interface Resource as TempResource;
+  uses interface Resource as HumResource;
+  uses interface SensirionSht11 as Sht11Temp;
+  uses interface SensirionSht11 as Sht11Hum;
+}
+implementation {
+  command error_t Temperature.read() {
+    // Start by requesting access to the SHT11
+    return call TempResource.request();
+  }
+
+  event void TempResource.granted() {
+    error_t result;
+    // If the HAL measurement fails, release the SHT11 and signal failure
+    if ((result = call Sht11Temp.measureTemperature()) != SUCCESS) {
+      call TempResource.release();
+      signal Temperature.readDone( result, 0 );
+    }
+  }
+
+  event void Sht11Temp.measureTemperatureDone( error_t result, uint16_t val ) {
+    // Release the SHT11 and signal the result
+    call TempResource.release();
+    signal Temperature.readDone( result, val );
+  }
+
+  command uint8_t TemperatureDeviceMetadata.getSignificantBits() { return 14; }
+
+  command error_t Humidity.read() {
+    // Start by requesting access to the SHT11
+    return call HumResource.request();
+  }
+
+  event void HumResource.granted() {
+    error_t result;
+    // If the HAL measurement fails, release the SHT11 and signal failure
+    if ((result = call Sht11Hum.measureHumidity()) != SUCCESS) {
+      call HumResource.release();
+      signal Humidity.readDone( result, 0 );
+    }
+  }
+
+  event void Sht11Hum.measureHumidityDone( error_t result, uint16_t val ) {
+    // Release the SHT11 and signal the result
+    call HumResource.release();
+    signal Humidity.readDone( result, val );
+  }
+
+  command uint8_t HumidityDeviceMetadata.getSignificantBits() { return 12; }
+
+  // Dummy handlers for unused portions of the HAL interface
+  event void Sht11Temp.resetDone( error_t result ) { }
+  event void Sht11Temp.measureHumidityDone( error_t result, uint16_t val ) { }
+  event void Sht11Temp.readStatusRegDone( error_t result, uint8_t val ) { }
+  event void Sht11Temp.writeStatusRegDone( error_t result ) { }
+
+  event void Sht11Hum.resetDone( error_t result ) { }
+  event void Sht11Hum.measureTemperatureDone( error_t result, uint16_t val ) { }
+  event void Sht11Hum.readStatusRegDone( error_t result, uint8_t val ) { }
+  event void Sht11Hum.writeStatusRegDone( error_t result ) { }
+
+  // We need default handlers as a client may wire to only the Temperature
+  // sensor or only the Humidity sensor
+  default event void Temperature.readDone( error_t result, uint16_t val ) { }
+  default event void Humidity.readDone( error_t result, uint16_t val ) { }
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HalSensirionSht11C.nc
+
+// HAL interface to Sensirion SHT11 temperature and humidity sensor
+configuration HalSensirionSht11C {
+  // The SHT11 HAL uses resource arbitration to allow the sensor to shared
+  // between multiple clients and for automatic power management (the SHT11
+  // is switched off when no clients are waiting to use it)
+  provides interface Resource[ uint8_t client ];
+  provides interface SensirionSht11[ uint8_t client ];
+}
+implementation {
+  // The HAL implementation logic
+  components new SensirionSht11LogicP();
+  SensirionSht11 = SensirionSht11LogicP;
+
+  // And it's wiring to the SHT11 HPL - the actual resource management is
+  // provided at the HPL layer
+  components HplSensirionSht11C;
+  Resource = HplSensirionSht11C.Resource;
+  SensirionSht11LogicP.DATA -&gt; HplSensirionSht11C.DATA;
+  SensirionSht11LogicP.CLOCK -&gt; HplSensirionSht11C.SCK;
+  SensirionSht11LogicP.InterruptDATA -&gt; HplSensirionSht11C.InterruptDATA;
+
+  components new TimerMilliC();
+  SensirionSht11LogicP.Timer -&gt; TimerMilliC;
+
+  components LedsC;
+  SensirionSht11LogicP.Leds -&gt; LedsC;
+}
+</pre>
+<pre class="literal-block">
+tos/chips/sht11/SensirionSht11LogicP.nc
+
+generic module SensirionSht11LogicP() {
+  provides interface SensirionSht11[ uint8_t client ];
+
+  uses interface GeneralIO as DATA;
+  uses interface GeneralIO as CLOCK;
+  uses interface GpioInterrupt as InterruptDATA;
+
+  uses interface Timer&lt;TMilli&gt;;
+
+  uses interface Leds;
+}
+implementation {
+
+  ... bus protocol details omitted for brevity ...
+
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HplSensirionSht11C.nc
+
+// Low-level, platform-specific glue-code to access the SHT11 sensor found
+// on telos-family motes - here  the HPL just provides resource management
+// and access to the SHT11 data, clock and interrupt pins
+configuration HplSensirionSht11C {
+  provides interface Resource[ uint8_t id ];
+  provides interface GeneralIO as DATA;
+  provides interface GeneralIO as SCK;
+  provides interface GpioInterrupt as InterruptDATA;
+}
+implementation {
+  // Pins used to access the SHT11
+  components HplMsp430GeneralIOC;
+
+  components new Msp430GpioC() as DATAM;
+  DATAM -&gt; HplMsp430GeneralIOC.Port15;
+  DATA = DATAM;
+
+  components new Msp430GpioC() as SCKM;
+  SCKM -&gt; HplMsp430GeneralIOC.Port16;
+  SCK = SCKM;
+
+  components new Msp430GpioC() as PWRM;
+  PWRM -&gt; HplMsp430GeneralIOC.Port17;
+
+  // HPL logic for switching the SHT11 on and off
+  components HplSensirionSht11P;
+  HplSensirionSht11P.PWR -&gt; PWRM;
+  HplSensirionSht11P.DATA -&gt; DATAM;
+  HplSensirionSht11P.SCK -&gt; SCKM;
+
+  components new TimerMilliC();
+  HplSensirionSht11P.Timer -&gt; TimerMilliC;
+
+  components HplMsp430InterruptC;
+  components new Msp430InterruptC() as InterruptDATAC;
+  InterruptDATAC.HplInterrupt -&gt; HplMsp430InterruptC.Port15;
+  InterruptDATA = InterruptDATAC.Interrupt;
+
+  // The arbiter and power manager for the SHT11
+  components new FcfsArbiterC( &quot;Sht11.Resource&quot; ) as Arbiter;
+  Resource = Arbiter;
+
+  components new SplitControlPowerManagerC();
+  SplitControlPowerManagerC.SplitControl -&gt; HplSensirionSht11P;
+  SplitControlPowerManagerC.ArbiterInit -&gt; Arbiter.Init;
+  SplitControlPowerManagerC.ArbiterInfo -&gt; Arbiter.ArbiterInfo;
+  SplitControlPowerManagerC.ResourceDefaultOwner -&gt; Arbiter.ResourceDefaultOwner;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HplSensirionSht11P.nc
+
+// Switch the SHT11 on and off, and handle the 11ms warmup delay
+module HplSensirionSht11P {
+  // The SplitControl interface powers the SHT11 on or off (it's automatically
+  // called by the SHT11 power manager, see HplSensirionSht11C)
+  // We use a SplitControl interface as we need to wait 11ms for the sensor to
+  // warm up
+  provides interface SplitControl;
+  uses interface Timer&lt;TMilli&gt;;
+  uses interface GeneralIO as PWR;
+  uses interface GeneralIO as DATA;
+  uses interface GeneralIO as SCK;
+}
+implementation {
+  task void stopTask();
+
+  command error_t SplitControl.start() {
+    // Power SHT11 on and wait for 11ms
+    call PWR.makeOutput();
+    call PWR.set();
+    call Timer.startOneShot( 11 );
+    return SUCCESS;
+  }
+
+  event void Timer.fired() {
+    signal SplitControl.startDone( SUCCESS );
+  }
+
+  command error_t SplitControl.stop() {
+    // Power the SHT11 off
+    call SCK.makeInput();
+    call SCK.clr();
+    call DATA.makeInput();
+    call DATA.clr();
+    call PWR.clr();
+    post stopTask();
+    return SUCCESS;
+  }
+
+  task void stopTask() {
+    signal SplitControl.stopDone( SUCCESS );
+  }
+}
+</pre>
+</div>
+<div class="section">
+<h2><a id="mda100-sensor-board-directory-organization" name="mda100-sensor-board-directory-organization">4. MDA100 Sensor Board Directory Organization</a></h2>
+<p>Here we show the organization of the sensor board directory for the
+mica-family Xbow MDA100CA and MDA100CB sensor boards, which have
+temperature and light sensors. It is found in
+<tt class="docutils literal"><span class="pre">tos/sensorboards/mda100</span></tt>:</p>
+<pre class="literal-block">
+./tos/sensorboards/mda100:
+.sensor                                       # Compiler configuration
+ArbitratedPhotoDeviceP.nc                     # Light sensor support component
+ArbitratedTempDeviceP.nc                      # Temperature sensor support component
+DemoSensorC.nc                                # Override TinyOS's default sensor
+PhotoC.nc                                     # Light sensor HIL
+PhotoImplP.nc                                 # Light sensor support component
+PhotoTempConfigC.nc                           # Shared support component
+PhotoTempConfigP.nc                           # Shared support component
+SharedAnalogDeviceC.nc                        # Shared support component
+SharedAnalogDeviceP.nc                        # Shared support component
+TempC.nc                                      # Temperature Sensor HIL
+ca/TempImplP.nc                               # Temperature sensor support component
+                                              # (MDA100CA board)
+cb/TempImplP.nc                               # Temperature sensor support component
+                                              # (MDA100CB board)
+mda100.h                                      # Header file for mda100
+</pre>
+<p>This sensor board provides only a HIL (PhotoC and TempC components), and overrides the
+TinyOS demo sensor (DemoSensorC). The demo sensor is an alias for PhotoC.</p>
+<p>The two forms of the mda100 differ only by the wiring of the
+temperature sensor.  The user has to specify which form of the sensor
+board is in use by providing a <tt class="docutils literal"><span class="pre">-I%T/sensorboards/mda100/ca</span></tt> or
+<tt class="docutils literal"><span class="pre">-I%T/sensorboards/mda100/cb</span></tt> compiler option.</p>
+<p>This sensor board relies on a platform-provided <tt class="docutils literal"><span class="pre">MicaBusC</span></tt> component
+that specifies how the mica-family sensor board bus is connected to
+the microcontroller.</p>
 </div>
 </div>
 </div>