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