[Tinyos-8051wg] Re: [Tinyos-2.0wg] Aligning TEP 101 (ADC) with TEP
108 (Resource Arbitration) and 109 (Sensorboards)
David Gay
dgay42 at gmail.com
Mon May 9 15:10:00 PDT 2005
[Long message follows...]
On 5/4/05, Jan Hauer <hauer at tkn.tu-berlin.de> wrote:
> 1. HPL and HAL
> [...]
> To align the HAL with TEP108 I would suggest to instead of platform
> dependent reserve commands provide the Resource interface introduced
> in TEP108. A successful call to an HAL's Resource.request() would
> reserve the ADC for the caller until he calls Resource.release(). For
> time critical sampling an additional platform dependent command e.g.
> MSP430ADC12Multiple.prepare(uint16_t *buf, uint16_t length, uint16_t
> jiffies) is provided that sets up ADC registers so that a subsequent
> MSP430ADC12Multiple.getData() will start the sampling process
> immediately with these settings.
Sounds good to me.
> 2. HIL
>
> As far as I understand our last conclusion was that an HIL will
> provide one lean ADC interface with only a getData() command and the
> Resource interface (see TEP108). The idea was to have a HIL component
> (wrapper) per channel (sensor). On top of multiple HIL components a
> service like round robin could be built.
>
> To align HIL with TEP109 I would like to provide the "Sensor" and
> "QSensor" as well as the "CalibrationData" interface by the HIL
> (wrapper) instead of providing a separate "ADC", "ADCSingle" or
> "ADCMultiple" interface. The Sensor interface already has the same
> commands as the suggested lean "ADCSingle" or "ADC" interface.
> "QSensor" is for async requests and "CalibrationData" to return
> calibration data, both should be provided optionally.
Actually QSensor isn't in tep 109, but after some discussion with Phil L.,
we came up with some thoughts about all this:
- first, both the names "Sensor" and "ADCxxx" are too specific: these
interfaces are really about data acquisition, and are offered by several
kinds of components: A/D converters, various sensors, etc.
- We do think there is a place for an "A/D converter" abstraction distinct
from the general concept of a sensor board (though it may well be just a
special case).
- There are some hardware-independent interfaces to sensors -- we propose
something along the lines of the following (note that we've removed
Sensor and ADC from the names, but I'm not 100% happy with all the new
names):
1) Simple, non-async data acquisition. For low-rate, non-time-sensitive
acquisition.
interface AcquireData { // similar to previous Sensor proposal
/** Start data acquisition
* @return SUCCESS if request accepted, EBUSY if it is refused
* 'dataReady' or 'error' will be signaled if SUCCESS is returned
*/
command error_t getData();
/** Data has been acquired.
* @param data Acquired value
* Values are "left-justified" within each 16-bit integer, i.e., if
* the data is acquired with n bits of precision, each value is
* shifted left by 16-n bits.
*/
event void dataReady(uint16_t data);
/** Signal that the data acquisition failed
* @param info error information
*/
event void error(uint16_t info);
}
2) Async data acquisition. Low-overhead, low-latency (note that
the error path is not async).
interface AcquireDataNow {
/** Start data acquisition. The data acquisition SHOULD start
* immediately (within hardware constraints).
* @return SUCCESS if request accepted, EBUSY if it is refused
* 'dataReady' or 'error' will be signaled if SUCCESS is returned.
*/
async command error_t getData();
/** Data has been acquired. This SHOULD be signaled as soon as
* possible after the hardware has acquired the value.
* @param data Acquired value
* Values are "left-justified" within each 16-bit integer, i.e., if
* the data is acquired with n bits of precision, each value is
* shifted left by 16-n bits.
*/
async event void dataReady(uint16_t data);
/** Signal that the data acquisition failed
* @param info error information
*/
event void error(uint16_t info);
}
3) Repeated data acquisition, at a specified rate, to a RAM buffer.
The getRate command allows you to enforce whatever error logic you
want (e.g., sampling rate must be within 10%).
interface AcquireDataBuffered {
/** Prepare to acquire 'count' samples into 'buffer', with
* 'rate' microseconds between each sample.
* There must be a call to 'prepare' before every call to 'getData'
* @param buffer Buffer in which to store samples
* @param count Number of samples to acquire
* @param rate Interval in microseconds between each sample. The
* actual rate may be (very) different from this value, use
* the getRate command to find out what value will be used.
* @return SUCCESS if request accepted, EBUSY if it is refused,
* EINVAL if the parameters are invalid.
* 'dataReady' or 'error' will be signaled if SUCCESS is returned
command error_t prepare(uint16_t *buffer, uint16_t count,
uint32_t rate);
/** Return the sampling rate for the next acquisition
* @return Sampling interval in microseconds that will be used by the
* next call to getData.
*/
command uint32_t getRate();
/** Request data. A call to 'getData' must be preceded by a call to
* 'prepare' to set up the data acquisition parameters.
* @return SUCCESS if request accepted, EBUSY if it is refused
* 'dataReady' or 'error' will be signaled if SUCCESS is returned.
* The data acquisition SHOULD start immediately (within
* hardware constraints).
*/
async command result_t getData();
/** Data has been acquired.
* @param buffer Buffer containing the data.
* Samples are "left-justified" within each 16-bit integer, i.e., if
* the data is acquired with n bits of precision, each value is
* shifted left by 16-n bits.
* @param count Number of samples acquired.
*/
event void dataReady(uint16_t *buffer, uint16_t count);
/** Signal that the data acquisition failed
* @param info error information
*/
event void error(uint16_t info);
}
- tep109 would be rephrased to say that all sensors provide AcquireData
interfaces, and that those sensors needing high-frequency sampling will
provide AcquireDataNow and/or AcquireDataBuffered.
- It makes sense to me (i.e., I'm quite possibly wrong) to present the
onboard A/D converter of the msps and atmegas as a component providing
parameterised AcquireData, AcquireDataNow and AcquireDataBuffered (maybe
this last one optional?) interfaces, along with a tep107 style Resource
interface (sensor board implementations using the onboard A/D will
want this anyway).
- This brings up a hole in tep109 (sensor boards): it doesn't talk about
resource reservation (oops!). Thoughts? (I'm tempted to say that sensors
are generally not shared, and we could annotate their interfaces with
@atmostonce() to enforce that...)
Summary: I think this is similar to your thoughts, with the addition of the
AcquireDataBuffered interface.
> 3. "Services"
>
> Services are built on top of the wrappers that represent a Sensor. A
> service component wires to a single or multiple wrappers and extends
> or combines the functionality of these wrappers. Examples are a round
> robin service or a service returning multiple samples taken at precise
> points in time. Services are (mostly) platform independent. Example
> configuration:
>
> configuration ADCRoundRobinServiceC
> {
> provides interface StdControl;
> provides interface Sensor as RoundRobinSensor[uint8_t id];
> uses interface Sensor as SimpleSensor[uint8_t id];
> }
> implementation
> {
> components ADCRoundRobinServiceM;
>
> StdControl = ADCRoundRobinServiceM;
> RoundRobinSensor = ADCRoundRobinServiceM;
> SimpleSensor = ADCRoundRobinServiceM;
> }
>
> and a client configuration:
>
> configuration RoundRobinClientC
> {
> }
> implementation
> {
> enum {
> TEMP_SENSOR = unique("ADCRoundRobinService")
> };
> components ADCRoundRobinServiceC, RoundRobinClientM,
> InternalTempC, Main;
>
> Main.StdControl -> ADCRoundRobinServiceC;
> Main.StdControl -> RoundRobinClientM;
> RoundRobinClientM.TempSensor -> ADCRoundRobinServiceC.RoundRobinSensor[TEMP_SENSOR];
>
> ADCRoundRobinServiceC.SimpleSensor[TEMP_SENSOR] -> InternalTempC;
> }
I like this. We can save clients a bit of typing with:
generic configuration ADCRRClient() {
provides interface Sensor as In;
uses interface Sensor as Out;
} implementation {
enum {
SENSOR = unique("ADCRoundRobinService")
};
components ADCRoundRobinServiceC;
In = ADCRoundRobinServiceC.RoundRobinSensor[SENSOR];
Out = ADCRoundRobinServiceC.SimpleSensor[SENSOR];
}
making the client shorter:
configuration RoundRobinClientC {}
implementation {
components new ADCRRClient() as MyClient, RoundRobinClientM,
InternalTempC, Main;
Main.StdControl -> RoundRobinClientM;
RoundRobinClientM.TempSensor -> MyClient;
MyClient -> InternalTempC;
}
(I'm assuming the Main.StdControl -> ADCRoundRobinServiceC line is moved into
ADCRoundRobinServiceC)
This would argue for mentioning the ADCRoundRobinServiceC in the tep (as
most clients will access the A/D chip that way?).
David
_______________________________________________
Tinyos-2.0wg mailing list
Tinyos-2.0wg at Mail.Millennium.Berkeley.EDU
http://Mail.Millennium.Berkeley.EDU/mailman/listinfo/tinyos-2.0wg
More information about the Tinyos-8051wg
mailing list