:TEP: 101
:Group: Core Working Group
:Type: Documentary
-:Status: Draft
+:Status: Final
:TinyOS-Version: 2.x
:Author: Jan-Hinrich Hauer, Philip Levis, Vlado Handziski, David Gay
-:Draft-Created: 20-Dec-2004
-:Draft-Version: $Revision$
-:Draft-Modified: $Date$
-:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
-
.. Note::
This memo documents a part of TinyOS for the TinyOS Community, and
This TEP proposes a hardware abstraction for analog-to-digital converters (ADCs)
in TinyOS 2.x, which is aligned to the three-layer Hardware Abstraction
-Architecture (HAA) specified in [TEP2]. It describes some design principles and
+Architecture (HAA) specified in [TEP2]_. It describes some design principles and
documents the set of hardware-independent interfaces to an ADC.
1. Introduction
programatically, even though the semantics and forms of operation were
completely different. To compensate for the difference non-ADC sensors
introduced additional interfaces, such as ``ADCError``, that were tightly bound
-to sensor acquisition but separate in wiring. The separation between the ADC and
-``ADCError`` interface is bug prone and problematic, as is the equation of a
-sensor and an ADC. TinyOS 2.x separates the structure and interfaces of an ADC
-from those of sensors (which may be on top of an ADC, but this fact is hidden
-from higher level components). This TEP presents how TinyOS 2.x structures ADC
-software. TEP 109 (Sensor Boards) shows how a platform can present actual named
-sensors [TEP109]_.
+to sensor acquisition but separate in wiring. The separation between the ADC
+and ``ADCError`` interface is bug prone and problematic, as is the equation of
+a sensor and an ADC. TinyOS 2.x separates the structure and interfaces of an
+ADC from those of sensor drivers (which may be on top of an ADC stack, but
+this fact is hidden from higher level components). This TEP presents how TinyOS
+2.x structures ADC software. [TEP109]_ (Sensor Boards) shows how a platform can
+present actual named sensors.
As can be seen in Appendix A the ADC hardware used on TinyOS platforms differ
in many respects, which makes it difficult to find a chip independent
predefine the type or semantics of the exchanged data (see [TEP114]_), a
configuration interface definition can abstract from the data type and
semantics of the involved configuration settings. For example, like a
-component can provide a ``Read<uint8_t>`` or ``Read<uint16_t>`` interface
-depending on the data it can offer, a component can also use a
-``AdcConfigure<atm128_adc_config_t>`` or
+component can provide a ``Read<uint8_t>`` or ``Read<uint16_t>`` interface, it
+can also provide a ``AdcConfigure<atm128_adc_config_t>`` or
``AdcConfigure<msp430adc12_channel_config_t>`` interface depending on what ADC
it represents. This TEP proposes the (typed) ``AdcConfigure`` interface as the
standard interface for configuring an ADC in TinyOS 2.x.
In spite of their hardware differences, one aspect represents a common
-denominator of all ADCs: they produce conversion results. To facilitate sensor
-software development conversion results are returned by the ADC hardware stack
-using the standard TinyOS interfaces ``Read``, ``ReadNow`` and ``ReadStream``
-(see `2. Interfaces`_ and [TEP114]_). Conversion results are returned as
-uninterpreted values and translating them to engineering units can only be done
-with the configuration knowledge of the respective platform, for example, the
-reference voltage or the resistance of a reference resistor in ratiometric
-measurements. Translating uninterpreted values to engineering units is
-performed by components located on top of the ADC hardware stack and out of the
-scope of this TEP.
+denominator of ADCs: they all produce conversion results. To facilitate sensor
+software development conversion results are returned by the ADC stack through
+the interfaces ``Read``, ``ReadStream`` and ``ReadNow`` (see `2. Interfaces`_
+and [TEP114]_). Conversion results are returned as uninterpreted values and
+translating them to engineering units can only be done with the configuration
+knowledge of the respective platform, for example, the reference voltage or the
+resistance of a reference resistor in ratiometric measurements. Translating
+uninterpreted values to engineering units may be performed by components
+located on top of the ADC stack and is out of the scope of this TEP.
The top layer of abstraction of an ADC - the Hardware Interface Layer (HIL) -
-thus provides the standard TinyOS interfaces ``Read``, ``ReadNow`` and
-``ReadStream`` and uses the ``AdcConfigure`` interface for hardware
-configuration (why it **uses** and does not **provide** ``AdcConfigure`` is
-explained below). Since the type and semantics of the parameters passed
-through these interfaces is dependent on the actual ADC implementation, it is
-only a "weak" HIL (see [TEP2]_).
+thus provides the interfaces ``Read``, ``ReadNow`` and ``ReadStream`` and uses
+the ``AdcConfigure`` interface for hardware configuration (why it **uses** and
+does not **provide** ``AdcConfigure`` is explained below). Since the type and
+semantics of the parameters passed through these interfaces is dependent on the
+actual ADC implementation, it is only a "weak" HIL (see [TEP2]_).
Following the principles of the HAA [TEP2]_ the Hardware Adaptation Layer (HAL,
which resides below the HIL) of an ADC should expose all the chip-specific
capabilities of the chip. For example, the ADC12 on the MSP430 MCU supports a
"Repeat-Sequence-of-Channels Mode" and therefore this function should be
-accessible on the HAL of the **MSP430 ADC12** hardware abstraction. Other ADCs
+accessible on the HAL of the MSP430 ADC12 hardware abstraction. Other ADCs
might not exhibit such functionality and might therefore - on the level of HAL
- provide only an interface to perform single conversions. Since all ADCs have
-the same HIL representation it may thus be necessary to perform some degree of
+the same HIL representation it may be necessary to perform some degree of
software emulation in the HIL implementation. For example, a ``ReadStream``
command can be emulated by multiple single conversion commands. Below the HAL
resides the Hardware Presentation Layer (HPL), a stateless component that
provides access to the hardware registers (see [TEP2]_). The general structure
-(without virtualization) of the ADC hardware stack is as follows ::
+(without virtualization) of the ADC stack is as follows ::
^ |
====================================================================
This TEP proposes the ``AdcConfigure`` interface for ADC hardware configuration
-and the ``Read``, ``ReadNow`` and ``ReadStream`` interfaces to acquire
-conversion results. A ``Read[Now|Stream]`` interface is always provided in
-conjunction with a ``AdcConfigure`` interface.
+and the ``Read``, ``ReadStream`` and ``ReadNow`` interfaces to acquire
+conversion results. The ``Read`` and ``ReadStream`` interfaces are documented
+in [TEP114]_ and the ``ReadNow`` interface is documented in this TEP. A
+``Read[Now|Stream]`` interface is always provided in conjunction with a
+``AdcConfigure`` interface.
Interface for configuring the ADC hardware
--------------------------------------------------------------------
async command config_type getConfiguration();
}
-This interface is used by the ADC implementation to retrieve the hardware
-configuration of an ADC client. ``config_type`` is a chip-specific data type
-(simple or structured) that contains all information necessary to configure the
-respective ADC hardware. For example, on the ADC12 of the MSP430 the
-``AdcConfigure`` interface will be instantiated with the ``const
-msp430adc12_channel_config_t*`` data type. A client MUST always return the same
-configuration through a ``AdcConfigure`` interface and, if configuration data
-is passed as a pointer, the HIL component (see `4. HIL requirements`_) MUST NOT
-reference it after the return of the ``getConfiguration()`` command. If a
-client wants to use the ADC with different configurations it must provide
-multiple instances of the ``AdcConfigure`` interface.
-
+This interface is used by the ADC stack to retrieve the hardware configuration
+of an ADC HIL client. ``config_type`` is a chip-specific data type (simple or
+structured) that contains all information necessary to configure the respective
+ADC hardware. For example, on the ADC12 of the MSP430 the ``AdcConfigure``
+interface will be instantiated with the ``const msp430adc12_channel_config_t*``
+data type. A client MUST always return the same configuration through a
+``AdcConfigure`` interface and, if configuration data is passed as a pointer,
+the HIL component (see `4. HIL requirements`_) MUST NOT reference it after the
+return of the ``getConfiguration()`` command. If a client wants to use the ADC
+with different configurations it must provide multiple instances of the
+``AdcConfigure`` interface.
+
+Note that the ``AdcConfigure`` interface is **provided** by an ADC HIL client
+and it is **used** by the ADC HIL implementation. Therefore an ADC HIL client
+cannot initiate the configuration of the ADC hardware itself. Instead it is the
+ADC HIL implementation that can "pull" the client's ADC configuration just
+before it initates a conversion based on the respective client's configuration.
+The rationale is that the ADC HIL implementation does not have to store an ADC
+configuration per client - instead the ADC client can, for example, store its
+configuration in program memory.
Interfaces for acquiring conversion results
--------------------------------------------------------------------
-This TEP proposes to adopt the following three generic, source-independent data
+This TEP proposes to adopt the following two source-independent data
collection interfaces from [TEP114]_ for the collection of ADC conversion
results on the level of HIL::
interface Read< size_type >
- interface ReadNow< size_type >
interface ReadStream< size_type >
+In addition it proposes the following data collection interface for low-latency
+reading of conversion results::
+
+ interface ReadNow< size_type >
+
Every data collection interface is associated with an ``AdcConfigure``
interface (how this association is realized is explained in Section `4. HIL
requirements`_). As the resolution of conversion results is chip-specific, the
``size_type`` parameter reflects an upper bound for the chip-specific
resolution of the conversion results - the actual resolution may be smaller
-(e.g. uint16_t for a 12-bit ADC). The above interfaces are specified in
-[TEP114]_, in the following their usage is explained with respect to ADCs.
+(e.g. uint16_t for a 12-bit ADC).
Read
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``Read`` interface can be used to sample an ADC channel and return a single
-conversion result as an uninterpreted value. The meaning of the ``Read``
-interface is explained in [TEP114]_.
+The ``Read`` interface can be used to sample an ADC channel once and return a
+single conversion result as an uninterpreted value. The ``Read`` interface is
+documented in [TEP114]_.
-ReadNow
+ReadStream
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``ReadNow`` interface is similar to the ``Read`` interface. The difference
-is that if a call to ``ReadNow.read()`` succeeds, the ADC starts to sample the
-channel immediately (precisely: when ``SUCCESS`` is returned the hardware has
-started the sampling process). Due to its timing constraints the ``ReadNow``
-interface is always provided in conjunction with an instance of the
-``Resource`` interface (a client must reserve the ADC before the client may
-call ``ReadNow.read()``). Please refer to [TEP108]_ on how the ``Resource``
-interface should be used by a client component.
+The ``ReadStream`` interface can be used to sample an ADC channel multiple
+times with a specified sampling period. The ``ReadStream`` interface is
+documented in [TEP114]_ .
-ReadStream
+ReadNow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``ReadStream`` interface can be used to sample an ADC channel multiple times
-with a specified sampling period. The meaning of the ``ReadStream`` interface
-is explained in [TEP114]_ .
+The ``ReadNow`` interface is intended for split-phase low-latency
+reading of small values::
+
+ interface ReadNow<val_t>
+ {
+ async command error_t read();
+ async event void readDone( error_t result, val_t val );
+ }
+
+This interface is similar to the ``Read`` interface, but works in asynchronous
+context. A successful call to ``ReadNow.read()`` means that the ADC hardware
+has started the sampling process and that ``ReadNow.readDone()`` will be
+signalled once it has finished (note that the asynchronous
+``ReadNow.readDone()`` might be signalled even before the call to
+``ReadNow.read()`` has returned). Due to its timing constraints the
+``ReadNow`` interface is always provided in conjunction with an instance of the
+``Resource`` interface and a client must reserve the ADC through the
+``Resource`` interface before the client may call ``ReadNow.read()``. Please
+refer to [TEP108]_ on how the ``Resource`` interface should be used by a client
+component.
3. HAL guidelines
As explained in `1. Introduction`_ the HAL exposes the full capabilities of the
ADC hardware. Therefore only chip- and platform-dependent clients can wire to
the HAL. Although the HAL is chip-specific, both, in terms of implementation
-and representation, its design should follow the guidelines described below to
-facilitate the mapping to the HIL representation. Appendix B shows the
-signature of the HAL for the MSP430.
+and representation, its design should follow the guidelines described in this
+section to facilitate the mapping to the HIL representation. Appendix B shows
+the signature of the HAL for the MSP430.
Resource reservation
--------------------------------------------------------------------
immediately (a successful ``Read.read()`` command may not have this
implication, see [TEP114]_ and `2. Interfaces`_). A client MUST reserve the ADC
through the ``Resource`` interface before the client may call
-``ReadNow.read()`` and it must release the ADC through the ``Resource``
-interface when it no longer needs to access it (for more details on the
-``Resource`` interface please refer to [TEP108]_). The associated ADC channel
-(port) and further configuration details are returned by the
+``ReadNow.read()`` and it MUST release the ADC through the ``Resource``
+interface when it no longer needs to access it (for more details on how to use
+the ``Resource`` interface please refer to [TEP108]_). The associated ADC
+channel (port) and further configuration details are returned by the
``AdcConfigure.getConfiguration()`` command. It is the task of the client to
wire this interface to a component that provides the client's ADC
configuration. The HIL implementation will use the ``AdcConfigure`` interface
6. Implementation
====================================================================
+TestAdc application
+--------------------------------------------------------------------
+
+An ADC HIL test application can be found in ``tinyos-2.x/apps/tests/TestAdc``.
+Note that this application instantiates generic DemoSensorC, DemoSensorStreamC
+and DemoSensorNowC components (see [TEP114]_) and assumes that these components
+are actually wired to an ADC HIL. Please refer to
+``tinyos-2.x/apps/tests/TestAdc/README.txt`` for more information.
+
+
+HAA on the MSP430 and Atmega 128
+--------------------------------------------------------------------
+
The implementation of the ADC12 stack on the MSP430 can be found in
``tinyos-2.x/tos/chips/msp430/adc12``:
* ``HplAtm128AdcC.nc`` is the HPL implementation
* ``Atm128AdcP.nc`` is the HAL implementation
- * ``WireAdcP.nc`` and the library components for arbitrating 'Read',
- 'ReadNow' and 'ReadStream', ``ArbitratedReadC`` and
+ * ``AdcP.nc``, ``WireAdcP.nc`` and the library components for arbitrating
+ 'Read', 'ReadNow' and 'ReadStream', ``ArbitratedReadC`` and
``ArbitratedReadStreamC`` (in ``tinyos-2.x/tos/system``), realize
- the HAL
+ the HIL
* ``AdcReadClientC.nc``, ``AdcReadNowClientC.nc`` and
``AdcReadStreamClientC.nc`` provide virtualized access to the HIL
async event uint16_t* multipleDataReady(uint16_t buffer[], uint16_t numSamples);
}
- typedef struct {
+ typedef struct
+ {
unsigned int inch: 4; // input channel
unsigned int sref: 3; // reference voltage
unsigned int ref2_5v: 1; // reference voltage level