diff --git a/.github/workflows/c.check.yml b/.github/workflows/c.check.yml new file mode 100644 index 0000000..7ec1eaa --- /dev/null +++ b/.github/workflows/c.check.yml @@ -0,0 +1,47 @@ +on: + push: + pull_request: + branches: + - master + +jobs: + code-analysis: + runs-on: "ubuntu-22.04" + steps: + - uses: actions/checkout@v4 + - uses: awalsh128/cache-apt-pkgs-action@a6c3917cc929dd0345bfb2d3feaf9101823370ad + with: + packages: clang-format + version: 1.0 + - name: clang-format + run: find . -type f -iregex ".*\.\(c\|h\|cpp\|ino\)" -exec clang-format -i -style=file {} \; && git diff --exit-code + + raspberry-pi-example-sources: + runs-on: "ubuntu-22.04" + steps: + - uses: actions/checkout@v4 + - name: run-download + run: | + cd ./examples/raspberry-pi + ls + make download + - uses: actions/upload-artifact@v4 + with: + name: raspi-source-dist + path: ./examples/raspberry-pi/* + if-no-files-found: error + build-raspberry-pi-examples: + runs-on: "ubuntu-22.04" + needs: raspberry-pi-example-sources + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: raspi-source-dist + path: ./examples/raspberry-pi/build-test + - name: test-build + run: | + cd ./examples/raspberry-pi/build-test + ls + make algorithm_example_usage + make low_power_example \ No newline at end of file diff --git a/.github/workflows/pyhton.build_deploy.yml b/.github/workflows/pyhton.build_deploy.yml new file mode 100644 index 0000000..5f5c8f6 --- /dev/null +++ b/.github/workflows/pyhton.build_deploy.yml @@ -0,0 +1,240 @@ +on: + push: + pull_request: + branches: + - master + +jobs: + generate-wrapper: + runs-on: "ubuntu-22.04" + defaults: + run: + working-directory: ./python-wrapper + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + uses: awalsh128/cache-apt-pkgs-action@a6c3917cc929dd0345bfb2d3feaf9101823370ad + with: + packages: gcc g++ swig + version: 1.0 + - name: generate wrapper + run: ./generate_swig_wrapper.sh + shell: bash + - uses: actions/upload-artifact@v4 + with: + name: python-sources + path: python-wrapper/sensirion_gas_index_algorithm/** + if-no-files-found: error + - uses: actions/upload-artifact@v4 + with: + name: swig-sources + path: python-wrapper/swig/** + if-no-files-found: error + check_readme_rst_syntax: + runs-on: "ubuntu-22.04" + defaults: + run: + working-directory: ./python-wrapper + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.8 + - name: install rst linter + run: pip install restructuredtext-lint pygments + - name: run + run: rst-lint *.rst + build: + continue-on-error: true + strategy: + matrix: + py-version: ["3.8", "3.9"] + os: [ubuntu-22.04, windows-2019, macOS-15] + fail-fast: false + runs-on: ${{ matrix.os }} + needs: generate-wrapper + defaults: + run: + working-directory: ./python-wrapper + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: python-sources + path: python-wrapper/sensirion_gas_index_algorithm + - uses: actions/download-artifact@v4 + with: + name: swig-sources + path: python-wrapper/swig + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.py-version }} + - name: install package + run: | + pip3 install -e .[test] + pip3 install wheel + - name: static test + run: flake8 + - name: unit test + run: pytest + - name: create wheel + run: python3 setup.py bdist_wheel + - uses: actions/upload-artifact@v4 + with: + name: py_${{ matrix.py-version }}_${{ matrix.os}}_build + path: python-wrapper/dist/** + if-no-files-found: error + py3p8_linux_sdist: + runs-on: "ubuntu-22.04" + needs: generate-wrapper + defaults: + run: + working-directory: ./python-wrapper + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: python-sources + path: python-wrapper/sensirion_gas_index_algorithm + - uses: actions/download-artifact@v4 + with: + name: swig-sources + path: python-wrapper/swig + - uses: actions/setup-python@v5 + with: + python-version: 3.8 + - name: create dist package + run: python3 setup.py sdist + - uses: actions/upload-artifact@v4 + with: + name: py_source_dist + path: python-wrapper/dist/** + if-no-files-found: error + build_pages: + runs-on: "ubuntu-22.04" + needs: generate-wrapper + defaults: + run: + working-directory: ./python-wrapper + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: python-sources + path: python-wrapper/sensirion_gas_index_algorithm + - uses: actions/download-artifact@v4 + with: + name: swig-sources + path: python-wrapper/swig + - uses: actions/setup-python@v5 + with: + python-version: 3.8 + cache: "pip" + - name: Install the project dependencies + run: | + python setup.py install + python -m pip install -r docs/requirements.txt + - name: Build documentation + run: cd ./docs && make html + - name: Upload html + uses: actions/upload-pages-artifact@v3 + with: + path: python-wrapper/docs/_build/html + deploy_pages: + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + runs-on: "ubuntu-22.04" + needs: build_pages + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + # Deploy to the github-pages environment + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + deploy_pypi: + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + runs-on: "ubuntu-22.04" + permissions: + id-token: write + needs: ["py3p8_linux_sdist", "build"] + steps: + - name: download python source dist artifacts + uses: actions/download-artifact@v4 + with: + path: python-wrapper/dist + name: py_source_dist + - name: download win python build artifacts + uses: actions/download-artifact@v4 + with: + path: python-wrapper/dist + merge-multiple: true + pattern: py_*windows*_build + - name: download mac build artifacts + uses: actions/download-artifact@v4 + with: + path: python-wrapper/dist + merge-multiple: true + pattern: py_*macOS*_build + # pypi does not accept the linux wheels with _x86_64, thus not uploading any linux wheels + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} + github-release: + name: Create GitHub Release and add signature for python packages + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + needs: + - build + - py3p8_linux_sdist + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: ./python-wrapper + permissions: + contents: write + id-token: write + steps: + - uses: actions/checkout@v4 + - name: download python source dist artifacts + uses: actions/download-artifact@v4 + with: + path: python-wrapper/dist + merge-multiple: true + name: py_source_dist + - name: download python build artifacts + uses: actions/download-artifact@v4 + with: + path: python-wrapper/dist + merge-multiple: true + pattern: py_*_build + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if [[ "$(gh release view '${{ github.ref_name }}' 2>&1)" == "release not found" ]]; then + gh release create '${{ github.ref_name }}' --repo '${{ github.repository }}' --notes "" + fi + - name: Upload artifacts to GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Upload release artifacts before the signing, such that artifacts are still uploaded if signing fails + run: | + gh release upload '${{ github.ref_name }}' dist/** --repo '${{ github.repository }}' + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46 + with: + inputs: >- + ./python-wrapper/dist/*.tar.gz + ./python-wrapper/dist/*.whl + - name: Upload signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # upload sigstore-produced signatures and certificates from dist + run: | + gh release upload '${{ github.ref_name }}' dist/*.sigstore.json --repo '${{ github.repository }}' \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 9b78e2e..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,34 +0,0 @@ -include: - - local: python-wrapper/.gitlab-ci.yml - -variables: - RASPI_EXAMPLE_FOLDER: examples/raspberry-pi - RASPI_OUTPUT_FOLDER: raspi-gas-index-algorithm-example - -stages: - - prepare - - validate - - build - - deploy - -c_syntax_check: - stage: validate - image: - name: registry.gitlab.sensirion.lokal/mso-sw/drivers/docker-driver-generator:0.1.0 - tags: [linux, docker] - script: - - find . -type f -iregex ".*\.\(c\|h\|cpp\|ino\)" -exec clang-format-6.0 -i -style=file {} \; && git diff --exit-code - -raspberry-pi-example: - stage: build - image: - name: sensirion/embedded-ci:2.4.0 - tags: [linux, docker] - before_script: - script: - - cd ${RASPI_EXAMPLE_FOLDER} && make download - - cp -r ${CI_PROJECT_DIR}/${RASPI_EXAMPLE_FOLDER} ${CI_PROJECT_DIR}/${RASPI_OUTPUT_FOLDER} - artifacts: - name: Raspberry-Pi-Gas-Index-Algorithm-Example - paths: - - $RASPI_OUTPUT_FOLDER diff --git a/README.md b/README.md index 31ecd2c..fd65ad1 100644 --- a/README.md +++ b/README.md @@ -117,12 +117,6 @@ Continuous | 1 s | 6.3mW **Contributions are welcome!** -We develop and test this algorithm using our company internal tools (version -control, continuous integration, code review etc.) and automatically -synchronize the master branch with GitHub. But this doesn't mean that we don't -respond to issues or don't accept pull requests on GitHub. In fact, you're very -welcome to open issues or create pull requests :) - This Sensirion library uses [`clang-format`](https://releases.llvm.org/download.html) to standardize the formatting of all our `.c` and `.h` files. Make sure your contributions are diff --git a/examples/raspberry-pi/algorithm_example_usage.c b/examples/raspberry-pi/algorithm_example_usage.c index 2f8ceb0..3b7b4f2 100644 --- a/examples/raspberry-pi/algorithm_example_usage.c +++ b/examples/raspberry-pi/algorithm_example_usage.c @@ -30,8 +30,8 @@ */ #include "sensirion_gas_index_algorithm.h" -#include // printf #include +#include // printf #include "sensirion_common.h" #include "sensirion_i2c_hal.h" diff --git a/examples/raspberry-pi/low_power_example.c b/examples/raspberry-pi/low_power_example.c index a3f9b3d..f437a5a 100644 --- a/examples/raspberry-pi/low_power_example.c +++ b/examples/raspberry-pi/low_power_example.c @@ -30,8 +30,8 @@ */ #include "sensirion_gas_index_algorithm.h" -#include // printf #include +#include // printf #include "sensirion_common.h" #include "sensirion_i2c_hal.h" @@ -41,7 +41,6 @@ uint16_t DEFAULT_COMPENSATION_RH = 0x8000; // in ticks as defined by SGP40 uint16_t DEFAULT_COMPENSATION_T = 0x6666; // in ticks as defined by SGP40 - void read_compensation_values(uint16_t* compensation_rh, uint16_t* compensation_t); @@ -52,13 +51,14 @@ int main(void) { uint16_t sraw_voc = 0; int32_t voc_index_value = 0; // Sampling interval in seconds - // This code uses a fixed heating pulse of ca. 200 ms for the measurement and thus, - // the sampling interval defines the duty cycle + // This code uses a fixed heating pulse of ca. 200 ms for the measurement + // and thus, the sampling interval defines the duty cycle float sampling_interval = 1.f; // initialize gas index parameters GasIndexAlgorithmParams voc_params; - GasIndexAlgorithm_init_with_sampling_interval(&voc_params, GasIndexAlgorithm_ALGORITHM_TYPE_VOC, sampling_interval); + GasIndexAlgorithm_init_with_sampling_interval( + &voc_params, GasIndexAlgorithm_ALGORITHM_TYPE_VOC, sampling_interval); // initialize i2c communication used for SHT4x and SGP40 sensirion_i2c_hal_init(); @@ -66,8 +66,10 @@ int main(void) { for (int i = 0; i < 100; i += 1) { // 1. Sleep: Total loop time should match the chosen sampling interval - // Therefore we take into account the heater delay and the measurement delays. - sensirion_i2c_hal_sleep_usec(((uint32_t)(sampling_interval*1000)-240)*1000); + // Therefore we take into account the heater delay and the measurement + // delays. + sensirion_i2c_hal_sleep_usec( + ((uint32_t)(sampling_interval * 1000) - 240) * 1000); // 2. Measure SHT4x RH and T signals and convert to SGP40 ticks read_compensation_values(&compensation_rh, &compensation_t); @@ -75,7 +77,7 @@ int main(void) { // 3. Measure SGP40 signal with low power mode // 3.1 Request a first measurement to turn the heater on error = sgp40_measure_raw_signal(compensation_rh, compensation_t, - &sraw_voc); + &sraw_voc); if (error) { printf("Error executing sgp40_measure_raw_signals(): %i\n", error); continue; @@ -86,7 +88,7 @@ int main(void) { // 3.3 Request the actual measurement error = sgp40_measure_raw_signal(compensation_rh, compensation_t, - &sraw_voc); + &sraw_voc); if (error) { printf("Error executing sgp40_measure_raw_signals(): %i\n", error); @@ -105,7 +107,6 @@ int main(void) { // index values GasIndexAlgorithm_process(&voc_params, sraw_voc, &voc_index_value); printf("VOC Raw: %i\tVOC Index: %i\n", sraw_voc, voc_index_value); - } return 0; @@ -122,8 +123,8 @@ int main(void) { void read_compensation_values(uint16_t* compensation_rh, uint16_t* compensation_t) { int16_t error = 0; - float s_rh = 0; // %RH - float s_temperature = 0; // degC + float s_rh = 0; // %RH + float s_temperature = 0; // degC error = sht4x_measure_high_precision(&s_temperature, &s_rh); if (error) { printf("Error executing sht4x_measure_high_precision(): %i\n", error); @@ -134,7 +135,7 @@ void read_compensation_values(uint16_t* compensation_rh, printf("T: %.2f\tRH: %.2f\n", s_temperature, s_rh); // convert temperature and humidity to ticks as defined by SGP40 - // interface + // interface // NOTE: in case you read RH and T raw signals check out the // ticks specification in the datasheet, as they can be different for // different sensors diff --git a/python-wrapper/.gitlab-ci.yml b/python-wrapper/.gitlab-ci.yml deleted file mode 100644 index 0796b8a..0000000 --- a/python-wrapper/.gitlab-ci.yml +++ /dev/null @@ -1,119 +0,0 @@ -include: - - project: 'Sensirion/Python/ci-config-python' - ref: master - file: 'gitlab-ci-template-v2.yml' - -before_script: - - cd python-wrapper - -generate_swig_wrappers: - stage: prepare - tags: - - linux - - docker - image: registry.gitlab.sensirion.lokal/sensirion/docker/docker-python:3.8-20.04-2.11.0 - script: - - ./generate_swig_wrapper.sh - artifacts: - expire_in: 1 week - untracked: true - -check_rst_syntax: - extends: .check_rst_syntax_v2 - -check_editorconfig: - extends: .check_editorconfig_v2 - -py3p6_linux_build: - extends: .py3p6_linux_build_v2 - artifacts: - expire_in: 1 week - paths: - - python-wrapper/dist/ - -py3p8_linux_sdist: - extends: .py3p8_linux_sdist_v2 - artifacts: - expire_in: 1 week - paths: - - python-wrapper/dist/ - -py3p8_linux_build: - extends: .py3p8_linux_build_v2 - artifacts: - expire_in: 1 week - paths: - - python-wrapper/dist/ - -py3p8_64bit_win_build: - extends: .py3p8_64bit_win_docker_build_v2 - artifacts: - expire_in: 1 week - paths: - - python-wrapper/dist/ - -py3p8_osx_build: - stage: build - tags: [osx, python38] - script: - # avoid using new pip resolver as it takes a very long time to resolve dependencies - - pip install --use-deprecated=legacy-resolver -e .[test] - - pytest - - python3 setup.py bdist_wheel - artifacts: - expire_in: 1 week - paths: - - python-wrapper/dist/ - -build_docs: - stage: build - tags: [ linux, docker ] - image: registry.gitlab.sensirion.lokal/sensirion/docker/docker-python:3.8-20.04-2.11.0 - variables: - SPHINXOPTS: "-W --keep-going" - script: - - python setup.py install - - pip install -r docs/requirements.txt - - cd docs - - make html - after_script: - - mv python-wrapper/docs/_build/html/ public/ # everything in public/ will get published - artifacts: - paths: [public] - expire_in: 1 week - when: always - -deploy_staging: - extends: .deploy_staging_v2 - before_script: - # For performance and stability reasons, use offline installation. - - pip install --no-index --find-links=/pip devpi-client - - cd python-wrapper - -deploy_stable: - extends: .deploy_stable_v2 - needs: [py3p8_linux_sdist, py3p8_64bit_win_build] - environment: - name: pypi.org - url: https://pypi.org/project/sensirion-gas-index-algorithm/ - before_script: - - cd python-wrapper - - pip install twine~=1.12.1 - script: - - PKG_VERSION=$(python setup.py --version --quiet | tail -n1) - - TAG_VERSION=$(git describe --tags) - - if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then echo "Tag Version ($TAG_VERSION) != Package Version ($PKG_VERSION)" && exit 1; fi - - twine upload dist/* - -deploy_docs: - stage: deploy - tags: [linux, docker] - image: registry.gitlab.sensirion.lokal/sensirion/docker/docker-python:3.8-20.04-2.11.0 - dependencies: [build_docs] - only: [master, tags] - script: - - cd .. - - chmod 777 ./python-wrapper/ci/set_git_config.sh - - ./python-wrapper/ci/set_git_config.sh - - chmod 777 ./python-wrapper/ci/checkin_doc.sh - - ./python-wrapper/ci/checkin_doc.sh \ No newline at end of file diff --git a/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.c b/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.c index 21e0234..acb510e 100644 --- a/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.c +++ b/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.c @@ -280,41 +280,67 @@ static fix16_t fix16_exp(fix16_t x) { return res; } - -static void GasIndexAlgorithm__init_instances(GasIndexAlgorithmParams *params); -static void GasIndexAlgorithm__mean_variance_estimator__set_parameters(GasIndexAlgorithmParams *params); -static void GasIndexAlgorithm__mean_variance_estimator__set_states(GasIndexAlgorithmParams *params, fix16_t mean, fix16_t std, fix16_t uptime_gamma); -static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_std(const GasIndexAlgorithmParams *params); -static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_mean(const GasIndexAlgorithmParams *params); -static bool GasIndexAlgorithm__mean_variance_estimator__is_initialized(GasIndexAlgorithmParams *params); -static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(GasIndexAlgorithmParams *params); -static void GasIndexAlgorithm__mean_variance_estimator__process(GasIndexAlgorithmParams *params, fix16_t sraw); -static void GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(GasIndexAlgorithmParams *params, fix16_t X0, fix16_t K); -static fix16_t GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(GasIndexAlgorithmParams *params, fix16_t sample); -static void GasIndexAlgorithm__mox_model__set_parameters(GasIndexAlgorithmParams *params, fix16_t SRAW_STD, fix16_t SRAW_MEAN); -static fix16_t GasIndexAlgorithm__mox_model__process(GasIndexAlgorithmParams *params, fix16_t sraw); -static void GasIndexAlgorithm__sigmoid_scaled__set_parameters(GasIndexAlgorithmParams *params, fix16_t X0, fix16_t K, fix16_t offset_default); -static fix16_t GasIndexAlgorithm__sigmoid_scaled__process(GasIndexAlgorithmParams *params, fix16_t sample); -static void GasIndexAlgorithm__adaptive_lowpass__set_parameters(GasIndexAlgorithmParams *params); -static fix16_t GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmParams *params, fix16_t sample); - -void GasIndexAlgorithm_init(GasIndexAlgorithmParams *params, int32_t algorithm_type) { +static void GasIndexAlgorithm__init_instances(GasIndexAlgorithmParams* params); +static void GasIndexAlgorithm__mean_variance_estimator__set_parameters( + GasIndexAlgorithmParams* params); +static void GasIndexAlgorithm__mean_variance_estimator__set_states( + GasIndexAlgorithmParams* params, fix16_t mean, fix16_t std, + fix16_t uptime_gamma); +static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_std( + const GasIndexAlgorithmParams* params); +static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_mean( + const GasIndexAlgorithmParams* params); +static bool GasIndexAlgorithm__mean_variance_estimator__is_initialized( + GasIndexAlgorithmParams* params); +static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma( + GasIndexAlgorithmParams* params); +static void GasIndexAlgorithm__mean_variance_estimator__process( + GasIndexAlgorithmParams* params, fix16_t sraw); +static void +GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters( + GasIndexAlgorithmParams* params, fix16_t X0, fix16_t K); +static fix16_t GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + GasIndexAlgorithmParams* params, fix16_t sample); +static void GasIndexAlgorithm__mox_model__set_parameters( + GasIndexAlgorithmParams* params, fix16_t SRAW_STD, fix16_t SRAW_MEAN); +static fix16_t +GasIndexAlgorithm__mox_model__process(GasIndexAlgorithmParams* params, + fix16_t sraw); +static void GasIndexAlgorithm__sigmoid_scaled__set_parameters( + GasIndexAlgorithmParams* params, fix16_t X0, fix16_t K, + fix16_t offset_default); +static fix16_t +GasIndexAlgorithm__sigmoid_scaled__process(GasIndexAlgorithmParams* params, + fix16_t sample); +static void GasIndexAlgorithm__adaptive_lowpass__set_parameters( + GasIndexAlgorithmParams* params); +static fix16_t +GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmParams* params, + fix16_t sample); + +void GasIndexAlgorithm_init(GasIndexAlgorithmParams* params, + int32_t algorithm_type) { params->mAlgorithm_Type = algorithm_type; if ((algorithm_type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) { params->mIndex_Offset = F16(GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT); params->mSraw_Minimum = GasIndexAlgorithm_NOX_SRAW_MINIMUM; - params->mGating_Max_Duration_Minutes = F16(GasIndexAlgorithm_GATING_NOX_MAX_DURATION_MINUTES); - params->mInit_Duration_Mean = F16(GasIndexAlgorithm_INIT_DURATION_MEAN_NOX); - params->mInit_Duration_Variance = F16(GasIndexAlgorithm_INIT_DURATION_VARIANCE_NOX); + params->mGating_Max_Duration_Minutes = + F16(GasIndexAlgorithm_GATING_NOX_MAX_DURATION_MINUTES); + params->mInit_Duration_Mean = + F16(GasIndexAlgorithm_INIT_DURATION_MEAN_NOX); + params->mInit_Duration_Variance = + F16(GasIndexAlgorithm_INIT_DURATION_VARIANCE_NOX); params->mGating_Threshold = F16(GasIndexAlgorithm_GATING_THRESHOLD_NOX); - } - else { + } else { params->mIndex_Offset = F16(GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT); params->mSraw_Minimum = GasIndexAlgorithm_VOC_SRAW_MINIMUM; - params->mGating_Max_Duration_Minutes = F16(GasIndexAlgorithm_GATING_VOC_MAX_DURATION_MINUTES); - params->mInit_Duration_Mean = F16(GasIndexAlgorithm_INIT_DURATION_MEAN_VOC); - params->mInit_Duration_Variance = F16(GasIndexAlgorithm_INIT_DURATION_VARIANCE_VOC); + params->mGating_Max_Duration_Minutes = + F16(GasIndexAlgorithm_GATING_VOC_MAX_DURATION_MINUTES); + params->mInit_Duration_Mean = + F16(GasIndexAlgorithm_INIT_DURATION_MEAN_VOC); + params->mInit_Duration_Variance = + F16(GasIndexAlgorithm_INIT_DURATION_VARIANCE_VOC); params->mGating_Threshold = F16(GasIndexAlgorithm_GATING_THRESHOLD_VOC); } params->mIndex_Gain = F16(GasIndexAlgorithm_INDEX_GAIN); @@ -324,112 +350,169 @@ void GasIndexAlgorithm_init(GasIndexAlgorithmParams *params, int32_t algorithm_ GasIndexAlgorithm_reset(params); } -void GasIndexAlgorithm_reset(GasIndexAlgorithmParams *params) { +void GasIndexAlgorithm_reset(GasIndexAlgorithmParams* params) { params->mUptime = F16(0.); params->mSraw = F16(0.); params->mGas_Index = 0; GasIndexAlgorithm__init_instances(params); } -static void GasIndexAlgorithm__init_instances(GasIndexAlgorithmParams *params) { +static void GasIndexAlgorithm__init_instances(GasIndexAlgorithmParams* params) { GasIndexAlgorithm__mean_variance_estimator__set_parameters(params); - GasIndexAlgorithm__mox_model__set_parameters(params, GasIndexAlgorithm__mean_variance_estimator__get_std(params), GasIndexAlgorithm__mean_variance_estimator__get_mean(params)); + GasIndexAlgorithm__mox_model__set_parameters( + params, GasIndexAlgorithm__mean_variance_estimator__get_std(params), + GasIndexAlgorithm__mean_variance_estimator__get_mean(params)); if ((params->mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) { - GasIndexAlgorithm__sigmoid_scaled__set_parameters(params, F16(GasIndexAlgorithm_SIGMOID_X0_NOX), F16(GasIndexAlgorithm_SIGMOID_K_NOX), F16(GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT)); - } - else { - GasIndexAlgorithm__sigmoid_scaled__set_parameters(params, F16(GasIndexAlgorithm_SIGMOID_X0_VOC), F16(GasIndexAlgorithm_SIGMOID_K_VOC), F16(GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT)); + GasIndexAlgorithm__sigmoid_scaled__set_parameters( + params, F16(GasIndexAlgorithm_SIGMOID_X0_NOX), + F16(GasIndexAlgorithm_SIGMOID_K_NOX), + F16(GasIndexAlgorithm_NOX_INDEX_OFFSET_DEFAULT)); + } else { + GasIndexAlgorithm__sigmoid_scaled__set_parameters( + params, F16(GasIndexAlgorithm_SIGMOID_X0_VOC), + F16(GasIndexAlgorithm_SIGMOID_K_VOC), + F16(GasIndexAlgorithm_VOC_INDEX_OFFSET_DEFAULT)); } GasIndexAlgorithm__adaptive_lowpass__set_parameters(params); } -void GasIndexAlgorithm_get_states(const GasIndexAlgorithmParams *params, int32_t *state0, int32_t *state1) { +void GasIndexAlgorithm_get_states(const GasIndexAlgorithmParams* params, + int32_t* state0, int32_t* state1) { *state0 = GasIndexAlgorithm__mean_variance_estimator__get_mean(params); *state1 = GasIndexAlgorithm__mean_variance_estimator__get_std(params); - return ; + return; } -void GasIndexAlgorithm_set_states(GasIndexAlgorithmParams *params, int32_t state0, int32_t state1) { +void GasIndexAlgorithm_set_states(GasIndexAlgorithmParams* params, + int32_t state0, int32_t state1) { - GasIndexAlgorithm__mean_variance_estimator__set_states(params, state0, state1, F16(GasIndexAlgorithm_PERSISTENCE_UPTIME_GAMMA)); - GasIndexAlgorithm__mox_model__set_parameters(params, GasIndexAlgorithm__mean_variance_estimator__get_std(params), GasIndexAlgorithm__mean_variance_estimator__get_mean(params)); + GasIndexAlgorithm__mean_variance_estimator__set_states( + params, state0, state1, + F16(GasIndexAlgorithm_PERSISTENCE_UPTIME_GAMMA)); + GasIndexAlgorithm__mox_model__set_parameters( + params, GasIndexAlgorithm__mean_variance_estimator__get_std(params), + GasIndexAlgorithm__mean_variance_estimator__get_mean(params)); params->mSraw = state0; } -void GasIndexAlgorithm_set_tuning_parameters(GasIndexAlgorithmParams *params, int32_t index_offset, int32_t learning_time_offset_hours, int32_t learning_time_gain_hours, int32_t gating_max_duration_minutes, int32_t std_initial, int32_t gain_factor) { +void GasIndexAlgorithm_set_tuning_parameters( + GasIndexAlgorithmParams* params, int32_t index_offset, + int32_t learning_time_offset_hours, int32_t learning_time_gain_hours, + int32_t gating_max_duration_minutes, int32_t std_initial, + int32_t gain_factor) { params->mIndex_Offset = (fix16_from_int(index_offset)); params->mTau_Mean_Hours = (fix16_from_int(learning_time_offset_hours)); params->mTau_Variance_Hours = (fix16_from_int(learning_time_gain_hours)); - params->mGating_Max_Duration_Minutes = (fix16_from_int(gating_max_duration_minutes)); + params->mGating_Max_Duration_Minutes = + (fix16_from_int(gating_max_duration_minutes)); params->mSraw_Std_Initial = (fix16_from_int(std_initial)); params->mIndex_Gain = (fix16_from_int(gain_factor)); GasIndexAlgorithm__init_instances(params); } -void GasIndexAlgorithm_get_tuning_parameters(const GasIndexAlgorithmParams *params, int32_t *index_offset, int32_t *learning_time_offset_hours, int32_t *learning_time_gain_hours, int32_t *gating_max_duration_minutes, int32_t *std_initial, int32_t *gain_factor) { +void GasIndexAlgorithm_get_tuning_parameters( + const GasIndexAlgorithmParams* params, int32_t* index_offset, + int32_t* learning_time_offset_hours, int32_t* learning_time_gain_hours, + int32_t* gating_max_duration_minutes, int32_t* std_initial, + int32_t* gain_factor) { *index_offset = (fix16_cast_to_int(params->mIndex_Offset)); *learning_time_offset_hours = (fix16_cast_to_int(params->mTau_Mean_Hours)); - *learning_time_gain_hours = (fix16_cast_to_int(params->mTau_Variance_Hours)); - *gating_max_duration_minutes = (fix16_cast_to_int(params->mGating_Max_Duration_Minutes)); + *learning_time_gain_hours = + (fix16_cast_to_int(params->mTau_Variance_Hours)); + *gating_max_duration_minutes = + (fix16_cast_to_int(params->mGating_Max_Duration_Minutes)); *std_initial = (fix16_cast_to_int(params->mSraw_Std_Initial)); *gain_factor = (fix16_cast_to_int(params->mIndex_Gain)); - return ; + return; } -void GasIndexAlgorithm_process(GasIndexAlgorithmParams *params, int32_t sraw, int32_t *gas_index) { +void GasIndexAlgorithm_process(GasIndexAlgorithmParams* params, int32_t sraw, + int32_t* gas_index) { if ((params->mUptime <= F16(GasIndexAlgorithm_INITIAL_BLACKOUT))) { - params->mUptime = (params->mUptime + F16(GasIndexAlgorithm_SAMPLING_INTERVAL)); - } - else { + params->mUptime = + (params->mUptime + F16(GasIndexAlgorithm_SAMPLING_INTERVAL)); + } else { if (((sraw > 0) && (sraw < 65000))) { if ((sraw < (params->mSraw_Minimum + 1))) { sraw = (params->mSraw_Minimum + 1); - } - else if ((sraw > (params->mSraw_Minimum + 32767))) { + } else if ((sraw > (params->mSraw_Minimum + 32767))) { sraw = (params->mSraw_Minimum + 32767); } params->mSraw = (fix16_from_int((sraw - params->mSraw_Minimum))); } - if (((params->mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_VOC) || GasIndexAlgorithm__mean_variance_estimator__is_initialized(params))) { - params->mGas_Index = GasIndexAlgorithm__mox_model__process(params, params->mSraw); - params->mGas_Index = GasIndexAlgorithm__sigmoid_scaled__process(params, params->mGas_Index); - } - else { + if (((params->mAlgorithm_Type == + GasIndexAlgorithm_ALGORITHM_TYPE_VOC) || + GasIndexAlgorithm__mean_variance_estimator__is_initialized( + params))) { + params->mGas_Index = + GasIndexAlgorithm__mox_model__process(params, params->mSraw); + params->mGas_Index = GasIndexAlgorithm__sigmoid_scaled__process( + params, params->mGas_Index); + } else { params->mGas_Index = params->mIndex_Offset; } - params->mGas_Index = GasIndexAlgorithm__adaptive_lowpass__process(params, params->mGas_Index); + params->mGas_Index = GasIndexAlgorithm__adaptive_lowpass__process( + params, params->mGas_Index); if ((params->mGas_Index < F16(0.5))) { params->mGas_Index = F16(0.5); } if ((params->mSraw > F16(0.))) { - GasIndexAlgorithm__mean_variance_estimator__process(params, params->mSraw); - GasIndexAlgorithm__mox_model__set_parameters(params, GasIndexAlgorithm__mean_variance_estimator__get_std(params), GasIndexAlgorithm__mean_variance_estimator__get_mean(params)); + GasIndexAlgorithm__mean_variance_estimator__process(params, + params->mSraw); + GasIndexAlgorithm__mox_model__set_parameters( + params, + GasIndexAlgorithm__mean_variance_estimator__get_std(params), + GasIndexAlgorithm__mean_variance_estimator__get_mean(params)); } } *gas_index = (fix16_cast_to_int((params->mGas_Index + F16(0.5)))); - return ; + return; } -static void GasIndexAlgorithm__mean_variance_estimator__set_parameters(GasIndexAlgorithmParams *params) { +static void GasIndexAlgorithm__mean_variance_estimator__set_parameters( + GasIndexAlgorithmParams* params) { params->m_Mean_Variance_Estimator___Initialized = false; params->m_Mean_Variance_Estimator___Mean = F16(0.); params->m_Mean_Variance_Estimator___Sraw_Offset = F16(0.); params->m_Mean_Variance_Estimator___Std = params->mSraw_Std_Initial; - params->m_Mean_Variance_Estimator___Gamma_Mean = (fix16_div(F16(((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING * GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) * (GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))), (params->mTau_Mean_Hours + F16((GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))))); - params->m_Mean_Variance_Estimator___Gamma_Variance = (fix16_div(F16((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING * (GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))), (params->mTau_Variance_Hours + F16((GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))))); + params->m_Mean_Variance_Estimator___Gamma_Mean = (fix16_div( + F16(( + (GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING * + GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) * + (GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))), + (params->mTau_Mean_Hours + + F16((GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))))); + params->m_Mean_Variance_Estimator___Gamma_Variance = (fix16_div( + F16((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING * + (GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))), + (params->mTau_Variance_Hours + + F16((GasIndexAlgorithm_SAMPLING_INTERVAL / 3600.))))); if ((params->mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) { - params->m_Mean_Variance_Estimator___Gamma_Initial_Mean = F16((((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING * GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) * GasIndexAlgorithm_SAMPLING_INTERVAL) / (GasIndexAlgorithm_TAU_INITIAL_MEAN_NOX + GasIndexAlgorithm_SAMPLING_INTERVAL))); - } - else { - params->m_Mean_Variance_Estimator___Gamma_Initial_Mean = F16((((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING * GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) * GasIndexAlgorithm_SAMPLING_INTERVAL) / (GasIndexAlgorithm_TAU_INITIAL_MEAN_VOC + GasIndexAlgorithm_SAMPLING_INTERVAL))); - } - params->m_Mean_Variance_Estimator___Gamma_Initial_Variance = F16(((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING * GasIndexAlgorithm_SAMPLING_INTERVAL) / (GasIndexAlgorithm_TAU_INITIAL_VARIANCE + GasIndexAlgorithm_SAMPLING_INTERVAL))); + params->m_Mean_Variance_Estimator___Gamma_Initial_Mean = F16(( + ((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING * + GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) * + GasIndexAlgorithm_SAMPLING_INTERVAL) / + (GasIndexAlgorithm_TAU_INITIAL_MEAN_NOX + + GasIndexAlgorithm_SAMPLING_INTERVAL))); + } else { + params->m_Mean_Variance_Estimator___Gamma_Initial_Mean = F16(( + ((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING * + GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) * + GasIndexAlgorithm_SAMPLING_INTERVAL) / + (GasIndexAlgorithm_TAU_INITIAL_MEAN_VOC + + GasIndexAlgorithm_SAMPLING_INTERVAL))); + } + params->m_Mean_Variance_Estimator___Gamma_Initial_Variance = + F16(((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING * + GasIndexAlgorithm_SAMPLING_INTERVAL) / + (GasIndexAlgorithm_TAU_INITIAL_VARIANCE + + GasIndexAlgorithm_SAMPLING_INTERVAL))); params->m_Mean_Variance_Estimator__Gamma_Mean = F16(0.); params->m_Mean_Variance_Estimator__Gamma_Variance = F16(0.); params->m_Mean_Variance_Estimator___Uptime_Gamma = F16(0.); @@ -437,7 +520,9 @@ static void GasIndexAlgorithm__mean_variance_estimator__set_parameters(GasIndex params->m_Mean_Variance_Estimator___Gating_Duration_Minutes = F16(0.); } -static void GasIndexAlgorithm__mean_variance_estimator__set_states(GasIndexAlgorithmParams *params, fix16_t mean, fix16_t std, fix16_t uptime_gamma) { +static void GasIndexAlgorithm__mean_variance_estimator__set_states( + GasIndexAlgorithmParams* params, fix16_t mean, fix16_t std, + fix16_t uptime_gamma) { params->m_Mean_Variance_Estimator___Mean = mean; params->m_Mean_Variance_Estimator___Std = std; @@ -445,22 +530,27 @@ static void GasIndexAlgorithm__mean_variance_estimator__set_states(GasIndexAlgo params->m_Mean_Variance_Estimator___Initialized = true; } -static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_std(const GasIndexAlgorithmParams *params) { +static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_std( + const GasIndexAlgorithmParams* params) { return params->m_Mean_Variance_Estimator___Std; } -static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_mean(const GasIndexAlgorithmParams *params) { +static fix16_t GasIndexAlgorithm__mean_variance_estimator__get_mean( + const GasIndexAlgorithmParams* params) { - return (params->m_Mean_Variance_Estimator___Mean + params->m_Mean_Variance_Estimator___Sraw_Offset); + return (params->m_Mean_Variance_Estimator___Mean + + params->m_Mean_Variance_Estimator___Sraw_Offset); } -static bool GasIndexAlgorithm__mean_variance_estimator__is_initialized(GasIndexAlgorithmParams *params) { +static bool GasIndexAlgorithm__mean_variance_estimator__is_initialized( + GasIndexAlgorithmParams* params) { return params->m_Mean_Variance_Estimator___Initialized; } -static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(GasIndexAlgorithmParams *params) { +static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma( + GasIndexAlgorithmParams* params) { fix16_t uptime_limit; fix16_t sigmoid_gamma_mean; @@ -472,37 +562,90 @@ static void GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(GasInd fix16_t gating_threshold_variance; fix16_t sigmoid_gating_variance; - uptime_limit = F16((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__FIX16_MAX - GasIndexAlgorithm_SAMPLING_INTERVAL)); + uptime_limit = F16((GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__FIX16_MAX - + GasIndexAlgorithm_SAMPLING_INTERVAL)); if ((params->m_Mean_Variance_Estimator___Uptime_Gamma < uptime_limit)) { - params->m_Mean_Variance_Estimator___Uptime_Gamma = (params->m_Mean_Variance_Estimator___Uptime_Gamma + F16(GasIndexAlgorithm_SAMPLING_INTERVAL)); + params->m_Mean_Variance_Estimator___Uptime_Gamma = + (params->m_Mean_Variance_Estimator___Uptime_Gamma + + F16(GasIndexAlgorithm_SAMPLING_INTERVAL)); } if ((params->m_Mean_Variance_Estimator___Uptime_Gating < uptime_limit)) { - params->m_Mean_Variance_Estimator___Uptime_Gating = (params->m_Mean_Variance_Estimator___Uptime_Gating + F16(GasIndexAlgorithm_SAMPLING_INTERVAL)); - } - GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(params, params->mInit_Duration_Mean, F16(GasIndexAlgorithm_INIT_TRANSITION_MEAN)); - sigmoid_gamma_mean = GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(params, params->m_Mean_Variance_Estimator___Uptime_Gamma); - gamma_mean = (params->m_Mean_Variance_Estimator___Gamma_Mean + (fix16_mul((params->m_Mean_Variance_Estimator___Gamma_Initial_Mean - params->m_Mean_Variance_Estimator___Gamma_Mean), sigmoid_gamma_mean))); - gating_threshold_mean = (params->mGating_Threshold + (fix16_mul((F16(GasIndexAlgorithm_GATING_THRESHOLD_INITIAL) - params->mGating_Threshold), GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(params, params->m_Mean_Variance_Estimator___Uptime_Gating)))); - GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(params, gating_threshold_mean, F16(GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION)); - sigmoid_gating_mean = GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(params, params->mGas_Index); - params->m_Mean_Variance_Estimator__Gamma_Mean = (fix16_mul(sigmoid_gating_mean, gamma_mean)); - GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(params, params->mInit_Duration_Variance, F16(GasIndexAlgorithm_INIT_TRANSITION_VARIANCE)); - sigmoid_gamma_variance = GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(params, params->m_Mean_Variance_Estimator___Uptime_Gamma); - gamma_variance = (params->m_Mean_Variance_Estimator___Gamma_Variance + (fix16_mul((params->m_Mean_Variance_Estimator___Gamma_Initial_Variance - params->m_Mean_Variance_Estimator___Gamma_Variance), (sigmoid_gamma_variance - sigmoid_gamma_mean)))); - gating_threshold_variance = (params->mGating_Threshold + (fix16_mul((F16(GasIndexAlgorithm_GATING_THRESHOLD_INITIAL) - params->mGating_Threshold), GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(params, params->m_Mean_Variance_Estimator___Uptime_Gating)))); - GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(params, gating_threshold_variance, F16(GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION)); - sigmoid_gating_variance = GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(params, params->mGas_Index); - params->m_Mean_Variance_Estimator__Gamma_Variance = (fix16_mul(sigmoid_gating_variance, gamma_variance)); - params->m_Mean_Variance_Estimator___Gating_Duration_Minutes = (params->m_Mean_Variance_Estimator___Gating_Duration_Minutes + (fix16_mul(F16((GasIndexAlgorithm_SAMPLING_INTERVAL / 60.)), ((fix16_mul((F16(1.) - sigmoid_gating_mean), F16((1. + GasIndexAlgorithm_GATING_MAX_RATIO)))) - F16(GasIndexAlgorithm_GATING_MAX_RATIO))))); - if ((params->m_Mean_Variance_Estimator___Gating_Duration_Minutes < F16(0.))) { + params->m_Mean_Variance_Estimator___Uptime_Gating = + (params->m_Mean_Variance_Estimator___Uptime_Gating + + F16(GasIndexAlgorithm_SAMPLING_INTERVAL)); + } + GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters( + params, params->mInit_Duration_Mean, + F16(GasIndexAlgorithm_INIT_TRANSITION_MEAN)); + sigmoid_gamma_mean = + GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + params, params->m_Mean_Variance_Estimator___Uptime_Gamma); + gamma_mean = + (params->m_Mean_Variance_Estimator___Gamma_Mean + + (fix16_mul((params->m_Mean_Variance_Estimator___Gamma_Initial_Mean - + params->m_Mean_Variance_Estimator___Gamma_Mean), + sigmoid_gamma_mean))); + gating_threshold_mean = + (params->mGating_Threshold + + (fix16_mul( + (F16(GasIndexAlgorithm_GATING_THRESHOLD_INITIAL) - + params->mGating_Threshold), + GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + params, params->m_Mean_Variance_Estimator___Uptime_Gating)))); + GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters( + params, gating_threshold_mean, + F16(GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION)); + sigmoid_gating_mean = + GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + params, params->mGas_Index); + params->m_Mean_Variance_Estimator__Gamma_Mean = + (fix16_mul(sigmoid_gating_mean, gamma_mean)); + GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters( + params, params->mInit_Duration_Variance, + F16(GasIndexAlgorithm_INIT_TRANSITION_VARIANCE)); + sigmoid_gamma_variance = + GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + params, params->m_Mean_Variance_Estimator___Uptime_Gamma); + gamma_variance = + (params->m_Mean_Variance_Estimator___Gamma_Variance + + (fix16_mul( + (params->m_Mean_Variance_Estimator___Gamma_Initial_Variance - + params->m_Mean_Variance_Estimator___Gamma_Variance), + (sigmoid_gamma_variance - sigmoid_gamma_mean)))); + gating_threshold_variance = + (params->mGating_Threshold + + (fix16_mul( + (F16(GasIndexAlgorithm_GATING_THRESHOLD_INITIAL) - + params->mGating_Threshold), + GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + params, params->m_Mean_Variance_Estimator___Uptime_Gating)))); + GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters( + params, gating_threshold_variance, + F16(GasIndexAlgorithm_GATING_THRESHOLD_TRANSITION)); + sigmoid_gating_variance = + GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + params, params->mGas_Index); + params->m_Mean_Variance_Estimator__Gamma_Variance = + (fix16_mul(sigmoid_gating_variance, gamma_variance)); + params->m_Mean_Variance_Estimator___Gating_Duration_Minutes = + (params->m_Mean_Variance_Estimator___Gating_Duration_Minutes + + (fix16_mul( + F16((GasIndexAlgorithm_SAMPLING_INTERVAL / 60.)), + ((fix16_mul((F16(1.) - sigmoid_gating_mean), + F16((1. + GasIndexAlgorithm_GATING_MAX_RATIO)))) - + F16(GasIndexAlgorithm_GATING_MAX_RATIO))))); + if ((params->m_Mean_Variance_Estimator___Gating_Duration_Minutes < + F16(0.))) { params->m_Mean_Variance_Estimator___Gating_Duration_Minutes = F16(0.); } - if ((params->m_Mean_Variance_Estimator___Gating_Duration_Minutes > params->mGating_Max_Duration_Minutes)) { + if ((params->m_Mean_Variance_Estimator___Gating_Duration_Minutes > + params->mGating_Max_Duration_Minutes)) { params->m_Mean_Variance_Estimator___Uptime_Gating = F16(0.); } } -static void GasIndexAlgorithm__mean_variance_estimator__process(GasIndexAlgorithmParams *params, fix16_t sraw) { +static void GasIndexAlgorithm__mean_variance_estimator__process( + GasIndexAlgorithmParams* params, fix16_t sraw) { fix16_t delta_sgp; fix16_t c; @@ -512,111 +655,167 @@ static void GasIndexAlgorithm__mean_variance_estimator__process(GasIndexAlgorit params->m_Mean_Variance_Estimator___Initialized = true; params->m_Mean_Variance_Estimator___Sraw_Offset = sraw; params->m_Mean_Variance_Estimator___Mean = F16(0.); - } - else { - if (((params->m_Mean_Variance_Estimator___Mean >= F16(100.)) || (params->m_Mean_Variance_Estimator___Mean <= F16(-100.)))) { - params->m_Mean_Variance_Estimator___Sraw_Offset = (params->m_Mean_Variance_Estimator___Sraw_Offset + params->m_Mean_Variance_Estimator___Mean); + } else { + if (((params->m_Mean_Variance_Estimator___Mean >= F16(100.)) || + (params->m_Mean_Variance_Estimator___Mean <= F16(-100.)))) { + params->m_Mean_Variance_Estimator___Sraw_Offset = + (params->m_Mean_Variance_Estimator___Sraw_Offset + + params->m_Mean_Variance_Estimator___Mean); params->m_Mean_Variance_Estimator___Mean = F16(0.); } sraw = (sraw - params->m_Mean_Variance_Estimator___Sraw_Offset); GasIndexAlgorithm__mean_variance_estimator___calculate_gamma(params); - delta_sgp = (fix16_div((sraw - params->m_Mean_Variance_Estimator___Mean), F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING))); + delta_sgp = (fix16_div( + (sraw - params->m_Mean_Variance_Estimator___Mean), + F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING))); if ((delta_sgp < F16(0.))) { c = (params->m_Mean_Variance_Estimator___Std - delta_sgp); - } - else { + } else { c = (params->m_Mean_Variance_Estimator___Std + delta_sgp); } additional_scaling = F16(1.); if ((c > F16(1440.))) { - additional_scaling = (fix16_mul((fix16_div(c, F16(1440.))), (fix16_div(c, F16(1440.))))); + additional_scaling = (fix16_mul((fix16_div(c, F16(1440.))), + (fix16_div(c, F16(1440.))))); } - params->m_Mean_Variance_Estimator___Std = (fix16_mul(fix16_sqrt((fix16_mul(additional_scaling, (F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) - params->m_Mean_Variance_Estimator__Gamma_Variance)))), fix16_sqrt(((fix16_mul(params->m_Mean_Variance_Estimator___Std, (fix16_div(params->m_Mean_Variance_Estimator___Std, (fix16_mul(F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING), additional_scaling)))))) + (fix16_mul((fix16_div((fix16_mul(params->m_Mean_Variance_Estimator__Gamma_Variance, delta_sgp)), additional_scaling)), delta_sgp)))))); - params->m_Mean_Variance_Estimator___Mean = (params->m_Mean_Variance_Estimator___Mean + (fix16_div((fix16_mul(params->m_Mean_Variance_Estimator__Gamma_Mean, delta_sgp)), F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING)))); + params->m_Mean_Variance_Estimator___Std = (fix16_mul( + fix16_sqrt((fix16_mul( + additional_scaling, + (F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING) - + params->m_Mean_Variance_Estimator__Gamma_Variance)))), + fix16_sqrt(( + (fix16_mul( + params->m_Mean_Variance_Estimator___Std, + (fix16_div( + params->m_Mean_Variance_Estimator___Std, + (fix16_mul( + F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING), + additional_scaling)))))) + + (fix16_mul( + (fix16_div( + (fix16_mul( + params->m_Mean_Variance_Estimator__Gamma_Variance, + delta_sgp)), + additional_scaling)), + delta_sgp)))))); + params->m_Mean_Variance_Estimator___Mean = + (params->m_Mean_Variance_Estimator___Mean + + (fix16_div( + (fix16_mul(params->m_Mean_Variance_Estimator__Gamma_Mean, + delta_sgp)), + F16(GasIndexAlgorithm_MEAN_VARIANCE_ESTIMATOR__ADDITIONAL_GAMMA_MEAN_SCALING)))); } } -static void GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters(GasIndexAlgorithmParams *params, fix16_t X0, fix16_t K) { +static void +GasIndexAlgorithm__mean_variance_estimator___sigmoid__set_parameters( + GasIndexAlgorithmParams* params, fix16_t X0, fix16_t K) { params->m_Mean_Variance_Estimator___Sigmoid__K = K; params->m_Mean_Variance_Estimator___Sigmoid__X0 = X0; } -static fix16_t GasIndexAlgorithm__mean_variance_estimator___sigmoid__process(GasIndexAlgorithmParams *params, fix16_t sample) { +static fix16_t GasIndexAlgorithm__mean_variance_estimator___sigmoid__process( + GasIndexAlgorithmParams* params, fix16_t sample) { fix16_t x; - x = (fix16_mul(params->m_Mean_Variance_Estimator___Sigmoid__K, (sample - params->m_Mean_Variance_Estimator___Sigmoid__X0))); + x = (fix16_mul(params->m_Mean_Variance_Estimator___Sigmoid__K, + (sample - params->m_Mean_Variance_Estimator___Sigmoid__X0))); if ((x < F16(-50.))) { return F16(1.); - } - else if ((x > F16(50.))) { + } else if ((x > F16(50.))) { return F16(0.); - } - else { + } else { return (fix16_div(F16(1.), (F16(1.) + fix16_exp(x)))); } } -static void GasIndexAlgorithm__mox_model__set_parameters(GasIndexAlgorithmParams *params, fix16_t SRAW_STD, fix16_t SRAW_MEAN) { +static void GasIndexAlgorithm__mox_model__set_parameters( + GasIndexAlgorithmParams* params, fix16_t SRAW_STD, fix16_t SRAW_MEAN) { params->m_Mox_Model__Sraw_Std = SRAW_STD; params->m_Mox_Model__Sraw_Mean = SRAW_MEAN; } -static fix16_t GasIndexAlgorithm__mox_model__process(GasIndexAlgorithmParams *params, fix16_t sraw) { +static fix16_t +GasIndexAlgorithm__mox_model__process(GasIndexAlgorithmParams* params, + fix16_t sraw) { if ((params->mAlgorithm_Type == GasIndexAlgorithm_ALGORITHM_TYPE_NOX)) { - return (fix16_mul((fix16_div((sraw - params->m_Mox_Model__Sraw_Mean), F16(GasIndexAlgorithm_SRAW_STD_NOX))), params->mIndex_Gain)); - } - else { - return (fix16_mul((fix16_div((sraw - params->m_Mox_Model__Sraw_Mean), (-(params->m_Mox_Model__Sraw_Std + F16(GasIndexAlgorithm_SRAW_STD_BONUS_VOC))))), params->mIndex_Gain)); + return (fix16_mul((fix16_div((sraw - params->m_Mox_Model__Sraw_Mean), + F16(GasIndexAlgorithm_SRAW_STD_NOX))), + params->mIndex_Gain)); + } else { + return (fix16_mul( + (fix16_div((sraw - params->m_Mox_Model__Sraw_Mean), + (-(params->m_Mox_Model__Sraw_Std + + F16(GasIndexAlgorithm_SRAW_STD_BONUS_VOC))))), + params->mIndex_Gain)); } } -static void GasIndexAlgorithm__sigmoid_scaled__set_parameters(GasIndexAlgorithmParams *params, fix16_t X0, fix16_t K, fix16_t offset_default) { +static void GasIndexAlgorithm__sigmoid_scaled__set_parameters( + GasIndexAlgorithmParams* params, fix16_t X0, fix16_t K, + fix16_t offset_default) { params->m_Sigmoid_Scaled__K = K; params->m_Sigmoid_Scaled__X0 = X0; params->m_Sigmoid_Scaled__Offset_Default = offset_default; } -static fix16_t GasIndexAlgorithm__sigmoid_scaled__process(GasIndexAlgorithmParams *params, fix16_t sample) { +static fix16_t +GasIndexAlgorithm__sigmoid_scaled__process(GasIndexAlgorithmParams* params, + fix16_t sample) { fix16_t x; fix16_t shift; - x = (fix16_mul(params->m_Sigmoid_Scaled__K, (sample - params->m_Sigmoid_Scaled__X0))); + x = (fix16_mul(params->m_Sigmoid_Scaled__K, + (sample - params->m_Sigmoid_Scaled__X0))); if ((x < F16(-50.))) { return F16(GasIndexAlgorithm_SIGMOID_L); - } - else if ((x > F16(50.))) { + } else if ((x > F16(50.))) { return F16(0.); - } - else { + } else { if ((sample >= F16(0.))) { if ((params->m_Sigmoid_Scaled__Offset_Default == F16(1.))) { - shift = (fix16_mul(F16((500. / 499.)), (F16(1.) - params->mIndex_Offset))); - } - else { - shift = (fix16_div((F16(GasIndexAlgorithm_SIGMOID_L) - (fix16_mul(F16(5.), params->mIndex_Offset))), F16(4.))); + shift = (fix16_mul(F16((500. / 499.)), + (F16(1.) - params->mIndex_Offset))); + } else { + shift = + (fix16_div((F16(GasIndexAlgorithm_SIGMOID_L) - + (fix16_mul(F16(5.), params->mIndex_Offset))), + F16(4.))); } - return ((fix16_div((F16(GasIndexAlgorithm_SIGMOID_L) + shift), (F16(1.) + fix16_exp(x)))) - shift); - } - else { - return (fix16_mul((fix16_div(params->mIndex_Offset, params->m_Sigmoid_Scaled__Offset_Default)), (fix16_div(F16(GasIndexAlgorithm_SIGMOID_L), (F16(1.) + fix16_exp(x)))))); + return ((fix16_div((F16(GasIndexAlgorithm_SIGMOID_L) + shift), + (F16(1.) + fix16_exp(x)))) - + shift); + } else { + return ( + fix16_mul((fix16_div(params->mIndex_Offset, + params->m_Sigmoid_Scaled__Offset_Default)), + (fix16_div(F16(GasIndexAlgorithm_SIGMOID_L), + (F16(1.) + fix16_exp(x)))))); } } } -static void GasIndexAlgorithm__adaptive_lowpass__set_parameters(GasIndexAlgorithmParams *params) { +static void GasIndexAlgorithm__adaptive_lowpass__set_parameters( + GasIndexAlgorithmParams* params) { - params->m_Adaptive_Lowpass__A1 = F16((GasIndexAlgorithm_SAMPLING_INTERVAL / (GasIndexAlgorithm_LP_TAU_FAST + GasIndexAlgorithm_SAMPLING_INTERVAL))); - params->m_Adaptive_Lowpass__A2 = F16((GasIndexAlgorithm_SAMPLING_INTERVAL / (GasIndexAlgorithm_LP_TAU_SLOW + GasIndexAlgorithm_SAMPLING_INTERVAL))); + params->m_Adaptive_Lowpass__A1 = F16(( + GasIndexAlgorithm_SAMPLING_INTERVAL / + (GasIndexAlgorithm_LP_TAU_FAST + GasIndexAlgorithm_SAMPLING_INTERVAL))); + params->m_Adaptive_Lowpass__A2 = F16(( + GasIndexAlgorithm_SAMPLING_INTERVAL / + (GasIndexAlgorithm_LP_TAU_SLOW + GasIndexAlgorithm_SAMPLING_INTERVAL))); params->m_Adaptive_Lowpass___Initialized = false; } -static fix16_t GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmParams *params, fix16_t sample) { +static fix16_t +GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmParams* params, + fix16_t sample) { fix16_t abs_delta; fix16_t F1; @@ -629,16 +828,28 @@ static fix16_t GasIndexAlgorithm__adaptive_lowpass__process(GasIndexAlgorithmPa params->m_Adaptive_Lowpass___X3 = sample; params->m_Adaptive_Lowpass___Initialized = true; } - params->m_Adaptive_Lowpass___X1 = ((fix16_mul((F16(1.) - params->m_Adaptive_Lowpass__A1), params->m_Adaptive_Lowpass___X1)) + (fix16_mul(params->m_Adaptive_Lowpass__A1, sample))); - params->m_Adaptive_Lowpass___X2 = ((fix16_mul((F16(1.) - params->m_Adaptive_Lowpass__A2), params->m_Adaptive_Lowpass___X2)) + (fix16_mul(params->m_Adaptive_Lowpass__A2, sample))); - abs_delta = (params->m_Adaptive_Lowpass___X1 - params->m_Adaptive_Lowpass___X2); + params->m_Adaptive_Lowpass___X1 = + ((fix16_mul((F16(1.) - params->m_Adaptive_Lowpass__A1), + params->m_Adaptive_Lowpass___X1)) + + (fix16_mul(params->m_Adaptive_Lowpass__A1, sample))); + params->m_Adaptive_Lowpass___X2 = + ((fix16_mul((F16(1.) - params->m_Adaptive_Lowpass__A2), + params->m_Adaptive_Lowpass___X2)) + + (fix16_mul(params->m_Adaptive_Lowpass__A2, sample))); + abs_delta = + (params->m_Adaptive_Lowpass___X1 - params->m_Adaptive_Lowpass___X2); if ((abs_delta < F16(0.))) { abs_delta = (-abs_delta); } F1 = fix16_exp((fix16_mul(F16(GasIndexAlgorithm_LP_ALPHA), abs_delta))); - tau_a = ((fix16_mul(F16((GasIndexAlgorithm_LP_TAU_SLOW - GasIndexAlgorithm_LP_TAU_FAST)), F1)) + F16(GasIndexAlgorithm_LP_TAU_FAST)); - a3 = (fix16_div(F16(GasIndexAlgorithm_SAMPLING_INTERVAL), (F16(GasIndexAlgorithm_SAMPLING_INTERVAL) + tau_a))); - params->m_Adaptive_Lowpass___X3 = ((fix16_mul((F16(1.) - a3), params->m_Adaptive_Lowpass___X3)) + (fix16_mul(a3, sample))); + tau_a = ((fix16_mul(F16((GasIndexAlgorithm_LP_TAU_SLOW - + GasIndexAlgorithm_LP_TAU_FAST)), + F1)) + + F16(GasIndexAlgorithm_LP_TAU_FAST)); + a3 = (fix16_div(F16(GasIndexAlgorithm_SAMPLING_INTERVAL), + (F16(GasIndexAlgorithm_SAMPLING_INTERVAL) + tau_a))); + params->m_Adaptive_Lowpass___X3 = + ((fix16_mul((F16(1.) - a3), params->m_Adaptive_Lowpass___X3)) + + (fix16_mul(a3, sample))); return params->m_Adaptive_Lowpass___X3; } - diff --git a/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.h b/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.h index 7e7fd53..8d9c192 100644 --- a/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.h +++ b/sensirion_gas_index_algorithm_fixpoint/sensirion_gas_index_algorithm.h @@ -169,7 +169,6 @@ typedef struct { fix16_t m_Adaptive_Lowpass___X3; } GasIndexAlgorithmParams; - /** * Initialize the gas index algorithm parameters for the specified algorithm * type and reset its internal states. Call this once at the beginning. @@ -177,7 +176,8 @@ typedef struct { * @param algorithm_type 0 (GasIndexAlgorithm_ALGORITHM_TYPE_VOC) for VOC or * 1 (GasIndexAlgorithm_ALGORITHM_TYPE_NOX) for NOx */ -void GasIndexAlgorithm_init(GasIndexAlgorithmParams *params, int32_t algorithm_type); +void GasIndexAlgorithm_init(GasIndexAlgorithmParams* params, + int32_t algorithm_type); /** * Reset the internal states of the gas index algorithm. Previously set tuning