Add Air Quality Sensor App for silabs (#35488)

* getter for air quality

* Added Air Quality Sample app for silabs

* Restyled by whitespace

* Restyled by clang-format

* Restyled by prettier-markdown

* added build in CI

* minor fix

* Revert "added build in CI"

This reverts commit 5a1fcda96096a172f1e7fb36fdbe8d269fce741d.

* Revert "minor fix"

This reverts commit 8fa8df289dcbfe6840e425d2330d3ee740577e6b.

* added build for app

* added app to target

* resolved comments

* Restyled by whitespace

* Restyled by clang-format

* using schedulework

* using schedulework instead of chiplock

* Restyled by clang-format

* removing unneccessary loggs, resolved memory leak

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml
index 75e4929..498a250 100644
--- a/.github/workflows/examples-efr32.yaml
+++ b/.github/workflows/examples-efr32.yaml
@@ -68,6 +68,7 @@
              "./scripts/build/build_examples.py \
                 --enable-flashbundle \
                 --target efr32-brd4187c-thermostat-openthread-mtd \
+                --target efr32-brd4187c-air-quality-sensor-app-openthread-mtd \
                 --target efr32-brd4187c-switch-shell-use-ot-coap-lib \
                 --target efr32-brd4187c-unit-test \
                 build \
diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/include/air-quality-sensor-manager.h b/examples/air-quality-sensor-app/air-quality-sensor-common/include/air-quality-sensor-manager.h
index 93e7bff..a4d6367 100644
--- a/examples/air-quality-sensor-app/air-quality-sensor-common/include/air-quality-sensor-manager.h
+++ b/examples/air-quality-sensor-app/air-quality-sensor-common/include/air-quality-sensor-manager.h
@@ -30,6 +30,11 @@
     };
 
     /**
+     * @return The current AirQuality value.
+     */
+    AirQuality::AirQualityEnum GetAirQuality();
+
+    /**
      * @brief Get an Air Quality Manager object - this class acts as a singleton device manager for the air quality device
      * @param[in] aEndpointId    Endpoint that the air quality is on
      * @return mInstance    The AirQualitySensorManager instance, note this this could be nullptr if InitInstance has not been
diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/src/air-quality-sensor-manager.cpp b/examples/air-quality-sensor-app/air-quality-sensor-common/src/air-quality-sensor-manager.cpp
index a6e9476..5fc8bd8 100644
--- a/examples/air-quality-sensor-app/air-quality-sensor-common/src/air-quality-sensor-manager.cpp
+++ b/examples/air-quality-sensor-app/air-quality-sensor-common/src/air-quality-sensor-manager.cpp
@@ -134,6 +134,11 @@
     mFormaldehydeConcentrationMeasurementInstance.SetLevelValue(LevelValueEnum::kLow);
 }
 
+AirQualityEnum AirQualitySensorManager::GetAirQuality()
+{
+    return mAirQualityInstance.GetAirQuality();
+}
+
 void AirQualitySensorManager::OnAirQualityChangeHandler(AirQualityEnum newValue)
 {
     mAirQualityInstance.UpdateAirQuality(newValue);
diff --git a/examples/air-quality-sensor-app/silabs/.gn b/examples/air-quality-sensor-app/silabs/.gn
new file mode 100644
index 0000000..b05216f
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+  target_cpu = "arm"
+  target_os = "freertos"
+  chip_openthread_ftd = true
+
+  import("//openthread.gni")
+}
diff --git a/examples/air-quality-sensor-app/silabs/BUILD.gn b/examples/air-quality-sensor-app/silabs/BUILD.gn
new file mode 100644
index 0000000..ed3077a
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/BUILD.gn
@@ -0,0 +1,226 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${efr32_sdk_build_root}/silabs_executable.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${chip_root}/third_party/silabs/silabs_board.gni")
+
+if (chip_enable_pw_rpc) {
+  import("//build_overrides/pigweed.gni")
+  import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+silabs_project_dir = "${chip_root}/examples/air-quality-sensor-app/silabs"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+if (wifi_soc) {
+  import("${chip_root}/third_party/silabs/SiWx917_sdk.gni")
+  examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917"
+} else {
+  import("${efr32_sdk_build_root}/efr32_sdk.gni")
+  examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+}
+
+import("${examples_common_plat_dir}/args.gni")
+
+declare_args() {
+  # Dump memory usage at link time.
+  chip_print_memory_usage = false
+
+  # Enable the air quality sensor
+  # Some boards do not have a air quality sensor
+  use_air_quality_sensor = false
+}
+
+if (wifi_soc) {
+  siwx917_sdk("sdk") {
+    sources = [
+      "${examples_common_plat_dir}/FreeRTOSConfig.h",
+      "${silabs_project_dir}/include/CHIPProjectConfig.h",
+    ]
+
+    include_dirs = [
+      "${chip_root}/src/platform/silabs/SiWx917",
+      "${silabs_project_dir}/include",
+      "${examples_plat_dir}",
+      "${chip_root}/src/lib",
+      "${examples_common_plat_dir}",
+    ]
+
+    defines = []
+    if (chip_enable_pw_rpc) {
+      defines += [
+        "HAL_VCOM_ENABLE=1",
+        "PW_RPC_ENABLED",
+      ]
+    }
+  }
+} else {
+  efr32_sdk("sdk") {
+    sources = [
+      "${examples_common_plat_dir}/FreeRTOSConfig.h",
+      "${silabs_project_dir}/include/CHIPProjectConfig.h",
+    ]
+
+    include_dirs = [
+      "${chip_root}/src/platform/silabs/efr32",
+      "${silabs_project_dir}/include",
+      "${examples_plat_dir}",
+      "${chip_root}/src/lib",
+      "${examples_common_plat_dir}",
+    ]
+
+    defines = []
+    if (chip_enable_pw_rpc) {
+      defines += [
+        "HAL_VCOM_ENABLE=1",
+        "PW_RPC_ENABLED",
+      ]
+    }
+
+    #TODO: This is a placeholder for the actual implementation
+    if (use_air_quality_sensor) {
+      include_dirs +=
+          [ "${efr32_sdk_root}/examples/platform/silabs/sensors/AirQuality" ]
+
+      defines += [ "USE_AIR_QUALITY_SENSOR" ]
+    }
+  }
+}
+
+#ENDTODO
+
+silabs_executable("air_quality_sensor_app") {
+  output_name = "matter-silabs-air-quality-sensor-example.out"
+  include_dirs = [
+    "include",
+    "${chip_root}/examples/air-quality-sensor-app/air-quality-sensor-common/include",
+  ]
+  defines = []
+
+  sources = [
+    "${chip_root}/examples/air-quality-sensor-app/air-quality-sensor-common/src/air-quality-sensor-manager.cpp",
+    "${examples_common_plat_dir}/main.cpp",
+    "src/AppTask.cpp",
+    "src/SensorManager.cpp",
+    "src/ZclCallbacks.cpp",
+  ]
+
+  #TODO: This is a placeholder for the actual implementation
+  if (use_air_quality_sensor) {
+    sources += [ "${efr32_sdk_root}/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp" ]
+  }
+
+  #ENDTODO
+
+  if (!disable_lcd) {
+    sources += [ "src/AirQualitySensorUI.cpp" ]
+  }
+
+  deps = [
+    ":sdk",
+    "${chip_root}/src/platform/logging:default",
+    app_data_model,
+  ]
+
+  if (wifi_soc) {
+    deps += [ "${examples_plat_dir}:siwx917-common" ]
+  } else {
+    deps += [ "${examples_plat_dir}:efr32-common" ]
+  }
+
+  if (chip_enable_pw_rpc) {
+    defines += [
+      "PW_RPC_ENABLED",
+      "PW_RPC_ATTRIBUTE_SERVICE=1",
+      "PW_RPC_BUTTON_SERVICE=1",
+      "PW_RPC_DESCRIPTOR_SERVICE=1",
+      "PW_RPC_DEVICE_SERVICE=1",
+      "PW_RPC_LIGHTING_SERVICE=1",
+    ]
+
+    sources += [
+      "${chip_root}/examples/common/pigweed/RpcService.cpp",
+      "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+      "${examples_common_plat_dir}/PigweedLogger.cpp",
+      "${examples_common_plat_dir}/Rpc.cpp",
+    ]
+
+    deps += [
+      "$dir_pw_hdlc:default_addresses",
+      "$dir_pw_hdlc:rpc_channel_output",
+      "$dir_pw_stream:sys_io_stream",
+      "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+      "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc",
+    ]
+
+    if (wifi_soc) {
+      deps += [ "${examples_plat_dir}/pw_sys_io:pw_sys_io_siwx917" ]
+    } else {
+      deps += [ "${examples_common_plat_dir}/pw_sys_io:pw_sys_io_silabs" ]
+    }
+
+    deps += pw_build_LINK_DEPS
+
+    include_dirs += [
+      "${chip_root}/examples/common",
+      "${chip_root}/examples/common/pigweed/efr32",
+    ]
+  }
+
+  ldscript = "${examples_common_plat_dir}/ldscripts/${silabs_family}.ld"
+
+  inputs = [ ldscript ]
+
+  ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+  if (chip_print_memory_usage) {
+    ldflags += [
+      "-Wl,--print-memory-usage",
+      "-fstack-usage",
+    ]
+  }
+
+  # WiFi Settings
+  if (chip_enable_wifi) {
+    ldflags += [
+      "-Wl,--defsym",
+      "-Wl,SILABS_WIFI=1",
+    ]
+  }
+
+  output_dir = root_out_dir
+}
+
+group("silabs") {
+  deps = [ ":air_quality_sensor_app" ]
+}
+
+group("default") {
+  deps = [ ":silabs" ]
+}
diff --git a/examples/air-quality-sensor-app/silabs/README.md b/examples/air-quality-sensor-app/silabs/README.md
new file mode 100644
index 0000000..d0e89d3
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/README.md
@@ -0,0 +1,366 @@
+# Matter Air Quality Sensor Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+<hr>
+
+-   [Matter Air Quality Sensor Example](#matter-air-quality-sensor-example)
+    -   [Introduction](#introduction)
+    -   [Building](#building)
+        -   [Linux](#linux)
+        -   [Mac OS X](#mac-os-x)
+    -   [Flashing the Application](#flashing-the-application)
+    -   [Viewing Logging Output](#viewing-logging-output)
+    -   [Running the Complete Example](#running-the-complete-example)
+        -   [Notes](#notes)
+            -   [On Border Router:](#on-border-router)
+            -   [On PC(Linux):](#on-pclinux)
+    -   [Running RPC console](#running-rpc-console)
+    -   [Memory settings](#memory-settings)
+    -   [OTA Software Update](#ota-software-update)
+    -   [Building options](#building-options)
+        -   [Disabling logging](#disabling-logging)
+        -   [Debug build / release build](#debug-build--release-build)
+        -   [Disabling LCD](#disabling-lcd)
+        -   [KVS maximum entry count](#kvs-maximum-entry-count)
+
+<hr>
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+## Introduction
+
+The EFR32 Air Quality Sensor example provides a baseline demonstration of a air
+quality sensor device, built using Matter and the Silicon Labs gecko SDK. It can
+be controlled by a Chip controller over an Openthread or Wifi network.
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. If using Thread, Thread Network credentials are then provided to the
+EFR32 device which will then join the Thread network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure.
+
+The air quality sensor example is intended to serve both as a means to explore
+the workings of Matter as well as a template for creating real products based on
+the Silicon Labs platform.
+
+## Building
+
+-   Download the
+    [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+    command line tool, and ensure that `commander` is your shell search path.
+    (For Mac OS X, `commander` is located inside
+    `Commander.app/Contents/MacOS/`.)
+
+-   Download and install a suitable ARM gcc tool chain (For most Host, the
+    bootstrap already installs the toolchain):
+    [GNU Arm Embedded Toolchain 12.2 Rel1](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads)
+
+-   Install some additional tools(likely already present for CHIP developers):
+
+#### Linux
+
+    $ sudo apt-get install git ninja-build
+
+#### Mac OS X
+
+    $ brew install ninja
+
+-   Supported hardware:
+
+    -   > For the latest supported hardware please refer to the
+        > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+        > in the Silicon Labs Matter Github Repo
+
+    MG21 boards: Currently not supported due to RAM limitation.
+
+    -   BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+    MG24 boards :
+
+    -   BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+    -   BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+*   Build the example application:
+
+          cd ~/connectedhomeip
+          ./scripts/examples/gn_silabs_example.sh ./examples/air-quality-sensor-app/silabs/ ./out/air-quality-sensor-app BRD4187C
+
+-   To delete generated executable, libraries and object files use:
+
+          $ cd ~/connectedhomeip
+          $ rm -rf ./out/
+
+    OR use GN/Ninja directly
+
+          $ cd ~/connectedhomeip/examples/air-quality-sensor-app/silabs
+          $ git submodule update --init
+          $ source third_party/connectedhomeip/scripts/activate.sh
+          $ export SILABS_BOARD=BRD4187C
+          $ gn gen out/debug
+          $ ninja -C out/debug
+
+-   To delete generated executable, libraries and object files use:
+
+          $ cd ~/connectedhomeip/examples/air-quality-sensor-app/silabs
+          $ rm -rf out/
+
+*   Build the example with Matter shell
+
+          ./scripts/examples/gn_silabs_example.sh examples/air-quality-sensor-app/silabs/ out/air-quality-sensor-app-app BRD4187C chip_build_libshell=true
+
+*   Build the example as Intermittently Connected Device (ICD)
+
+          $ ./scripts/examples/gn_silabs_example.sh ./examples/air-quality-sensor-app/silabs/ ./out/air-quality-sensor-app-app_ICD BRD4187C --icd
+
+    or use gn as previously mentioned but adding the following arguments:
+
+          $ gn gen out/debug '--args=SILABS_BOARD="BRD4187C" enable_sleepy_device=true chip_openthread_ftd=false chip_build_libshell=true'
+
+*   Build the example with pigweed RCP
+
+          $ ./scripts/examples/gn_silabs_example.sh examples/air-quality-sensor-app/silabs/ out/air-quality-sensor-app-app_rpc BRD4187C 'import("//with_pw_rpc.gni")'
+
+    or use GN/Ninja Directly
+
+          $ cd ~/connectedhomeip/examples/air-quality-sensor-app/silabs
+          $ git submodule update --init
+          $ source third_party/connectedhomeip/scripts/activate.sh
+          $ export SILABS_BOARD=BRD4187C
+          $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+          $ ninja -C out/debug
+
+For more build options, help is provided when running the build script without
+arguments
+
+    ./scripts/examples/gn_silabs_example.sh
+
+## Flashing the Application
+
+-   On the command line:
+
+          $ cd ~/connectedhomeip/examples/air-quality-sensor-app/silabs
+          $ python3 out/debug/matter-silabs-air-quality-sensor-app-switch-example.flash.py
+
+-   Or with the Ozone debugger, just load the .out file.
+
+All EFR32 boards require a bootloader, see Silicon Labs documentation for more
+info. Pre-built bootloader binaries are available in the Assets section of the
+Releases page on
+[Silabs Matter Github](https://github.com/SiliconLabs/matter/releases) .
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+-   Download the J-Link installer by navigating to the appropriate URL and
+    agreeing to the license agreement.
+
+-   [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+-   [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+*   Install the J-Link software
+
+          $ cd ~/Downloads
+          $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+
+*   In Linux, grant the logged in user the ability to talk to the development
+    hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+    dialout group.
+
+          $ sudo usermod -a -G dialout ${USER}
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+-   Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+    For MG12 use:
+
+          $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+
+    For MG21 use:
+
+          $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+
+-   In a second terminal, run the JLinkRTTClient to view logs:
+
+          $ JLinkRTTClient
+
+## Running the Complete Example
+
+-   It is assumed here that you already have an OpenThread border router
+    configured and running. If not see the following guide
+    [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+    for more information on how to setup a border router on a raspberryPi.
+
+    Take note that the RCP code is available directly through
+    [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+    under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+-   For this example to work, it is necessary to have a second efr32 device
+    running the
+    [air quality sensor app example](https://github.com/project-chip/connectedhomeip/blob/master/examples/air-quality-sensor-app/silabs/README.md)
+    commissioned on the same openthread network
+
+-   User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+    Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+    BLE
+
+        * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+          a URL can be found in the RTT logs.
+
+          <info  > [SVR] Copy/paste the below URL in a browser to see the QR Code:
+          <info  > [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+    **LED 0** shows the overall state of the device and its connectivity. The
+    following states are possible:
+
+        -   Short Flash On (50 ms on/950 ms off): The device is in the
+            unprovisioned (unpaired) state and is waiting for a commissioning
+            application to connect.
+
+        -   Rapid Even Flashing (100 ms on/100 ms off): The device is in the
+            unprovisioned state and a commissioning application is connected through
+            Bluetooth LE.
+
+        -   Short Flash Off (950ms on/50ms off): The device is fully
+            provisioned, but does not yet have full Thread network or service
+            connectivity.
+
+        -   Solid On: The device is fully provisioned and has full Thread
+            network and service connectivity.
+
+    **Push Button 0**
+
+        -   _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
+            for 30 seconds. The device will then switch to a slower interval advertisement.
+            After 15 minutes, the advertisement stops.
+
+        -   _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
+            Releasing the button within the 6-second window cancels the factory reset
+            procedure. **LEDs** blink in unison when the factory reset procedure is
+            initiated.
+
+*   You can provision and control the Chip device using the python controller,
+    [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+    standalone, Android or iOS app
+
+    Here is an example with the CHIPTool:
+
+    ```
+    chip-tool pairing ble-thread 1 hex:<operationalDataset> 20202021 3840
+    ```
+
+### Notes
+
+-   Depending on your network settings your router might not provide native ipv6
+    addresses to your devices (Border router / PC). If this is the case, you
+    need to add a static ipv6 addresses on both device and then an ipv6 route to
+    the border router on your PC
+
+#### On Border Router:
+
+`$ sudo ip addr add dev <Network interface> 2002::2/64`
+
+#### On PC(Linux):
+
+`$ sudo ip addr add dev <Network interface> 2002::1/64`
+
+#Add Ipv6 route on PC(Linux) \$ sudo ip route add <Thread global ipv6 prefix>/64
+via 2002::2
+
+## Running RPC console
+
+-   As part of building the example with RPCs enabled the chip_rpc python
+    interactive console is installed into your venv. The python wheel files are
+    also created in the output folder: out/debug/chip_rpc_console_wheels. To
+    install the wheel files without rebuilding:
+
+    `pip3 install out/debug/chip_rpc_console_wheels/*.whl`
+
+-   To use the chip-rpc console after it has been installed run:
+
+    `chip-console --device /dev/tty.<SERIALDEVICE> -b 115200 -o /<YourFolder>/pw_log.out`
+
+-   Then you can simulate a button press or release using the following command
+    where : idx = 0 or 1 for Button PB0 or PB1 action = 0 for PRESSED, 1 for
+    RELEASE Test toggling the LED with
+
+    `rpcs.chip.rpc.Button.Event(idx=1, pushed=True)`
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+OpenThread. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory
+tracking code inside the `trackAlloc` and `trackFree` function
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md)
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options :
+
+### Disabling logging
+
+chip_progress_logging, chip_detail_logging, chip_automation_logging
+
+    $ ./scripts/examples/gn_silabs_example.sh ./examples/air-quality-sensor-app/silabs ./out/air-quality-sensor-app-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+is_debug
+
+    $ ./scripts/examples/gn_silabs_example.sh ./examples/air-quality-sensor-app/silabs ./out/air-quality-sensor-app-app BRD4164A "is_debug=false"
+
+### Disabling LCD
+
+show_qr_code
+
+    $ ./scripts/examples/gn_silabs_example.sh ./examples/air-quality-sensor-app/silabs ./out/air-quality-sensor-app-app BRD4164A "show_qr_code=false"
+
+### KVS maximum entry count
+
+kvs_max_entries
+
+    Set the maximum Kvs entries that can be stored in NVM (Default 75)
+    Thresholds: 30 <= kvs_max_entries <= 255
+
+    $ ./scripts/examples/gn_silabs_example.sh ./examples/air-quality-sensor-app/silabs ./out/air-quality-sensor-app-app BRD4164A kvs_max_entries=50
diff --git a/examples/air-quality-sensor-app/silabs/build_for_wifi_args.gni b/examples/air-quality-sensor-app/silabs/build_for_wifi_args.gni
new file mode 100644
index 0000000..718600a
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/build_for_wifi_args.gni
@@ -0,0 +1,22 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+import("${chip_root}/src/platform/silabs/wifi_args.gni")
+chip_enable_wifi = true
+chip_enable_ota_requestor = true
+app_data_model =
+    "${chip_root}/examples/air-quality-sensor-app/air-quality-sensor-common"
diff --git a/examples/air-quality-sensor-app/silabs/build_for_wifi_gnfile.gn b/examples/air-quality-sensor-app/silabs/build_for_wifi_gnfile.gn
new file mode 100644
index 0000000..d391814
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+  target_cpu = "arm"
+  target_os = "freertos"
+  chip_enable_wifi = true
+  import("//build_for_wifi_args.gni")
+}
diff --git a/examples/air-quality-sensor-app/silabs/build_overrides b/examples/air-quality-sensor-app/silabs/build_overrides
new file mode 120000
index 0000000..e578e73
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/build_overrides
@@ -0,0 +1 @@
+../../build_overrides
\ No newline at end of file
diff --git a/examples/air-quality-sensor-app/silabs/include/AirQualityConfig.h b/examples/air-quality-sensor-app/silabs/include/AirQualityConfig.h
new file mode 100644
index 0000000..9cc9d77
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/AirQualityConfig.h
@@ -0,0 +1,41 @@
+#ifndef SL_MATTER_AIR_QUALITY_CONFIG_H
+#define SL_MATTER_AIR_QUALITY_CONFIG_H
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+// AirQualityConfig.h
+// This header file contains preprocessor directives to set air quality thresholds.
+// Users should modify these #define statements to customize thresholds for their application.
+// These thresholds are used to categorize air quality into various levels.
+
+// <o MIN_THRESHOLD> Minimum Threshold Value
+// <i> Default: 0
+#define MIN_THRESHOLD 0
+
+// <o GOOD_THRESHOLD> Good Threshold Value
+// <i> Default: 50
+#define GOOD_THRESHOLD 50
+
+// <o FAIR_THRESHOLD> Fair Threshold Value
+// <i> Default: 100
+#define FAIR_THRESHOLD 100
+
+// <o MODERATE_THRESHOLD> Moderate Threshold Value
+// <i> Default: 150
+#define MODERATE_THRESHOLD 150
+
+// <o POOR_THRESHOLD> Poor Threshold Value
+// <i> Default: 200
+#define POOR_THRESHOLD 200
+
+// <o VERY_POOR_THRESHOLD> Very Poor Threshold Value
+// <i> Default: 250
+#define VERY_POOR_THRESHOLD 250
+
+// <o EXTREMELY_POOR_THRESHOLD> Extremely Poor Threshold Value
+// <i> Default: 300
+#define EXTREMELY_POOR_THRESHOLD 300
+
+// <<< end of configuration section >>>
+
+#endif // SL_MATTER_AIR_QUALITY_CONFIG_H
diff --git a/examples/air-quality-sensor-app/silabs/include/AirQualitySensorUI.h b/examples/air-quality-sensor-app/silabs/include/AirQualitySensorUI.h
new file mode 100644
index 0000000..0ee7123
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/AirQualitySensorUI.h
@@ -0,0 +1,38 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include "demo-ui-bitmaps.h"
+#include "dmd.h"
+#include "glib.h"
+#include "lcd.h"
+
+class AirQualitySensorUI
+{
+
+public:
+    static void DrawUI(GLIB_Context_t * glibContext);
+
+private:
+    static void DrawHeader(GLIB_Context_t * glibContext);
+    static void DrawFooter(GLIB_Context_t * glibContext);
+    static void DrawCurrentAirQuality(GLIB_Context_t * glibContext);
+    static void DrawFont(GLIB_Context_t * glibContext, uint8_t initial_x, uint8_t initial_y, uint8_t width, uint8_t * data,
+                         uint32_t size);
+};
diff --git a/examples/air-quality-sensor-app/silabs/include/AppConfig.h b/examples/air-quality-sensor-app/silabs/include/AppConfig.h
new file mode 100644
index 0000000..fafcfd3
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/AppConfig.h
@@ -0,0 +1,59 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 Project CHIP Authors
+ *    Copyright (c) 2019-2024 Google LLC.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include "silabs_utils.h"
+
+// ---- Air Quality Sensor Example App Config ----
+
+#define APP_TASK_NAME "AQS"
+
+#define BLE_DEV_NAME "SiLabs-Air-Quality-Sensor"
+
+// Time it takes in ms for the simulated actuator to move from one
+// APP Logo, boolean only. must be 64x64
+#define ON_DEMO_BITMAP                                                                                                             \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,    \
+        0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00,    \
+        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00,    \
+        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,    \
+        0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#define OFF_DEMO_BITMAP ON_DEMO_BITMAP
diff --git a/examples/air-quality-sensor-app/silabs/include/AppEvent.h b/examples/air-quality-sensor-app/silabs/include/AppEvent.h
new file mode 100644
index 0000000..f521829
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/AppEvent.h
@@ -0,0 +1,56 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 Project CHIP Authors
+ *    Copyright (c) 2018-2024 Nest Labs, Inc.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+#include <cstdint>
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+    enum AppEventTypes
+    {
+        kEventType_Button = 0,
+        kEventType_Timer,
+        kEventType_AirQualitySensor,
+        kEventType_Install,
+    };
+
+    uint16_t Type;
+
+    union
+    {
+        struct
+        {
+            uint8_t Action;
+        } ButtonEvent;
+        struct
+        {
+            void * Context;
+        } TimerEvent;
+        struct
+        {
+            uint8_t Action;
+            int32_t Actor;
+        } AirQualitySensorEvent;
+    };
+
+    EventHandler Handler;
+};
diff --git a/examples/air-quality-sensor-app/silabs/include/AppTask.h b/examples/air-quality-sensor-app/silabs/include/AppTask.h
new file mode 100644
index 0000000..4a42295
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/AppTask.h
@@ -0,0 +1,108 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 Project CHIP Authors
+ *    Copyright (c) 2019-2024 Google LLC.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef DISPLAY_ENABLED
+#include "AirQualitySensorUI.h"
+#endif
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "SensorManager.h"
+#include <ble/BLEEndPoint.h>
+#include <cmsis_os2.h>
+#include <lib/core/CHIPError.h>
+#include <platform/CHIPDeviceLayer.h>
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+class AppTask : public BaseApplication
+{
+
+public:
+    AppTask() = default;
+
+    static AppTask & GetAppTask() { return sAppTask; }
+
+    /**
+     * @brief AppTask task main loop function
+     *
+     * @param pvParameter FreeRTOS task parameter
+     */
+    static void AppTaskMain(void * pvParameter);
+
+    CHIP_ERROR StartAppTask();
+
+    /**
+     * @brief Request an update of the Air Quality Senor LCD UI
+     */
+    void UpdateAirQualitySensorUI();
+
+    /**
+     * @brief Event handler when a button is pressed
+     * Function posts an event for button processing
+     *
+     * @param buttonHandle APP_CONTROL_BUTTON or APP_FUNCTION_BUTTON
+     * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+     *                  SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+     */
+    static void ButtonEventHandler(uint8_t button, uint8_t btnAction);
+
+private:
+    static AppTask sAppTask;
+
+    /**
+     * @brief AppTask initialisation function
+     *
+     * @return CHIP_ERROR
+     */
+    CHIP_ERROR Init();
+
+    /**
+     * @brief PB0 Button event processing function
+     *        Press and hold will trigger a factory reset timer start
+     *        Press and release will restart BLEAdvertising if not commisionned
+     *
+     * @param aEvent button event being processed
+     */
+    static void ButtonHandler(AppEvent * aEvent);
+
+    static void AirQualitySensorActionEventHandler(AppEvent * aEvent);
+};
diff --git a/examples/air-quality-sensor-app/silabs/include/CHIPProjectConfig.h b/examples/air-quality-sensor-app/silabs/include/CHIPProjectConfig.h
new file mode 100644
index 0000000..f4e9709
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/CHIPProjectConfig.h
@@ -0,0 +1,110 @@
+/*
+ *
+ *    Copyright (c) 2020-2024 Project CHIP Authors
+ *    Copyright (c) 2019-2024 Google LLC.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ *    @file
+ *          Example project configuration file for CHIP.
+ *
+ *          This is a place to put application or project-specific overrides
+ *          to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+//    WARNING: These options make it possible to circumvent basic Chip security functionality,
+//    including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x800E: example Air Quality Sensor app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x800E
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC
+ *
+ * Enables synchronizing the device's real time clock with a remote Chip Time service
+ * using the Chip Time Sync protocol.
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 0
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ *  @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ *  @brief
+ *    Active retransmit interval, or time to wait before retransmission after
+ *    subsequent failures in milliseconds.
+ *
+ *  This is the default value, that might be adjusted by end device depending on its
+ *  needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
diff --git a/examples/air-quality-sensor-app/silabs/include/SensorManager.h b/examples/air-quality-sensor-app/silabs/include/SensorManager.h
new file mode 100644
index 0000000..52b753c
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/include/SensorManager.h
@@ -0,0 +1,43 @@
+/*
+ *
+ *    Copyright (c) 2019-2024 Google LLC.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include "AppEvent.h"
+#include <cmsis_os2.h>
+#include <lib/core/CHIPError.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+class SensorManager
+{
+public:
+    CHIP_ERROR Init();
+    static SensorManager & SensorMgr() { return sSensorManager; }
+
+private:
+    SensorManager()  = default;
+    ~SensorManager() = default;
+
+    osTimerId_t mSensorTimer;
+
+    // Reads new generated sensor value, stores it, and updates local Air Quality attribute
+    static void SensorTimerEventHandler(void * arg);
+
+    static SensorManager sSensorManager;
+};
diff --git a/examples/air-quality-sensor-app/silabs/openthread.gn b/examples/air-quality-sensor-app/silabs/openthread.gn
new file mode 100644
index 0000000..b05216f
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/openthread.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+  target_cpu = "arm"
+  target_os = "freertos"
+  chip_openthread_ftd = true
+
+  import("//openthread.gni")
+}
diff --git a/examples/air-quality-sensor-app/silabs/openthread.gni b/examples/air-quality-sensor-app/silabs/openthread.gni
new file mode 100644
index 0000000..c6a8cbf
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/openthread.gni
@@ -0,0 +1,27 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/efr32/args.gni")
+
+silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+app_data_model =
+    "${chip_root}/examples/air-quality-sensor-app/air-quality-sensor-common"
+chip_enable_ota_requestor = true
+chip_enable_openthread = true
+
+openthread_external_platform =
+    "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/examples/air-quality-sensor-app/silabs/src/AirQualitySensorUI.cpp b/examples/air-quality-sensor-app/silabs/src/AirQualitySensorUI.cpp
new file mode 100644
index 0000000..ee2ceb3
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/src/AirQualitySensorUI.cpp
@@ -0,0 +1,184 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "AirQualitySensorUI.h"
+#include "AppTask.h"
+#include "SensorManager.h"
+#include "demo-ui-bitmaps.h"
+#include "dmd.h"
+#include <air-quality-sensor-manager.h>
+#if DISPLAY_ENABLED
+#include "glib.h"
+#include "lcd.h"
+#endif
+
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::AirQuality;
+
+namespace {
+// Bitmap
+const uint8_t silabsLogo[]       = { SILABS_LOGO_SMALL };
+const uint8_t matterLogoBitmap[] = { MATTER_LOGO_BITMAP };
+
+const uint8_t wifiLogo[]   = { WIFI_BITMAP };
+const uint8_t threadLogo[] = { THREAD_BITMAP };
+const uint8_t bleLogo[]    = { BLUETOOTH_ICON_SMALL };
+
+const unsigned char monaco_48pt[] = { MONACO_48PT };
+
+#ifdef SL_WIFI
+constexpr bool UI_WIFI = true;
+#else
+constexpr bool UI_WIFI = false;
+#endif
+} // namespace
+
+void AirQualitySensorUI::DrawUI(GLIB_Context_t * glibContext)
+{
+    if (glibContext == nullptr)
+    {
+        ChipLogDetail(AppServer, "Context is null");
+        return;
+    }
+
+    GLIB_clear(glibContext);
+    DrawHeader(glibContext);
+    DrawCurrentAirQuality(glibContext);
+    DrawFooter(glibContext);
+
+#if SL_LCDCTRL_MUX
+    sl_wfx_host_pre_lcd_spi_transfer();
+#endif // SL_LCDCTRL_MUX
+    DMD_updateDisplay();
+#if SL_LCDCTRL_MUX
+    sl_wfx_host_post_lcd_spi_transfer();
+#endif // SL_LCDCTRL_MUX
+}
+
+void AirQualitySensorUI::DrawHeader(GLIB_Context_t * glibContext)
+{
+    // Draw Silabs Corner icon
+    GLIB_drawBitmap(glibContext, SILABS_ICON_POSITION_X, STATUS_ICON_LINE, SILABS_LOGO_WIDTH, SILABS_LOGO_HEIGHT, silabsLogo);
+    // Draw BLE Icon
+    GLIB_drawBitmap(glibContext, BLE_ICON_POSITION_X, STATUS_ICON_LINE, BLUETOOTH_ICON_SIZE, BLUETOOTH_ICON_SIZE, bleLogo);
+    // Draw WiFi/OpenThread Icon
+    GLIB_drawBitmap(glibContext, NETWORK_ICON_POSITION_X, STATUS_ICON_LINE, (UI_WIFI) ? WIFI_BITMAP_HEIGHT : THREAD_BITMAP_WIDTH,
+                    WIFI_BITMAP_HEIGHT, (UI_WIFI) ? wifiLogo : threadLogo);
+    // Draw Matter Icon
+    GLIB_drawBitmap(glibContext, MATTER_ICON_POSITION_X, STATUS_ICON_LINE, MATTER_LOGO_WIDTH, MATTER_LOGO_HEIGHT, matterLogoBitmap);
+#if SL_LCDCTRL_MUX
+    sl_wfx_host_pre_lcd_spi_transfer();
+#endif // SL_LCDCTRL_MUX
+    DMD_updateDisplay();
+#if SL_LCDCTRL_MUX
+    sl_wfx_host_post_lcd_spi_transfer();
+#endif // SL_LCDCTRL_MUX
+}
+
+void AirQualitySensorUI::DrawFooter(GLIB_Context_t * glibContext)
+{
+    switch (AirQualitySensorManager::GetInstance()->GetAirQuality())
+    {
+    case AirQualityEnum::kGood:
+        GLIB_drawStringOnLine(glibContext, "AQ : Good", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    case AirQualityEnum::kFair:
+        GLIB_drawStringOnLine(glibContext, "AQ : Fair", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    case AirQualityEnum::kModerate:
+        GLIB_drawStringOnLine(glibContext, "AQ : Moderate", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    case AirQualityEnum::kPoor:
+        GLIB_drawStringOnLine(glibContext, "AQ : Poor", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    case AirQualityEnum::kVeryPoor:
+        GLIB_drawStringOnLine(glibContext, "AQ : VPoor", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    case AirQualityEnum::kExtremelyPoor:
+        GLIB_drawStringOnLine(glibContext, "AQ : EPoor", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    case AirQualityEnum::kUnknown:
+        GLIB_drawStringOnLine(glibContext, "AQ : Unknown", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+        break;
+    default:
+        break;
+    }
+
+#if SL_LCDCTRL_MUX
+    sl_wfx_host_pre_lcd_spi_transfer();
+#endif // SL_LCDCTRL_MUX
+    DMD_updateDisplay();
+#if SL_LCDCTRL_MUX
+    sl_wfx_host_post_lcd_spi_transfer();
+#endif // SL_LCDCTRL_MUX
+}
+
+/**
+ * @brief Draw a 2 digit Air Quality of screen. Because of this Celsius is used by default
+ * @param GLIB_Context_t * pointer to the context for the GLIB library
+ * @param int8_t current Air Quality
+ */
+void AirQualitySensorUI::DrawCurrentAirQuality(GLIB_Context_t * glibContext)
+{
+    // LCD line define
+    constexpr uint8_t kAirQualityLcdInitialX = 30;
+    uint8_t position_x                       = 10;
+    uint8_t * data;
+    uint8_t print_val;
+
+    // Print Current air quality
+    print_val = 0;
+    data      = (uint8_t *) &monaco_48pt[print_val * MONACO_FONT_NB_LENGTH];
+    DrawFont(glibContext, position_x, kAirQualityLcdInitialX, MONACO_FONT_WIDTH, data, MONACO_FONT_NB_LENGTH);
+    position_x += MONACO_FONT_WIDTH;
+
+    print_val = static_cast<uint8_t>(AirQualitySensorManager::GetInstance()->GetAirQuality());
+    data      = (uint8_t *) &monaco_48pt[print_val * MONACO_FONT_NB_LENGTH];
+    DrawFont(glibContext, position_x, kAirQualityLcdInitialX, MONACO_FONT_WIDTH, data, MONACO_FONT_NB_LENGTH);
+}
+
+void AirQualitySensorUI::DrawFont(GLIB_Context_t * glibContext, uint8_t initial_x, uint8_t initial_y, uint8_t width, uint8_t * data,
+                                  uint32_t size)
+{
+    uint8_t x = initial_x, y = initial_y;
+    for (uint16_t i = 0; i < size; i++)
+    {
+        for (uint8_t mask = 0; mask < 8; mask++)
+        {
+            if (!(data[i] & (0x01 << mask)))
+            {
+                GLIB_drawPixel(glibContext, x, y);
+            }
+            // Check line changes
+            if (((x - initial_x) % width) == 0 && x != initial_x)
+            {
+                x = initial_x;
+                y++;
+                // Font is 8 bit align with paddings bits;
+                mask = 8;
+            }
+            else
+            {
+                x++;
+            }
+        }
+    }
+}
diff --git a/examples/air-quality-sensor-app/silabs/src/AppTask.cpp b/examples/air-quality-sensor-app/silabs/src/AppTask.cpp
new file mode 100644
index 0000000..572ec66
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/src/AppTask.cpp
@@ -0,0 +1,154 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors\
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+
+#include "LEDWidget.h"
+
+#ifdef DISPLAY_ENABLED
+#include "AirQualitySensorUI.h"
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+#include <air-quality-sensor-manager.h>
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/callback.h>
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
+#include <app/util/attribute-storage.h>
+#include <assert.h>
+#include <lib/support/CodeUtils.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/silabs/platformAbstraction/SilabsPlatform.h>
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#include <setup_payload/SetupPayload.h>
+
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+#define APP_FUNCTION_BUTTON 0
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::TLV;
+using namespace chip::DeviceLayer;
+using namespace chip::app::Clusters::AirQuality;
+using namespace chip::app::Clusters;
+
+/**********************************************************
+ * AppTask Definitions
+ *********************************************************/
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    chip::DeviceLayer::Silabs::GetPlatform().SetButtonsCb(AppTask::ButtonEventHandler);
+#ifdef DISPLAY_ENABLED
+    GetLCD().Init((uint8_t *) "Air-Quality-Sensor");
+    GetLCD().SetCustomUI(AirQualitySensorUI::DrawUI);
+#endif
+
+    err = BaseApplication::Init();
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogDetail(AppServer, "BaseApplication::Init() failed");
+        appError(err);
+    }
+    err = SensorManager::SensorMgr().Init();
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogDetail(AppServer, "SensorMgr::Init() failed");
+        appError(err);
+    }
+
+    return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+    return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+    AppEvent event;
+    osMessageQueueId_t sAppEventQueue = *(static_cast<osMessageQueueId_t *>(pvParameter));
+
+    CHIP_ERROR err = sAppTask.Init();
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogDetail(AppServer, "AppTask.Init() failed");
+        appError(err);
+    }
+
+#if !(defined(CHIP_CONFIG_ENABLE_ICD_SERVER) && CHIP_CONFIG_ENABLE_ICD_SERVER)
+    sAppTask.StartStatusLEDTimer();
+#endif
+
+    ChipLogDetail(AppServer, "App Task started");
+    while (true)
+    {
+        osStatus_t eventReceived = osMessageQueueGet(sAppEventQueue, &event, NULL, osWaitForever);
+        while (eventReceived == osOK)
+        {
+            sAppTask.DispatchEvent(&event);
+            eventReceived = osMessageQueueGet(sAppEventQueue, &event, NULL, 0);
+        }
+    }
+}
+
+void AppTask::UpdateAirQualitySensorUI()
+{
+// Update the LCD with the Stored value. Show QR Code if not provisioned
+#ifdef DISPLAY_ENABLED
+    GetLCD().WriteDemoUI(false);
+#ifdef QR_CODE_ENABLED
+    if (BaseApplication::GetProvisionStatus())
+    {
+        GetLCD().ShowQRCode(true);
+    }
+#endif // QR_CODE_ENABLED
+#endif
+}
+
+void AppTask::ButtonEventHandler(uint8_t button, uint8_t btnAction)
+{
+    AppEvent aEvent           = {};
+    aEvent.Type               = AppEvent::kEventType_Button;
+    aEvent.ButtonEvent.Action = btnAction;
+
+    if (button == APP_FUNCTION_BUTTON)
+    {
+        aEvent.Handler = BaseApplication::ButtonHandler;
+        sAppTask.PostEvent(&aEvent);
+    }
+}
diff --git a/examples/air-quality-sensor-app/silabs/src/SensorManager.cpp b/examples/air-quality-sensor-app/silabs/src/SensorManager.cpp
new file mode 100644
index 0000000..3b76450
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/src/SensorManager.cpp
@@ -0,0 +1,180 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "SensorManager.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+#include <AirQualityConfig.h>
+#include <air-quality-sensor-manager.h>
+
+#ifdef USE_AIR_QUALITY_SENSOR
+#include "AirQualitySensor.h"
+#endif
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+using namespace chip;
+using namespace chip::DeviceLayer;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::AirQuality;
+
+/**********************************************************
+ * Variable declarations
+ *********************************************************/
+SensorManager SensorManager::sSensorManager;
+namespace {
+constexpr uint16_t kSensorTImerPeriodMs = 30000; // 30s timer period
+
+#ifndef USE_AIR_QUALITY_SENSOR
+constexpr uint16_t kSimulatedReadingFrequency =
+    (60000 / kSensorTImerPeriodMs); // for every two timer cycles, a simulated sensor update is triggered.
+int32_t mSimulatedAirQuality[] = { 5, 55, 105, 155, 205, 255, 305, 355, 400 };
+#endif
+
+} // namespace
+
+/**
+ * @brief Classifies the air quality based on a given sensor value.
+ *
+ * This function compares the input value against predefined thresholds
+ * defined in the AirQualityConfig.h file. The thresholds are used
+ * to classify the air quality into categories defined by the AirQualityEnum.
+ * The thresholds are defined in the SensorThresholds enum.
+ *
+ * @param value The sensor value used to classify air quality.
+ * @return AirQualityEnum The classified air quality category.
+ */
+AirQualityEnum classifyAirQuality(int32_t value)
+{
+    if (value < MIN_THRESHOLD)
+    {
+        return AirQualityEnum::kUnknown;
+    }
+    else if (value < GOOD_THRESHOLD)
+    {
+        return AirQualityEnum::kGood;
+    }
+    else if (value < FAIR_THRESHOLD)
+    {
+        return AirQualityEnum::kFair;
+    }
+    else if (value < MODERATE_THRESHOLD)
+    {
+        return AirQualityEnum::kModerate;
+    }
+    else if (value < POOR_THRESHOLD)
+    {
+        return AirQualityEnum::kPoor;
+    }
+    else if (value < VERY_POOR_THRESHOLD)
+    {
+        return AirQualityEnum::kVeryPoor;
+    }
+    else
+    {
+        return AirQualityEnum::kExtremelyPoor;
+    }
+}
+
+void InitAirQualitySensorManager(intptr_t arg)
+{
+    AirQualitySensorManager::InitInstance();
+}
+
+CHIP_ERROR SensorManager::Init()
+{
+    DeviceLayer::PlatformMgr().ScheduleWork(InitAirQualitySensorManager);
+    // Create cmsisos sw timer for air quality sensor timer.
+    mSensorTimer = osTimerNew(SensorTimerEventHandler, osTimerPeriodic, nullptr, nullptr);
+    if (mSensorTimer == NULL)
+    {
+        ChipLogDetail(AppServer, "mSensorTimer timer create failed");
+        return APP_ERROR_CREATE_TIMER_FAILED;
+    }
+
+#ifdef USE_AIR_QUALITY_SENSOR
+    if (SL_STATUS_OK != AirQualitySensor::Init())
+    {
+        ChipLogDetail(AppServer, "Failed to Init Sensor");
+        return CHIP_ERROR_INTERNAL;
+    }
+#endif
+    // Update Air Quality immediatly at bootup
+    SensorTimerEventHandler(nullptr);
+    // Trigger periodic update
+    uint32_t delayTicks = ((uint64_t) osKernelGetTickFreq() * kSensorTImerPeriodMs) / 1000;
+
+    // Starts or restarts the function timer
+    if (osTimerStart(mSensorTimer, delayTicks))
+    {
+        ChipLogDetail(AppServer, "mSensor Timer start() failed");
+        appError(APP_ERROR_START_TIMER_FAILED);
+    }
+    return CHIP_NO_ERROR;
+}
+
+void writeAirQualityToAttribute(intptr_t context)
+{
+    int32_t * air_quality_ptr = reinterpret_cast<int32_t *>(context);
+    AirQualitySensorManager::GetInstance()->OnAirQualityChangeHandler(classifyAirQuality(*air_quality_ptr));
+    ChipLogDetail(AppServer, "RAW AirQuality value: %ld and corresponding Enum value : %d", *air_quality_ptr,
+                  chip::to_underlying(AirQualitySensorManager::GetInstance()->GetAirQuality()));
+    AppTask::GetAppTask().UpdateAirQualitySensorUI();
+    delete air_quality_ptr;
+}
+
+void SensorManager::SensorTimerEventHandler(void * arg)
+{
+    int32_t air_quality;
+#ifdef USE_AIR_QUALITY_SENSOR
+    if (SL_STATUS_OK != AirQualitySensor::GetAirQuality(air_quality))
+    {
+        ChipLogDetail(AppServer, "Failed to read Air Quality !!!");
+        return;
+    }
+#else
+    // Initialize static variables to keep track of the current index and repetition count
+    static uint8_t nbOfRepetition = 0;
+    static uint8_t simulatedIndex = 0;
+
+    // Ensure the simulatedIndex wraps around the array size to avoid out-of-bounds access
+    simulatedIndex = simulatedIndex % ArraySize(mSimulatedAirQuality);
+    // Retrieve the current air quality value from the simulated data array using the simulatedIndex
+    air_quality = mSimulatedAirQuality[simulatedIndex];
+
+    // Increment the repetition count
+    nbOfRepetition++;
+    // Check if the number of repetitions has reached the threshold to simulate a new reading
+    if (nbOfRepetition >= kSimulatedReadingFrequency)
+    {
+        // Move to the next index for the next simulated reading
+        simulatedIndex++;
+        // Reset the repetition count
+        nbOfRepetition = 0;
+    }
+#endif // USE_AIR_QUALITY_SENSOR
+    // create pointer for the int32_t air_quality
+    int32_t * air_quality_ptr = new int32_t(air_quality);
+    DeviceLayer::PlatformMgr().ScheduleWork(writeAirQualityToAttribute, reinterpret_cast<intptr_t>(air_quality_ptr));
+}
diff --git a/examples/air-quality-sensor-app/silabs/src/ZclCallbacks.cpp b/examples/air-quality-sensor-app/silabs/src/ZclCallbacks.cpp
new file mode 100644
index 0000000..5bd4dd3
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/src/ZclCallbacks.cpp
@@ -0,0 +1,50 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file
+ *   This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+
+#include <air-quality-sensor-manager.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+#ifdef DIC_ENABLE
+#include "dic_control.h"
+#endif // DIC_ENABLE
+
+using namespace ::chip;
+using namespace ::chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+                                       uint8_t * value)
+{
+    ClusterId clusterId                      = attributePath.mClusterId;
+    [[maybe_unused]] AttributeId attributeId = attributePath.mAttributeId;
+    ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
+
+    if (clusterId == Identify::Id)
+    {
+        ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+                        ChipLogValueMEI(attributeId), type, *value, size);
+    }
+}
diff --git a/examples/air-quality-sensor-app/silabs/third_party/connectedhomeip b/examples/air-quality-sensor-app/silabs/third_party/connectedhomeip
new file mode 120000
index 0000000..c866b86
--- /dev/null
+++ b/examples/air-quality-sensor-app/silabs/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../..
\ No newline at end of file
diff --git a/examples/platform/silabs/display/demo-ui-bitmaps.h b/examples/platform/silabs/display/demo-ui-bitmaps.h
index 2a46413..fd2fff5 100644
--- a/examples/platform/silabs/display/demo-ui-bitmaps.h
+++ b/examples/platform/silabs/display/demo-ui-bitmaps.h
@@ -136,4 +136,162 @@
 #define OFF_DEMO_BITMAP ON_DEMO_BITMAP
 #endif
 
+#define SILABS_LOGO_WIDTH 47
+#define SILABS_LOGO_HEIGHT 18
+#define BLUETOOTH_ICON_SIZE 18
+
+// Status Icon defines
+#define STATUS_ICON_LINE 0
+#define SILABS_ICON_POSITION_X 0
+#define BLE_ICON_POSITION_X 72
+#define NETWORK_ICON_POSITION_X 90
+#define MATTER_ICON_POSITION_X 108
+
+#define BLUETOOTH_ICON_SMALL                                                                                                       \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xFE, 0xEF, 0xF1, 0x7F, 0x9F, 0xFF, 0x7B, 0xFF, 0x1F, 0xFE, 0xFF, 0xFC, 0xFF,  \
+        0xF3, 0xFF, 0x87, 0xFF, 0xEF, 0xFD, 0xDF, 0xE7, 0xBF, 0xC7, 0xFF, 0x9F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F
+
+#define SILABS_LOGO_SMALL                                                                                                          \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,  \
+        0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0x9F, 0xFF, 0xE7, 0x3F, 0xE0, 0xF1, 0x83,    \
+        0xFF, 0xF9, 0xEF, 0xFF, 0x3F, 0xE0, 0x3F, 0xFC, 0xFF, 0xFF, 0x7F, 0xF8, 0x0F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFE, 0x03, 0xFC,    \
+        0xFF, 0xF7, 0x9F, 0xFF, 0x81, 0x07, 0x02, 0xF8, 0xFF, 0xFF, 0xE0, 0x07, 0x00, 0xFE, 0xFF, 0xFF, 0xF8, 0x03, 0xC0, 0xFF,    \
+        0xFF, 0xFF, 0xFE, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0x3F
+
+#define MONACO_FONT_WIDTH 29
+#define MONACO_FONT_NB_LENGTH 232
+#define MONACO_FONT_CH_LENGTH 50
+
+#define MONACO_48PT                                                                                                                \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, 0xFF,    \
+        0x00, 0xF0, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x1F, 0x60, 0x00, 0xFF, 0x1F, 0xF8, 0x03, 0xFF, 0x0F,    \
+        0xFC, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xFC, 0x07, 0xFF, 0x03, 0xFC, 0x03, 0xFF, 0x03, 0xFC, 0x03,    \
+        0xFF, 0x01, 0xF8, 0x83, 0xFF, 0x00, 0xF8, 0x83, 0xFF, 0x00, 0xF8, 0x83, 0x7F, 0x30, 0xF8, 0x83, 0x3F, 0x30, 0xF8, 0x83,    \
+        0x3F, 0x38, 0xF8, 0x81, 0x1F, 0x3C, 0xF8, 0x81, 0x0F, 0x3C, 0xF8, 0x81, 0x0F, 0x3E, 0xF8, 0x81, 0x07, 0x3E, 0xF8, 0x81,    \
+        0x07, 0x3F, 0xF8, 0x83, 0x83, 0x3F, 0xF8, 0x83, 0x81, 0x3F, 0xF8, 0x83, 0xC1, 0x3F, 0xF8, 0x83, 0xE0, 0x1F, 0xF8, 0x03,    \
+        0xE0, 0x1F, 0xF8, 0x03, 0xF0, 0x1F, 0xF8, 0x03, 0xF8, 0x1F, 0xFC, 0x07, 0xF8, 0x0F, 0xFC, 0x07, 0xFC, 0x0F, 0xFC, 0x07,    \
+        0xFC, 0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFE, 0x0F, 0xF8, 0x03, 0xFF, 0x1F, 0xE0, 0x00, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x7F,    \
+        0x00, 0xC0, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x30 (48: '0')*/                            \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0xFC, 0xFF,    \
+        0x1F, 0x00, 0xFC, 0xFF, 0x0F, 0x10, 0xFC, 0xFF, 0x0F, 0x1C, 0xFC, 0xFF, 0x0F, 0x1E, 0xFC, 0xFF, 0xCF, 0x1F, 0xFC, 0xFF,    \
+        0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF,    \
+        0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF,    \
+        0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF,    \
+        0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF,    \
+        0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8,    \
+        0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x31 (49: '1')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF8, 0xFF,    \
+        0x3F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xF8, 0x00, 0xFF, 0x0F, 0xFF, 0x03, 0xFE,    \
+        0xEF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE,    \
+        0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF,    \
+        0xFF, 0x7F, 0xC0, 0xFF, 0xFF, 0x3F, 0xE0, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF, 0x07, 0xFC, 0xFF,    \
+        0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF,    \
+        0x3F, 0xF0, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF,    \
+        0x0F, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0xFC, 0x07, 0x00, 0x00, 0xFC,    \
+        0x07, 0x00, 0x00, 0xFC, 0x07, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x32 (50: '2')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFF,    \
+        0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x7C, 0x80, 0xFF, 0x8F, 0xFF, 0x01, 0xFF,    \
+        0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF,    \
+        0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x7F, 0xC0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF,    \
+        0x7F, 0x00, 0xF0, 0xFF, 0x7F, 0x00, 0xF8, 0xFF, 0x7F, 0x00, 0xE0, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0xFF,    \
+        0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC,    \
+        0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC,    \
+        0xFF, 0xFF, 0x07, 0xFE, 0xF7, 0xFF, 0x07, 0xFE, 0x87, 0xFF, 0x01, 0xFF, 0x07, 0x7C, 0x80, 0xFF, 0x07, 0x00, 0xC0, 0xFF,    \
+        0x07, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0xF0, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x33 (51: '3')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x3F, 0xE0, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF,    \
+        0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x83, 0xE0, 0xFF,    \
+        0xFF, 0x81, 0xE0, 0xFF, 0xFF, 0xC0, 0xE0, 0xFF, 0xFF, 0xE0, 0xE0, 0xFF, 0x7F, 0xE0, 0xE0, 0xFF, 0x3F, 0xF0, 0xE0, 0xFF,    \
+        0x3F, 0xF8, 0xE0, 0xFF, 0x1F, 0xF8, 0xE0, 0xFF, 0x0F, 0xFC, 0xE0, 0xFF, 0x0F, 0xFE, 0xE0, 0xFF, 0x07, 0xFE, 0xE0, 0xFF,    \
+        0x03, 0xFF, 0xE0, 0xFF, 0x83, 0xFF, 0xE0, 0xFF, 0x81, 0xFF, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xF0,    \
+        0x01, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x34 (52: '4')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE,    \
+        0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF,    \
+        0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xC0, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF,    \
+        0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFE,    \
+        0xFF, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC,    \
+        0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC,    \
+        0xFF, 0xFF, 0x07, 0xFE, 0xEF, 0xFF, 0x03, 0xFE, 0x07, 0xFF, 0x00, 0xFF, 0x07, 0x00, 0x80, 0xFF, 0x07, 0x00, 0xC0, 0xFF,    \
+        0x07, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x35 (53: '5')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF,    \
+        0xFF, 0x07, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0xFE, 0x7F, 0x80, 0x07, 0xFE, 0x3F, 0xE0, 0x7F, 0xFE,    \
+        0x1F, 0xF0, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF,    \
+        0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0x0F, 0xE0, 0xFF,    \
+        0x83, 0x03, 0x80, 0xFF, 0x83, 0x01, 0x00, 0xFF, 0x83, 0x00, 0x00, 0xFE, 0x03, 0xC0, 0x07, 0xFC, 0x03, 0xF0, 0x0F, 0xFC,    \
+        0x03, 0xF8, 0x1F, 0xF8, 0x03, 0xFC, 0x3F, 0xF8, 0x03, 0xFC, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8,    \
+        0x07, 0xFE, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, 0x0F, 0xFE, 0x3F, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8,    \
+        0x0F, 0xFC, 0x1F, 0xFC, 0x1F, 0xF8, 0x0F, 0xFC, 0x1F, 0xF0, 0x07, 0xFE, 0x3F, 0xC0, 0x01, 0xFE, 0x7F, 0x00, 0x00, 0xFF,    \
+        0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x36 (54: '6')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8,    \
+        0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE,    \
+        0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF,    \
+        0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF,    \
+        0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,    \
+        0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF,    \
+        0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0xFF,    \
+        0x7F, 0xF0, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x37 (55: '7')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF,    \
+        0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, 0xE0, 0x00, 0xFF, 0x3F, 0xF8, 0x03, 0xFF,    \
+        0x1F, 0xFC, 0x07, 0xFE, 0x1F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFC, 0x07, 0xFE,    \
+        0x1F, 0xF8, 0x07, 0xFF, 0x3F, 0xF0, 0x03, 0xFF, 0x3F, 0xE0, 0x81, 0xFF, 0x7F, 0xC0, 0x80, 0xFF, 0x7F, 0x00, 0xC0, 0xFF,    \
+        0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0x7F, 0x00, 0xC0, 0xFF,    \
+        0x3F, 0x60, 0x80, 0xFF, 0x1F, 0xF0, 0x00, 0xFF, 0x1F, 0xF8, 0x01, 0xFE, 0x0F, 0xFC, 0x03, 0xFE, 0x0F, 0xFC, 0x07, 0xFC,    \
+        0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFF, 0x1F, 0xFC, 0x07, 0xFF, 0x1F, 0xFC, 0x07, 0xFF, 0x1F, 0xFC,    \
+        0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFC, 0x0F, 0xFC, 0x0F, 0xF8, 0x07, 0xFE, 0x0F, 0xE0, 0x01, 0xFE, 0x1F, 0x00, 0x00, 0xFF,    \
+        0x3F, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x38 (56: '8')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFE, 0xFF,    \
+        0xFF, 0x00, 0xF0, 0xFF, 0x3F, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0xC0, 0xFF, 0x0F, 0x70, 0x80, 0xFF, 0x07, 0xFC, 0x01, 0xFF,    \
+        0x07, 0xFE, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x83, 0xFF, 0x07, 0xFE, 0x83, 0xFF, 0x07, 0xFE, 0x83, 0xFF, 0x0F, 0xFC,    \
+        0xC1, 0xFF, 0x0F, 0xFC, 0xC1, 0xFF, 0x0F, 0xFC, 0xC1, 0xFF, 0x0F, 0xFC, 0x83, 0xFF, 0x07, 0xFC, 0x83, 0xFF, 0x07, 0xFC,    \
+        0x83, 0xFF, 0x07, 0xFC, 0x03, 0xFF, 0x03, 0xF8, 0x03, 0xFE, 0x01, 0xF8, 0x07, 0x7C, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8,    \
+        0x1F, 0x00, 0x10, 0xF8, 0x3F, 0x00, 0x1C, 0xFC, 0xFF, 0x00, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC,    \
+        0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFE,    \
+        0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xCF, 0xFF, 0x80, 0xFF, 0x0F, 0x3E, 0xC0, 0xFF, 0x0F, 0x00, 0xE0, 0xFF,    \
+        0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x39 (57: '9')*/                      \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0x1F, 0xE0, 0x0F, 0xE3, 0xC7, 0xFF,    \
+        0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xC3, 0xFF, 0x87, 0xEF, 0x0F, 0xE0, 0x1F, 0xE0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x63 (99: 'c')*/                                  \
+        0xFF, 0xFB, 0x7F, 0xC0, 0x3F, 0xC0, 0x1F, 0xFF, 0x1F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x03, 0xF0, 0x03, 0xF0,    \
+        0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x66 (102: 'f')*/                                 \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xE3, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x20 (32: 'degree')*/
+
 #endif // SILABS_DEMO_UI_BITMAPS_H
diff --git a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp
new file mode 100644
index 0000000..43c5a55
--- /dev/null
+++ b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp
@@ -0,0 +1,109 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    Copyright (c) 2024 Google LLC.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "AirQualitySensor.h"
+#include "sl_board_control.h"
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef USE_SPARKFUN_AIR_QUALITY_SENSOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <sparkfun_sgp40.h>
+#include <sparkfun_sgp40_i2c.h>
+}
+#include "sl_i2cspm_instances.h"
+#endif // USE_SPARKFUN_AIR_QUALITY_SENSOR
+
+namespace {
+bool initialized = false;
+}
+
+namespace AirQualitySensor {
+
+/**
+ * @brief Initializes the air quality sensor.
+ *
+ * This function initializes the air quality sensor, specifically supporting the SparkFun SGP40 air quality sensor.
+ * It uses the I2C protocol for communication and sets up the VOC (Volatile Organic Compounds) algorithm for air quality
+ * measurement.
+ *
+ * @note If the macro USE_SPARKFUN_AIR_QUALITY_SENSOR is defined, the SparkFun SGP40 sensor is initialized.
+ *       If initialization is successful, the function returns SL_STATUS_OK, indicating the sensor is ready for use.
+ *       If the initialization fails, it returns SL_STATUS_FAIL. If USE_SPARKFUN_AIR_QUALITY_SENSOR is not defined,
+ *       it is expected that the user provides an implementation for their specific air quality sensor.
+ *
+ * @return sl_status_t Returns SL_STATUS_OK if the initialization is successful, otherwise returns SL_STATUS_FAIL.
+ */
+
+sl_status_t Init()
+{
+    sl_status_t status = SL_STATUS_FAIL;
+
+#ifdef USE_SPARKFUN_AIR_QUALITY_SENSOR
+    status = sparkfun_sgp40_init(sl_i2cspm_qwiic);
+    VerifyOrReturnError(status == SL_STATUS_OK, SL_STATUS_FAIL);
+    initialized = true;
+
+    sparkfun_sgp40_voc_algorithm_init();
+
+#else
+// User implementation of Init
+#endif // USE_SPARKFUN_AIR_QUALITY_SENSOR
+
+    return status;
+}
+
+/**
+ * @brief Retrieves the air quality measurement.
+ *
+ * This function fetches the current air quality measurement from the air quality sensor. It is designed to work
+ * with the SparkFun SGP40 air quality sensor when the USE_SPARKFUN_AIR_QUALITY_SENSOR macro is defined. The function
+ * calculates the VOC (Volatile Organic Compounds) index, which is used as a measure of air quality.
+ *
+ * @note The function requires the sensor to be initialized before calling. If the sensor is not initialized,
+ *       SL_STATUS_NOT_INITIALIZED is returned. For the SparkFun SGP40 sensor, the function uses hardcoded
+ *       values for humidity and temperature (50% and 25°C, respectively) as part of the VOC index calculation.
+ *       It is recommended to replace these magic numbers with actual sensor readings.
+ *
+ * @param air_quality A pointer to an integer where the air quality measurement will be stored.
+ *
+ * @return sl_status_t Returns SL_STATUS_OK if the air quality measurement is successfully retrieved,
+ *         SL_STATUS_NOT_INITIALIZED if the sensor has not been initialized, or other error codes as defined.
+ */
+
+sl_status_t GetAirQuality(int32_t & air_quality)
+{
+    sl_status_t status = SL_STATUS_FAIL;
+    VerifyOrReturnError(initialized, SL_STATUS_NOT_INITIALIZED);
+
+#ifdef USE_SPARKFUN_AIR_QUALITY_SENSOR
+    constexpr float relativeHumidity = 50; // 50%
+    constexpr float temperature      = 25; // 25°C
+
+    status = sparkfun_sgp40_get_voc_index(&air_quality, relativeHumidity, temperature);
+    VerifyOrReturnError(status == SL_STATUS_OK, status);
+
+#else
+    // User implementation of GetAirQuality
+#endif // USE_SPARKFUN_AIR_QUALITY_SENSOR
+
+    return status;
+}
+}; // namespace AirQualitySensor
diff --git a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.h b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.h
new file mode 100644
index 0000000..0ec2b9b
--- /dev/null
+++ b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.h
@@ -0,0 +1,28 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    Copyright (c) 2024 Google LLC.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <sl_status.h>
+#include <stdint.h>
+
+namespace AirQualitySensor {
+sl_status_t Init();
+sl_status_t GetAirQuality(int32_t & air_quality);
+}; // namespace AirQualitySensor
diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py
index 5f230e7..8d1b302 100755
--- a/scripts/build/build/targets.py
+++ b/scripts/build/build/targets.py
@@ -267,7 +267,8 @@
         TargetPart('light', app=Efr32App.LIGHT),
         TargetPart('lock', app=Efr32App.LOCK),
         TargetPart('thermostat', app=Efr32App.THERMOSTAT),
-        TargetPart('pump', app=Efr32App.PUMP)
+        TargetPart('pump', app=Efr32App.PUMP),
+        TargetPart('air-quality-sensor-app', app=Efr32App.AIR_QUALITY_SENSOR)
     ])
 
     target.AppendModifier('rpc', enable_rpcs=True)
diff --git a/scripts/build/builders/efr32.py b/scripts/build/builders/efr32.py
index 3c15cd4..0ca8649 100644
--- a/scripts/build/builders/efr32.py
+++ b/scripts/build/builders/efr32.py
@@ -31,6 +31,7 @@
     THERMOSTAT = auto()
     PUMP = auto()
     UNIT_TEST = auto()
+    AIR_QUALITY_SENSOR = auto()
 
     def ExampleName(self):
         if self == Efr32App.LIGHT:
@@ -45,6 +46,8 @@
             return 'thermostat'
         elif self == Efr32App.PUMP:
             return 'pump-app'
+        elif self == Efr32App.AIR_QUALITY_SENSOR:
+            return 'air-quality-sensor-app'
         else:
             raise Exception('Unknown app type: %r' % self)
 
@@ -63,6 +66,8 @@
             return 'matter-silabs-pump-example'
         elif self == Efr32App.UNIT_TEST:
             return 'matter-silabs-device_tests'
+        elif self == Efr32App.AIR_QUALITY_SENSOR:
+            return 'matter-silabs-air-quality-sensor-example'
         else:
             raise Exception('Unknown app type: %r' % self)
 
@@ -81,6 +86,8 @@
             return 'pump_app.flashbundle.txt'
         elif self == Efr32App.UNIT_TEST:
             return os.path.join('tests', 'efr32_device_tests.flashbundle.txt')
+        elif self == Efr32App.AIR_QUALITY_SENSOR:
+            return 'air_quality_sensor_app.flashbundle.txt'
         else:
             raise Exception('Unknown app type: %r' % self)
 
diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt
index 4ace53b..93e375c 100644
--- a/scripts/build/testdata/all_targets_linux_x64.txt
+++ b/scripts/build/testdata/all_targets_linux_x64.txt
@@ -5,7 +5,7 @@
 cc32xx-{lock,air-purifier}
 ti-cc13x4_26x4-{lighting,lock,pump,pump-controller}[-mtd][-ftd]
 cyw30739-{cyw30739b2_p5_evk_01,cyw30739b2_p5_evk_02,cyw30739b2_p5_evk_03,cyw930739m2evb_01,cyw930739m2evb_02}-{light,light-switch,lock,thermostat}
-efr32-{brd2704b,brd4316a,brd4317a,brd4318a,brd4319a,brd4186a,brd4187a,brd2601b,brd4187c,brd4186c,brd2703a,brd4338a,brd2605a}-{window-covering,switch,unit-test,light,lock,thermostat,pump}[-rpc][-with-ota-requestor][-icd][-low-power][-shell][-no-logging][-openthread-mtd][-heap-monitoring][-no-openthread-cli][-show-qr-code][-wifi][-rs9116][-wf200][-siwx917][-ipv4][-additional-data-advertising][-use-ot-lib][-use-ot-coap-lib][-no-version][-skip-rps-generation]
+efr32-{brd2704b,brd4316a,brd4317a,brd4318a,brd4319a,brd4186a,brd4187a,brd2601b,brd4187c,brd4186c,brd2703a,brd4338a,brd2605a}-{window-covering,switch,unit-test,light,lock,thermostat,pump,air-quality-sensor-app}[-rpc][-with-ota-requestor][-icd][-low-power][-shell][-no-logging][-openthread-mtd][-heap-monitoring][-no-openthread-cli][-show-qr-code][-wifi][-rs9116][-wf200][-siwx917][-ipv4][-additional-data-advertising][-use-ot-lib][-use-ot-coap-lib][-no-version][-skip-rps-generation]
 esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,energy-management,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only][-tracing][-data-model-disabled][-data-model-enabled]
 genio-lighting-app
 linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-pw-fuzztest][-coverage][-dmalloc][-clang]