|  | .. _sensing: | 
|  |  | 
|  | Sensing Subsystem | 
|  | ######################## | 
|  |  | 
|  | .. contents:: | 
|  | :local: | 
|  | :depth: 2 | 
|  |  | 
|  | Overview | 
|  | ******** | 
|  |  | 
|  | Sensing Subsystem is a high level sensor framework inside the OS user | 
|  | space service layer. It is a framework focused on sensor fusion, client | 
|  | arbitration, sampling, timing, scheduling and sensor based power management. | 
|  |  | 
|  | Key concepts in Sensing Subsystem include physical sensor and virtual sensor objects, | 
|  | and a scheduling framework over sensor object relationships. | 
|  | Physical sensors do not depend on any other sensor objects for input, and | 
|  | will directly interact with existing zephyr sensor device drivers. | 
|  | Virtual sensors rely on other sensor objects (physical or virtual) as | 
|  | report inputs. | 
|  |  | 
|  | The sensing subsystem relies on Zephyr sensor device APIs (existing version or update in future) | 
|  | to leverage Zephyr's large library of sensor device drivers (100+). | 
|  |  | 
|  | Use of the sensing subsystem is optional. Applications that only need to access simple sensors | 
|  | devices can use the Zephyr :ref:`sensor` API directly. | 
|  |  | 
|  | Since the sensing subsystem is separated from device driver layer or | 
|  | kernel space and could support various customizations and sensor | 
|  | algorithms in user space with virtual sensor concepts. The existing | 
|  | sensor device driver can focus on low layer device side works, can keep | 
|  | simple as much as possible, just provide device HW abstraction and | 
|  | operations etc. This is very good for system stability. | 
|  |  | 
|  | The sensing subsystem is decoupled with any sensor expose/transfer | 
|  | protocols, the target is to support various up-layer frameworks and | 
|  | Applications with different sensor expose/transfer protocols, | 
|  | such as `CHRE <https://github.com/zephyrproject-rtos/chre>`_, HID sensors Applications, | 
|  | MQTT sensor Applications according different products requirements. Or even support multiple | 
|  | Applications with different up-layer sensor protocols at the same time | 
|  | with it's multiple clients support design. | 
|  |  | 
|  | Sensing subsystem can help build a unified Zephyr sensing architecture for | 
|  | cross host OSes support and as well as IoT sensor solutions. | 
|  |  | 
|  | The diagram below illustrates how the Sensing Subsystem integrates with up-layer frameworks. | 
|  |  | 
|  | .. image:: images/sensing_solution.png | 
|  | :align: center | 
|  | :alt: Unified Zephyr sensing architecture. | 
|  |  | 
|  | Configurability | 
|  | *************** | 
|  |  | 
|  | * Reusable and configurable standalone subsystem. | 
|  | * Based on Zephyr existing low-level Sensor API (reuse 100+ existing sensor device drivers) | 
|  | * Provide Zephyr high-level Sensing Subsystem API for Applications. | 
|  | * Separate option CHRE Sensor PAL Implementation module to support CHRE. | 
|  | * Decoupled with any host link protocols, it's Zephyr Application's role to handle different | 
|  | protocols (MQTT, HID or Private, all configurable) | 
|  |  | 
|  | Main Features | 
|  | ************* | 
|  |  | 
|  | * Scope | 
|  | * Focus on framework for sensor fusion, multiple clients, arbitration, data sampling, timing | 
|  | management and scheduling. | 
|  |  | 
|  | * Sensor Abstraction | 
|  | * ``Physical sensor``: interacts with Zephyr sensor device drivers, focus on data collecting. | 
|  | * ``Virtual sensor``: relies on other sensor(s), ``physical`` or ``virtual``, focus on | 
|  | data fusion. | 
|  |  | 
|  | * Data Driven Model | 
|  | * ``Polling mode``: periodical sampling rate | 
|  | * ``Interrupt mode``: data ready, threshold interrupt etc. | 
|  |  | 
|  | * Scheduling | 
|  | * single thread main loop for all sensor objects sampling and process. | 
|  |  | 
|  | * Buffer Mode for Batching | 
|  |  | 
|  | * Configurable Via Device Tree | 
|  |  | 
|  |  | 
|  | Below diagram shows the API position and scope: | 
|  |  | 
|  | .. image:: images/sensing_api_org.png | 
|  | :align: center | 
|  | :alt: Sensing subsystem API organization. | 
|  |  | 
|  | ``Sensing Subsystem API`` is for Applications. | 
|  | ``Sensing Sensor API`` is for development ``sensors``. | 
|  |  | 
|  |  | 
|  | Major Flows | 
|  | *********** | 
|  |  | 
|  | * Sensor Configuration Flow | 
|  |  | 
|  | .. image:: images/sensor_config_flow.png | 
|  | :align: center | 
|  | :alt: Sensor Configuration Flow (App set report interval to hinge angel sensor example). | 
|  |  | 
|  | * Sensor Data Flow | 
|  |  | 
|  | .. image:: images/sensor_data_flow.png | 
|  | :align: center | 
|  | :alt: Sensor Data Flow (App receive hinge angel data through data event callback example). | 
|  |  | 
|  | Sensor Types And Instance | 
|  | ************************* | 
|  |  | 
|  | The ``Sensing Subsystem`` supports multiple instances of the same sensor type, | 
|  | there're two methods for Applications to identify and open an unique sensor instance: | 
|  |  | 
|  | * Enumerate all sensor instances | 
|  |  | 
|  | :c:func:`sensing_get_sensors` returns all current board configuration supported sensor instances' | 
|  | information in a :c:struct:`sensing_sensor_info` pointer array . | 
|  |  | 
|  | Then Applications can use :c:func:`sensing_open_sensor` to | 
|  | open specific sensor instance for future accessing, configuration and receive sensor data etc. | 
|  |  | 
|  | This method is suitable for supporting some up-layer frameworks like ``CHRE``, ``HID`` which need | 
|  | to dynamically enumerate the underlying platform's sensor instances. | 
|  |  | 
|  | * Open the sensor instance by devicetree node directly | 
|  |  | 
|  | Applications can use :c:func:`sensing_open_sensor_by_dt` to open a sensor instance directly with | 
|  | sensor devicetree node identifier. | 
|  |  | 
|  | For example: | 
|  |  | 
|  | .. code-block:: c | 
|  |  | 
|  | sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_NODELABEL(base_accel)), cb_list, handle); | 
|  | sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_CHOSEN(zephyr_sensing_base_accel)), cb_list, handle); | 
|  |  | 
|  | This method is useful and easy use for some simple Application which just want to access specific | 
|  | sensor(s). | 
|  |  | 
|  |  | 
|  | ``Sensor type`` follows the | 
|  | `HID standard sensor types definition <https://usb.org/sites/default/files/hutrr39b_0.pdf>`_. | 
|  |  | 
|  | See :zephyr_file:`include/zephyr/sensing/sensing_sensor_types.h` | 
|  |  | 
|  | Sensor Instance Handler | 
|  | *********************** | 
|  |  | 
|  | Clients using a :c:type:`sensing_sensor_handle_t` type handler to handle a opened sensor | 
|  | instance, and all subsequent operations on this sensor instance need use this handler, | 
|  | such as set configurations, read sensor sample data, etc. | 
|  |  | 
|  | For a sensor instance, could have two kinds of clients: | 
|  | ``Application clients`` and ``Sensor clients``. | 
|  |  | 
|  | ``Application clients`` can use :c:func:`sensing_open_sensor` to open a sensor instance | 
|  | and get it's handler. | 
|  |  | 
|  | For ``Sensor clients``, there is no open API for opening a reporter, because the client-report | 
|  | relationship is built at the sensor's registration stage with devicetree. | 
|  |  | 
|  | The ``Sensing Subsystem`` will auto open and create ``handlers`` for client sensor | 
|  | to it's reporter sensors. | 
|  | ``Sensor clients`` can get it's reporters' handlers via :c:func:`sensing_sensor_get_reporters`. | 
|  |  | 
|  | .. image:: images/sensor_top.png | 
|  | :align: center | 
|  | :alt: Sensor Reporting Topology. | 
|  |  | 
|  | .. note:: | 
|  | Sensors inside the Sensing Subsystem, the reporting relationship between them are all auto | 
|  | generated by Sensing Subsystem according devicetree definitions, handlers between client sensor | 
|  | and reporter sensors are auto created. | 
|  | Application(s) need to call :c:func:`sensing_open_sensor` to explicitly open the sensor instance. | 
|  |  | 
|  | Sensor Sample Value | 
|  | ******************* | 
|  |  | 
|  | * Data Structure | 
|  |  | 
|  | Each sensor sample value defines as a common ``header`` + ``readings[]`` data structure, like | 
|  | :c:struct:`sensing_sensor_value_3d_q31`, :c:struct:`sensing_sensor_value_q31`, and | 
|  | :c:struct:`sensing_sensor_value_uint32`. | 
|  |  | 
|  | The ``header`` definition :c:func:`sensing_sensor_value_header`. | 
|  |  | 
|  |  | 
|  | * Time Stamp | 
|  |  | 
|  | Time stamp unit in sensing subsystem is ``micro seconds``. | 
|  |  | 
|  | The ``header`` defines a **base_timestamp**, and | 
|  | each element in the **readings[]** array defines **timestamp_delta**. | 
|  |  | 
|  | The **timestamp_delta** is in relation to the previous **readings** (or the **base_timestamp**) | 
|  |  | 
|  | For example: | 
|  |  | 
|  | * timestamp of ``readings[0]`` is ``header.base_timestamp`` + ``readings[0].timestamp_delta``. | 
|  |  | 
|  | * timestamp of ``readings[1]`` is ``timestamp of readings[0]`` + ``readings[1].timestamp_delta``. | 
|  |  | 
|  | Since timestamp unit is micro seconds, | 
|  | the max **timestamp_delta** (``uint32_t``) is ``4295`` seconds. | 
|  |  | 
|  | If a sensor has batched data where two consecutive readings differ by more than ``4295`` seconds, | 
|  | the sensing subsystem runtime will split them across multiple instances of the readings structure, | 
|  | and send multiple events. | 
|  |  | 
|  | This concept is referred from `CHRE Sensor API <https://github.com/zephyrproject-rtos/ | 
|  | chre/blob/zephyr/chre_api/include/chre_api/chre/sensor_types.h>`_. | 
|  |  | 
|  | * Data Format | 
|  |  | 
|  | ``Sensing Subsystem`` uses per sensor type defined data format structure, | 
|  | and support ``Q Format`` defined in :zephyr_file:`include/zephyr/dsp/types.h` | 
|  | for ``zdsp`` lib support. | 
|  |  | 
|  | For example :c:struct:`sensing_sensor_value_3d_q31` can be used by 3D IMU sensors like | 
|  | :c:macro:`SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D`, | 
|  | :c:macro:`SENSING_SENSOR_TYPE_MOTION_UNCALIB_ACCELEROMETER_3D`, | 
|  | and :c:macro:`SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D`. | 
|  |  | 
|  | :c:struct:`sensing_sensor_value_uint32` can be used by | 
|  | :c:macro:`SENSING_SENSOR_TYPE_LIGHT_AMBIENTLIGHT` sensor, | 
|  |  | 
|  | and :c:struct:`sensing_sensor_value_q31` can be used by | 
|  | :c:macro:`SENSING_SENSOR_TYPE_MOTION_HINGE_ANGLE` sensor | 
|  |  | 
|  | See :zephyr_file:`include/zephyr/sensing/sensing_datatypes.h` | 
|  |  | 
|  |  | 
|  | Device Tree Configuration | 
|  | ************************* | 
|  |  | 
|  | Sensing subsystem using device tree to configuration all sensor instances and their properties, | 
|  | reporting relationships. | 
|  |  | 
|  | See the example :zephyr_file:`samples/subsys/sensing/simple/boards/native_sim.overlay` | 
|  |  | 
|  | API Reference | 
|  | ************* | 
|  |  | 
|  | .. doxygengroup:: sensing_sensor_types | 
|  | .. doxygengroup:: sensing_datatypes | 
|  | .. doxygengroup:: sensing_api | 
|  | .. doxygengroup:: sensing_sensor |