xref: /aosp_15_r20/external/pigweed/seed/0119.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _seed-0119:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker=============
4*61c4878aSAndroid Build Coastguard Worker0119: Sensors
5*61c4878aSAndroid Build Coastguard Worker=============
6*61c4878aSAndroid Build Coastguard Worker.. seed::
7*61c4878aSAndroid Build Coastguard Worker   :number: 0119
8*61c4878aSAndroid Build Coastguard Worker   :name: Sensors
9*61c4878aSAndroid Build Coastguard Worker   :status: Accepted
10*61c4878aSAndroid Build Coastguard Worker   :proposal_date: 2023-10-18
11*61c4878aSAndroid Build Coastguard Worker   :cl: 175479
12*61c4878aSAndroid Build Coastguard Worker   :authors: Yuval Peress
13*61c4878aSAndroid Build Coastguard Worker   :facilitator: Taylor Cramer
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker-------
16*61c4878aSAndroid Build Coastguard WorkerSummary
17*61c4878aSAndroid Build Coastguard Worker-------
18*61c4878aSAndroid Build Coastguard WorkerThis SEED proposes that Pigweed provide a full end-to-end sensor solution,
19*61c4878aSAndroid Build Coastguard Workerincluding a shared set of abstractions and communication primitives. This
20*61c4878aSAndroid Build Coastguard Workerwill allow Pigweed users to build reusable drivers and portable applications.
21*61c4878aSAndroid Build Coastguard Worker
22*61c4878aSAndroid Build Coastguard Worker----------
23*61c4878aSAndroid Build Coastguard WorkerMotivation
24*61c4878aSAndroid Build Coastguard Worker----------
25*61c4878aSAndroid Build Coastguard WorkerSensors are part of nearly every embedded device. However, sensor drivers and
26*61c4878aSAndroid Build Coastguard Workerapplication logic are often bespoke. Current clients of Pigweed must write
27*61c4878aSAndroid Build Coastguard Workersensor drivers using various bus APIs. This results in drivers and applications
28*61c4878aSAndroid Build Coastguard Workerthat are deeply integrated and not reusable. When drivers are custom-built for
29*61c4878aSAndroid Build Coastguard Workerparticular applications, they frequently omit significant functionality needed
30*61c4878aSAndroid Build Coastguard Workerby other potential users.
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard WorkerThis solution does not scale.
33*61c4878aSAndroid Build Coastguard Worker
34*61c4878aSAndroid Build Coastguard WorkerIntroducing a standard sensor driver interface will allow Pigweed users to
35*61c4878aSAndroid Build Coastguard Workerbuild drivers that can be reused across applications, and applications that
36*61c4878aSAndroid Build Coastguard Workerare compatible with multiple different drivers.
37*61c4878aSAndroid Build Coastguard Worker
38*61c4878aSAndroid Build Coastguard WorkerA second layer of a sensor framework will then be introduced. This secondary
39*61c4878aSAndroid Build Coastguard Workerlayer will provide functionality required for more advanced applications and
40*61c4878aSAndroid Build Coastguard Workerwill include support for virtual sensors and multi-client connections per
41*61c4878aSAndroid Build Coastguard Workersensor. It will also be compatible with Android's `CHRE`_.
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker---------
44*61c4878aSAndroid Build Coastguard WorkerPrior Art
45*61c4878aSAndroid Build Coastguard Worker---------
46*61c4878aSAndroid Build Coastguard WorkerSensor APIs are available today on many platforms:
47*61c4878aSAndroid Build Coastguard Worker
48*61c4878aSAndroid Build Coastguard Worker- `Android`_
49*61c4878aSAndroid Build Coastguard Worker- `Apple iOS and macOS`_
50*61c4878aSAndroid Build Coastguard Worker- `Linux`_
51*61c4878aSAndroid Build Coastguard Worker- `Windows`_
52*61c4878aSAndroid Build Coastguard Worker- `Zephyr`_
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard WorkerWhere possible, we strive to make it possible for Pigweed's Sensor API to
55*61c4878aSAndroid Build Coastguard Workerdelegate to these platform-level APIs without significant loss of
56*61c4878aSAndroid Build Coastguard Workerfunctionality.
57*61c4878aSAndroid Build Coastguard Worker
58*61c4878aSAndroid Build Coastguard WorkerHowever, where performance, code size, API comprehensibility, or reusability
59*61c4878aSAndroid Build Coastguard Workerare of particular concern, priority is given to ensuring that Pigweed-native
60*61c4878aSAndroid Build Coastguard Workersensor drivers and APIs meet the needs of Pigweed applications.
61*61c4878aSAndroid Build Coastguard Worker
62*61c4878aSAndroid Build Coastguard Worker-------------
63*61c4878aSAndroid Build Coastguard WorkerSystem Design
64*61c4878aSAndroid Build Coastguard Worker-------------
65*61c4878aSAndroid Build Coastguard WorkerAt the high level, the ``pw_sensor`` module will introduce the following
66*61c4878aSAndroid Build Coastguard Workerconcepts:
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker- ``Sensor``: a class which will enable a single user to **configure**,
69*61c4878aSAndroid Build Coastguard Worker  **read**, or **stream** data. The implementation can vary. Some
70*61c4878aSAndroid Build Coastguard Worker  implementations may call down to an already implemented sensor driver of the
71*61c4878aSAndroid Build Coastguard Worker  underlying RTOS, others may be software sensors which themselves will open
72*61c4878aSAndroid Build Coastguard Worker  ``Connection``\s to other sensors, or in other cases, the ``Sensor``
73*61c4878aSAndroid Build Coastguard Worker  implementation will actually perform remote calls to a sensor on another SoC
74*61c4878aSAndroid Build Coastguard Worker  or board.
75*61c4878aSAndroid Build Coastguard Worker- ``Connection``: a class which will enable us to abstract away the single
76*61c4878aSAndroid Build Coastguard Worker  client concept of the ``Sensor``. A ``Connection`` is owned by some logic
77*61c4878aSAndroid Build Coastguard Worker  and uses the same configuration as the ``Sensor``. The only difference is
78*61c4878aSAndroid Build Coastguard Worker  that the Pigweed provided sensor framework will then mux all the
79*61c4878aSAndroid Build Coastguard Worker  configurations targeting the same sensor into a single configuration. This
80*61c4878aSAndroid Build Coastguard Worker  single configuration will be used for the actual ``Sensor`` object (see
81*61c4878aSAndroid Build Coastguard Worker  `pw sensor configuration mux`_ as an example). When data becomes
82*61c4878aSAndroid Build Coastguard Worker  available, the sensor framework will demux the data and provide it to the
83*61c4878aSAndroid Build Coastguard Worker  various clients based on the live ``Connection``\s.
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard Worker.. image:: 0119/high-level-view.svg
86*61c4878aSAndroid Build Coastguard Worker
87*61c4878aSAndroid Build Coastguard WorkerActually reading the data is a 2 step process. The first is getting the data
88*61c4878aSAndroid Build Coastguard Workerfrom the ``Sensor`` object. The second step is decoding it into something
89*61c4878aSAndroid Build Coastguard Workerthat's usable. Data from the first step is generally still in register format
90*61c4878aSAndroid Build Coastguard Workerand includes some headers from the driver which will allow the ``Decoder`` to
91*61c4878aSAndroid Build Coastguard Workerconvert the values to the appropriate representation (most likely ``float``).
92*61c4878aSAndroid Build Coastguard Worker
93*61c4878aSAndroid Build Coastguard Worker.. image:: 0119/data-pipeline.svg
94*61c4878aSAndroid Build Coastguard Worker
95*61c4878aSAndroid Build Coastguard Worker-----------------
96*61c4878aSAndroid Build Coastguard WorkerThe Sensor Driver
97*61c4878aSAndroid Build Coastguard Worker-----------------
98*61c4878aSAndroid Build Coastguard WorkerThe sensor driver provides the 3 functionalities listed above (configuring,
99*61c4878aSAndroid Build Coastguard Workerreading, and streaming).
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard WorkerEach sensor may assume it has exactly 1 caller. It is up to the application to
102*61c4878aSAndroid Build Coastguard Workerleverage the right locking and arbitration mechanisms if a sensor is to be
103*61c4878aSAndroid Build Coastguard Workershared between parts of the code. Doing this keeps the driver implementor's job
104*61c4878aSAndroid Build Coastguard Workermuch simpler and allows them to focus on performance, testing, and simplicity.
105*61c4878aSAndroid Build Coastguard WorkerIn order to provide consumers of sensor data with more advanced features, a
106*61c4878aSAndroid Build Coastguard Workersensor framework will also be provided and discussed in the following section
107*61c4878aSAndroid Build Coastguard Worker:ref:`the sensor framework`.
108*61c4878aSAndroid Build Coastguard Worker
109*61c4878aSAndroid Build Coastguard WorkerAsynchronous APIs
110*61c4878aSAndroid Build Coastguard Worker-----------------
111*61c4878aSAndroid Build Coastguard WorkerBus transactions are asynchronous by nature and often can be set up to use an
112*61c4878aSAndroid Build Coastguard Workerinterrupt to signal completion. By making the assumption that all reading,
113*61c4878aSAndroid Build Coastguard Workerwriting, and configuring of the sensor are asynchronous, it's possible to
114*61c4878aSAndroid Build Coastguard Workerprovide an API which is callable even from an interrupt context. The final
115*61c4878aSAndroid Build Coastguard Workerresult of any operation of the API will use the ``pw_async`` logic. Doing so
116*61c4878aSAndroid Build Coastguard Workerwill allow the clients to avoid concerns about the context in which callbacks
117*61c4878aSAndroid Build Coastguard Workerare called and having to schedule work on the right thread. Instead, they're
118*61c4878aSAndroid Build Coastguard Workerable to rely on the async dispatcher.
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard WorkerConfiguring
121*61c4878aSAndroid Build Coastguard Worker-----------
122*61c4878aSAndroid Build Coastguard WorkerSensors generally provide some variable configurations. In some cases, these
123*61c4878aSAndroid Build Coastguard Workerconfigurations are global (i.e. they apply to the device). An example of such
124*61c4878aSAndroid Build Coastguard Workerglobal configuration might be a FIFO watermark (via a batching duration). In
125*61c4878aSAndroid Build Coastguard Workerother cases, the configuration might apply to specific sub-sensors /
126*61c4878aSAndroid Build Coastguard Workermeasurements. An example of a specific configuration attribute can be the sample
127*61c4878aSAndroid Build Coastguard Workerrate which on an Inertial Measurement Unit (IMU) might be an acceleration and
128*61c4878aSAndroid Build Coastguard Workerrotational velocity. We can describe each configuration with the following:
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker- Measurement type: such as acceleration or rotational velocity
131*61c4878aSAndroid Build Coastguard Worker- Measurement index: the index of the measurement. This is almost always 0, but
132*61c4878aSAndroid Build Coastguard Worker  some sensors do provide multiple samples of the same measurement type (range
133*61c4878aSAndroid Build Coastguard Worker  finders). In which case it's possible that we would need to configure
134*61c4878aSAndroid Build Coastguard Worker  separate instances of the sensor.
135*61c4878aSAndroid Build Coastguard Worker- Attribute: such as the sample rate, scale, offset, or batch duration
136*61c4878aSAndroid Build Coastguard Worker- Value: the value associated with the configuration (might be a ``bool``,
137*61c4878aSAndroid Build Coastguard Worker  ``float``, ``uint64_t``, or something else entirely).
138*61c4878aSAndroid Build Coastguard Worker
139*61c4878aSAndroid Build Coastguard WorkerHere's an example:
140*61c4878aSAndroid Build Coastguard Worker
141*61c4878aSAndroid Build Coastguard Worker+---------------+----------------+--------+
142*61c4878aSAndroid Build Coastguard Worker| Measurement   | Attribute      | Value  |
143*61c4878aSAndroid Build Coastguard Worker+-------+-------+----------------+--------+
144*61c4878aSAndroid Build Coastguard Worker| Type  | Index |                |        |
145*61c4878aSAndroid Build Coastguard Worker+=======+=======+================+========+
146*61c4878aSAndroid Build Coastguard Worker| Accel | 0     | Sample Rate    | 1000Hz |
147*61c4878aSAndroid Build Coastguard Worker+-------+-------+----------------+--------+
148*61c4878aSAndroid Build Coastguard Worker| All   | 0     | Batch duration | 200ms  |
149*61c4878aSAndroid Build Coastguard Worker+-------+-------+----------------+--------+
150*61c4878aSAndroid Build Coastguard Worker
151*61c4878aSAndroid Build Coastguard WorkerReading
152*61c4878aSAndroid Build Coastguard Worker-------
153*61c4878aSAndroid Build Coastguard WorkerReading a sensor involves initiating some I/O which will fetch an unknown amount
154*61c4878aSAndroid Build Coastguard Workerof data. As such, the operation will require some ``Allocator`` to be used along
155*61c4878aSAndroid Build Coastguard Workerwith a possible *Measurement Type* filter to limit the amount of data being
156*61c4878aSAndroid Build Coastguard Workerretrieved and stored. When complete, the result will be provided in a
157*61c4878aSAndroid Build Coastguard Worker``pw::ConstByteSpan`` which was allocated from the ``Allocator``. This byte span
158*61c4878aSAndroid Build Coastguard Workercan be cached or possibly sent over a wire for decoding.
159*61c4878aSAndroid Build Coastguard Worker
160*61c4878aSAndroid Build Coastguard WorkerStreaming
161*61c4878aSAndroid Build Coastguard Worker---------
162*61c4878aSAndroid Build Coastguard WorkerStreaming data from a sensor is effectively the same as reading the sensor with
163*61c4878aSAndroid Build Coastguard Workerminor considerations. Instead of filtering "what" data we want, we're able to
164*61c4878aSAndroid Build Coastguard Workerspecify "when" we want the data. This happens in the form of one or more
165*61c4878aSAndroid Build Coastguard Workerinterrupts. There will be some additional control over the data returned from
166*61c4878aSAndroid Build Coastguard Workerthe stream; it will come in the form of an operation. 3 operations will be
167*61c4878aSAndroid Build Coastguard Workersupported for streams:
168*61c4878aSAndroid Build Coastguard Worker
169*61c4878aSAndroid Build Coastguard Worker- ``Include``: which tells the driver to include any/all associated data with
170*61c4878aSAndroid Build Coastguard Worker  the trigger. As an example, a batching trigger will include all the data from
171*61c4878aSAndroid Build Coastguard Worker  the FIFO so it can be decoded later.
172*61c4878aSAndroid Build Coastguard Worker- ``Drop``: which tells the driver to get rid of the associated data and just
173*61c4878aSAndroid Build Coastguard Worker  report that the event happened. This might be done on a FIFO full event to
174*61c4878aSAndroid Build Coastguard Worker  reset the state and start over.
175*61c4878aSAndroid Build Coastguard Worker- ``Noop``: which tells the driver to just report the event and do nothing with
176*61c4878aSAndroid Build Coastguard Worker  the associated data (maybe the developer wants to read it separately).
177*61c4878aSAndroid Build Coastguard Worker
178*61c4878aSAndroid Build Coastguard Worker.. note::
179*61c4878aSAndroid Build Coastguard Worker   We do not allow specifying a measurement filter like we do in the reading API
180*61c4878aSAndroid Build Coastguard Worker   because it would drastically increase the cost of the driver developer.
181*61c4878aSAndroid Build Coastguard Worker   Imagine a trigger for the stream on an IMU using the batch duration where we
182*61c4878aSAndroid Build Coastguard Worker   want to only get the acceleration values from the FIFO. This scenario doesn't
183*61c4878aSAndroid Build Coastguard Worker   make much sense to support since the caller should simply turn off the
184*61c4878aSAndroid Build Coastguard Worker   gyroscope in the FIFO via the configuration. Having the gyroscope
185*61c4878aSAndroid Build Coastguard Worker   measurements in the FIFO usually means they will simply be discarded when
186*61c4878aSAndroid Build Coastguard Worker   read. This puts a very heavy burden on the driver author to place a filter in
187*61c4878aSAndroid Build Coastguard Worker   the reader logic as well as in the decoder.
188*61c4878aSAndroid Build Coastguard Worker
189*61c4878aSAndroid Build Coastguard WorkerDecoder
190*61c4878aSAndroid Build Coastguard Worker-------
191*61c4878aSAndroid Build Coastguard WorkerThe decoder provides functionality to peek into the raw data returned from the
192*61c4878aSAndroid Build Coastguard Worker``Sensor``. It should implement functionality such as:
193*61c4878aSAndroid Build Coastguard Worker
194*61c4878aSAndroid Build Coastguard Worker- Checking if a measurement type is present in the buffer. If so, how many
195*61c4878aSAndroid Build Coastguard Worker  :ref:`pw sensor define frame` and indices?
196*61c4878aSAndroid Build Coastguard Worker- Checking how much memory will be required to decode the frame header (which
197*61c4878aSAndroid Build Coastguard Worker  includes information like the base timestamp, frame count, etc) and each frame
198*61c4878aSAndroid Build Coastguard Worker  of data.
199*61c4878aSAndroid Build Coastguard Worker- Decoding frames of data. There will be a hard mapping of a measurement type to
200*61c4878aSAndroid Build Coastguard Worker  data representation. Example: a measurement type of *Acceleration* will always
201*61c4878aSAndroid Build Coastguard Worker  decode to a ``struct acceleration_data``.
202*61c4878aSAndroid Build Coastguard Worker
203*61c4878aSAndroid Build Coastguard Worker.. _the sensor framework:
204*61c4878aSAndroid Build Coastguard Worker
205*61c4878aSAndroid Build Coastguard Worker--------------------
206*61c4878aSAndroid Build Coastguard WorkerThe Sensor Framework
207*61c4878aSAndroid Build Coastguard Worker--------------------
208*61c4878aSAndroid Build Coastguard WorkerThe sensor framework is an abstraction above the ``Sensor`` class which provides
209*61c4878aSAndroid Build Coastguard Workera superset of features but on a ``Connection`` object. The framework will be a
210*61c4878aSAndroid Build Coastguard Workersingleton object and will provide consumers the following:
211*61c4878aSAndroid Build Coastguard Worker
212*61c4878aSAndroid Build Coastguard Worker- List all sensors represented as read-only ``SensorInfo`` objects.
213*61c4878aSAndroid Build Coastguard Worker- Ability to open/close connections. When a connection is open, a ``Connection``
214*61c4878aSAndroid Build Coastguard Worker  object is returned. The connection can be closed by either calling
215*61c4878aSAndroid Build Coastguard Worker  ``Connection::Close()`` or simply calling the ``Connection``\s deconstructor.
216*61c4878aSAndroid Build Coastguard Worker
217*61c4878aSAndroid Build Coastguard WorkerOnce the sensor framework is linked into the application, ``Sensor`` objects
218*61c4878aSAndroid Build Coastguard Workershould not be manipulated directly. Instead, the only direct client of the
219*61c4878aSAndroid Build Coastguard Worker``Sensor``\s is the framework. Users can request a list of all the sensors
220*61c4878aSAndroid Build Coastguard Worker(``SensorInfo`` objects). Once the client finds the sensor they want to listen
221*61c4878aSAndroid Build Coastguard Workerto, they can request a ``Connection`` to be opened to that sensor. A
222*61c4878aSAndroid Build Coastguard Worker``Connection`` provides very similar functionality to that of the ``Sensor`` but
223*61c4878aSAndroid Build Coastguard Workeris owned by the framework. As an example, a configuration change made on the
224*61c4878aSAndroid Build Coastguard Worker``Connection`` will trigger the framework to mux together all the configurations
225*61c4878aSAndroid Build Coastguard Workerof all the connections that point to the same ``Sensor``. Once complete, a
226*61c4878aSAndroid Build Coastguard Workersingle configuration will be selected and set on the ``Sensor``. Similarly, when
227*61c4878aSAndroid Build Coastguard Workerthe ``Sensor`` produces data, the data will be demuxed and sent to all the open
228*61c4878aSAndroid Build Coastguard Worker``Connection``\s.
229*61c4878aSAndroid Build Coastguard Worker
230*61c4878aSAndroid Build Coastguard WorkerVirtual Sensors
231*61c4878aSAndroid Build Coastguard Worker---------------
232*61c4878aSAndroid Build Coastguard WorkerThis framework provides an interesting way to build portable virtual (soft)
233*61c4878aSAndroid Build Coastguard Workersensors. If the library containing the virtual sensors depends on the framework,
234*61c4878aSAndroid Build Coastguard Workerit's possible for the virtual sensors to own connections, configure the sources,
235*61c4878aSAndroid Build Coastguard Workerand perform all the necessary signal processing without compromising other
236*61c4878aSAndroid Build Coastguard Workerunknown clients of the same sensor (since the framework handles all the
237*61c4878aSAndroid Build Coastguard Workerconfiguration arbitration).
238*61c4878aSAndroid Build Coastguard Worker
239*61c4878aSAndroid Build Coastguard WorkerAs an example, a hinge angle sensor could accept 2 ``Connection`` objects to
240*61c4878aSAndroid Build Coastguard Workeraccelerometers in its constructor. When the hinge angle sensor is configured
241*61c4878aSAndroid Build Coastguard Worker(such as sample rate) it would pass the configuration down to the connections
242*61c4878aSAndroid Build Coastguard Workerand request the same sample rate from the 2 accelerometers.
243*61c4878aSAndroid Build Coastguard Worker
244*61c4878aSAndroid Build Coastguard Worker--------
245*61c4878aSAndroid Build Coastguard WorkerGlossary
246*61c4878aSAndroid Build Coastguard Worker--------
247*61c4878aSAndroid Build Coastguard Worker
248*61c4878aSAndroid Build Coastguard Worker.. _pw sensor define frame:
249*61c4878aSAndroid Build Coastguard Worker
250*61c4878aSAndroid Build Coastguard WorkerFrame
251*61c4878aSAndroid Build Coastguard Worker   A single time slice. Usually this is used to reference a single sample of
252*61c4878aSAndroid Build Coastguard Worker   multiple sensor measurement types such as an IMU measuring both acceleration
253*61c4878aSAndroid Build Coastguard Worker   and rotational velocity at the same time.
254*61c4878aSAndroid Build Coastguard Worker
255*61c4878aSAndroid Build Coastguard Worker--------
256*61c4878aSAndroid Build Coastguard WorkerExamples
257*61c4878aSAndroid Build Coastguard Worker--------
258*61c4878aSAndroid Build Coastguard Worker
259*61c4878aSAndroid Build Coastguard Worker.. _pw sensor configuration mux:
260*61c4878aSAndroid Build Coastguard Worker
261*61c4878aSAndroid Build Coastguard WorkerPigweed will provide some default mechanism for muxing together
262*61c4878aSAndroid Build Coastguard Worker``Configuration`` objects. Like many other modules and backends in Pigweed, this
263*61c4878aSAndroid Build Coastguard Workermechanism will be overridable by the application. Below is an example of what it
264*61c4878aSAndroid Build Coastguard Workermight look like:
265*61c4878aSAndroid Build Coastguard Worker
266*61c4878aSAndroid Build Coastguard Worker- Assume a client requests samples at 1kHz
267*61c4878aSAndroid Build Coastguard Worker- Assume a second client requests samples at 1.1kHz
268*61c4878aSAndroid Build Coastguard Worker- The resulting sample rate is 1.1kHz, but it's much more likely that the sensor
269*61c4878aSAndroid Build Coastguard Worker  doesn't support 1.1kHz and will instead be giving both clients 2kHz of
270*61c4878aSAndroid Build Coastguard Worker  samples. It will then be up to both clients to decimate the data correctly.
271*61c4878aSAndroid Build Coastguard Worker
272*61c4878aSAndroid Build Coastguard Worker.. note::
273*61c4878aSAndroid Build Coastguard Worker   Decimating 2kHz down to 1.1kHz isn't as simple as just throwing away 9
274*61c4878aSAndroid Build Coastguard Worker   samples for every 20. What the client is likely to do is use a weighted
275*61c4878aSAndroid Build Coastguard Worker   average in order to simulate the 1.1kHz. It's likely that Pigweed should at
276*61c4878aSAndroid Build Coastguard Worker   some point provide a decimation library with a few common strategies which
277*61c4878aSAndroid Build Coastguard Worker   would help developers with the task.
278*61c4878aSAndroid Build Coastguard Worker
279*61c4878aSAndroid Build Coastguard Worker.. _`Android`: https://developer.android.com/develop/sensors-and-location/sensors/sensors_overview
280*61c4878aSAndroid Build Coastguard Worker.. _`Apple iOS and macOS`: https://developer.apple.com/documentation/sensorkit
281*61c4878aSAndroid Build Coastguard Worker.. _CHRE: https://source.android.com/docs/core/interaction/contexthub
282*61c4878aSAndroid Build Coastguard Worker.. _Linux: https://www.kernel.org/doc/html/v4.14/driver-api/iio/intro.html
283*61c4878aSAndroid Build Coastguard Worker.. _Windows: https://learn.microsoft.com/en-us/windows/win32/sensorsapi/the-sensor-object
284*61c4878aSAndroid Build Coastguard Worker.. _Zephyr: https://docs.zephyrproject.org/apidoc/latest/group__sensor__interface.html
285