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 }
<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 may be attached to the microcontroller on a
+<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>Connected through a standard digital bus protocol (1-Wire, I2C, SPI)</li>
</ul>
</blockquote>
-<p>Physically, these connections may also be decoupled by attaching the
+<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 may fit multiple different TinyOS platforms.</p>
+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
+<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>
+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
+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 may be shared, can benefit from
+<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 may be followed by sensor
+pattern for sensor virtualization that SHOULD be followed by sensor
drivers.</p>
-<p>The same physical sensor may be attached to multiple different TinyOS
+<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
+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 optionally provide a
-component with a generic name for application authors who only care
-about the general class of the sensor.</p>
-<p>This document assumes that sensors return uninterpreted values of
-arbitrary size or datatype. Conversion of sensor values to something
-with actual physical meaning is beyond the scope of this document.</p>
+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 takes no position on the meaning of the values returned
+by sensor drivers. 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 needed to properly
+interpret the value.</p>
</div>
<div class="section">
<h1><a id="sensor-hil-components" name="sensor-hil-components">2. Sensor HIL Components</a></h1>
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. This virtualization may be easier to accomplish
-by using one of the arbiters provided by the system.</p>
+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<uint16_t> as Temperature;
provides interface ReadStream<uint16_t> as TemperatureStream;
+ provides interface DeviceMetadata as TemperatureDeviceMetadata;
+
provides interface Read<uint16_t> as Humidity;
provides interface ReadStream<uint16_t> as HumidityStream;
+ provides interface DeviceMetadata as HumidityDeviceMetadata;
}
implementation {
// connect to the ADC HIL, GPIO HAL, or sensor's HAL
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. One of the power-management
-components described in <a class="citation-reference" href="#tep115" id="id4" name="id4">[TEP115]</a> may be useful for this purpose.</p>
+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. A device MAY
-specify the precision of one of its interfaces with the DeviceMetadata
-interface:</p>
+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 SHOULD clearly indicate
-which interface it corresponds to.</p>
-<p>A value contained returned from the device through a SID interface
-MAY be left shifted so that it covers as much of the type's range as
-possible. For example, if a 12-bit ADC reading is presented as a
-16-bit Read interface:</p>
-<pre class="literal-block">
-component DemoSensorC {
- provides interface Read<uint16_t>;
-}
-</pre>
-<p>then the driver MAY shift the 12-bit value left so that its range is
-0x0000 - 0xfff0, rather than 0x0000 - 0x0fff.</p>
+<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 MUST return the value "12".</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
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 "common" naming layer atop a HIL may look like this:</p>
+<p>A "common" naming layer atop a HIL might look like this:</p>
<pre class="literal-block">
generic configuration TemperatureC() {
provides interface Read<uint16_t>;
provides interface ReadStream<uint16_t>;
+ provides interface DeviceMetadata;
}
implementation {
components new SensirionSht11C();
Read = SensirionSht11C.Temperature;
ReadStream = SensirionSht11C.TemperatureStream;
+ DeviceMetadata = SensirionSht11C.TemperatureDeviceMetadata;
}
generic configuration HumidityC() {
provides interface Read<uint16_t>;
provides interface ReadStream<uint16_t>;
+ provides interface DeviceMetadata;
}
implementation {
components new SensirionSht11C();
Read = SensirionSht11C.Humidity;
ReadStream = SensirionSht11C.HumidityStream;
+ DeviceMetadata = SensirionSht11C.HumidityDeviceMetadata;
}
</pre>
</div>
</pre>
</div>
<div class="section">
-<h1><a id="sensor-hpl-components" name="sensor-hpl-components">4. Sensor HPL Components</a></h1>
-<p>A sensor HPL is necessarily platform-dependent or
-sensorboard-dependent. These components should provide access to the
-physical resources needed by the sensor, in a platform-independent
-manner that can be used by the shared logic of the sensor HAL
-components. In the case of bus-based sensors, this HPL may be nothing
-more than wiring to the appropriate bus interface for use by the HAL
-component.</p>
-<p>For example:</p>
-<pre class="literal-block">
-configuration HplSensirionSht11C {
- provides interface Init;
- provides interface Resource[ uint8_t id ];
- provides interface GeneralIO as DATA;
- provides interface GeneralIO as SCK;
- provides interface GpioInterrupt as InterruptDATA;
-}
-implementation {
- // connect to platform or sensorboard-dependent resources
- // power-manage the sensor through platform-specific means
-}
-</pre>
-</div>
-<div class="section">
-<h1><a id="directory-organization-guidelines" name="directory-organization-guidelines">5. Directory Organization Guidelines</a></h1>
-<p>Because the same physical sensor may be attached to TinyOS platforms
-in many different ways, the organization of sensor drivers should
+<h1><a id="directory-organization-guidelines" name="directory-organization-guidelines">4. Directory Organization Guidelines</a></h1>
+<p>Because the same physical sensor can be attached to TinyOS platforms
+in many different ways, the organization of sensor drivers SHOULD
reflect the distinction between sensor and sensor interconnect.</p>
<p>Sensor components commonly exist at three levels:
platform-independent, sensorboard-dependent, and
with push @new_args, <cite>-Isomedir</cite>. This could be used to include
subdirectories.</li>
<li>@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
+will be added to the include path list. These sensor boards MUST be
in tinyos-2.x/tos/sensorboards.</li>
</ul>
<p>If the sensor board wishes to define any C types or constants, it
subdirectories for each of the sensors connected to the sensor board.
If a "chips" subdirectory is used, sensorboard-dependent driver
components needed to connect platform-independent logic to a
-particular attachment for that sensor should be placed in
+particular attachment for that sensor SHOULD be placed in
"<sensorboard>/chips/<sensor>".</p>
<p>Components needed to connect the platform-independent sensor driver
components or sensorboard-dependent components to the hardware
resources available on a particular platform SHOULD be placed in
"tos/<platform>/chips/<sensor>". In addition, components for a sensor
-that only exists on a particular platform should be placed in a such a
+that only exists on a particular platform SHOULD be placed in a such a
directory.</p>
<p>Sensors that exist as part of a larger chip, like a MCU internal
voltage sensor, SHOULD be placed in a subdirectory of the chip's
the sensors on a platform and/or sensorboard.</p>
<p>All of these directory organization guidelines are only intended for
code that will enter the core source tree. In general, sensor
-components may be placed anywhere as long as the nesC compiler
+components can be placed anywhere as long as the nesC compiler
receives enough <cite>-I</cite> directives to locate all of the necessary pieces.</p>
</div>
<div class="section">
-<h1><a id="authors-addresses" name="authors-addresses">6. Authors' Addresses</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>
</div>
</div>
<div class="section">
-<h1><a id="citations" name="citations">7. Citations</a></h1>
+<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">
</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
+
+generic configuration HamamatsuS1087ParC() {
+ provides interface Read<uint16_t>;
+ provides interface ReadStream<uint16_t>;
+ provides interface DeviceMetadata;
+}
+implementation {
+ components new AdcReadClientC();
+ Read = AdcReadClientC;
+
+ components new AdcReadStreamClientC();
+ ReadStream = AdcReadStreamClientC;
+
+ components HamamatsuS1087ParP;
+ DeviceMetadata = HamamatsuS1087ParP;
+ AdcReadClientC.AdcConfigure -> HamamatsuS1087ParP;
+ AdcReadStreamClientC.AdcConfigure -> HamamatsuS1087ParP;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/s1087/HamamatsuS1087ParP.nc
+
+#include "Msp430Adc12.h"
+
+module HamamatsuS1087ParP {
+ provides interface AdcConfigure<const msp430adc12_channel_config_t*>;
+ 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 &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
+
+configuration UserButtonC {
+ provides interface Get<bool>;
+ provides interface Notify<bool>;
+ provides interface DeviceMetadata;
+}
+implementation {
+
+ components UserButtonLogicP;
+ Get = UserButtonLogicP;
+ Notify = UserButtonLogicP;
+ DeviceMetadata = UserButtonLogicP;
+
+ components HplUserButtonC;
+ UserButtonLogicP.GpioInterrupt -> HplUserButtonC.GpioInterrupt;
+ UserButtonLogicP.GeneralIO -> HplUserButtonC.GeneralIO;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/UserButtonLogicP.nc
+
+module UserButtonLogicP {
+ provides interface Get<bool>;
+ provides interface Notify<bool>;
+ 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 ( 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();
+ }
+
+ 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
+
+configuration HplUserButtonC {
+ provides interface GeneralIO;
+ provides interface GpioInterrupt;
+}
+implementation {
+
+ components HplMsp430GeneralIOC as GeneralIOC;
+
+ components new Msp430GpioC() as UserButtonC;
+ UserButtonC -> GeneralIOC.Port27;
+ GeneralIO = UserButtonC;
+
+ components HplMsp430InterruptC as InterruptC;
+
+ components new Msp430InterruptC() as InterruptUserButtonC;
+ InterruptUserButtonC.HplInterrupt -> 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
+
+generic configuration SensirionSht11C() {
+ provides interface Read<uint16_t> as Temperature;
+ provides interface DeviceMetadata as TemperatureDeviceMetadata;
+ provides interface Read<uint16_t> as Humidity;
+ provides interface DeviceMetadata as HumidityDeviceMetadata;
+}
+implementation {
+ components new SensirionSht11ReaderP();
+
+ Temperature = SensirionSht11ReaderP.Temperature;
+ TemperatureDeviceMetadata = SensirionSht11ReaderP.TemperatureDeviceMetadata;
+ Humidity = SensirionSht11ReaderP.Humidity;
+ HumidityDeviceMetadata = SensirionSht11ReaderP.HumidityDeviceMetadata;
+
+ components HalSensirionSht11C;
+
+ enum { TEMP_KEY = unique("Sht11.Resource") };
+ enum { HUM_KEY = unique("Sht11.Resource") };
+
+ SensirionSht11ReaderP.TempResource -> HalSensirionSht11C.Resource[ TEMP_KEY ];
+ SensirionSht11ReaderP.Sht11Temp -> HalSensirionSht11C.SensirionSht11[ TEMP_KEY ];
+ SensirionSht11ReaderP.HumResource -> HalSensirionSht11C.Resource[ HUM_KEY ];
+ SensirionSht11ReaderP.Sht11Hum -> HalSensirionSht11C.SensirionSht11[ HUM_KEY ];
+}
+</pre>
+<pre class="literal-block">
+tos/chips/sht11/SensirionSht11ReaderP.nc
+
+generic module SensirionSht11ReaderP() {
+ provides interface Read<uint16_t> as Temperature;
+ provides interface DeviceMetadata as TemperatureDeviceMetadata;
+ provides interface Read<uint16_t> as Humidity;
+ provides interface DeviceMetadata as HumidityDeviceMetadata;
+
+ 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() {
+ call TempResource.request();
+ return SUCCESS;
+ }
+
+ event void TempResource.granted() {
+ error_t result;
+ if ((result = call Sht11Temp.measureTemperature()) != SUCCESS) {
+ call TempResource.release();
+ signal Temperature.readDone( result, 0 );
+ }
+ }
+
+ event void Sht11Temp.measureTemperatureDone( error_t result, uint16_t val ) {
+ call TempResource.release();
+ signal Temperature.readDone( result, val );
+ }
+
+ command uint8_t TemperatureDeviceMetadata.getSignificantBits() { return 14; }
+
+ command error_t Humidity.read() {
+ call HumResource.request();
+ return SUCCESS;
+ }
+
+ event void HumResource.granted() {
+ error_t result;
+ if ((result = call Sht11Hum.measureHumidity()) != SUCCESS) {
+ call HumResource.release();
+ signal Humidity.readDone( result, 0 );
+ }
+ }
+
+ event void Sht11Hum.measureHumidityDone( error_t result, uint16_t val ) {
+ call HumResource.release();
+ signal Humidity.readDone( result, val );
+ }
+
+ command uint8_t HumidityDeviceMetadata.getSignificantBits() { return 12; }
+
+ 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 ) { }
+
+ 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
+
+configuration HalSensirionSht11C {
+ provides interface Resource[ uint8_t client ];
+ provides interface SensirionSht11[ uint8_t client ];
+}
+implementation {
+ components new SensirionSht11LogicP();
+ SensirionSht11 = SensirionSht11LogicP;
+
+ components HplSensirionSht11C;
+ Resource = HplSensirionSht11C.Resource;
+ SensirionSht11LogicP.DATA -> HplSensirionSht11C.DATA;
+ SensirionSht11LogicP.CLOCK -> HplSensirionSht11C.SCK;
+ SensirionSht11LogicP.InterruptDATA -> HplSensirionSht11C.InterruptDATA;
+
+ components new TimerMilliC();
+ SensirionSht11LogicP.Timer -> TimerMilliC;
+
+ components LedsC;
+ SensirionSht11LogicP.Leds -> 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<TMilli>;
+
+ uses interface Leds;
+}
+implementation {
+
+ ... bus protocol details omitted for brevity ...
+
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HplSensirionSht11C.nc
+
+configuration HplSensirionSht11C {
+ provides interface Resource[ uint8_t id ];
+ provides interface GeneralIO as DATA;
+ provides interface GeneralIO as SCK;
+ provides interface GpioInterrupt as InterruptDATA;
+}
+implementation {
+ components HplMsp430GeneralIOC;
+
+ components new Msp430GpioC() as DATAM;
+ DATAM -> HplMsp430GeneralIOC.Port15;
+ DATA = DATAM;
+
+ components new Msp430GpioC() as SCKM;
+ SCKM -> HplMsp430GeneralIOC.Port16;
+ SCK = SCKM;
+
+ components new Msp430GpioC() as PWRM;
+ PWRM -> HplMsp430GeneralIOC.Port17;
+
+ components HplSensirionSht11P;
+ HplSensirionSht11P.PWR -> PWRM;
+ HplSensirionSht11P.DATA -> DATAM;
+ HplSensirionSht11P.SCK -> SCKM;
+
+ components new TimerMilliC();
+ HplSensirionSht11P.Timer -> TimerMilliC;
+
+ components HplMsp430InterruptC;
+ components new Msp430InterruptC() as InterruptDATAC;
+ InterruptDATAC.HplInterrupt -> HplMsp430InterruptC.Port15;
+ InterruptDATA = InterruptDATAC.Interrupt;
+
+ components new FcfsArbiterC( "Sht11.Resource" ) as Arbiter;
+ Resource = Arbiter;
+
+ components new SplitControlPowerManagerC();
+ SplitControlPowerManagerC.SplitControl -> HplSensirionSht11P;
+ SplitControlPowerManagerC.ArbiterInit -> Arbiter.Init;
+ SplitControlPowerManagerC.ArbiterInfo -> Arbiter.ArbiterInfo;
+ SplitControlPowerManagerC.ResourceDefaultOwner -> Arbiter.ResourceDefaultOwner;
+}
+</pre>
+<pre class="literal-block">
+tos/platforms/telosa/chips/sht11/HplSensirionSht11P.nc
+
+module HplSensirionSht11P {
+ provides interface SplitControl;
+ uses interface Timer<TMilli>;
+ uses interface GeneralIO as PWR;
+ uses interface GeneralIO as DATA;
+ uses interface GeneralIO as SCK;
+}
+implementation {
+ task void stopTask();
+
+ command error_t SplitControl.start() {
+ 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() {
+ 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>
</div>
</body>
</html>