├── .gitattributes ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── build_arduino.yml │ ├── build_docs.yml │ ├── build_linux.yml │ ├── build_pico_sdk.yml │ ├── build_platformio.yml │ ├── build_python.yml │ └── cpp_lint.yaml ├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── LICENSE ├── MANIFEST.in ├── README.rst ├── cspell.config.yml ├── docs ├── API │ ├── arduino_wrappers.rst │ ├── cpp.rst │ └── python.rst ├── _static │ ├── Cirque_GlidePoint-Circle-Trackpad.png │ ├── Logo.png │ ├── extra_css.css │ └── favicon.ico ├── arduino.rst ├── conf.py ├── datasheets │ ├── Application Notes │ │ ├── InterfacingtoPinnacle_I2C-SPI.pdf │ │ ├── Pinnacle Extended Registers.pdf │ │ ├── Pinnacle Sensor Compensation.pdf │ │ └── Using a Stylus with Pinnacle.pdf │ ├── Overlay Blueprints │ │ ├── 35mm_Concaved_Overlay_blueprint.pdf │ │ └── 40mm_Concaved_Overlay_blueprint.pdf │ ├── Pinnacle Specification.pdf │ ├── README.md │ └── Trackpad Specifications │ │ ├── TM023023 Trackpad Spec.pdf │ │ ├── TM035035 Trackpad Spec.pdf │ │ └── TM040040 Trackpad Spec.pdf ├── examples.rst ├── index.rst ├── linux.rst ├── pico_sdk.rst ├── python.rst └── requirements.txt ├── examples ├── .clang-format ├── README.md ├── absolute_mode │ └── absolute_mode.ino ├── anymeas_mode │ └── anymeas_mode.ino ├── cpython │ ├── absolute_mode.py │ ├── anymeas_mode.py │ └── relative_mode.py ├── linux │ ├── .clang-format │ ├── CMakeLists.txt │ ├── absolute_mode.cpp │ ├── anymeas_mode.cpp │ └── relative_mode.cpp ├── pico_sdk │ ├── .clang-format │ ├── CMakeLists.txt │ ├── absolute_mode.cpp │ ├── anymeas_mode.cpp │ ├── defaultPins.h │ ├── relative_mode.cpp │ └── usb_mouse │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── main.cpp │ │ ├── tusb_config.h │ │ ├── usb_descriptors.c │ │ └── usb_descriptors.h ├── relative_mode │ └── relative_mode.ino └── usb_mouse │ └── usb_mouse.ino ├── install-linux.sh ├── keywords.txt ├── library.json ├── library.properties ├── pyproject.toml ├── setup.py └── src ├── .clang-format ├── CMakeLists.txt ├── CirquePinnacle.cpp ├── CirquePinnacle.h ├── CirquePinnacle_common.h ├── cirque_pinnacle-stubs └── __init__.pyi ├── cmake ├── CPackInfo.cmake ├── Cache.cmake ├── CompilerWarnings.cmake ├── GetLibInfo.cmake ├── PreventInSourceBuilds.cmake ├── Sanitizers.cmake ├── StandardProjectSettings.cmake ├── StaticAnalyzers.cmake ├── auto_config_driver.cmake ├── detectCPU.cmake ├── pico_sdk_import.cmake └── toolchains │ ├── arm64.cmake │ ├── armhf.cmake │ ├── clang.cmake │ ├── default.cmake │ ├── i686.cmake │ └── x86_64.cmake ├── linux └── gpio.h ├── py_bindings.cpp └── utility ├── CMakeLists.txt ├── includes.h.in ├── linux_kernel ├── gpio.cpp ├── gpio.h ├── i2c.cpp ├── i2c.h ├── spi.cpp ├── spi.h ├── time_keeping.cpp └── time_keeping.h ├── rp2 ├── CMakeLists.txt ├── gpio.cpp ├── gpio.h ├── i2c.cpp ├── i2c.h ├── spi.cpp ├── spi.h └── time_keeping.h └── template ├── gpio.h ├── i2c.h ├── spi.h └── time_keeping.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Prevent line ending conversions by default to avoid problems with binary files. 2 | * -text 3 | 4 | # Known text files should have LF line endings. 5 | *.py text eol=lf 6 | *.rst text eol=lf 7 | *.md text eol=lf 8 | *.toml text eol=lf 9 | *.txt text eol=lf 10 | *.css text eol=lf 11 | *.svg text eol=lf 12 | *.h text eol=lf 13 | *.cpp text eol=lf 14 | LICENSE text eol=lf 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: 2bndy5 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ["https://www.paypal.me/Brendan884"] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | # Workflow files stored in the 10 | # default location of `.github/workflows` 11 | directory: "/" 12 | schedule: 13 | interval: "weekly" 14 | groups: 15 | actions: 16 | patterns: 17 | - "*" 18 | -------------------------------------------------------------------------------- /.github/workflows/build_arduino.yml: -------------------------------------------------------------------------------- 1 | name: Arduino 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | paths: 7 | - ".github/workflows/build_arduino.yml" 8 | - "examples/**/*.ino" 9 | - "src/*.h" 10 | - "src/*.cpp" 11 | - "!src/py_bindings.cpp" 12 | push: 13 | branches: [master] 14 | paths: 15 | - ".github/workflows/build_arduino.yml" 16 | - "examples/**/*.ino" 17 | 18 | env: 19 | SKETCH_REPORTS_PATH: sketches-reports 20 | 21 | jobs: 22 | check_formatting: 23 | uses: ./.github/workflows/cpp_lint.yaml 24 | with: 25 | extensions: 'ino' 26 | 27 | build: 28 | needs: check_formatting 29 | runs-on: ubuntu-latest 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | fqbn: 34 | - "arduino:avr:uno" 35 | - "arduino:avr:mega" 36 | - "arduino:avr:leonardo" 37 | - "arduino:avr:micro" 38 | - "arduino:avr:mini" 39 | - "arduino:avr:pro" 40 | - "arduino:avr:atmegang" 41 | - "arduino:avr:unowifi" 42 | - "arduino:megaavr:uno2018" 43 | - "arduino:mbed:nano33ble" 44 | - "arduino:samd:mkrwifi1010" 45 | - "arduino:samd:nano_33_iot" 46 | - "arduino:samd:adafruit_circuitplayground_m0" 47 | # By default, don't generate size deltas data. 48 | enable-deltas-report: 49 | - false 50 | # Generate size deltas data for these boards 51 | include: 52 | - fqbn: arduino:samd:mkrzero 53 | enable-deltas-report: true 54 | 55 | steps: 56 | - name: Checkout 57 | uses: actions/checkout@v4 58 | 59 | - name: Compile examples 60 | uses: arduino/compile-sketches@main 61 | with: 62 | fqbn: ${{ matrix.fqbn }} 63 | enable-deltas-report: ${{ matrix.enable-deltas-report }} 64 | sketches-report-path: ${{ env.SKETCH_REPORTS_PATH }} 65 | sketch-paths: | 66 | - examples/absolute_mode 67 | - examples/anymeas_mode 68 | - examples/relative_mode 69 | 70 | - name: sketch reports 71 | if: matrix.enable-deltas-report 72 | id: delta-report-name 73 | run: >- 74 | echo "report-name=${{ matrix.fqbn }}" | tr : - >> "$GITHUB_OUTPUT" 75 | 76 | # This step is needed to pass the size data to the report job 77 | - name: Upload sketches report to workflow artifact 78 | if: matrix.enable-deltas-report 79 | uses: actions/upload-artifact@v4 80 | with: 81 | name: arduino-deltas-${{ steps.delta-report-name.outputs.report-name }} 82 | path: ${{ env.SKETCH_REPORTS_PATH }} 83 | 84 | report_size_deltas: 85 | runs-on: ubuntu-latest 86 | needs: [build] 87 | steps: 88 | - name: Download sketches reports artifact 89 | uses: actions/download-artifact@v4 90 | with: 91 | pattern: arduino-deltas-* 92 | path: ${{ env.SKETCH_REPORTS_PATH }} 93 | 94 | - uses: 2bndy5/report-size-deltas@update-comment 95 | with: 96 | sketches-reports-source: ${{ env.SKETCH_REPORTS_PATH }} 97 | update-comment: true 98 | -------------------------------------------------------------------------------- /.github/workflows/build_docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | paths: 7 | - "src/CirquePinnacle.h" 8 | - "docs/**" 9 | - "examples/**/*.ino" 10 | - "examples/**/*.cpp" 11 | - ".github/workflows/build_docs.yml" 12 | push: 13 | branches: [master] 14 | paths: 15 | - "src/CirquePinnacle.h" 16 | - "docs/**" 17 | - "examples/**/*.ino" 18 | - "examples/**/*.cpp" 19 | - ".github/workflows/build_docs.yml" 20 | release: 21 | types: [published, edited] 22 | workflow_dispatch: 23 | 24 | jobs: 25 | build: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/setup-python@v5 29 | with: 30 | python-version: 3.x 31 | 32 | - uses: actions/checkout@v4 33 | 34 | - name: Install sphinx deps 35 | run: python -m pip install -r docs/requirements.txt 36 | 37 | - name: build docs with Sphinx 38 | working-directory: docs 39 | run: sphinx-build . _build/html 40 | 41 | - name: Save sphinx docs as artifact 42 | uses: actions/upload-artifact@v4 43 | with: 44 | name: Cirque_Pinnacle_docs 45 | path: ${{ github.workspace }}/docs/_build/html 46 | -------------------------------------------------------------------------------- /.github/workflows/build_pico_sdk.yml: -------------------------------------------------------------------------------- 1 | name: Pico SDK 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | paths: 7 | - "src/*.cpp" 8 | - "!src/py_bindings.cpp" 9 | - "src/*.h" 10 | - "src/CMakeLists.txt" 11 | - "src/utility/rp2/**" 12 | - "examples/pico_sdk/**" 13 | - ".github/workflows/build_pico_sdk.yml" 14 | push: 15 | branches: [master] 16 | paths: 17 | - "src/*.cpp" 18 | - "!src/py_bindings.cpp" 19 | - "src/*.h" 20 | - "src/CMakeLists.txt" 21 | - "src/utility/rp2/**" 22 | - "examples/pico_sdk/**" 23 | - ".github/workflows/build_pico_sdk.yml" 24 | 25 | jobs: 26 | check_formatting: 27 | uses: ./.github/workflows/cpp_lint.yaml 28 | with: 29 | ignore: '!examples/pico_sdk|' 30 | build: 31 | needs: check_formatting 32 | runs-on: ubuntu-latest 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | board: 37 | - "pico" 38 | - "pico_w" 39 | - "adafruit_feather_rp2040" 40 | - "adafruit_itsybitsy_rp2040" 41 | - "adafruit_qtpy_rp2040" 42 | i2c-bus: [USE_I2C=ON, USE_I2C=OFF] 43 | env: 44 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 45 | BUILD_TYPE: Release 46 | 47 | steps: 48 | - name: get repo info 49 | id: lib-info 50 | run: echo "name=$(echo ${{ github.repository }} | sed 's;.\+/;;')" >> $GITHUB_OUTPUT 51 | 52 | - uses: actions/checkout@v4 53 | with: 54 | path: ${{ steps.lib-info.outputs.name }} 55 | 56 | - name: Install toolchain 57 | run: sudo apt update && sudo apt install gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential 58 | 59 | - name: Clone pico-sdk 60 | uses: actions/checkout@v4 61 | with: 62 | repository: raspberrypi/pico-sdk 63 | # master branch is latest stable release 64 | path: pico-sdk 65 | clean: false 66 | submodules: true 67 | 68 | - name: Checkout pico-sdk submodules 69 | working-directory: ${{ github.workspace }}/pico-sdk 70 | run: git submodule update --init 71 | 72 | - name: Create Build Environment 73 | working-directory: ${{ github.workspace }}/${{ steps.lib-info.outputs.name }} 74 | run: mkdir build 75 | 76 | - name: Configure CMake 77 | working-directory: ${{ github.workspace }}/${{ steps.lib-info.outputs.name }}/build 78 | env: 79 | PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk 80 | run: cmake ../examples/pico_sdk -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DPICO_BOARD=${{ matrix.board }} -D${{ matrix.i2c-bus }} 81 | 82 | - name: Build 83 | working-directory: ${{ github.workspace }}/${{ steps.lib-info.outputs.name }}/build 84 | # Execute the build. You can specify a specific target with "--target " 85 | run: cmake --build . --config $BUILD_TYPE 86 | 87 | - name: Save artifact 88 | uses: actions/upload-artifact@v4 89 | with: 90 | name: examples_pico_${{ matrix.board }}_${{ matrix.i2c-bus }} 91 | path: | 92 | ${{ github.workspace }}/${{ steps.lib-info.outputs.name }}/build/**/*.uf2 93 | # ${{ github.workspace }}/${{ steps.lib-info.outputs.name }}/build/**/*.elf 94 | # ${{ github.workspace }}/${{ steps.lib-info.outputs.name }}/build/**/*.hex 95 | # ${{ github.workspace }}/${{ steps.lib-info.outputs.name }}/build/**/*.bin 96 | -------------------------------------------------------------------------------- /.github/workflows/build_platformio.yml: -------------------------------------------------------------------------------- 1 | name: PlatformIO 2 | 3 | on: 4 | pull_request: 5 | branches: [master] 6 | paths: 7 | - ".github/workflows/build_platformio.yml" 8 | - "library.json" 9 | - "examples/**/*.ino" 10 | push: 11 | branches: [master] 12 | paths: 13 | - ".github/workflows/build_platformio.yml" 14 | - "library.json" 15 | - "examples/**/*.ino" 16 | release: 17 | types: [created] 18 | 19 | jobs: 20 | validate_lib_json: 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | 26 | - name: get lib info 27 | id: lib-info 28 | run: | 29 | echo "name=$(echo ${{ github.repository }} | sed -e 's;.\+/;;')" >> $GITHUB_OUTPUT 30 | echo "release=$(awk -F "=" '/version/ {print $2}' library.properties)" >> $GITHUB_OUTPUT 31 | 32 | - name: Set up Python 33 | uses: actions/setup-python@v5 34 | with: 35 | python-version: 3.x 36 | 37 | - name: Install PlatformIO 38 | run: | 39 | python -m pip install --upgrade pip 40 | pip install --upgrade platformio 41 | 42 | - name: package lib 43 | run: pio package pack -o PlatformIO-${{ steps.lib-info.outputs.name }}-${{ steps.lib-info.outputs.release }}.tar.gz 44 | 45 | - name: Save artifact 46 | uses: actions/upload-artifact@v4 47 | with: 48 | name: PIO_pkg_${{ steps.lib-info.outputs.name }} 49 | path: PlatformIO*.tar.gz 50 | 51 | - name: Upload Release assets 52 | if: github.event_name == 'release' 53 | uses: shogo82148/actions-upload-release-asset@v1 54 | with: 55 | upload_url: ${{ github.event.release.upload_url }} 56 | asset_path: "PlatformIO*.tar.gz" 57 | 58 | - name: upload package to PlatformIO Registry 59 | if: github.event_name == 'release' 60 | # PIO lib packages cannot be re-published under the same tag 61 | env: 62 | PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }} 63 | run: pio package publish --owner 2bndy5 --non-interactive 64 | 65 | check_formatting: 66 | uses: ./.github/workflows/cpp_lint.yaml 67 | with: 68 | extensions: ino 69 | 70 | build: 71 | needs: [check_formatting, validate_lib_json] 72 | runs-on: ubuntu-latest 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | board: 77 | - "teensy31" 78 | - "teensy35" 79 | - "teensy36" 80 | - "teensy40" 81 | - "teensy41" 82 | - "teensylc" 83 | - "genericSTM32F411CE" 84 | - "blackpill_f103c8" 85 | - "nodemcuv2" 86 | - "adafruit_qtpy_esp32s2" 87 | example: 88 | - "examples/absolute_mode/absolute_mode.ino" 89 | - "examples/relative_mode/relative_mode.ino" 90 | - "examples/anymeas_mode/anymeas_mode.ino" 91 | 92 | steps: 93 | - name: Cache pip 94 | uses: actions/cache@v4 95 | with: 96 | path: ~/.cache/pip 97 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 98 | restore-keys: | 99 | ${{ runner.os }}-pip- 100 | 101 | - name: Cache PlatformIO 102 | uses: actions/cache@v4 103 | with: 104 | path: ~/.platformio 105 | key: ${{ runner.os }}-${{ matrix.board }} 106 | 107 | - name: Set up Python 108 | uses: actions/setup-python@v5 109 | with: 110 | python-version: 3.x 111 | 112 | - uses: actions/checkout@v4 113 | 114 | - name: Install PlatformIO 115 | run: | 116 | python -m pip install --upgrade pip 117 | pip install --upgrade platformio 118 | 119 | - name: Run PlatformIO 120 | run: pio ci --lib="." --board=${{ matrix.board }} 121 | env: 122 | PLATFORMIO_CI_SRC: ${{ matrix.example }} 123 | -------------------------------------------------------------------------------- /.github/workflows/cpp_lint.yaml: -------------------------------------------------------------------------------- 1 | name: Run clang-format on src changes 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | ignore: 7 | required: false 8 | type: string 9 | default: .github 10 | extensions: 11 | required: false 12 | type: string 13 | default: c,h,cpp,hpp 14 | 15 | jobs: 16 | cpp_linter: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/setup-python@v5 21 | with: 22 | python-version: 3.x 23 | - name: Install linter python package and clang-format 24 | run: | 25 | sudo apt-get install clang-format-14 26 | python3 -m pip install cpp-linter 27 | - name: run linter as a python package 28 | id: linter 29 | run: >- 30 | cpp-linter 31 | --version=14 32 | --style=file 33 | --tidy-checks="-*" 34 | --files-changed-only=false 35 | --step-summary=true 36 | --extensions="${{ inputs.extensions }}" 37 | --ignore='${{ inputs.ignore }}' 38 | - name: Linter checks failed? 39 | if: steps.linter.outputs.checks-failed > 0 40 | run: exit 1 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | #### ignores for Python 35 | # Byte-compiled / optimized / DLL files 36 | __pycache__/ 37 | *.py[cod] 38 | *$py.class 39 | 40 | # Distribution / packaging 41 | .Python 42 | build/ 43 | develop-eggs/ 44 | dist/ 45 | downloads/ 46 | eggs/ 47 | .eggs/ 48 | lib/ 49 | lib64/ 50 | parts/ 51 | sdist/ 52 | var/ 53 | wheels/ 54 | pip-wheel-metadata/ 55 | share/python-wheels/ 56 | *.egg-info/ 57 | .installed.cfg 58 | *.egg 59 | MANIFEST 60 | wheelhouse/ 61 | 62 | # Unit test / coverage reports 63 | htmlcov/ 64 | .tox/ 65 | .nox/ 66 | .coverage 67 | .coverage.* 68 | .cache 69 | nosetests.xml 70 | coverage.xml 71 | *.cover 72 | *.py,cover 73 | .hypothesis/ 74 | .pytest_cache/ 75 | 76 | # Translations 77 | *.mo 78 | *.pot 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # pyenv 84 | .python-version 85 | 86 | # python Environments 87 | .env 88 | .venv 89 | env/ 90 | venv/ 91 | ENV/ 92 | env.bak/ 93 | venv.bak/ 94 | 95 | # mypy 96 | .mypy_cache/ 97 | .dmypy.json 98 | dmypy.json 99 | 100 | # ruff (python linter) 101 | .ruff_cache/ 102 | 103 | # exclude local VSCode's settings folder 104 | .vscode/ 105 | 106 | # docs build folder 107 | _build/ 108 | docs/API/cpp-generated/ 109 | docs/doxygen/* 110 | 111 | # ignore files generated by CMake (upon build config) 112 | src/utility/includes.h 113 | build/ 114 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pybind11"] 2 | path = src/pybind11 3 | url = https://github.com/pybind/pybind11.git 4 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # Install pre-commit hooks via 2 | # pre-commit install 3 | 4 | exclude: > 5 | (?x)^( 6 | \.vscode/settings\.json| 7 | test.*\.md| 8 | test.*\.txt| 9 | test.*\.html| 10 | src/utility/bcm2xxx/bcm2835.* 11 | )$ 12 | repos: 13 | 14 | - repo: https://github.com/pre-commit/pre-commit-hooks 15 | rev: v5.0.0 16 | hooks: 17 | - id: check-toml 18 | - id: check-yaml 19 | - id: end-of-file-fixer 20 | - id: trailing-whitespace 21 | - id: mixed-line-ending 22 | args: ["--fix=lf"] 23 | 24 | - repo: https://github.com/charliermarsh/ruff-pre-commit 25 | rev: v0.11.5 26 | hooks: 27 | - id: ruff 28 | - id: ruff-format 29 | 30 | - repo: https://github.com/pre-commit/mirrors-mypy 31 | rev: v1.15.0 32 | hooks: 33 | - id: mypy 34 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | # Path to your Sphinx configuration file. 5 | configuration: docs/conf.py 6 | 7 | build: 8 | os: "ubuntu-24.04" 9 | tools: 10 | python: "latest" 11 | python: 12 | install: 13 | - requirements: docs/requirements.txt 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Brendan Doherty (2bndy5) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include src *.cpp *.h *.typed CMakeLists.txt 2 | recursive-include src/pybind11 * 3 | recursive-exclude src/pybind11/.github * 4 | recursive-exclude src/pybind11/docs * 5 | recursive-exclude src/pybind11/tests * 6 | recursive-exclude .github * 7 | recursive-exclude docs * 8 | recursive-exclude examples * 9 | recursive-exclude build * 10 | recursive-exclude src/cmake/toolchains *.cmake 11 | recursive-include src/cmake *.cmake 12 | recursive-exclude src/utility/template* *.h 13 | recursive-exclude src/utility/rp2 *.h *.cpp *.txt 14 | recursive-exclude cirque_pinnacle.egg-info * 15 | global-exclude .clang-format .clang-tidy .git* library.json keywords.txt **.yml **.yaml 16 | exclude src/utility/includes.h src/cmake/pico_sdk_import.cmake src/cmake/CPackInfo.cmake 17 | include pyproject.toml setup.py src/utility/includes.h.in library.properties 18 | -------------------------------------------------------------------------------- /cspell.config.yml: -------------------------------------------------------------------------------- 1 | version: "0.2" 2 | words: 3 | - adafruit 4 | - anymeas 5 | - apidoc 6 | - apigen 7 | - ARCHS 8 | - armhf 9 | - armv 10 | - ASIC 11 | - atmegang 12 | - baudrate 13 | - bdist 14 | - binfmt 15 | - bndy 16 | - cibuildwheels 17 | - CIBW 18 | - circuitplayground 19 | - cirquepinnacle 20 | - cpack 21 | - CPHA 22 | - cppreference 23 | - cpython 24 | - CROSSCOMPILING 25 | - cxxabiv 26 | - datasheet 27 | - DCMAKE 28 | - Doherty 29 | - DPICO 30 | - DPINNACLE 31 | - DPYTHON 32 | - eabi 33 | - endforeach 34 | - fqbn 35 | - ftime 36 | - gnueabihf 37 | - gpiochip 38 | - intellimouse 39 | - intersphinx 40 | - itsybitsy 41 | - ldconfig 42 | - libcirquepinnacle 43 | - libnewlib 44 | - linenos 45 | - literalinclude 46 | - LSBFIRST 47 | - Makefiles 48 | - manylinux 49 | - mbed 50 | - megaavr 51 | - mkrwifi 52 | - mkrzero 53 | - MOSI 54 | - MSBFIRST 55 | - musllinux 56 | - Muxing 57 | - Ofast 58 | - pico 59 | - PIMORONI 60 | - pinout 61 | - pkgs 62 | - postinst 63 | - postrm 64 | - println 65 | - pthread 66 | - pybind 67 | - pypa 68 | - pythonic 69 | - qtpy 70 | - raspberrypi 71 | - repr 72 | - samd 73 | - sdist 74 | - seealso 75 | - setuptools 76 | - shogo 77 | - sourcedir 78 | - SOVERSION 79 | - SPARFUN 80 | - Sparkfun 81 | - spidev 82 | - stddef 83 | - stdlib 84 | - STREQUAL 85 | - THINGPLUS 86 | - tinyusb 87 | - toctree 88 | - tonistiigi 89 | - trackpad 90 | - trackpads 91 | - unowifi 92 | - venv 93 | - viewcode 94 | -------------------------------------------------------------------------------- /docs/API/arduino_wrappers.rst: -------------------------------------------------------------------------------- 1 | Arduino-like Wrappers 2 | ===================== 3 | 4 | This library ships with wrapper classes for non-Arduino platforms as a utility for portability. 5 | All Arduino-like API exists in a library-specific namespace, ``cirque_pinnacle_arduino_wrappers``. 6 | 7 | .. cpp:namespace:: cirque_pinnacle_arduino_wrappers 8 | 9 | .. code-block:: cpp 10 | 11 | // an alias for the lib-specific namespace 12 | namespace arduino = cirque_pinnacle_arduino_wrappers; 13 | 14 | // the default I2C bus 15 | arduino::Wire; 16 | 17 | // the default SPI bus 18 | arduino::SPI; 19 | 20 | .. info:: Generic API documented 21 | 22 | The following API is documented from the template used to extend portability to non-Arduino 23 | platforms (like Linux and the Pico SDK). Therefor, the following API is not entirely representative 24 | of the actual API implemented for any specific platform. Although, it is very similar to the 25 | implementation exposed for the Linux platform using the ``linux_kernel`` driver. 26 | 27 | Arduino TwoWire 28 | --------------- 29 | 30 | This is library-specific API wrapping the Arduino I2C interface. 31 | 32 | .. cpp-apigen-group:: arduino-i2c 33 | 34 | Arduino SPIClass 35 | ---------------- 36 | 37 | This is library-specific API wrapping the Arduino SPI interface. 38 | 39 | .. cpp-apigen-group:: arduino-spi 40 | 41 | Arduino GPIOClass 42 | ------------------ 43 | 44 | This is library-specific API wrapping the Arduino GPIO interface. 45 | 46 | .. cpp-apigen-group:: arduino-gpio 47 | -------------------------------------------------------------------------------- /docs/API/cpp.rst: -------------------------------------------------------------------------------- 1 | 2 | C++ API 3 | ================== 4 | 5 | .. toctree:: 6 | 7 | arduino_wrappers 8 | 9 | .. _Data Mode: 10 | 11 | Data Mode 12 | *********** 13 | 14 | .. cpp-apigen-group:: data-mode 15 | 16 | Relative Data 17 | ************** 18 | 19 | .. cpp-apigen-group:: relative-mode 20 | 21 | Absolute Data 22 | ************** 23 | 24 | .. cpp-apigen-group:: absolute-mode 25 | 26 | AnyMeas Constants 27 | ***************** 28 | 29 | .. cpp-apigen-group:: anymeas-const 30 | 31 | PinnacleTouch API 32 | ***************** 33 | 34 | .. cpp-apigen-group:: pinnacle-touch-api 35 | -------------------------------------------------------------------------------- /docs/_static/Cirque_GlidePoint-Circle-Trackpad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/_static/Cirque_GlidePoint-Circle-Trackpad.png -------------------------------------------------------------------------------- /docs/_static/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/_static/Logo.png -------------------------------------------------------------------------------- /docs/_static/extra_css.css: -------------------------------------------------------------------------------- 1 | 2 | th { 3 | background-color: var(--md-default-fg-color--lightest); 4 | } 5 | 6 | .md-nav.md-nav--primary > label { 7 | white-space: normal; 8 | line-height: inherit; 9 | padding-top: 3.5rem; 10 | } 11 | 12 | .md-typeset .annotated-with-numbers .md-annotation__index > ::before { 13 | content: attr(data-md-annotation-id); 14 | } 15 | .md-typeset .annotated-with-numbers :focus-within > .md-annotation__index > ::before { 16 | transform: none; 17 | } 18 | 19 | .md-typeset .annotated-with-numbers .md-annotation__index::after { 20 | background-color: var(--md-primary-fg-color); 21 | } 22 | /* style for the unchecked checkboxes */ 23 | .custom-task-list-style > ul > li > label .task-list-indicator::before { 24 | -webkit-mask-image: var(--md-admonition-icon--failure); 25 | mask-image: var(--md-admonition-icon--failure); 26 | background-color: hsl(0, 72%, 55%); 27 | } 28 | 29 | /* style for the checked checkboxes */ 30 | .custom-task-list-style > ul > li > .task-list-control > [type="checkbox"]:checked + .task-list-indicator::before { 31 | -webkit-mask-image: var(--md-admonition-icon--success); 32 | mask-image: var(--md-admonition-icon--success); 33 | background-color: hsl(122, 84%, 45%); 34 | } 35 | 36 | @keyframes heart { 37 | 0%, 40%, 80%, 100% { 38 | transform: scale(0.85); 39 | } 40 | 20%, 60% { 41 | transform: scale(1); 42 | } 43 | } 44 | 45 | @keyframes pulse-red { 46 | 50% { 47 | background-color: var(--md-default-fg-color); 48 | } 49 | 0%, 100% { 50 | background-color: red; 51 | } 52 | } 53 | 54 | .pulsing-red::before { 55 | animation: heart 1s infinite, pulse-red 1.5s infinite; 56 | } 57 | -------------------------------------------------------------------------------- /docs/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/_static/favicon.ico -------------------------------------------------------------------------------- /docs/arduino.rst: -------------------------------------------------------------------------------- 1 | Arduino Support 2 | =============== 3 | 4 | This library was primarily written for the Arduino IDE. Therefore, it uses the SPI and I2C bus 5 | implementations from the Arduino framework (as provided by various board support -- AKA "Arduino 6 | Cores"). 7 | 8 | Using a non-default SPI or I2C bus 9 | ---------------------------------- 10 | 11 | .. md-tab-set:: 12 | 13 | .. md-tab-item:: SPI 14 | 15 | It is possible to use a specific SPI bus on boards that expose more than 1 SPI bus. As noted above, 16 | the ``SPIClass`` interface may vary depending on the targeted board. 17 | 18 | The following code snippet exemplifies the necessary steps: 19 | 20 | .. code-block:: cpp 21 | :class: annotated-with-numbers 22 | :emphasize-lines: 7,18,20 23 | 24 | #include 25 | #include 26 | 27 | #define SS_PIN 2 28 | #define DR_PIN 7 29 | 30 | SPIClass my_spi_obj; // (1)! 31 | 32 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 33 | 34 | void begin() 35 | { 36 | Serial.begin(115200); 37 | while (!Serial) { 38 | // some boards need this for the prompts to show immediately after boot 39 | } 40 | 41 | my_spi_obj.begin(); // (2)! 42 | 43 | if (!trackpad.begin(&my_spi_obj)) { // (3)! 44 | Serial.println(F("Cirque Pinnacle not responding!")); 45 | while (true) {} // hold program in infinite loop 46 | } 47 | 48 | // continue program as usual... 49 | } 50 | 51 | .. code-annotations:: 52 | 1. Instantiate a ``SPIClass`` object for use with a specific SPI bus. 53 | 2. Initialize the SPI bus using ``SPIClass::begin()`` method. The arguments passed to this function 54 | may differ depending on the Arduino core used (for a certain family of boards). 55 | 56 | Developers are encouraged to identify the use of ``SPIClass::begin()`` (or any 57 | ``SPIClass::set()``) as instructed by the utilized Arduino core's SPI library. 58 | 3. Pass a reference of the instantiated ``SPIClass`` object to `PinnacleTouchSPI::begin()`. 59 | 60 | 61 | .. md-tab-item:: I2C 62 | 63 | It is possible to use a specific I2C bus on boards that expose more than 1 I2C bus. As noted above, 64 | the ``TwoWire`` interface may vary depending on the targeted board. 65 | 66 | The following code snippet exemplifies the necessary steps: 67 | 68 | .. code-block:: cpp 69 | :class: annotated-with-numbers 70 | :emphasize-lines: 6,17,19 71 | 72 | #include 73 | #include 74 | 75 | #define DR_PIN 7 76 | 77 | TwoWire my_i2c_obj; // (1)! 78 | 79 | PinnacleTouchI2C trackpad(DR_PIN); 80 | 81 | void begin() 82 | { 83 | Serial.begin(115200); 84 | while (!Serial) { 85 | // some boards need this for the prompts to show immediately after boot 86 | } 87 | 88 | my_i2c_obj.begin(); // (2)! 89 | 90 | if (!trackpad.begin(&my_i2c_obj)) { // (3)! 91 | Serial.println(F("Cirque Pinnacle not responding!")); 92 | while (true) {} // hold program in infinite loop 93 | } 94 | 95 | // continue program as usual... 96 | } 97 | 98 | .. code-annotations:: 99 | 1. Instantiate a ``TwoWire`` object for use with a specific I2C bus. 100 | 2. Initialize the I2C bus using ``TwoWire::begin()`` method. The arguments passed to this function 101 | may differ depending on the Arduino core used (for a certain family of boards). 102 | 103 | Developers are encouraged to identify the use of ``TwoWire::begin()`` (or any 104 | ``TwoWire::set()``) as instructed by the utilized Arduino core's I2C library. 105 | 3. Pass a reference of the instantiated ``TwoWire`` object to `PinnacleTouchI2C::begin()`. 106 | -------------------------------------------------------------------------------- /docs/datasheets/Application Notes/InterfacingtoPinnacle_I2C-SPI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Application Notes/InterfacingtoPinnacle_I2C-SPI.pdf -------------------------------------------------------------------------------- /docs/datasheets/Application Notes/Pinnacle Extended Registers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Application Notes/Pinnacle Extended Registers.pdf -------------------------------------------------------------------------------- /docs/datasheets/Application Notes/Pinnacle Sensor Compensation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Application Notes/Pinnacle Sensor Compensation.pdf -------------------------------------------------------------------------------- /docs/datasheets/Application Notes/Using a Stylus with Pinnacle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Application Notes/Using a Stylus with Pinnacle.pdf -------------------------------------------------------------------------------- /docs/datasheets/Overlay Blueprints/35mm_Concaved_Overlay_blueprint.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Overlay Blueprints/35mm_Concaved_Overlay_blueprint.pdf -------------------------------------------------------------------------------- /docs/datasheets/Overlay Blueprints/40mm_Concaved_Overlay_blueprint.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Overlay Blueprints/40mm_Concaved_Overlay_blueprint.pdf -------------------------------------------------------------------------------- /docs/datasheets/Pinnacle Specification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Pinnacle Specification.pdf -------------------------------------------------------------------------------- /docs/datasheets/README.md: -------------------------------------------------------------------------------- 1 | # Cirque Official Documents 2 | 3 | This folder contains copies of the official documentation provided by Cirque. 4 | 5 | ## Resource origins 6 | 7 | - The [Cirque Pinnacle (1CA027) homepage](https://www.cirque.com/gen2gen3-asic-details) 8 | contains links for the latest datasheet and application notes. 9 | - The [Cirque Glidepoint Circle Trackpads homepage](https://www.cirque.com/glidepoint-circle-trackpads) 10 | contains link to the latest specifications about the manufactured trackpads that use the Pinnacle ASIC. 11 | - The [cirque-corp/Pinnacle_1CA027](https://github.com/cirque-corp/Pinnacle_1CA027) GitHub repository contains 12 | demonstration, example, and test code about the Cirque Pinnacle ASIC. Most of the information about 13 | the Pinnacle's AnyMeas mode was gathered from that code. 14 | -------------------------------------------------------------------------------- /docs/datasheets/Trackpad Specifications/TM023023 Trackpad Spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Trackpad Specifications/TM023023 Trackpad Spec.pdf -------------------------------------------------------------------------------- /docs/datasheets/Trackpad Specifications/TM035035 Trackpad Spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Trackpad Specifications/TM035035 Trackpad Spec.pdf -------------------------------------------------------------------------------- /docs/datasheets/Trackpad Specifications/TM040040 Trackpad Spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2bndy5/CirquePinnacle/2ae487ebcbbcc93c99e3837c63d432567a9595b5/docs/datasheets/Trackpad Specifications/TM040040 Trackpad Spec.pdf -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | Arduino Examples 5 | **************** 6 | 7 | Relative Mode 8 | ------------- 9 | 10 | Example to output data reports in Relative Mode. 11 | 12 | .. literalinclude:: ../examples/relative_mode/relative_mode.ino 13 | :caption: examples/relative_mode/relative_mode.ino 14 | :linenos: 15 | 16 | Absolute Mode 17 | ------------- 18 | 19 | Example to output data reports in Absolute Mode. 20 | 21 | .. literalinclude:: ../examples/absolute_mode/absolute_mode.ino 22 | :caption: examples/absolute_mode/absolute_mode.ino 23 | :linenos: 24 | 25 | .. _arduino_anymeas_example: 26 | 27 | AnyMeas Mode 28 | ------------ 29 | 30 | Example to output data reports in AnyMeas Mode. 31 | 32 | .. literalinclude:: ../examples/anymeas_mode/anymeas_mode.ino 33 | :caption: examples/anymeas_mode/anymeas_mode.ino 34 | :linenos: 35 | :emphasize-lines: 21-25 36 | 37 | Linux Examples 38 | ************** 39 | 40 | Relative Mode 41 | ------------- 42 | 43 | Example to output data reports in Relative Mode. 44 | 45 | .. literalinclude:: ../examples/linux/relative_mode.cpp 46 | :caption: examples/linux/relative_mode.cpp 47 | :linenos: 48 | 49 | Absolute Mode 50 | ------------- 51 | 52 | Example to output data reports in Absolute Mode. 53 | 54 | .. literalinclude:: ../examples/linux/absolute_mode.cpp 55 | :caption: examples/linux/absolute_mode.cpp 56 | :linenos: 57 | 58 | AnyMeas Mode 59 | ------------ 60 | 61 | Example to output data reports in AnyMeas Mode. 62 | 63 | .. literalinclude:: ../examples/linux/anymeas_mode.cpp 64 | :caption: examples/linux/anymeas_mode.cpp 65 | :linenos: 66 | :emphasize-lines: 30-34 67 | 68 | RPi Pico SDK Examples 69 | ********************* 70 | 71 | .. _pico_example_pins: 72 | 73 | defaultPins.h 74 | ------------- 75 | 76 | The ``DR_PIN`` AND ``SS_PIN`` example definitions for various RP2040 based boards. 77 | 78 | .. literalinclude:: ../examples/pico_sdk/defaultPins.h 79 | :caption: examples/pico_sdk/defaultPins.h 80 | :linenos: 81 | 82 | Relative Mode 83 | ------------- 84 | 85 | Example to output data reports in Relative Mode. 86 | 87 | .. literalinclude:: ../examples/pico_sdk/relative_mode.cpp 88 | :caption: examples/pico_sdk/relative_mode.cpp 89 | :linenos: 90 | 91 | Absolute Mode 92 | ------------- 93 | 94 | Example to output data reports in Absolute Mode. 95 | 96 | .. literalinclude:: ../examples/pico_sdk/absolute_mode.cpp 97 | :caption: examples/pico_sdk/absolute_mode.cpp 98 | :linenos: 99 | 100 | AnyMeas Mode 101 | ------------ 102 | 103 | Example to output data reports in AnyMeas Mode. 104 | 105 | .. literalinclude:: ../examples/pico_sdk/anymeas_mode.cpp 106 | :caption: examples/pico_sdk/anymeas_mode.cpp 107 | :linenos: 108 | :emphasize-lines: 25-29 109 | 110 | .. _py_examples: 111 | 112 | Python Examples 113 | *************** 114 | 115 | Relative Mode 116 | ------------- 117 | 118 | Example to output data reports in Relative Mode. 119 | 120 | .. literalinclude:: ../examples/cpython/relative_mode.py 121 | :caption: examples/cpython/relative_mode.py 122 | :linenos: 123 | :language: python 124 | 125 | Absolute Mode 126 | ------------- 127 | 128 | Example to output data reports in Absolute Mode. 129 | 130 | .. literalinclude:: ../examples/cpython/absolute_mode.py 131 | :caption: examples/cpython/absolute_mode.py 132 | :linenos: 133 | :language: python 134 | 135 | AnyMeas Mode 136 | ------------ 137 | 138 | Example to output data reports in AnyMeas Mode. 139 | 140 | .. literalinclude:: ../examples/cpython/anymeas_mode.py 141 | :caption: examples/cpython/anymeas_mode.py 142 | :linenos: 143 | :language: python 144 | :emphasize-lines: 34-44 145 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | 2 | .. toctree:: 3 | :hidden: 4 | 5 | self 6 | 7 | .. toctree:: 8 | :hidden: 9 | 10 | examples 11 | 12 | .. toctree:: 13 | :hidden: 14 | :caption: API Reference 15 | 16 | API/cpp 17 | API/python 18 | 19 | .. toctree:: 20 | :hidden: 21 | 22 | arduino 23 | 24 | .. toctree:: 25 | :hidden: 26 | 27 | linux 28 | 29 | .. toctree:: 30 | :hidden: 31 | 32 | python 33 | 34 | .. toctree:: 35 | :hidden: 36 | 37 | pico_sdk 38 | 39 | .. toctree:: 40 | :caption: Related Products 41 | :hidden: 42 | 43 | Cirque GlidePoint circle trackpads 44 | 12-pin FPC cable (0.5mm pitch) 45 | 46 | .. toctree:: 47 | :caption: Other Links 48 | :hidden: 49 | 50 | Download 51 | 52 | .. include:: ../README.rst 53 | -------------------------------------------------------------------------------- /docs/linux.rst: -------------------------------------------------------------------------------- 1 | Linux Support 2 | ============= 3 | 4 | This library can be used on any Linux device that exposes GPIO pins. 5 | 6 | Automated install script 7 | ************************ 8 | 9 | There is a file named ``install-linux.sh`` that automates the process outlined in :ref:`man_install` section. 10 | To use this script the file permission must be modified (only once): 11 | 12 | .. code-block:: shell 13 | 14 | chmod u+x install-linux.sh 15 | 16 | Now you can run the script and follow the prompts: 17 | 18 | .. code-block:: shell 19 | 20 | ./install-linux.sh 21 | 22 | .. _man_install: 23 | 24 | Installing from Source 25 | ********************** 26 | 27 | 1. Building the library from the source code requires CMake. 28 | 29 | .. code-block:: shell 30 | :caption: on Linux 31 | 32 | sudo apt install cmake 33 | 34 | 2. Clone the repository: 35 | 36 | .. code-block:: shell 37 | 38 | git clone https://github.com/2bndy5/CirquePinnacle.git 39 | 40 | 3. Navigate into the repository folder and create a build folder. Then navigate into the build folder. 41 | 42 | .. code-block:: shell 43 | 44 | cd CirquePinnacle 45 | mkdir build && cd build 46 | 47 | 4. Configure CMake to build the library: 48 | 49 | .. code-block:: shell 50 | 51 | cmake ../src 52 | 53 | .. tip:: 54 | :title: Optional arguments 55 | :collapsible: 56 | 57 | ``-DPINNACLE_SPI_SPEED=6000000`` 58 | The SPI speed can be set with ``-DPINNACLE_SPI_SPEED=xxx`` to lower the default speed/baudrate used on 59 | the SPI bus. Default value is the officially recommended 6 MHz; maximum supported is 13 MHz. 60 | 61 | ``-DPINNACLE_ANYMEAS_SUPPORT=OFF`` 62 | To reduce the compile size of the CirquePinnacle library, you can use ``-DPINNACLE_ANYMEAS_SUPPORT=OFF`` 63 | when the application won't use the Pinnacle's anymeas mode. 64 | 5. Build and install the library: 65 | 66 | .. code-block:: shell 67 | 68 | make 69 | sudo make install 70 | 71 | Run an example 72 | ************** 73 | 74 | After the library is installed, open one of the linux examples (located in examples/linux) and change the pin 75 | numbers accordingly. The following steps will use a build folder created in the CirquePinnacle 76 | repository's root folder (as created in step 3 above). 77 | 78 | 1. First make sure the created build folder is empty. 79 | 80 | .. code-block:: shell 81 | :caption: :si-icon:`fontawesome/regular/trash-can;pulsing-red` 82 | Be sure to do this from within the build folder!!! 83 | :si-icon:`material/sign-yield;pulsing-red` 84 | 85 | rm -r ./* 86 | 87 | 2. Configure CMake to build the examples: 88 | 89 | .. code-block:: shell 90 | 91 | cmake ../examples/linux 92 | 93 | .. tip:: 94 | :title: Optional arguments 95 | :collapsible: 96 | 97 | ``-DUSE_I2C=ON`` 98 | If using the I2C interface (`PinnacleTouchI2C`), then you can enable this for the examples with 99 | ``-DUSE_I2C=ON``. 100 | 3. Build the examples: 101 | 102 | .. code-block:: shell 103 | 104 | make 105 | 4. Run an example: 106 | 107 | .. code-block:: shell 108 | 109 | ./relative_mode 110 | 111 | .. _slaveSelectPin: 112 | 113 | SlaveSelect pin 114 | *************** 115 | 116 | Using the SPI bus' SS pin (Slave Select, aka Chip Select) on a Linux platform is a bit different 117 | from the Arduino platform because the Linux kernel controls the pin during bus transactions. 118 | Therefore, the pin number passed to the `~PinnacleTouchSPI::PinnacleTouchSPI()` constructor should 119 | follow the form ``ab`` where ``a`` is the SPI bus number and ``b`` is the specified bus' SS pin 120 | (often labeled ``CE`` on Raspberry Pi pinout diagrams). 121 | 122 | .. csv-table:: 123 | :header: "bus ID","CE number","constructor's ``slaveSelectPin`` value","spidev adapter" 124 | :widths: 2, 4, 8, 6 125 | 126 | ``0``,``0``,:expr:`0`,``/dev/spidev0.0`` 127 | ``0``,``1``,:expr:`1`,``/dev/spidev0.1`` 128 | ``1``,``0``,:expr:`10`,``/dev/spidev1.0`` 129 | ``1``,``1``,:expr:`11`,``/dev/spidev1.1`` 130 | ``1``,``2``,:expr:`12`,``/dev/spidev1.2`` 131 | 132 | Using a non-default I2C bus 133 | *************************** 134 | 135 | The default I2C bus used is ``/dev/i2c-1``. However, some boards may use a different I2C bus number 136 | as a default. This can be remedied by passing the correct bus number to `cirque_pinnacle_arduino_wrappers::TwoWire::begin()`. 137 | 138 | .. code-block:: cpp 139 | :caption: To use ``/dev/i2c-0`` bus 140 | :class: annotated-with-numbers 141 | :emphasize-lines: 7,9 142 | 143 | #include 144 | #define DR_PIN 25 145 | PinnacleTouchI2C trackpad(DR_PIN); 146 | 147 | int main() { 148 | // specify the I2C bus 149 | cirque_pinnacle_arduino_wrappers::Wire.begin(0); // (1)! 150 | 151 | if (!trackpad.begin(&cirque_pinnacle_arduino_wrappers::Wire)) { // (2)! 152 | return 1; // failed to initialize the trackpad 153 | } 154 | // continue the program as usual ... 155 | } 156 | 157 | .. code-annotations:: 158 | 1. Use :expr:`0` for ``/dev/i2c-0``. Default is :expr:`1` for ``/dev/i2c-1``. 159 | 160 | .. seealso:: `cirque_pinnacle_arduino_wrappers::TwoWire::begin()` 161 | 2. Explicitly pass a reference of the `~cirque_pinnacle_arduino_wrappers::TwoWire` object to 162 | `PinnacleTouchI2C::begin()`. 163 | -------------------------------------------------------------------------------- /docs/python.rst: -------------------------------------------------------------------------------- 1 | Python Binding 2 | ============== 3 | 4 | This library has bindings for use in CPython on Linux. While it is only meant to function on Linux, 5 | you can still install the python bindings on other platforms which will only yield the stubs-only 6 | package (type hints) for the python bindings. 7 | 8 | Installing via ``pip`` 9 | ********************** 10 | 11 | A distributable package is deployed to PyPI, so users can simply install the python bindings 12 | with the following: 13 | 14 | .. code-block:: shell 15 | 16 | pip install cirque-pinnacle 17 | 18 | .. note:: 19 | While this library is designed to function only on Linux boards with GPIO pins exposed, this 20 | python package includes a stub-only package for non-Linux platforms. This stub-only package is 21 | meant to aid in remote development environments that do type checking in python. 22 | 23 | Installing from Github 24 | ********************** 25 | 26 | 1. Building the bindings from the source code requires a couple dependencies. 27 | On linux, the CPython's dev headers and CMake are needed. 28 | 29 | .. code-block:: shell 30 | :caption: on Linux 31 | 32 | sudo apt install python3-dev cmake 33 | 34 | .. note:: 35 | Building on non-Linux platforms doesn't require any installed dependencies (other than 36 | Python 3). 37 | 2. Clone the repository and initialize the submodule for pybind11. 38 | 39 | .. code-block:: shell 40 | 41 | git clone --recurse-submodules https://github.com/2bndy5/CirquePinnacle.git 42 | 43 | Or, if you already cloned the repository, you can simply ensure the pybind11 submodule is 44 | initialized in the src folder: 45 | 46 | .. code-block:: shell 47 | :caption: from the repository's root folder 48 | 49 | git submodule update --init src/pybind11 50 | 51 | 3. Navigate into the repository folder. 52 | 53 | .. code-block:: shell 54 | 55 | cd CirquePinnacle 56 | 57 | 4. Build and install the package: 58 | 59 | .. code-block:: shell 60 | 61 | python3 -m pip install . -v 62 | 63 | The optional ``-v`` will use ``pip``\ 's verbosity to show that the process isn't frozen. Otherwise, the 64 | step labeled "building wheel" may look like it isn't doing anything for a few minutes. 65 | 66 | .. info:: Optional ``CMAKE_ARGS`` environment variable 67 | :collapsible: 68 | 69 | You can customize the build further using an environment variable named ``CMAKE_ARGS`` set to a string of 70 | space-separated options that get passed to CMake. Supported options include: 71 | 72 | ``-DPINNACLE_SPI_SPEED=6000000`` 73 | The SPI speed can be set with ``-DPINNACLE_SPI_SPEED=xxx`` to lower the default speed/baudrate used on 74 | the SPI bus. Default value is the officially recommended 6 MHz; maximum supported is 13 MHz. 75 | 76 | ``-DPINNACLE_ANYMEAS_SUPPORT=OFF`` 77 | To reduce the compile size of the CirquePinnacle library, you can use ``-DPINNACLE_ANYMEAS_SUPPORT=OFF`` 78 | when the application won't use the Pinnacle's anymeas mode. 79 | 80 | 5. Open one of the python examples (located in examples/cpython), change the pin numbers accordingly, and run the example. 81 | 82 | .. seealso:: 83 | The :cpp:expr:`PinnacleTouchSPI::begin(pinnacle_spi_t*)` function is not exposed in the python binding. 84 | Please review how to specify the :ref:`slaveSelectPin` for Linux platforms. 85 | 86 | .. code-block:: shell 87 | 88 | python3 examples/cpython/relative_mode.py 89 | 90 | .. important:: 91 | :title: ``sudo`` in a Virtual Environment 92 | 93 | Using ``sudo`` from a python virtual environment *will* cause problems because 94 | ``sudo`` will invoke the system install of the python interpreter (not the virtual 95 | environment's install of the python interpreter). 96 | 97 | If you need to use ``sudo`` from within a virtual environment, then you *must* specify the 98 | path to the virtual environment's install of the python interpreter. 99 | 100 | .. code-block:: shell 101 | :caption: given that the virtual environment is located in ``~/venv`` 102 | 103 | sudo ~/venv/bin/python examples/cpython/relative_mode.py 104 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx-immaterial[cpp] 2 | -------------------------------------------------------------------------------- /examples/.clang-format: -------------------------------------------------------------------------------- 1 | # See: https://releases.llvm.org/11.0.1/tools/clang/docs/ClangFormatStyleOptions.html 2 | --- 3 | Language: Cpp 4 | # LLVM is the default style setting, used when a configuration option is not set here 5 | BasedOnStyle: LLVM 6 | AccessModifierOffset: -2 7 | AlignAfterOpenBracket: Align 8 | AlignConsecutiveAssignments: false 9 | AlignConsecutiveBitFields: false 10 | AlignConsecutiveDeclarations: false 11 | AlignConsecutiveMacros: false 12 | AlignEscapedNewlines: DontAlign 13 | AlignOperands: Align 14 | AlignTrailingComments: true 15 | AllowAllArgumentsOnNextLine: true 16 | AllowAllConstructorInitializersOnNextLine: true 17 | AllowAllParametersOfDeclarationOnNextLine: true 18 | AllowShortBlocksOnASingleLine: Always 19 | AllowShortCaseLabelsOnASingleLine: true 20 | AllowShortEnumsOnASingleLine: true 21 | AllowShortFunctionsOnASingleLine: Empty 22 | AllowShortIfStatementsOnASingleLine: Always 23 | AllowShortLambdasOnASingleLine: Empty 24 | AllowShortLoopsOnASingleLine: true 25 | AlwaysBreakAfterDefinitionReturnType: None 26 | AlwaysBreakAfterReturnType: None 27 | AlwaysBreakBeforeMultilineStrings: false 28 | AlwaysBreakTemplateDeclarations: No 29 | BinPackArguments: true 30 | BinPackParameters: true 31 | # Only used when "BreakBeforeBraces" set to "Custom" 32 | BraceWrapping: 33 | AfterCaseLabel: false 34 | AfterClass: false 35 | AfterControlStatement: Never 36 | AfterEnum: false 37 | AfterFunction: false 38 | AfterNamespace: false 39 | #AfterObjCDeclaration: 40 | AfterStruct: false 41 | AfterUnion: false 42 | AfterExternBlock: false 43 | BeforeCatch: false 44 | BeforeElse: false 45 | BeforeLambdaBody: false 46 | BeforeWhile: false 47 | IndentBraces: false 48 | SplitEmptyFunction: false 49 | SplitEmptyRecord: false 50 | SplitEmptyNamespace: false 51 | # Java-specific 52 | #BreakAfterJavaFieldAnnotations: 53 | BreakBeforeBinaryOperators: NonAssignment 54 | BreakBeforeBraces: Attach 55 | BreakBeforeTernaryOperators: true 56 | BreakConstructorInitializers: BeforeColon 57 | BreakInheritanceList: BeforeColon 58 | BreakStringLiterals: false 59 | ColumnLimit: 0 60 | # "" matches none 61 | CommentPragmas: "" 62 | CompactNamespaces: false 63 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 64 | ConstructorInitializerIndentWidth: 2 65 | ContinuationIndentWidth: 2 66 | Cpp11BracedListStyle: false 67 | DeriveLineEnding: true 68 | DerivePointerAlignment: true 69 | DisableFormat: false 70 | # Docs say "Do not use this in config files". The default (LLVM 11.0.1) is "false". 71 | #ExperimentalAutoDetectBinPacking: 72 | FixNamespaceComments: false 73 | ForEachMacros: [] 74 | IncludeBlocks: Preserve 75 | IncludeCategories: [] 76 | # "" matches none 77 | IncludeIsMainRegex: "" 78 | IncludeIsMainSourceRegex: "" 79 | IndentCaseBlocks: true 80 | IndentCaseLabels: true 81 | IndentExternBlock: Indent 82 | IndentGotoLabels: false 83 | IndentPPDirectives: None 84 | IndentWidth: 2 85 | IndentWrappedFunctionNames: false 86 | InsertTrailingCommas: None 87 | # Java-specific 88 | #JavaImportGroups: 89 | # JavaScript-specific 90 | #JavaScriptQuotes: 91 | #JavaScriptWrapImports 92 | KeepEmptyLinesAtTheStartOfBlocks: true 93 | MacroBlockBegin: "" 94 | MacroBlockEnd: "" 95 | # Set to a large number to effectively disable 96 | MaxEmptyLinesToKeep: 100000 97 | NamespaceIndentation: None 98 | NamespaceMacros: [] 99 | # Objective C-specific 100 | #ObjCBinPackProtocolList: 101 | #ObjCBlockIndentWidth: 102 | #ObjCBreakBeforeNestedBlockParam: 103 | #ObjCSpaceAfterProperty: 104 | #ObjCSpaceBeforeProtocolList 105 | PenaltyBreakAssignment: 1 106 | PenaltyBreakBeforeFirstCallParameter: 1 107 | PenaltyBreakComment: 1 108 | PenaltyBreakFirstLessLess: 1 109 | PenaltyBreakString: 1 110 | PenaltyBreakTemplateDeclaration: 1 111 | PenaltyExcessCharacter: 1 112 | PenaltyReturnTypeOnItsOwnLine: 1 113 | # Used as a fallback if alignment style can't be detected from code (DerivePointerAlignment: true) 114 | PointerAlignment: Right 115 | RawStringFormats: [] 116 | ReflowComments: false 117 | SortIncludes: false 118 | SortUsingDeclarations: false 119 | SpaceAfterCStyleCast: false 120 | SpaceAfterLogicalNot: false 121 | SpaceAfterTemplateKeyword: false 122 | SpaceBeforeAssignmentOperators: true 123 | SpaceBeforeCpp11BracedList: false 124 | SpaceBeforeCtorInitializerColon: true 125 | SpaceBeforeInheritanceColon: true 126 | SpaceBeforeParens: ControlStatements 127 | SpaceBeforeRangeBasedForLoopColon: true 128 | SpaceBeforeSquareBrackets: false 129 | SpaceInEmptyBlock: false 130 | SpaceInEmptyParentheses: false 131 | SpacesBeforeTrailingComments: 2 132 | SpacesInAngles: false 133 | SpacesInCStyleCastParentheses: false 134 | SpacesInConditionalStatement: false 135 | SpacesInContainerLiterals: false 136 | SpacesInParentheses: false 137 | SpacesInSquareBrackets: false 138 | Standard: Auto 139 | StatementMacros: [] 140 | TabWidth: 2 141 | TypenameMacros: [] 142 | # Default to LF if line endings can't be detected from the content (DeriveLineEnding). 143 | UseCRLF: false 144 | UseTab: Never 145 | WhitespaceSensitiveMacros: [] 146 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | This folder contains CirquePinnacle library examples for the various supported platforms/frameworks. 4 | 5 | The following folders have examples for the Arduino IDE (and PlatformIO): 6 | 7 | - `absolute_mode` 8 | - `relative_mode` 9 | - `anymeas_mode` 10 | - `usb_mouse` uses Arduino framework's `Mouse` object (board dependent). 11 | 12 | The `pico_sdk` folder has examples for the RPi Pico SDK. 13 | 14 | The `linux` folder has examples for Linux (C++ only). 15 | 16 | The `cpython` folder has examples for the CPython bindings. 17 | 18 | There is no USB mouse example for `linux` (and consequently `cpython`). 19 | -------------------------------------------------------------------------------- /examples/absolute_mode/absolute_mode.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "absolute mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include // sqrt(), pow(), atan2() 7 | #include 8 | 9 | #define SS_PIN 2 10 | #define DR_PIN 7 11 | 12 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 13 | // If using I2C, then use the following line (not the line above) 14 | // PinnacleTouchI2C trackpad(DR_PIN); 15 | 16 | // an object to hold data reported by the Cirque trackpad 17 | AbsoluteReport data; 18 | 19 | void setup() { 20 | Serial.begin(115200); 21 | while (!Serial) { 22 | // wait till Serial monitor is opened 23 | } 24 | if (!trackpad.begin()) { 25 | Serial.println(F("Cirque Pinnacle not responding!")); 26 | while (true) { 27 | // hold program in infinite loop 28 | } 29 | } 30 | Serial.println(F("CirquePinnacle/examples/absolute_mode")); 31 | trackpad.setDataMode(PINNACLE_ABSOLUTE); 32 | trackpad.absoluteModeConfig(1); // set count of z-idle packets to 1 33 | Serial.println(F("\n*** Enter 'M' to measure and print raw data.")); 34 | Serial.println(F("*** Enter 'T' to measure and print trigonometric calculations.\n")); 35 | Serial.println(F("Touch the trackpad to see the data.")); 36 | } 37 | 38 | /* 39 | Showing all the Serial output below will slow down the board's ability to 40 | read() data from the trackpad in a timely manner (resulting in data loss). 41 | Use this compile-time definition to switch between printing 42 | raw data (false) or trigonometry data (true) 43 | */ 44 | bool onlyShowTrigVals = false; 45 | 46 | #ifndef M_PI 47 | #define PI M_PI 48 | #else 49 | #define PI 3.14159 50 | #endif 51 | 52 | void loop() { 53 | if (trackpad.available()) { 54 | trackpad.read(&data); 55 | 56 | // datasheet recommends clamping the axes value to reliable range 57 | if (data.z) { // only clamp values if Z axis is not idle. 58 | 59 | data.x = data.x > 1920 ? 1920 : (data.x < 128 ? 128 : data.x); // 128 <= x <= 1920 60 | data.y = data.y > 1472 ? 1472 : (data.y < 64 ? 64 : data.y); // 64 <= y <= 1472 61 | } 62 | 63 | if (!onlyShowTrigVals) { 64 | // print raw data from the trackpad 65 | Serial.print(F("B1:")); 66 | Serial.print(data.buttons & 1); 67 | Serial.print(F(" B2:")); 68 | Serial.print(data.buttons & 2); 69 | Serial.print(F(" B3:")); 70 | Serial.print(data.buttons & 4); 71 | Serial.print(F("\tX:")); 72 | Serial.print(data.x); 73 | Serial.print(F("\tY:")); 74 | Serial.print(data.y); 75 | Serial.print(F("\tZ:")); 76 | Serial.println(data.z); 77 | } else { 78 | // print trigonometric data from the trackpad 79 | if (!data.z) { // only compute angle and radius if touching (or near) the sensor 80 | Serial.println(F("Idling")); 81 | } else { 82 | // coordinates assume axes have been clamped to recommended ranges 83 | double coord_x = (int16_t)(data.x) - 960; 84 | double coord_y = (int16_t)(data.y) - 736; // NOTE: y-axis is inverted by default 85 | double radius = sqrt(pow(coord_x, 2) + pow(coord_y, 2)); 86 | // angle (in degrees) ranges (-180, 180] 87 | double angle = atan2(coord_y, coord_x) * 180 / PI; 88 | 89 | // This Serial output is meant to be compatible with the Arduino IDE Serial Plotter applet. 90 | Serial.print(F("angle:")); 91 | Serial.print(angle); 92 | Serial.print(F(",radius:")); 93 | Serial.println(radius); 94 | } 95 | } 96 | } // end if trackpad.available() 97 | 98 | while (Serial.available()) { 99 | char input = Serial.read(); 100 | if (input == 't' || input == 'T') { 101 | onlyShowTrigVals = true; 102 | } else if (input == 'm' || input == 'M') { 103 | onlyShowTrigVals = false; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /examples/anymeas_mode/anymeas_mode.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "anymeas mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include 7 | 8 | #define SS_PIN 2 9 | #define DR_PIN 7 10 | 11 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 12 | // If using I2C, then use the following line (not the line above) 13 | // PinnacleTouchI2C trackpad(DR_PIN); 14 | 15 | typedef struct _MeasureVector { 16 | uint32_t toggle; 17 | uint32_t polarity; 18 | } measureVector; 19 | 20 | measureVector vectorDeterminants[] = { 21 | // toggle , polarity 22 | { 0x0000FFFF, 0x00000000 }, // toggle all x-axis bits negatively (to 0) 23 | { 0x0FFF0000, 0x00000000 }, // toggle all y-axis bits negatively (to 0) 24 | { 0x00FF00FF, 0x000000FF }, // toggle Y0-Y7 negatively (to 0) & X0-X7 positively (to 1) 25 | { 0x00FF00FF, 0x00FF0000 } // toggle Y0-Y7 positively (to 1) & X0-X7 negatively (to 0) 26 | }; 27 | 28 | const uint8_t variousVectors_size = sizeof(vectorDeterminants) / sizeof(measureVector); 29 | int16_t compensations[variousVectors_size]; 30 | 31 | void compensate() { 32 | int16_t value; 33 | int32_t accumulatedValue; 34 | for (uint8_t i = 0; i < variousVectors_size; ++i) { 35 | uint8_t sweep = 0; 36 | accumulatedValue = 0; 37 | while (sweep < 5) // take 5 measurements and average them for a bit lower noise compensation value 38 | { 39 | value = trackpad.measureAdc(vectorDeterminants[i].toggle, vectorDeterminants[i].polarity); 40 | sweep++; 41 | accumulatedValue += value; 42 | } 43 | compensations[i] = accumulatedValue / 5; 44 | Serial.print(F("compensate ")); 45 | Serial.print(i); 46 | Serial.print(F(": ")); 47 | Serial.println(compensations[i]); 48 | } 49 | } 50 | 51 | void setup() { 52 | Serial.begin(115200); 53 | while (!Serial) { 54 | // wait till Serial monitor is opened 55 | } 56 | if (!trackpad.begin()) { 57 | Serial.println(F("Cirque Pinnacle not responding!")); 58 | while (true) { 59 | // hold program in infinite loop 60 | } 61 | } 62 | Serial.println(F("CirquePinnacle/examples/anymeas_mode")); 63 | trackpad.setDataMode(PINNACLE_ANYMEAS); 64 | trackpad.anymeasModeConfig(); 65 | compensate(); 66 | Serial.println(F("starting in 5 seconds...")); 67 | delay(5000); 68 | } 69 | 70 | void loop() { 71 | for (uint8_t i = 0; i < variousVectors_size; i++) { 72 | int16_t measurement = trackpad.measureAdc(vectorDeterminants[i].toggle, 73 | vectorDeterminants[i].polarity); 74 | measurement -= compensations[i]; 75 | Serial.print(F("meas")); 76 | Serial.print(i); 77 | Serial.print(F(":")); 78 | Serial.print(measurement); 79 | Serial.print(F(" \t")); 80 | } 81 | Serial.println(); 82 | } 83 | -------------------------------------------------------------------------------- /examples/cpython/absolute_mode.py: -------------------------------------------------------------------------------- 1 | """ 2 | This example reads data from the Cirque trackpad in "absolute mode" and 3 | prints the values. 4 | 5 | See documentation at https://cirquepinnacle.rtfd.io/ 6 | """ 7 | 8 | import math 9 | import time 10 | from typing import Union 11 | from cirque_pinnacle import ( 12 | AbsoluteReport, 13 | PinnacleTouchSPI, 14 | PinnacleTouchI2C, 15 | PINNACLE_ABSOLUTE, 16 | ) 17 | 18 | print("CirquePinnacle/examples/cpython/absolute_mode") 19 | 20 | # The digital input pin connected to the trackpad's DR (DataReady) pin 21 | dr_pin = 25 # GPIO25 22 | 23 | trackpad: Union[PinnacleTouchSPI, PinnacleTouchI2C] 24 | if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"): 25 | print("-- Using SPI interface.") 26 | ss_pin = 0 # uses /dev/spidev0.0 (CE0 or GPIO8) 27 | trackpad = PinnacleTouchSPI(dr_pin, ss_pin) 28 | else: 29 | print("-- Using I2C interface") 30 | trackpad = PinnacleTouchI2C(dr_pin) 31 | 32 | if not trackpad.begin(): 33 | raise OSError("Cirque Pinnacle not responding!") 34 | 35 | trackpad.data_mode = PINNACLE_ABSOLUTE 36 | trackpad.absolute_mode_config(1) # set count of z-idle packets to 1 37 | 38 | # an object to hold data reported by the Cirque trackpad 39 | data = AbsoluteReport() 40 | 41 | 42 | def print_data(timeout=6): 43 | """Print available data reports from the Pinnacle touch controller 44 | until there's no input for a period of ``timeout`` seconds.""" 45 | print( 46 | "Touch the sensor to see the data. Exits after", 47 | timeout, 48 | "seconds of inactivity.", 49 | ) 50 | start = time.monotonic() 51 | while time.monotonic() - start < timeout: 52 | while trackpad.available(): # is there new data? 53 | trackpad.read(data) 54 | 55 | # specification sheet recommends clamping absolute position data of 56 | # X & Y axis for reliability 57 | if data.z: # only clamp values if Z axis is not idle 58 | data.x = max(128, min(1920, data.x)) # 128 <= x < = 1920 59 | data.y = max(64, min(1472, data.y)) # 64 <= y < = 1472 60 | 61 | print(data) 62 | start = time.monotonic() 63 | 64 | 65 | def print_trig(timeout=6): 66 | """Print available data reports from the Pinnacle touch controller as trigonometric 67 | calculations until there's no input for a period of ``timeout`` seconds.""" 68 | print( 69 | "Touch the trackpad to see the data. Exits after", 70 | timeout, 71 | "seconds of inactivity.", 72 | ) 73 | start = time.monotonic() 74 | while time.monotonic() - start < timeout: 75 | while trackpad.available(): # is there new data? 76 | trackpad.read(data) 77 | 78 | if not data.z: # if not touching (or near) the sensor 79 | print("Idling") # don't do calc when both axes are 0 80 | else: # if touching (or near) the sensor 81 | # datasheet recommends clamping X & Y axis for reliability 82 | data.x = max(128, min(1920, data.x)) # 128 <= x <= 1920 83 | data.y = max(64, min(1472, data.y)) # 64 <= y <= 1472 84 | 85 | # coordinates assume axes have been clamped to recommended ranges 86 | coord_x = data.x - 960 87 | coord_y = data.y - 736 # NOTE: y-axis is inverted by default 88 | radius = math.sqrt(math.pow(coord_x, 2) + math.pow(coord_y, 2)) 89 | # angle (in degrees) ranges [-180, 180]; 90 | angle = math.atan2(coord_y, coord_x) * 180 / math.pi 91 | print("angle: %.2f\tradius: %.2f" % (angle, radius)) 92 | start = time.monotonic() 93 | 94 | 95 | def set_role(): 96 | """Set the role using stdin stream. Arguments for functions can be 97 | specified using a space delimiter (e.g. 'M 10' calls `print_data(10)`) 98 | """ 99 | user_input = ( 100 | input( 101 | "\n*** Enter 'M' to measure and print raw data." 102 | "\n*** Enter 'T' to measure and print trigonometric calculations." 103 | "\n*** Enter 'Q' to quit example.\n" 104 | ) 105 | or "?" 106 | ).split() 107 | if user_input[0].upper().startswith("M"): 108 | print_data(*[int(x) for x in user_input[1:2]]) 109 | return True 110 | if user_input[0].upper().startswith("T"): 111 | print_trig(*[int(x) for x in user_input[1:2]]) 112 | return True 113 | if user_input[0].upper().startswith("Q"): 114 | return False 115 | print(user_input[0], "is an unrecognized input. Please try again.") 116 | return set_role() 117 | 118 | 119 | if __name__ == "__main__": 120 | try: 121 | while set_role(): 122 | pass # continue example until 'Q' is entered 123 | except KeyboardInterrupt: 124 | print(" Keyboard Interrupt detected.") 125 | else: 126 | print( 127 | "\nRun print_data() to read and print raw data.", 128 | "Run print_trig() to measure and print trigonometric calculations.", 129 | sep="\n", 130 | ) 131 | -------------------------------------------------------------------------------- /examples/cpython/anymeas_mode.py: -------------------------------------------------------------------------------- 1 | """ 2 | This example reads data from the Cirque trackpad in "anymeas mode" and 3 | prints the values. 4 | 5 | See documentation at https://cirquepinnacle.rtfd.io/ 6 | """ 7 | 8 | import time 9 | from typing import Union 10 | from cirque_pinnacle import ( 11 | PinnacleTouchSPI, 12 | PinnacleTouchI2C, # noqa: imported but unused 13 | PINNACLE_ANYMEAS, 14 | ) 15 | 16 | print("CirquePinnacle/examples/cpython/anymeas_mode\n") 17 | 18 | # The digital input pin connected to the trackpad's DR (DataReady) pin 19 | dr_pin = 25 # GPIO25 20 | 21 | trackpad: Union[PinnacleTouchSPI, PinnacleTouchI2C] 22 | if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"): 23 | print("-- Using SPI interface.") 24 | ss_pin = 0 # uses /dev/spidev0.0 (CE0 or GPIO8) 25 | trackpad = PinnacleTouchSPI(dr_pin, ss_pin) 26 | else: 27 | print("-- Using I2C interface") 28 | trackpad = PinnacleTouchI2C(dr_pin) 29 | 30 | if not trackpad.begin(): 31 | raise OSError("Cirque Pinnacle not responding!") 32 | trackpad.data_mode = PINNACLE_ANYMEAS 33 | 34 | # we'll use this list of tuples as args to PinnacleTouch.measure_adc() 35 | vectors = [ 36 | # toggle , polarity 37 | (0x0000FFFF, 0x00000000), # toggle all x-axis bits negatively (to 0) 38 | (0x0FFF0000, 0x00000000), # toggle all y-axis bits negatively (to 0) 39 | ( 40 | 0x00FF00FF, 41 | 0x000000FF, 42 | ), # toggle Y0-Y7 negatively (to 0) & X0-X7 positively (to 1) 43 | ( 44 | 0x00FF00FF, 45 | 0x00FF0000, 46 | ), # toggle Y0-Y7 positively (to 1) & X0-X7 negatively (to 0) 47 | ] 48 | 49 | # a list of compensations to use with measured `vectors` 50 | compensation = [0] * len(vectors) 51 | 52 | 53 | def compensate(): 54 | sweep = 5 55 | for i, (toggle, polarity) in enumerate(vectors): 56 | value = 0 57 | for _ in range(sweep): 58 | value += trackpad.measure_adc(toggle, polarity) 59 | compensation[i] = int(value / sweep) 60 | print("compensation {}: {}".format(i, compensation[i])) 61 | 62 | 63 | def take_measurements(timeout=6): 64 | """Read ``len(vectors)`` number of measurements and print results for 65 | ``timeout`` number of seconds.""" 66 | print("Taking measurements for", timeout, "seconds.") 67 | start = time.monotonic() 68 | while time.monotonic() - start < timeout: 69 | for i, (toggle, polarity) in enumerate(vectors): 70 | result = trackpad.measure_adc(toggle, polarity) 71 | print("meas{}: {}".format(i, result - compensation[i]), end="\t") 72 | print() 73 | 74 | 75 | def set_role(): 76 | """Set the role using stdin stream. Arguments for functions can be 77 | specified using a space delimiter (e.g. 'C 10' calls `compensate(10)`) 78 | """ 79 | user_input = ( 80 | input( 81 | "\n*** Enter 'C' to get compensations for measurements." 82 | "\n*** Enter 'M' to read and print measurements." 83 | "\n*** Enter 'Q' to quit example.\n" 84 | ) 85 | or "?" 86 | ).split() 87 | if user_input[0].upper().startswith("C"): 88 | compensate(*[int(x) for x in user_input[1:2]]) 89 | return True 90 | if user_input[0].upper().startswith("M"): 91 | take_measurements(*[int(x) for x in user_input[1:2]]) 92 | return True 93 | if user_input[0].upper().startswith("Q"): 94 | return False 95 | print(user_input[0], "is an unrecognized input. Please try again.") 96 | return set_role() 97 | 98 | 99 | if __name__ == "__main__": 100 | try: 101 | while set_role(): 102 | pass # continue example until 'Q' is entered 103 | except KeyboardInterrupt: 104 | print(" Keyboard Interrupt detected.") 105 | else: 106 | print( 107 | "\nRun compensate() to set compensations for measurements.", 108 | "Run take_measurements() to read and print measurements.", 109 | sep="\n", 110 | ) 111 | -------------------------------------------------------------------------------- /examples/cpython/relative_mode.py: -------------------------------------------------------------------------------- 1 | """ 2 | This example reads data from the Cirque trackpad in "relative mode" and 3 | prints the values. 4 | 5 | See documentation at https://cirquepinnacle.rtfd.io/ 6 | """ 7 | 8 | import time 9 | from typing import Union 10 | from cirque_pinnacle import ( 11 | RelativeReport, 12 | PinnacleTouchSPI, 13 | PinnacleTouchI2C, 14 | ) 15 | 16 | print("CirquePinnacle/examples/cpython/relative_mode\n") 17 | 18 | # The digital input pin connected to the trackpad's DR (DataReady) pin 19 | dr_pin = 25 # GPIO25 20 | 21 | trackpad: Union[PinnacleTouchSPI, PinnacleTouchI2C] 22 | if not input("Is the trackpad configured for I2C? [y/N] ").lower().startswith("y"): 23 | print("-- Using SPI interface.") 24 | ss_pin = 0 # uses /dev/spidev0.0 (CE0 or GPIO8) 25 | trackpad = PinnacleTouchSPI(dr_pin, ss_pin) 26 | else: 27 | print("-- Using I2C interface") 28 | trackpad = PinnacleTouchI2C(dr_pin) 29 | 30 | if not trackpad.begin(): 31 | raise OSError("Cirque Pinnacle not responding!") 32 | 33 | # an object to hold data reported by the Cirque trackpad 34 | data = RelativeReport() 35 | 36 | 37 | def print_data(timeout=6): 38 | """Print available data reports from the Pinnacle touch controller 39 | until there's no input for a period of ``timeout`` seconds.""" 40 | print( 41 | "Touch the sensor to see the data. Exits after", 42 | timeout, 43 | "seconds of inactivity.", 44 | ) 45 | start = time.monotonic() 46 | while time.monotonic() - start < timeout: 47 | while trackpad.available(): # is there new data? 48 | trackpad.read(data) 49 | print(data) 50 | start = time.monotonic() 51 | 52 | 53 | def set_role(): 54 | """Set the role using stdin stream. Arguments for functions can be 55 | specified using a space delimiter (e.g. 'M 10' calls `print_data(10)`) 56 | """ 57 | user_input = ( 58 | input( 59 | "\n*** Enter 'M' to measure and print data." 60 | "\n*** Enter 'Q' to quit example.\n" 61 | ) 62 | or "?" 63 | ).split() 64 | if user_input[0].upper().startswith("M"): 65 | print_data(*[int(x) for x in user_input[1:2]]) 66 | return True 67 | if user_input[0].upper().startswith("Q"): 68 | return False 69 | print(user_input[0], "is an unrecognized input. Please try again.") 70 | return set_role() 71 | 72 | 73 | if __name__ == "__main__": 74 | try: 75 | while set_role(): 76 | pass # continue example until 'Q' is entered 77 | except KeyboardInterrupt: 78 | print(" Keyboard Interrupt detected.") 79 | else: 80 | print("\nRun print_data() to read and print data.") 81 | -------------------------------------------------------------------------------- /examples/linux/.clang-format: -------------------------------------------------------------------------------- 1 | # See options listed at https://releases.llvm.org/12.0.1/tools/clang/docs/ClangFormatStyleOptions.html 2 | --- 3 | Language: Cpp 4 | # BasedOnStyle: WebKit 5 | AccessModifierOffset: -4 6 | AlignAfterOpenBracket: Align 7 | AlignConsecutiveMacros: Consecutive 8 | AlignConsecutiveAssignments: None 9 | AlignConsecutiveBitFields: None 10 | AlignConsecutiveDeclarations: None 11 | AlignEscapedNewlines: Left 12 | AlignOperands: DontAlign 13 | AlignTrailingComments: true 14 | AllowAllArgumentsOnNextLine: true 15 | AllowAllConstructorInitializersOnNextLine: true 16 | AllowAllParametersOfDeclarationOnNextLine: true 17 | AllowShortEnumsOnASingleLine: false 18 | AllowShortBlocksOnASingleLine: Empty 19 | AllowShortCaseLabelsOnASingleLine: true 20 | AllowShortFunctionsOnASingleLine: All 21 | AllowShortLambdasOnASingleLine: All 22 | AllowShortIfStatementsOnASingleLine: Never 23 | AllowShortLoopsOnASingleLine: false 24 | AlwaysBreakAfterReturnType: None 25 | AlwaysBreakBeforeMultilineStrings: false 26 | AlwaysBreakTemplateDeclarations: Yes 27 | AttributeMacros: ["__capability", "__output", "__ununsed"] 28 | BinPackArguments: true 29 | BinPackParameters: true 30 | BitFieldColonSpacing: Both 31 | BraceWrapping: 32 | AfterCaseLabel: false 33 | AfterClass: true 34 | AfterControlStatement: MultiLine 35 | AfterEnum: true 36 | AfterFunction: true 37 | AfterNamespace: false 38 | AfterStruct: true 39 | AfterUnion: true 40 | AfterExternBlock: false 41 | BeforeCatch: true 42 | BeforeElse: true 43 | BeforeLambdaBody: false 44 | BeforeWhile: false 45 | IndentBraces: false 46 | SplitEmptyFunction: true 47 | SplitEmptyRecord: true 48 | SplitEmptyNamespace: true 49 | BreakBeforeBinaryOperators: All 50 | BreakBeforeConceptDeclarations: true 51 | BreakBeforeBraces: Custom 52 | BreakBeforeInheritanceComma: false 53 | BreakInheritanceList: BeforeColon 54 | BreakBeforeTernaryOperators: true 55 | BreakConstructorInitializersBeforeComma: false 56 | BreakConstructorInitializers: BeforeColon 57 | BreakStringLiterals: true 58 | ColumnLimit: 0 59 | # CommentPragmas are a regex pattern indicating the comment is not be touched by the formatter 60 | CommentPragmas: "^ Include gaurd .*" 61 | CompactNamespaces: false 62 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 63 | ConstructorInitializerIndentWidth: 4 64 | ContinuationIndentWidth: 4 65 | Cpp11BracedListStyle: true 66 | DeriveLineEnding: false 67 | DerivePointerAlignment: false 68 | DisableFormat: false 69 | EmptyLineBeforeAccessModifier: Always 70 | EmptyLineAfterAccessModifier: Leave 71 | ExperimentalAutoDetectBinPacking: false 72 | FixNamespaceComments: true 73 | IncludeBlocks: Preserve 74 | IncludeCategories: 75 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 76 | Priority: 2 77 | SortPriority: 0 78 | CaseSensitive: false 79 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 80 | Priority: 3 81 | SortPriority: 0 82 | CaseSensitive: false 83 | - Regex: ".*" 84 | Priority: 1 85 | SortPriority: 0 86 | CaseSensitive: false 87 | IncludeIsMainRegex: "(Test)?$" 88 | IncludeIsMainSourceRegex: "" 89 | IndentAccessModifiers: false 90 | IndentCaseLabels: true 91 | IndentCaseBlocks: false 92 | IndentGotoLabels: false 93 | IndentPPDirectives: BeforeHash 94 | IndentExternBlock: AfterExternBlock 95 | IndentRequires: false 96 | IndentWidth: 4 97 | IndentWrappedFunctionNames: false 98 | InsertTrailingCommas: None 99 | KeepEmptyLinesAtTheStartOfBlocks: true 100 | MacroBlockBegin: "" 101 | MacroBlockEnd: "" 102 | MaxEmptyLinesToKeep: 1 103 | NamespaceIndentation: Inner 104 | PenaltyBreakAssignment: 2 105 | PenaltyBreakBeforeFirstCallParameter: 19 106 | PenaltyBreakComment: 300 107 | PenaltyBreakFirstLessLess: 120 108 | PenaltyBreakString: 1000 109 | PenaltyBreakTemplateDeclaration: 10 110 | PenaltyExcessCharacter: 1000000 111 | PenaltyReturnTypeOnItsOwnLine: 60 112 | PenaltyIndentedWhitespace: 0 113 | PointerAlignment: Left 114 | ReferenceAlignment: Pointer 115 | ReflowComments: true 116 | SpacesInLineCommentPrefix: 117 | Maximum: -1 118 | Minimum: 0 119 | ShortNamespaceLines: 0 120 | # Sort**** is about sorting include/using statements alphabetically 121 | SortIncludes: false 122 | SortUsingDeclarations: false 123 | SpaceAfterCStyleCast: false 124 | SpaceAfterLogicalNot: false 125 | SpaceAfterTemplateKeyword: false 126 | SpaceBeforeAssignmentOperators: true 127 | SpaceBeforeCaseColon: false 128 | SpaceBeforeCpp11BracedList: true 129 | SpaceBeforeCtorInitializerColon: true 130 | SpaceBeforeInheritanceColon: true 131 | SpaceBeforeParens: ControlStatements 132 | SpaceAroundPointerQualifiers: Default 133 | SpaceBeforeRangeBasedForLoopColon: true 134 | SpaceInEmptyBlock: false 135 | SpaceInEmptyParentheses: false 136 | SpacesBeforeTrailingComments: 1 137 | SpacesInAngles: false 138 | SpacesInConditionalStatement: false 139 | SpacesInContainerLiterals: false 140 | SpacesInCStyleCastParentheses: false 141 | SpacesInParentheses: false 142 | SpacesInSquareBrackets: false 143 | SpaceBeforeSquareBrackets: false 144 | Standard: c++11 145 | StatementAttributeLikeMacros: [emit] 146 | StatementMacros: [Q_UNUSED, QT_REQUIRE_VERSION] 147 | TabWidth: 4 148 | UseCRLF: false 149 | UseTab: Never 150 | WhitespaceSensitiveMacros: 151 | - PRIPSTR 152 | - STRINGIZE 153 | - PP_STRINGIZE 154 | - BOOST_PP_STRINGIZE 155 | - NS_SWIFT_NAME 156 | - CF_SWIFT_NAME 157 | -------------------------------------------------------------------------------- /examples/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | project(CirquePinnacleExamples CXX) 4 | add_compile_options(-Ofast -Wall) # passing the compiler a `-pthread` flag doesn't work here 5 | 6 | # detect the CPU make and type 7 | include(../../src/cmake/detectCPU.cmake) # sets the variable SOC accordingly 8 | 9 | # auto-detect what driver to use 10 | include(../../src/cmake/auto_config_driver.cmake) 11 | 12 | find_library(CirquePinnacle cirquepinnacle REQUIRED) 13 | message(STATUS "using CirquePinnacle library: ${CirquePinnacle}") 14 | 15 | # These options are really useful in testing different interfaces. 16 | # Typical applications shouldn't need them 17 | option(USE_I2C "option to use a I2C bus instead of a SPI bus" OFF) 18 | 19 | # iterate over a list of examples by name 20 | set(EXAMPLES_LIST 21 | absolute_mode 22 | relative_mode 23 | anymeas_mode 24 | ) 25 | 26 | if (USE_I2C) 27 | message(STATUS "Using I2C bus interface") 28 | else() 29 | message(STATUS "Using SPI bus interface") 30 | endif() 31 | 32 | foreach(example ${EXAMPLES_LIST}) 33 | # make a target 34 | add_executable(${example} ${example}.cpp) 35 | 36 | # link the CirquePinnacle lib to the target. Notice we specify pthread as a linked lib here 37 | target_link_libraries(${example} PUBLIC ${CirquePinnacle} pthread) 38 | 39 | if (USE_I2C) 40 | target_compile_definitions(${example} PUBLIC USE_I2C=1) 41 | endif() 42 | endforeach() 43 | -------------------------------------------------------------------------------- /examples/linux/absolute_mode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "absolute mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include // sqrt(), pow(), atan2(), M_PI 7 | #include // cout, endl, cin 8 | #include // setprecision() 9 | #include // trackpad object, absoluteClampAxis() 10 | 11 | #define DR_PIN 25 // GPIO25 12 | #define SS_PIN 0 13 | 14 | #ifndef USE_I2C 15 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 16 | #else // If using I2C, then use the following line (not the line above) 17 | PinnacleTouchI2C trackpad(DR_PIN); 18 | #endif 19 | 20 | // an object to hold data reported by the Cirque trackpad 21 | AbsoluteReport data; 22 | 23 | /* 24 | Showing all the printed output below will slow down the board's ability to 25 | read() data from the trackpad in a timely manner (resulting in data loss). 26 | Use this compile-time definition to switch between printing 27 | raw data (false) or trigonometry data (true) 28 | */ 29 | static bool onlyShowTrigVals; 30 | 31 | bool setup() 32 | { 33 | if (!trackpad.begin()) { 34 | std::cout << "Cirque Pinnacle not responding!" << std::endl; 35 | return false; 36 | } 37 | std::cout << "CirquePinnacle/examples/linux/absolute_mode\n" 38 | << std::endl; 39 | trackpad.setDataMode(PINNACLE_ABSOLUTE); 40 | trackpad.absoluteModeConfig(1); // set count of z-idle packets to 1 41 | #ifndef USE_I2C 42 | std::cout << "-- Using SPI interface." << std::endl; 43 | #else 44 | std::cout << "-- Using I2C interface." << std::endl; 45 | #endif 46 | std::cout << "\nShow trigonometric calculations? [y/N] ('N' means show raw data) "; 47 | char input[4] = {0}; 48 | std::cin.getline(input, 3); 49 | onlyShowTrigVals = input[0] == 'y' || input[0] == 'Y'; 50 | std::cout << "showing "; 51 | if (onlyShowTrigVals) 52 | std::cout << "trigonometric calculations." << std::endl; 53 | else 54 | std::cout << "raw data." << std::endl; 55 | std::cout << "\nTouch the trackpad to see the data" << std::endl; 56 | return true; 57 | } 58 | 59 | void loop() 60 | { 61 | if (trackpad.available()) { 62 | trackpad.read(&data); 63 | 64 | // datasheet recommends clamping the axes value to reliable range 65 | if (data.z) { // only clamp values if Z axis is not idle. 66 | 67 | data.x = data.x > 1920 ? 1920 : (data.x < 128 ? 128 : data.x); // 128 <= x <= 1920 68 | data.y = data.y > 1472 ? 1472 : (data.y < 64 ? 64 : data.y); // 64 <= y <= 1472 69 | } 70 | 71 | if (!onlyShowTrigVals) { 72 | // print raw data from the trackpad 73 | std::cout << "B1: " << (unsigned int)(data.buttons & 1) 74 | << " B2: " << (unsigned int)(data.buttons & 2) 75 | << " B3: " << (unsigned int)(data.buttons & 4) 76 | << "\tX: " << data.x 77 | << "\tY: " << data.y 78 | << "\tZ: " << (unsigned int)(data.z) << std::endl; 79 | } 80 | else { 81 | // print trigonometric data from the trackpad 82 | if (!data.z) { // only compute angle and radius if touching (or near) the sensor 83 | std::cout << "Idling" << std::endl; 84 | } 85 | else { 86 | // coordinates assume axes have been clamped to recommended ranges 87 | double coord_x = (int16_t)(data.x) - 960; 88 | double coord_y = (int16_t)(data.y) - 736; // NOTE: y-axis is inverted by default 89 | 90 | double radius = sqrt(pow(coord_x, 2) + pow(coord_y, 2)); 91 | double angle = atan2(coord_y, coord_x) * 180 / M_PI; // angle (in degrees) ranges (-180, 180] 92 | 93 | std::cout << std::setprecision(5) << "angle: " << angle << "\tradius: " << radius << std::endl; 94 | } 95 | } 96 | } // end if trackpad.available() 97 | } //end loop() 98 | 99 | int main() 100 | { 101 | if (!setup()) { // if trackpad.begin() failed 102 | return -1; // fail fast 103 | } 104 | while (true) { // use ctrl+C to exit 105 | loop(); 106 | } 107 | return 0; // we will never reach this 108 | } 109 | -------------------------------------------------------------------------------- /examples/linux/anymeas_mode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "anymeas mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include // cout, endl 7 | #include // sleep() 8 | #include // trackpad object 9 | 10 | #define DR_PIN 25 // GPIO25 11 | #define SS_PIN 0 12 | 13 | #ifndef USE_I2C 14 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 15 | #else // If using I2C, then use the following line (not the line above) 16 | PinnacleTouchI2C trackpad(DR_PIN); 17 | #endif 18 | 19 | typedef struct _MeasureVector 20 | { 21 | unsigned long toggle; 22 | unsigned long polarity; 23 | } measureVector; 24 | 25 | measureVector vectorDeterminants[] = { 26 | // toggle , polarity 27 | {0x0000FFFF, 0x00000000}, // toggle all x-axis bits negatively (to 0) 28 | {0x0FFF0000, 0x00000000}, // toggle all y-axis bits negatively (to 0) 29 | {0x00FF00FF, 0x000000FF}, // toggle Y0-Y7 negatively (to 0) & X0-X7 positively (to 1) 30 | {0x00FF00FF, 0x00FF0000} // toggle Y0-Y7 positively (to 1) & X0-X7 negatively (to 0) 31 | }; 32 | 33 | const uint8_t variousVectors_size = sizeof(vectorDeterminants) / sizeof(measureVector); 34 | int16_t compensations[variousVectors_size]; 35 | 36 | void compensate() 37 | { 38 | signed long accumulatedValue; 39 | for (uint8_t i = 0; i < variousVectors_size; ++i) { 40 | uint8_t sweep = 0; 41 | accumulatedValue = 0; 42 | while (sweep < 5) // take 5 measurements and average them for a bit lower noise compensation value 43 | { 44 | int16_t value = trackpad.measureAdc(vectorDeterminants[i].toggle, vectorDeterminants[i].polarity); 45 | sweep++; 46 | accumulatedValue += value; 47 | } 48 | compensations[i] = accumulatedValue / 5; 49 | std::cout << "compensation " << (unsigned int)i << ": " << compensations[i] << std::endl; 50 | } 51 | } 52 | 53 | bool setup() 54 | { 55 | if (!trackpad.begin()) { 56 | std::cout << "Cirque Pinnacle not responding!" << std::endl; 57 | return false; 58 | } 59 | std::cout << "CirquePinnacle/examples/linux/anymeas_mode" << std::endl; 60 | trackpad.setDataMode(PINNACLE_ANYMEAS); 61 | trackpad.anymeasModeConfig(); 62 | #ifndef USE_I2C 63 | std::cout << "-- Using SPI interface." << std::endl; 64 | #else 65 | std::cout << "-- Using I2C interface." << std::endl; 66 | #endif 67 | compensate(); 68 | 69 | for (uint8_t i = 5; i; --i) { 70 | std::cout << "starting in " << (unsigned int)i << "second" << (i < 1 ? 's' : ' ') << '\r'; 71 | sleep(1); 72 | } 73 | std::cout << std::endl; 74 | return true; 75 | } 76 | 77 | void loop() 78 | { 79 | for (unsigned int i = 0; i < variousVectors_size; i++) { 80 | int16_t measurement = trackpad.measureAdc( 81 | vectorDeterminants[i].toggle, 82 | vectorDeterminants[i].polarity); 83 | measurement -= compensations[i]; 84 | std::cout << "meas" << i << ": " << measurement << "\t"; 85 | } 86 | std::cout << std::endl; 87 | } 88 | 89 | int main() 90 | { 91 | if (!setup()) { // if trackpad.begin() failed 92 | return -1; // fail fast 93 | } 94 | while (true) { // use ctrl+C to exit 95 | loop(); 96 | } 97 | return 0; // we will never reach this 98 | } 99 | -------------------------------------------------------------------------------- /examples/linux/relative_mode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "relative mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include // cout, endl 7 | #include // trackpad object 8 | 9 | #define DR_PIN 25 // GPIO25 10 | #define SS_PIN 0 11 | 12 | #ifndef USE_I2C 13 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 14 | #else // If using I2C, then use the following line (not the line above) 15 | PinnacleTouchI2C trackpad(DR_PIN); 16 | #endif 17 | 18 | // an object to hold data reported by the Cirque trackpad 19 | RelativeReport data; 20 | 21 | bool setup() 22 | { 23 | if (!trackpad.begin()) { 24 | std::cout << "Cirque Pinnacle not responding!" << std::endl; 25 | return false; 26 | } 27 | std::cout << "CirquePinnacle/examples/linux/relative_mode\n" 28 | << std::endl; 29 | #ifndef USE_I2C 30 | std::cout << "-- Using SPI interface." << std::endl; 31 | #else 32 | std::cout << "-- Using I2C interface." << std::endl; 33 | #endif 34 | std::cout << "\nTouch the trackpad to see the data" << std::endl; 35 | return true; 36 | } 37 | 38 | void loop() 39 | { 40 | if (trackpad.available()) { 41 | trackpad.read(&data); 42 | std::cout << "Left:" << (unsigned int)(data.buttons & 1) 43 | << " Right:" << (unsigned int)(data.buttons & 2) 44 | << " Middle:" << (unsigned int)(data.buttons & 4) 45 | << "\tX:" << (int)(data.x) 46 | << "\tY:" << (int)(data.y) 47 | << "\tScroll:" << (int)(data.scroll) << std::endl; 48 | } 49 | } 50 | 51 | int main() 52 | { 53 | if (!setup()) { // if trackpad.begin() failed 54 | return -1; // fail fast 55 | } 56 | while (true) { // use ctrl+C to exit 57 | loop(); 58 | } 59 | return 0; // we will never reach this 60 | } 61 | -------------------------------------------------------------------------------- /examples/pico_sdk/.clang-format: -------------------------------------------------------------------------------- 1 | # See options listed at https://releases.llvm.org/12.0.1/tools/clang/docs/ClangFormatStyleOptions.html 2 | --- 3 | Language: Cpp 4 | # BasedOnStyle: WebKit 5 | AccessModifierOffset: -4 6 | AlignAfterOpenBracket: Align 7 | AlignConsecutiveMacros: Consecutive 8 | AlignConsecutiveAssignments: None 9 | AlignConsecutiveBitFields: None 10 | AlignConsecutiveDeclarations: None 11 | AlignEscapedNewlines: Left 12 | AlignOperands: DontAlign 13 | AlignTrailingComments: true 14 | AllowAllArgumentsOnNextLine: true 15 | AllowAllConstructorInitializersOnNextLine: true 16 | AllowAllParametersOfDeclarationOnNextLine: true 17 | AllowShortEnumsOnASingleLine: false 18 | AllowShortBlocksOnASingleLine: Empty 19 | AllowShortCaseLabelsOnASingleLine: true 20 | AllowShortFunctionsOnASingleLine: All 21 | AllowShortLambdasOnASingleLine: All 22 | AllowShortIfStatementsOnASingleLine: Never 23 | AllowShortLoopsOnASingleLine: false 24 | AlwaysBreakAfterReturnType: None 25 | AlwaysBreakBeforeMultilineStrings: false 26 | AlwaysBreakTemplateDeclarations: Yes 27 | AttributeMacros: ["__capability", "__output", "__ununsed"] 28 | BinPackArguments: true 29 | BinPackParameters: true 30 | BitFieldColonSpacing: Both 31 | BraceWrapping: 32 | AfterCaseLabel: false 33 | AfterClass: true 34 | AfterControlStatement: MultiLine 35 | AfterEnum: true 36 | AfterFunction: true 37 | AfterNamespace: false 38 | AfterStruct: true 39 | AfterUnion: true 40 | AfterExternBlock: false 41 | BeforeCatch: true 42 | BeforeElse: true 43 | BeforeLambdaBody: false 44 | BeforeWhile: false 45 | IndentBraces: false 46 | SplitEmptyFunction: true 47 | SplitEmptyRecord: true 48 | SplitEmptyNamespace: true 49 | BreakBeforeBinaryOperators: All 50 | BreakBeforeConceptDeclarations: true 51 | BreakBeforeBraces: Custom 52 | BreakBeforeInheritanceComma: false 53 | BreakInheritanceList: BeforeColon 54 | BreakBeforeTernaryOperators: true 55 | BreakConstructorInitializersBeforeComma: false 56 | BreakConstructorInitializers: BeforeColon 57 | BreakStringLiterals: true 58 | ColumnLimit: 0 59 | # CommentPragmas are a regex pattern indicating the comment is not be touched by the formatter 60 | CommentPragmas: "^ Include gaurd .*" 61 | CompactNamespaces: false 62 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 63 | ConstructorInitializerIndentWidth: 4 64 | ContinuationIndentWidth: 4 65 | Cpp11BracedListStyle: true 66 | DeriveLineEnding: false 67 | DerivePointerAlignment: false 68 | DisableFormat: false 69 | EmptyLineBeforeAccessModifier: Always 70 | EmptyLineAfterAccessModifier: Leave 71 | ExperimentalAutoDetectBinPacking: false 72 | FixNamespaceComments: true 73 | IncludeBlocks: Preserve 74 | IncludeCategories: 75 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 76 | Priority: 2 77 | SortPriority: 0 78 | CaseSensitive: false 79 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 80 | Priority: 3 81 | SortPriority: 0 82 | CaseSensitive: false 83 | - Regex: ".*" 84 | Priority: 1 85 | SortPriority: 0 86 | CaseSensitive: false 87 | IncludeIsMainRegex: "(Test)?$" 88 | IncludeIsMainSourceRegex: "" 89 | IndentAccessModifiers: false 90 | IndentCaseLabels: true 91 | IndentCaseBlocks: false 92 | IndentGotoLabels: false 93 | IndentPPDirectives: BeforeHash 94 | IndentExternBlock: AfterExternBlock 95 | IndentRequires: false 96 | IndentWidth: 4 97 | IndentWrappedFunctionNames: false 98 | InsertTrailingCommas: None 99 | KeepEmptyLinesAtTheStartOfBlocks: true 100 | MacroBlockBegin: "" 101 | MacroBlockEnd: "" 102 | MaxEmptyLinesToKeep: 1 103 | NamespaceIndentation: Inner 104 | PenaltyBreakAssignment: 2 105 | PenaltyBreakBeforeFirstCallParameter: 19 106 | PenaltyBreakComment: 300 107 | PenaltyBreakFirstLessLess: 120 108 | PenaltyBreakString: 1000 109 | PenaltyBreakTemplateDeclaration: 10 110 | PenaltyExcessCharacter: 1000000 111 | PenaltyReturnTypeOnItsOwnLine: 60 112 | PenaltyIndentedWhitespace: 0 113 | PointerAlignment: Left 114 | ReferenceAlignment: Pointer 115 | ReflowComments: true 116 | SpacesInLineCommentPrefix: 117 | Maximum: -1 118 | Minimum: 0 119 | ShortNamespaceLines: 0 120 | # Sort**** is about sorting include/using statements alphabetically 121 | SortIncludes: false 122 | SortUsingDeclarations: false 123 | SpaceAfterCStyleCast: false 124 | SpaceAfterLogicalNot: false 125 | SpaceAfterTemplateKeyword: false 126 | SpaceBeforeAssignmentOperators: true 127 | SpaceBeforeCaseColon: false 128 | SpaceBeforeCpp11BracedList: true 129 | SpaceBeforeCtorInitializerColon: true 130 | SpaceBeforeInheritanceColon: true 131 | SpaceBeforeParens: ControlStatements 132 | SpaceAroundPointerQualifiers: Default 133 | SpaceBeforeRangeBasedForLoopColon: true 134 | SpaceInEmptyBlock: false 135 | SpaceInEmptyParentheses: false 136 | SpacesBeforeTrailingComments: 1 137 | SpacesInAngles: false 138 | SpacesInConditionalStatement: false 139 | SpacesInContainerLiterals: false 140 | SpacesInCStyleCastParentheses: false 141 | SpacesInParentheses: false 142 | SpacesInSquareBrackets: false 143 | SpaceBeforeSquareBrackets: false 144 | Standard: c++11 145 | StatementAttributeLikeMacros: [emit] 146 | StatementMacros: [Q_UNUSED, QT_REQUIRE_VERSION] 147 | TabWidth: 4 148 | UseCRLF: false 149 | UseTab: Never 150 | WhitespaceSensitiveMacros: 151 | - PRIPSTR 152 | - STRINGIZE 153 | - PP_STRINGIZE 154 | - BOOST_PP_STRINGIZE 155 | - NS_SWIFT_NAME 156 | - CF_SWIFT_NAME 157 | -------------------------------------------------------------------------------- /examples/pico_sdk/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | # Pull in SDK (must be before project) 4 | include(../../src/cmake/pico_sdk_import.cmake) 5 | 6 | project(pico_examples C CXX ASM) 7 | 8 | # Initialize the Pico SDK 9 | pico_sdk_init() 10 | 11 | # In YOUR project, include CirquePinnacle lib's root-level CMakeLists.txt 12 | # giving the path depending on where the library 13 | # is cloned to in your project 14 | include(../../src/CMakeLists.txt) 15 | 16 | # These options are really useful in testing different interfaces. 17 | # Typical applications shouldn't need them 18 | option(USE_I2C "option to use a I2C bus instead of a SPI bus" OFF) 19 | 20 | # iterate over a list of examples by name 21 | set(EXAMPLES_LIST 22 | absolute_mode 23 | relative_mode 24 | anymeas_mode 25 | ) 26 | 27 | if (USE_I2C) 28 | message(STATUS "Using I2C bus interface") 29 | else() 30 | message(STATUS "Using SPI bus interface") 31 | endif() 32 | 33 | foreach(example ${EXAMPLES_LIST}) 34 | # make a target 35 | add_executable(${example} ${example}.cpp defaultPins.h) 36 | 37 | # link the necessary libs to the target 38 | target_link_libraries(${example} PUBLIC 39 | CirquePinnacle 40 | pico_stdlib 41 | hardware_gpio 42 | hardware_spi 43 | hardware_i2c 44 | ) 45 | 46 | if (USE_I2C) 47 | target_compile_definitions(${example} PUBLIC USE_I2C=1) 48 | endif() 49 | 50 | # specify USB port as default serial communication's interface (not UART RX/TX pins) 51 | pico_enable_stdio_usb(${example} 1) 52 | pico_enable_stdio_uart(${example} 0) 53 | 54 | # create map/bin/hex file etc. 55 | pico_add_extra_outputs(${example}) 56 | endforeach() 57 | 58 | add_subdirectory(usb_mouse) 59 | -------------------------------------------------------------------------------- /examples/pico_sdk/absolute_mode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "absolute mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include // sqrt(), pow(), atan2() 7 | #include "pico/stdlib.h" // printf(), getchar_timeout_us() 8 | #include "pico/bootrom.h" // reset_usb_boot() 9 | #include // tud_cdc_connected() 10 | #include // trackpad object 11 | #include "defaultPins.h" // board presumptive default pin numbers for SS_PIN and DR_PIN 12 | 13 | #ifndef USE_I2C 14 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 15 | #else // If using I2C, then use the following line (not the line above) 16 | PinnacleTouchI2C trackpad(DR_PIN); 17 | #endif 18 | 19 | // an object to hold data reported by the Cirque trackpad 20 | AbsoluteReport data; 21 | 22 | #ifndef PI 23 | #define PI 3.14159 24 | #endif 25 | 26 | /* 27 | Showing all the printed output below will slow down the board's ability to 28 | read() data from the trackpad in a timely manner (resulting in data loss). 29 | Change this variable (via Serial input) to switch between printing 30 | raw data (false) or trigonometric data (true) 31 | */ 32 | bool onlyShowTrigVals = false; 33 | 34 | bool setup() 35 | { 36 | // wait here until the CDC ACM (serial port emulation) is connected 37 | while (!tud_cdc_connected()) { 38 | sleep_ms(10); 39 | } 40 | 41 | if (!trackpad.begin()) { 42 | printf("Cirque Pinnacle not responding!\n"); 43 | return false; 44 | } 45 | printf("CirquePinnacle/examples/pico_sdk/absolute_mode\n"); 46 | trackpad.setDataMode(PINNACLE_ABSOLUTE); 47 | trackpad.absoluteModeConfig(1); // set count of z-idle packets to 1 48 | 49 | #ifndef USE_I2C 50 | printf("-- Using SPI interface\n"); 51 | #else 52 | printf("-- Using I2C interface\n"); 53 | #endif 54 | printf("\n*** Enter 'M' to measure and print raw data."); 55 | printf("\n*** Enter 'T' to measure and print trigonometric calculations."); 56 | printf("\n*** Enter 'B' to reset to bootloader.\n"); 57 | printf("\nTouch the trackpad to see the data\n"); 58 | return true; 59 | } 60 | 61 | void loop() 62 | { 63 | if (trackpad.available()) { 64 | trackpad.read(&data); 65 | 66 | // datasheet recommends clamping the axes value to reliable range 67 | if (data.z) { // only clamp values if Z axis is not idle. 68 | 69 | data.x = data.x > 1920 ? 1920 : (data.x < 128 ? 128 : data.x); // 128 <= x <= 1920 70 | data.y = data.y > 1472 ? 1472 : (data.y < 64 ? 64 : data.y); // 64 <= y <= 1472 71 | } 72 | 73 | if (!onlyShowTrigVals) { 74 | // print raw data from the trackpad 75 | printf("B1:%d B2:%d B3:%d", data.buttons & 1, data.buttons & 2, data.buttons & 4); 76 | printf("\tX:%d\tY:%d\tZ:%d\n", data.x, data.y, data.z); 77 | } 78 | else { 79 | // print trigonometric calculations from the trackpad data 80 | if (!data.z) { // only compute angle and radius if touching (or near) the sensor 81 | printf("Idling\n"); 82 | } 83 | else { 84 | // coordinates assume axes have been clamped to recommended ranges 85 | double coord_x = (int16_t)(data.x) - 960; 86 | double coord_y = (int16_t)(data.y) - 736; // NOTE: y-axis is inverted by default 87 | 88 | double radius = sqrt(pow(coord_x, 2) + pow(coord_y, 2)); 89 | double angle = atan2(coord_y, coord_x) * 180 / PI; // angle (in degrees) ranges (-180, 180] 90 | 91 | printf("angle: %.2f\tradius: %.2f\n", angle, radius); 92 | } 93 | } 94 | } // end if trackpad.available() 95 | 96 | char input = getchar_timeout_us(0); // get char from buffer for user input 97 | if (input != PICO_ERROR_TIMEOUT && (input == 'b' || input == 'B')) { 98 | reset_usb_boot(0, 0); // reset to bootloader 99 | } 100 | else if (input != PICO_ERROR_TIMEOUT && (input == 'm' || input == 'M')) { 101 | onlyShowTrigVals = false; 102 | } 103 | else if (input != PICO_ERROR_TIMEOUT && (input == 't' || input == 'T')) { 104 | onlyShowTrigVals = true; 105 | } 106 | } //end loop() 107 | 108 | int main() 109 | { 110 | stdio_init_all(); // init necessary IO for the RP2040 111 | 112 | while (!setup()) { // if trackpad.begin() failed 113 | // hold program in infinite attempts to initialize trackpad 114 | } 115 | while (true) { 116 | loop(); 117 | } 118 | return 0; // we will never reach this 119 | } 120 | -------------------------------------------------------------------------------- /examples/pico_sdk/anymeas_mode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "anymeas mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include "pico/stdlib.h" // printf(), getchar_timeout_us() 7 | #include "pico/bootrom.h" // reset_usb_boot() 8 | #include // tud_cdc_connected() 9 | #include // trackpad object 10 | #include "defaultPins.h" // board presumptive default pin numbers for SS_PIN and DR_PIN 11 | 12 | #ifndef USE_I2C 13 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 14 | #else // If using I2C, then use the following line (not the line above) 15 | PinnacleTouchI2C trackpad(DR_PIN); 16 | #endif 17 | 18 | typedef struct _MeasureVector 19 | { 20 | unsigned long toggle; 21 | unsigned long polarity; 22 | } measureVector; 23 | 24 | measureVector vectorDeterminants[] = { 25 | // toggle , polarity 26 | {0x0000FFFF, 0x00000000}, // toggle all x-axis bits negatively (to 0) 27 | {0x0FFF0000, 0x00000000}, // toggle all y-axis bits negatively (to 0) 28 | {0x00FF00FF, 0x000000FF}, // toggle Y0-Y7 negatively (to 0) & X0-X7 positively (to 1) 29 | {0x00FF00FF, 0x00FF0000} // toggle Y0-Y7 positively (to 1) & X0-X7 negatively (to 0) 30 | }; 31 | 32 | const uint8_t variousVectors_size = sizeof(vectorDeterminants) / sizeof(measureVector); 33 | int16_t compensations[variousVectors_size]; 34 | 35 | void compensate() 36 | { 37 | int32_t accumulatedValue; 38 | for (uint8_t i = 0; i < variousVectors_size; ++i) { 39 | uint8_t sweep = 0; 40 | accumulatedValue = 0; 41 | while (sweep < 5) // take 5 measurements and average them for a bit lower noise compensation value 42 | { 43 | int16_t value = trackpad.measureAdc(vectorDeterminants[i].toggle, vectorDeterminants[i].polarity); 44 | sweep++; 45 | accumulatedValue += value; 46 | } 47 | compensations[i] = accumulatedValue / 5; 48 | printf("compensation %d: %d\n", i, compensations[i]); 49 | } 50 | } 51 | 52 | bool setup() 53 | { 54 | // wait here until the CDC ACM (serial port emulation) is connected 55 | while (!tud_cdc_connected()) { 56 | sleep_ms(10); 57 | } 58 | 59 | if (!trackpad.begin()) { 60 | printf("Cirque Pinnacle not responding!\n"); 61 | return false; 62 | } 63 | printf("CirquePinnacle/examples/pico_sdk/anymeas_mode\n"); 64 | trackpad.setDataMode(PINNACLE_ANYMEAS); 65 | 66 | #ifndef USE_I2C 67 | printf("-- Using SPI interface\n"); 68 | #else 69 | printf("-- Using I2C interface\n"); 70 | #endif 71 | printf("\n*** Enter 'B' to reset to bootloader.\n"); 72 | compensate(); 73 | for (uint8_t i = 5; i; --i) { 74 | printf("starting in %d second%c\r", i, i > 1 ? 's' : ' '); 75 | sleep_ms(1000); 76 | } 77 | return true; 78 | } 79 | 80 | void loop() 81 | { 82 | for (uint8_t i = 0; i < variousVectors_size; i++) { 83 | int16_t measurement = trackpad.measureAdc( 84 | vectorDeterminants[i].toggle, 85 | vectorDeterminants[i].polarity); 86 | measurement -= compensations[i]; 87 | printf("meas%d: %d\t", i, measurement); 88 | } 89 | printf("\n"); 90 | 91 | char input = getchar_timeout_us(0); // get char from buffer for user input 92 | if (input != PICO_ERROR_TIMEOUT && (input == 'b' || input == 'B')) { 93 | // reset to bootloader 94 | trackpad.shutdown(true); 95 | reset_usb_boot(0, 0); 96 | } 97 | } 98 | 99 | int main() 100 | { 101 | stdio_init_all(); // init necessary IO for the RP2040 102 | 103 | while (!setup()) { // if trackpad.begin() failed 104 | // hold program in infinite attempts to initialize trackpad 105 | } 106 | while (true) { 107 | loop(); 108 | } 109 | return 0; // we will never reach this 110 | } 111 | -------------------------------------------------------------------------------- /examples/pico_sdk/defaultPins.h: -------------------------------------------------------------------------------- 1 | // pre-chosen pins for different boards 2 | #ifndef DEFAULTPINS_H 3 | #define DEFAULTPINS_H 4 | 5 | #if defined(ADAFRUIT_QTPY_RP2040) 6 | #define SS_PIN PICO_DEFAULT_UART_RX_PIN // the pin labeled RX (GPIO5) 7 | #define DR_PIN PICO_DEFAULT_UART_TX_PIN // the pin labeled TX (GPIO20) 8 | 9 | #elif defined(PIMORONI_TINY2040) 10 | #define SS_PIN PICO_DEFAULT_SPI_CSN_PIN // pin 5 11 | #define DR_PIN 1 // pin 1 12 | 13 | #elif defined(SPARFUN_THINGPLUS) 14 | #define SS_PIN 21 // the pin labeled 21 15 | #define DR_PIN 22 // the pin labeled 22 16 | 17 | #elif defined(ADAFRUIT_ITSYBITSY_RP2040) 18 | #define SS_PIN 12 // the pin labeled 2 19 | #define DR_PIN 6 // the pin labeled 7 20 | 21 | #else 22 | // pins available on (ADAFRUIT_FEATHER_RP2040 || Pico_board || Sparkfun_ProMicro || SparkFun MicroMod) 23 | 24 | #define SS_PIN 6 25 | #define DR_PIN 8 26 | #endif // board detection macro defs 27 | 28 | #endif // DEFAULTPINS_H 29 | -------------------------------------------------------------------------------- /examples/pico_sdk/relative_mode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "relative mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include "pico/stdlib.h" // printf(), getchar_timeout_us() 7 | #include "pico/bootrom.h" // reset_usb_boot() 8 | #include // tud_cdc_connected() 9 | #include // trackpad object 10 | #include "defaultPins.h" // board presumptive default pin numbers for SS_PIN and DR_PIN 11 | 12 | #ifndef USE_I2C 13 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 14 | #else // If using I2C, then use the following line (not the line above) 15 | PinnacleTouchI2C trackpad(DR_PIN); 16 | #endif 17 | 18 | // an object to hold data reported by the Cirque trackpad 19 | RelativeReport data; 20 | 21 | bool setup() 22 | { 23 | // wait here until the CDC ACM (serial port emulation) is connected 24 | while (!tud_cdc_connected()) { 25 | sleep_ms(10); 26 | } 27 | 28 | if (!trackpad.begin()) { 29 | printf("Cirque Pinnacle not responding!\n"); 30 | return false; 31 | } 32 | printf("CirquePinnacle/examples/pico_sdk/relative_mode\n"); 33 | 34 | #ifndef USE_I2C 35 | printf("-- Using SPI interface\n"); 36 | #else 37 | printf("-- Using I2C interface\n"); 38 | #endif 39 | printf("\n*** Enter 'B' to reset to bootloader.\n"); 40 | printf("\nTouch the trackpad to see the data\n"); 41 | return true; 42 | } 43 | 44 | void loop() 45 | { 46 | if (trackpad.available()) { 47 | trackpad.read(&data); 48 | printf("Left:%d ", data.buttons & 1); 49 | printf("Right:%d ", data.buttons & 2); 50 | printf("Middle:%d", data.buttons & 4); 51 | printf("\tX: %d\tY: %d\tScroll: %d\n", data.x, data.y, data.scroll); 52 | } 53 | 54 | char input = getchar_timeout_us(0); // get char from buffer for user input 55 | if (input != PICO_ERROR_TIMEOUT && (input == 'b' || input == 'B')) { 56 | // reset to bootloader 57 | trackpad.shutdown(true); 58 | reset_usb_boot(0, 0); 59 | } 60 | } 61 | 62 | int main() 63 | { 64 | stdio_init_all(); // init necessary IO for the RP2040 65 | 66 | while (!setup()) { // if trackpad.begin() failed 67 | // hold program in infinite attempts to initialize trackpad 68 | } 69 | while (true) { 70 | loop(); 71 | } 72 | return 0; // we will never reach this 73 | } 74 | -------------------------------------------------------------------------------- /examples/pico_sdk/usb_mouse/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | set(targetName "dev_hid_composite") 4 | add_executable(${targetName}) 5 | 6 | target_sources(${targetName} PUBLIC 7 | ${CMAKE_CURRENT_LIST_DIR}/main.cpp 8 | ${CMAKE_CURRENT_LIST_DIR}/usb_descriptors.c 9 | ) 10 | 11 | # Make sure TinyUSB can find tusb_config.h 12 | target_include_directories(${targetName} PUBLIC 13 | ${CMAKE_CURRENT_LIST_DIR} 14 | ) 15 | 16 | # In addition to pico_stdlib required for common PicoSDK functionality, add dependency on tinyusb_device 17 | # for TinyUSB device support and tinyusb_board for the additional board support library used by the example 18 | target_link_libraries(${targetName} PUBLIC 19 | pico_stdlib 20 | tinyusb_device 21 | tinyusb_board 22 | hardware_gpio 23 | hardware_spi 24 | hardware_i2c 25 | CirquePinnacle 26 | ) 27 | 28 | if (USE_I2C) 29 | target_compile_definitions(${targetName} PUBLIC USE_I2C=1) 30 | endif() 31 | 32 | target_compile_definitions(${targetName} PUBLIC PICO_DEFAULT_I2C=1) 33 | 34 | # Uncomment this line to enable fix for Errata RP2040-E5 (the fix requires use of GPIO 15) 35 | # target_compile_definitions(${targetName} PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1) 36 | 37 | pico_add_extra_outputs(dev_hid_composite) 38 | -------------------------------------------------------------------------------- /examples/pico_sdk/usb_mouse/README.md: -------------------------------------------------------------------------------- 1 | # USB Mouse Example 2 | 3 | This example was copied and modified from the example in the 4 | [pico-examples/usb/device/dev_hid_composite](https://github.com/raspberrypi/pico-examples/tree/master/usb/device/dev_hid_composite) 5 | (which is a modified copy of the original TinyUSB repo example). 6 | 7 | ## Modifications 8 | 9 | Instead of using the board's builtin button, this example uses the Cirque circle trackpad as user input. All modifications are marked or preceded by a comment like: 10 | 11 | ```c 12 | // MODIFIED for using the CirquePinnacle library 13 | ``` 14 | 15 | ## Known issues 16 | 17 | According to RP2040 datasheet (in Appendix B: Errata), "RP2040-E5", the board can fail to enumerate as a USB device. To fix this, uncomment a line in this example's CMakeLists.txt file: 18 | 19 | ```cmake 20 | # Uncomment this line to enable fix for Errata RP2040-E5 (the fix requires use of GPIO 15) 21 | #target_compile_definitions(dev_hid_composite PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1) 22 | ``` 23 | 24 | Note, that GPIO15 should not be claimed in user code for this fix to work. This is usually required if multiple USB devices are connected, including the RP2040 board(s). 25 | -------------------------------------------------------------------------------- /examples/pico_sdk/usb_mouse/tusb_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef _TUSB_CONFIG_H_ 27 | #define _TUSB_CONFIG_H_ 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | //-------------------------------------------------------------------- 34 | // COMMON CONFIGURATION 35 | //-------------------------------------------------------------------- 36 | 37 | // defined by board.mk 38 | #ifndef CFG_TUSB_MCU 39 | #error CFG_TUSB_MCU must be defined 40 | #endif 41 | 42 | // RHPort number used for device can be defined by board.mk, default to port 0 43 | #ifndef BOARD_DEVICE_RHPORT_NUM 44 | #define BOARD_DEVICE_RHPORT_NUM 0 45 | #endif 46 | 47 | // RHPort max operational speed can defined by board.mk 48 | // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed 49 | #ifndef BOARD_DEVICE_RHPORT_SPEED 50 | #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) 51 | #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED 52 | #else 53 | #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED 54 | #endif 55 | #endif 56 | 57 | // Device mode with rhport and speed defined by board.mk 58 | #if BOARD_DEVICE_RHPORT_NUM == 0 59 | #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) 60 | #elif BOARD_DEVICE_RHPORT_NUM == 1 61 | #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) 62 | #else 63 | #error "Incorrect RHPort configuration" 64 | #endif 65 | 66 | #ifndef CFG_TUSB_OS 67 | #define CFG_TUSB_OS OPT_OS_NONE 68 | #endif 69 | 70 | // CFG_TUSB_DEBUG is defined by compiler in DEBUG build 71 | // #define CFG_TUSB_DEBUG 0 72 | 73 | /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. 74 | * Tinyusb use follows macros to declare transferring memory so that they can be put 75 | * into those specific section. 76 | * e.g 77 | * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) 78 | * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) 79 | */ 80 | #ifndef CFG_TUSB_MEM_SECTION 81 | #define CFG_TUSB_MEM_SECTION 82 | #endif 83 | 84 | #ifndef CFG_TUSB_MEM_ALIGN 85 | #define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4))) 86 | #endif 87 | 88 | //-------------------------------------------------------------------- 89 | // DEVICE CONFIGURATION 90 | //-------------------------------------------------------------------- 91 | 92 | #ifndef CFG_TUD_ENDPOINT0_SIZE 93 | #define CFG_TUD_ENDPOINT0_SIZE 64 94 | #endif 95 | 96 | //------------- CLASS -------------// 97 | #define CFG_TUD_HID 1 98 | #define CFG_TUD_CDC 0 99 | #define CFG_TUD_MSC 0 100 | #define CFG_TUD_MIDI 0 101 | #define CFG_TUD_VENDOR 0 102 | 103 | // HID buffer size Should be sufficient to hold ID (if any) + Data 104 | #define CFG_TUD_HID_EP_BUFSIZE 16 105 | 106 | #ifdef __cplusplus 107 | } 108 | #endif 109 | 110 | #endif /* _TUSB_CONFIG_H_ */ 111 | -------------------------------------------------------------------------------- /examples/pico_sdk/usb_mouse/usb_descriptors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef USB_DESCRIPTORS_H_ 26 | #define USB_DESCRIPTORS_H_ 27 | 28 | enum 29 | { 30 | REPORT_ID_KEYBOARD = 1, 31 | REPORT_ID_MOUSE, 32 | REPORT_ID_CONSUMER_CONTROL, 33 | REPORT_ID_GAMEPAD, 34 | REPORT_ID_COUNT 35 | }; 36 | 37 | #endif /* USB_DESCRIPTORS_H_ */ 38 | -------------------------------------------------------------------------------- /examples/relative_mode/relative_mode.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example reads data from the Cirque trackpad in "relative mode" and prints the values. 3 | * 4 | * See documentation at https://cirquepinnacle.rtfd.io/ 5 | */ 6 | #include 7 | 8 | #define SS_PIN 2 9 | #define DR_PIN 7 10 | 11 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 12 | // If using I2C, then use the following line (not the line above) 13 | // PinnacleTouchI2C trackpad(DR_PIN); 14 | 15 | // an object to hold data reported by the Cirque trackpad 16 | RelativeReport data; 17 | 18 | void setup() { 19 | Serial.begin(115200); 20 | while (!Serial) { 21 | // wait till Serial monitor is opened 22 | } 23 | if (!trackpad.begin()) { 24 | Serial.println(F("Cirque Pinnacle not responding!")); 25 | while (true) { 26 | // hold program in infinite loop 27 | } 28 | } 29 | Serial.println(F("CirquePinnacle/examples/relative_mode")); 30 | trackpad.setDataMode(PINNACLE_RELATIVE); 31 | trackpad.relativeModeConfig(); // uses default config 32 | Serial.println(F("Touch the trackpad to see the data.")); 33 | } 34 | 35 | void loop() { 36 | if (trackpad.available()) { 37 | trackpad.read(&data); 38 | Serial.print(F("Left:")); 39 | Serial.print(data.buttons & 1); 40 | Serial.print(F(" Right:")); 41 | Serial.print(data.buttons & 2); 42 | Serial.print(F(" Middle:")); 43 | Serial.print(data.buttons & 4); 44 | Serial.print(F("\tX:")); 45 | Serial.print(data.x); 46 | Serial.print(F("\tY:")); 47 | Serial.print(data.y); 48 | Serial.print(F("\tScroll:")); 49 | Serial.println(data.scroll); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/usb_mouse/usb_mouse.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SS_PIN 2 5 | #define DR_PIN 7 6 | #define LED LED_BUILTIN 7 | 8 | PinnacleTouchSPI trackpad(DR_PIN, SS_PIN); 9 | // If using I2C, then use the following line (not the line above) 10 | // PinnacleTouchI2C trackpad(DR_PIN); 11 | 12 | // an object to hold data reported by the Cirque trackpad 13 | RelativeReport data; 14 | 15 | const uint32_t interval = 750; // milliseconds used to blink LED 16 | uint32_t lastLedChange = 0; // millis() since last digitalWrite() 17 | bool ledState = false; // last state sent to digitalWrite() 18 | 19 | void setup() { 20 | pinMode(LED, OUTPUT); 21 | digitalWrite(LED, HIGH); 22 | 23 | if (!trackpad.begin()) { 24 | while (true) { 25 | // hold program in infinite loop 26 | } 27 | } 28 | // By default, the trackpad is configured to use relative mode with 29 | // tap detection enabled. This config fits nicely with Mouse HID reports! 30 | 31 | trackpad.setDataMode(PINNACLE_RELATIVE); // ensure mouse mode is enabled 32 | // tell the Pinnacle ASIC to rotate the orientation of the axis data by +90 degrees 33 | trackpad.relativeModeConfig(true, true); // (enable taps, rotate90) 34 | 35 | 36 | digitalWrite(LED, LOW); 37 | lastLedChange = millis(); 38 | } 39 | 40 | void loop() { 41 | 42 | if (trackpad.available()) { // is there new data? 43 | 44 | // save buttons' previous state before getting updates 45 | uint8_t prevButtonStates = data.buttons; // for edge detection 46 | 47 | trackpad.read(&data); // get new data 48 | 49 | // edge detection for binary button data 50 | uint8_t buttonsChanged = prevButtonStates ^ data.buttons; 51 | if (buttonsChanged) { 52 | uint8_t toggledOff = buttonsChanged ^ (data.buttons & buttonsChanged); 53 | uint8_t toggledOn = buttonsChanged ^ toggledOff; 54 | if (toggledOn) { 55 | Mouse.press(toggledOn); 56 | } 57 | if (toggledOff) { 58 | Mouse.release(toggledOff); 59 | } 60 | } 61 | 62 | if (data.x || data.y || data.scroll) { 63 | // invert the x-axis, use the others as is 64 | Mouse.move(data.x * -1, data.y, data.scroll); 65 | } 66 | } // end if trackpad.available() 67 | 68 | if (millis() - lastLedChange > interval) { 69 | lastLedChange = millis(); 70 | ledState = !ledState; 71 | digitalWrite(LED, ledState); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /install-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | args=("$@") 3 | driver="" 4 | USE_I2C="OFF" 5 | 6 | if [[ ${#args[@]} -gt 0 ]] 7 | then 8 | if [[ ${args[0]} == "linux_kernel" ]] 9 | then 10 | driver=${args[0]} 11 | fi 12 | fi 13 | 14 | # verify git is installed 15 | if ! command -v git &> /dev/null 16 | then 17 | echo "*** Installing git from apt-get"$'\n' 18 | sudo apt-get install git 19 | fi 20 | 21 | # verify CMake is installed 22 | if ! command -v cmake &> /dev/null 23 | then 24 | echo "*** Installing cmake from apt-get"$'\n' 25 | sudo apt-get install cmake 26 | fi 27 | 28 | # set utility driver (if not set from CLI arg) 29 | if [ -z $driver ] 30 | then 31 | driver="linux_kernel" 32 | fi 33 | 34 | # set an env var for easier reuse (specific to RF24 repos). 35 | # Any applicable CMakeLists.txt is configured to use this when it is set. 36 | export PINNACLE_DRIVER=$driver 37 | 38 | 39 | # Ensures we have a fresh build directory 40 | # NOTE: navigate to source dir before entering this function 41 | create_build_env() { 42 | if [[ -d "./build" ]] 43 | then 44 | echo "Purging build environment."$'\n' 45 | sudo rm -r build/ 46 | fi 47 | mkdir build 48 | cd build 49 | } 50 | 51 | uninstall_lib() { 52 | if [[ -f "/usr/local/lib/libcirquepinnacle.so" ]] 53 | then 54 | echo $'\n*** Uninstalling older version of CirquePinnacle\n' 55 | sudo rm /usr/local/lib/libcirquepinnacle.so* 56 | sudo rm -r /usr/local/include/CirquePinnacle/ 57 | fi 58 | } 59 | 60 | install_lib() { 61 | echo $'\n\n*** Installing CirquePinnacle library\n' 62 | create_build_env 63 | if ! cmake ../src 64 | then 65 | echo "!!! CMake failed to configure build system. Quitting now." 66 | exit 1 67 | fi 68 | if ! make 69 | then 70 | echo "!!! Building lib failed. Quitting now." 71 | exit 1 72 | fi 73 | uninstall_lib 74 | if ! sudo make install 75 | then 76 | echo "!!! Installing lib failed. Quitting now." 77 | exit 1 78 | fi 79 | # go back to repo root 80 | cd ../ 81 | } 82 | 83 | build_examples() { 84 | echo $'\n\n*** Building CirquePinnacle examples\n' 85 | cd ./examples/linux 86 | create_build_env 87 | if ! cmake .. -DUSE_I2C=$USE_I2C 88 | then 89 | echo "!!! CMake failed to configure build system. Quitting now." 90 | exit 1 91 | fi 92 | if ! make 93 | then 94 | echo "!!! Building examples failed. Quitting now." 95 | exit 1 96 | fi 97 | # go back to repo root 98 | cd ../../../ 99 | } 100 | 101 | install_python_binding() { 102 | echo $'\n\n*** Installing cirque-pinnacle python library\n' 103 | create_build_env 104 | # go back to repo root 105 | cd ../ 106 | # ensure pybind11 submodule is present 107 | if [[ ! -f "src/pybind11/CMakeLists.txt" ]] 108 | then 109 | echo $'\n*** Initializing frozen submodules\n' 110 | git submodule update --init 111 | fi 112 | # ensure there are no previous wheels in the dist/ folder 113 | if [[ -d "dist" ]] 114 | then 115 | rm -r dist/ 116 | fi 117 | if ! python3 -m pip wheel -w dist --no-deps -v . 118 | then 119 | echo "!!! Building Python distributable wheel failed. Quitting now." 120 | exit 1 121 | fi 122 | python3 -m pip install dist/cirque_pinnacle*.whl 123 | } 124 | 125 | INSTALL_LIB="N" 126 | read -p "*** Install CirquePinnacle lib? [y/N] " INSTALL_LIB 127 | BUILD_EXAMPLES="N" 128 | read -p "*** Build CirquePinnacle examples? [y/N] " BUILD_EXAMPLES 129 | if [[ ${BUILD_EXAMPLES^^} == "Y" ]] 130 | then 131 | read -p " Make examples use I2C (instead of SPI)? [y/N] " answer 132 | case ${answer^^} in 133 | Y ) USE_I2C="ON";; 134 | esac 135 | fi 136 | INSTALL_PY_BINDING="N" 137 | read -p "*** Build/Install the python package (cirque-pinnacle) from source? [y/N] " INSTALL_PY_BINDING 138 | 139 | case ${INSTALL_LIB^^} in 140 | Y ) install_lib;; 141 | esac 142 | 143 | case ${BUILD_EXAMPLES^^} in 144 | Y ) build_examples;; 145 | esac 146 | 147 | case ${INSTALL_PY_BINDING^^} in 148 | Y ) install_python_binding;; 149 | esac 150 | 151 | echo $'\n\n*** Done' 152 | echo "*** See https://cirquepinnacle.rtfd.io for documentation" 153 | 154 | # clean up env var 155 | unset PINNACLE_DRIVER 156 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Mouse 3 | ####################################### 4 | 5 | ####################################### 6 | # Constants (LITERAL1) 7 | ####################################### 8 | PINNACLE_RELATIVE LITERAL1 9 | PINNACLE_ANYMEAS LITERAL1 10 | PINNACLE_ABSOLUTE LITERAL1 11 | PINNACLE_GAIN_100 LITERAL1 12 | PINNACLE_GAIN_133 LITERAL1 13 | PINNACLE_GAIN_166 LITERAL1 14 | PINNACLE_GAIN_200 LITERAL1 15 | PINNACLE_FREQ_0 LITERAL1 16 | PINNACLE_FREQ_1 LITERAL1 17 | PINNACLE_FREQ_2 LITERAL1 18 | PINNACLE_FREQ_3 LITERAL1 19 | PINNACLE_FREQ_4 LITERAL1 20 | PINNACLE_FREQ_5 LITERAL1 21 | PINNACLE_FREQ_6 LITERAL1 22 | PINNACLE_FREQ_7 LITERAL1 23 | PINNACLE_MUX_REF1 LITERAL1 24 | PINNACLE_MUX_REF0 LITERAL1 25 | PINNACLE_MUX_PNP LITERAL1 26 | PINNACLE_MUX_NPN LITERAL1 27 | PINNACLE_CRTL_REPEAT LITERAL1 28 | PINNACLE_CRTL_PWR_IDLE LITERAL1 29 | 30 | ####################################### 31 | # Datatypes (KEYWORD1) 32 | ####################################### 33 | AbsoluteReport KEYWORD1 34 | RelativeReport KEYWORD1 35 | PinnacleTouch KEYWORD1 36 | PinnacleTouchSPI KEYWORD1 37 | PinnacleTouchI2C KEYWORD1 38 | 39 | ####################################### 40 | # Methods and Functions (KEYWORD2) 41 | ####################################### 42 | begin KEYWORD2 43 | feedEnabled KEYWORD2 44 | isFeedEnabled KEYWORD2 45 | setDataMode KEYWORD2 46 | getDataMode KEYWORD2 47 | isHardConfigured KEYWORD2 48 | available KEYWORD2 49 | read KEYWORD2 50 | absoluteModeConfig KEYWORD2 51 | relativeModeConfig KEYWORD2 52 | clearStatusFlags KEYWORD2 53 | allowSleep KEYWORD2 54 | isAllowSleep KEYWORD2 55 | shutdown KEYWORD2 56 | isShutdown KEYWORD2 57 | setSampleRate KEYWORD2 58 | getSampleRate KEYWORD2 59 | detectFingerStylus KEYWORD2 60 | calibrate KEYWORD2 61 | setCalibrationMatrix KEYWORD2 62 | getCalibrationMatrix KEYWORD2 63 | setAdcGain KEYWORD2 64 | tuneEdgeSensitivity KEYWORD2 65 | anymeasModeConfig KEYWORD2 66 | measureAdc KEYWORD2 67 | startMeasureAdc KEYWORD2 68 | getMeasureAdc KEYWORD2 69 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CirquePinnacle", 3 | "keywords": "spi, i2c, cirque, pinnacle, glidepoint, touch, sensor", 4 | "description": "A driver library for interfacing with the Cirque Pinnacle (1CA027) touch controller used in Cirque Glidepoint Circle Trackpads.", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/2bndy5/CirquePinnacle.git" 9 | }, 10 | "version": "1.0.1", 11 | "export": { 12 | "exclude": [ 13 | ".env/", 14 | ".github/", 15 | ".mypy_cache/", 16 | ".ruff_cache/", 17 | "docs/", 18 | "keywords.txt", 19 | "examples/pico_sdk/", 20 | "examples/cpython/", 21 | "examples/linux/", 22 | "src/cmake/*", 23 | "src/CMakeLists.txt", 24 | "src/utility/CMakeLists.txt", 25 | "src/utility/includes.h.in", 26 | "src/utility/includes.h", 27 | "src/utility/bcm2xxx/*", 28 | "src/utility/linux_kernel/*", 29 | "src/utility/mraa/*", 30 | "src/utility/pigpio/*", 31 | "src/utility/rp2/*", 32 | "src/utility/template/*", 33 | "src/pybind11/", 34 | "src/cirque_pinnacle-stubs/*", 35 | "src/py_bindings.cpp", 36 | ".pre-commit-config.yaml", 37 | ".readthedocs.yml", 38 | "install-linux.sh", 39 | "MANIFEST.in", 40 | "pyproject.toml", 41 | "setup.py" 42 | ] 43 | }, 44 | "frameworks": "arduino", 45 | "platforms": [ 46 | "atmelavr", 47 | "atmelsam", 48 | "teensy", 49 | "atmelmegaavr", 50 | "espressif32", 51 | "espressif8266", 52 | "ststm32", 53 | "nrf52", 54 | "nrf51" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=CirquePinnacle 2 | version=1.0.1 3 | author=2bndy5 4 | maintainer=2bndy5 5 | sentence=A driver library for interfacing with the Cirque Pinnacle (1CA027) touch controller used in Cirque Glidepoint Circle Trackpads. 6 | paragraph=Written to encompass all features demonstrated by the official Cirque example repository for the teensy3.2 and Cirque developer kit. 7 | category=Sensors 8 | includes=CirquePinnacle.h 9 | url=https://github.com/2bndy5/CirquePinnacle 10 | architectures=* 11 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | # building cmake from PyPI releases requires openssl-dev installed, so 3 | # just require users install cmake from apt when getting python-dev (CPython headers) 4 | requires = [ 5 | "setuptools>=61", 6 | "wheel", 7 | "setuptools_scm[toml]>=6.2", 8 | ] 9 | build-backend = "setuptools.build_meta" 10 | 11 | [project] 12 | name = "cirque_pinnacle" 13 | description = "A python package for the wrapping CirquePinnacle C++ library." 14 | readme = "README.rst" 15 | keywords = ["cirque", "pinnacle", "raspberry", "pi", "linux", "driver", "touch", "sensor"] 16 | license = {text = "MIT"} 17 | authors = [ 18 | { name = "Brendan Doherty", email = "2bndy5@gmail.com" }, 19 | ] 20 | classifiers = [ 21 | # https://pypi.org/pypi?%3Aaction=list_classifiers 22 | "Development Status :: 3 - Alpha", 23 | "Intended Audience :: Developers", 24 | "License :: OSI Approved :: MIT License", 25 | "Operating System :: POSIX :: Linux", 26 | "Programming Language :: C++", 27 | "Programming Language :: Python :: 3", 28 | "Programming Language :: Python :: 3.7", 29 | "Programming Language :: Python :: 3.8", 30 | "Programming Language :: Python :: 3.9", 31 | "Programming Language :: Python :: 3.10", 32 | "Topic :: Software Development :: Libraries", 33 | "Topic :: System :: Hardware", 34 | "Topic :: System :: Hardware :: Hardware Drivers", 35 | "Typing :: Typed", 36 | ] 37 | requires-python = ">=3.7" 38 | dynamic = ["version"] 39 | 40 | [project.urls] 41 | Documentation = "https://cirquepinnacle.rtfd.io/" 42 | Source = "https://github.com/2bndy5/CirquePinnacle" 43 | Tracker = "https://github.com/2bndy5/CirquePinnacle/issues" 44 | 45 | [tool.setuptools_scm] 46 | # pypi does not accept version strings with commit SHA in it. See PEP440 47 | local_scheme = "no-local-version" 48 | fallback_version = "0.0.0" 49 | version_scheme = "no-guess-dev" 50 | 51 | [tool.mypy] 52 | show_error_codes = true 53 | pretty = true 54 | files = [ 55 | "src/cirque_pinnacle-stubs/*.pyi", 56 | "examples/cpython/*.py", 57 | ] 58 | exclude = "setup.py" 59 | check_untyped_defs = true 60 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """Build & Install script for the CirquePinnacle C++ library python wrappers.""" 2 | 3 | import os 4 | import platform 5 | import subprocess 6 | import sys 7 | from pathlib import Path 8 | from setuptools import Extension, setup 9 | from setuptools.command.build_ext import build_ext 10 | 11 | IS_LINUX = platform.system().title() == "Linux" 12 | 13 | 14 | class CMakeExtension(Extension): 15 | """A class that wraps the generic mechanism for compiling a python C-extension. 16 | 17 | A CMakeExtension needs a sourcedir instead of a file list. 18 | The name must be the single output extension from the CMake build. 19 | """ 20 | 21 | def __init__(self, name, sourcedir="", **kwargs): 22 | kwargs.pop("sources", None) 23 | Extension.__init__(self, name, sources=[], **kwargs) 24 | self.sourcedir = str(Path(sourcedir).resolve()) 25 | 26 | 27 | class CMakeBuild(build_ext): 28 | """A class that wraps the builtin mechanism for building a 29 | distributable wheel from a compiled c-extension""" 30 | 31 | def build_extension(self, ext: Extension): 32 | # Must be in this form due to bug in .resolve() only fixed in Python 3.10+ 33 | ext_fullpath = Path.cwd() / self.get_ext_fullpath(ext.name) 34 | extdir = ext_fullpath.parent.resolve() 35 | 36 | # Using this requires trailing slash for auto-detection & inclusion of 37 | # auxiliary "native" libs 38 | 39 | debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug 40 | cfg = "Debug" if debug else "Release" 41 | 42 | cmake_args = [ 43 | f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}", 44 | f"-DPYTHON_EXECUTABLE={sys.executable}", 45 | f"-DCMAKE_BUILD_TYPE={cfg}", 46 | ] 47 | build_args = [] 48 | for key, value in ext.define_macros: 49 | macro = f"-D{key}" 50 | if value: 51 | macro += f"={value}" 52 | build_args.append(macro) 53 | 54 | # Adding CMake arguments set as environment variable 55 | # (needed e.g. to build for ARM OSx on conda-forge). 56 | if "CMAKE_ARGS" in os.environ: 57 | for item in os.environ["CMAKE_ARGS"].split(" "): 58 | if "PINNACLE_DRIVER" not in item: 59 | print( 60 | "!!! 'linux_kernel' is the only supported value for PINNACLE_DRIVER" 61 | ) 62 | continue 63 | elif item: 64 | cmake_args.append(item) 65 | 66 | build_temp = Path(self.build_temp, ext.name) 67 | if not build_temp.exists(): 68 | build_temp.mkdir(parents=True) 69 | 70 | cmake_args.append("-DPINNACLE_PY_BINDING=on") 71 | subprocess.check_call(["cmake", ext.sourcedir] + cmake_args, cwd=build_temp) 72 | # for verbose make output: 73 | # build_args.append("--verbose") 74 | # build_args.append(f"--target={ext.name}") 75 | subprocess.check_call(["cmake", "--build", "."] + build_args, cwd=build_temp) 76 | 77 | 78 | setup_args = dict( 79 | zip_safe=False, 80 | packages=["cirque_pinnacle-stubs"], 81 | package_data={"cirque_pinnacle-stubs": ["__init__.pyi"]}, 82 | package_dir={"cirque_pinnacle-stubs": "src/cirque_pinnacle-stubs"}, 83 | ) 84 | 85 | if IS_LINUX: 86 | setup_args["cmdclass"] = {"build_ext": CMakeBuild} 87 | setup_args["ext_modules"] = [CMakeExtension("cirque_pinnacle", sourcedir="src")] 88 | 89 | setup(**setup_args) 90 | -------------------------------------------------------------------------------- /src/.clang-format: -------------------------------------------------------------------------------- 1 | # See options listed at https://releases.llvm.org/12.0.1/tools/clang/docs/ClangFormatStyleOptions.html 2 | --- 3 | Language: Cpp 4 | # BasedOnStyle: WebKit 5 | AccessModifierOffset: -4 6 | AlignAfterOpenBracket: Align 7 | AlignConsecutiveMacros: Consecutive 8 | AlignConsecutiveAssignments: None 9 | AlignConsecutiveBitFields: None 10 | AlignConsecutiveDeclarations: None 11 | AlignEscapedNewlines: Left 12 | AlignOperands: DontAlign 13 | AlignTrailingComments: true 14 | AllowAllArgumentsOnNextLine: true 15 | AllowAllConstructorInitializersOnNextLine: true 16 | AllowAllParametersOfDeclarationOnNextLine: true 17 | AllowShortEnumsOnASingleLine: false 18 | AllowShortBlocksOnASingleLine: Empty 19 | AllowShortCaseLabelsOnASingleLine: true 20 | AllowShortFunctionsOnASingleLine: All 21 | AllowShortLambdasOnASingleLine: All 22 | AllowShortIfStatementsOnASingleLine: Never 23 | AllowShortLoopsOnASingleLine: false 24 | AlwaysBreakAfterReturnType: None 25 | AlwaysBreakBeforeMultilineStrings: false 26 | AlwaysBreakTemplateDeclarations: Yes 27 | AttributeMacros: ["__capability", "__output", "__ununsed"] 28 | BinPackArguments: true 29 | BinPackParameters: true 30 | BitFieldColonSpacing: Both 31 | BraceWrapping: 32 | AfterCaseLabel: false 33 | AfterClass: true 34 | AfterControlStatement: MultiLine 35 | AfterEnum: true 36 | AfterFunction: true 37 | AfterNamespace: false 38 | AfterStruct: true 39 | AfterUnion: true 40 | AfterExternBlock: false 41 | BeforeCatch: true 42 | BeforeElse: true 43 | BeforeLambdaBody: false 44 | BeforeWhile: false 45 | IndentBraces: false 46 | SplitEmptyFunction: true 47 | SplitEmptyRecord: true 48 | SplitEmptyNamespace: true 49 | BreakBeforeBinaryOperators: All 50 | BreakBeforeConceptDeclarations: true 51 | BreakBeforeBraces: Custom 52 | BreakBeforeInheritanceComma: false 53 | BreakInheritanceList: BeforeColon 54 | BreakBeforeTernaryOperators: true 55 | BreakConstructorInitializersBeforeComma: false 56 | BreakConstructorInitializers: BeforeColon 57 | BreakStringLiterals: true 58 | ColumnLimit: 0 59 | # CommentPragmas are a regex pattern indicating the comment is not be touched by the formatter 60 | CommentPragmas: "^ Include gaurd .*" 61 | CompactNamespaces: false 62 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 63 | ConstructorInitializerIndentWidth: 4 64 | ContinuationIndentWidth: 4 65 | Cpp11BracedListStyle: true 66 | DeriveLineEnding: false 67 | DerivePointerAlignment: false 68 | DisableFormat: false 69 | EmptyLineBeforeAccessModifier: Always 70 | EmptyLineAfterAccessModifier: Leave 71 | ExperimentalAutoDetectBinPacking: false 72 | FixNamespaceComments: true 73 | IncludeBlocks: Preserve 74 | IncludeCategories: 75 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 76 | Priority: 2 77 | SortPriority: 0 78 | CaseSensitive: false 79 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 80 | Priority: 3 81 | SortPriority: 0 82 | CaseSensitive: false 83 | - Regex: ".*" 84 | Priority: 1 85 | SortPriority: 0 86 | CaseSensitive: false 87 | IncludeIsMainRegex: "(Test)?$" 88 | IncludeIsMainSourceRegex: "" 89 | IndentAccessModifiers: false 90 | IndentCaseLabels: true 91 | IndentCaseBlocks: false 92 | IndentGotoLabels: false 93 | IndentPPDirectives: BeforeHash 94 | IndentExternBlock: AfterExternBlock 95 | IndentRequires: false 96 | IndentWidth: 4 97 | IndentWrappedFunctionNames: false 98 | InsertTrailingCommas: None 99 | KeepEmptyLinesAtTheStartOfBlocks: true 100 | MacroBlockBegin: "" 101 | MacroBlockEnd: "" 102 | MaxEmptyLinesToKeep: 1 103 | NamespaceIndentation: Inner 104 | PenaltyBreakAssignment: 2 105 | PenaltyBreakBeforeFirstCallParameter: 19 106 | PenaltyBreakComment: 300 107 | PenaltyBreakFirstLessLess: 120 108 | PenaltyBreakString: 1000 109 | PenaltyBreakTemplateDeclaration: 10 110 | PenaltyExcessCharacter: 1000000 111 | PenaltyReturnTypeOnItsOwnLine: 60 112 | PenaltyIndentedWhitespace: 0 113 | PointerAlignment: Left 114 | ReferenceAlignment: Pointer 115 | ReflowComments: true 116 | SpacesInLineCommentPrefix: 117 | Maximum: -1 118 | Minimum: 0 119 | ShortNamespaceLines: 0 120 | # Sort**** is about sorting include/using statements alphabetically 121 | SortIncludes: false 122 | SortUsingDeclarations: false 123 | SpaceAfterCStyleCast: false 124 | SpaceAfterLogicalNot: false 125 | SpaceAfterTemplateKeyword: false 126 | SpaceBeforeAssignmentOperators: true 127 | SpaceBeforeCaseColon: false 128 | SpaceBeforeCpp11BracedList: true 129 | SpaceBeforeCtorInitializerColon: true 130 | SpaceBeforeInheritanceColon: true 131 | SpaceBeforeParens: ControlStatements 132 | SpaceAroundPointerQualifiers: Default 133 | SpaceBeforeRangeBasedForLoopColon: true 134 | SpaceInEmptyBlock: false 135 | SpaceInEmptyParentheses: false 136 | SpacesBeforeTrailingComments: 1 137 | SpacesInAngles: false 138 | SpacesInConditionalStatement: false 139 | SpacesInContainerLiterals: false 140 | SpacesInCStyleCastParentheses: false 141 | SpacesInParentheses: false 142 | SpacesInSquareBrackets: false 143 | SpaceBeforeSquareBrackets: false 144 | Standard: c++11 145 | StatementAttributeLikeMacros: [emit] 146 | StatementMacros: [Q_UNUSED, QT_REQUIRE_VERSION] 147 | TabWidth: 4 148 | UseCRLF: false 149 | UseTab: Never 150 | WhitespaceSensitiveMacros: 151 | - PRIPSTR 152 | - STRINGIZE 153 | - PP_STRINGIZE 154 | - BOOST_PP_STRINGIZE 155 | - NS_SWIFT_NAME 156 | - CF_SWIFT_NAME 157 | -------------------------------------------------------------------------------- /src/CirquePinnacle_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_ARCH_COMMON_H_ 20 | #define CIRQUEPINNACLE_ARCH_COMMON_H_ 21 | 22 | #ifndef PINNACLE_ANYMEAS_SUPPORT 23 | /** 24 | * This will enable library support of the Pinnacle ASIC's anymeas mode (advanced usage). 25 | * 26 | * @note 27 | * Arduino users need to comment out this line to save space on memory. 28 | * 29 | * All other builds using CMake (including the python bindings) can simply define 30 | * ``-D PINNACLE_ANYMEAS_SUPPORT=OFF`` as a CMake option. 31 | * 32 | * @ingroup cmake-options 33 | */ 34 | #define PINNACLE_ANYMEAS_SUPPORT true 35 | #endif // !defined(PINNACLE_ANYMEAS_SUPPORT) 36 | 37 | #if defined(ARDUINO) 38 | #include 39 | #include 40 | #include 41 | 42 | #ifndef PINNACLE_SPI_SPEED 43 | // Default is the recommended 6 MHz (maximum supported SPI speed is 13 MHz) 44 | #define PINNACLE_SPI_SPEED 6000000 45 | #endif 46 | 47 | /** 48 | * alias for SPI bus implementation 49 | * 50 | * @ingroup arduino-spi 51 | */ 52 | typedef SPIClass pinnacle_spi_t; 53 | 54 | /** 55 | * alias for I2C bus implementation 56 | * 57 | * @ingroup arduino-i2c 58 | */ 59 | typedef TwoWire pinnacle_i2c_t; 60 | 61 | #ifdef NUM_DIGITAL_PINS 62 | #if NUM_DIGITAL_PINS < 0xFF 63 | typedef uint8_t pinnacle_gpio_t; 64 | #else 65 | typedef uint16_t pinnacle_gpio_t; 66 | #endif 67 | #else 68 | typedef uint16_t pinnacle_gpio_t; 69 | #endif 70 | 71 | #define PINNACLE_SS_CTRL(pin, value) digitalWrite(pin, value) 72 | 73 | #define PINNACLE_USE_ARDUINO_API 74 | 75 | #else 76 | // all other platforms/frameworks will be included via "utility/includes.h" file generated by CMake. 77 | // see src/cmake/auto_config_driver.cmake script for supported options (on linux) 78 | #include "utility/includes.h" 79 | #endif 80 | 81 | #endif // CIRQUEPINNACLE_ARCH_COMMON_H_ 82 | -------------------------------------------------------------------------------- /src/cmake/CPackInfo.cmake: -------------------------------------------------------------------------------- 1 | # This module will build a debian compatible package to install - handy for cross-compiling 2 | 3 | if(NOT PKG_REV) 4 | set(PKG_REV "1") 5 | endif() 6 | 7 | # get target arch if not cross-compiling 8 | if(NOT TARGET_ARCH) # TARGET_ARCH is defined only in the toolchain_.cmake files 9 | execute_process(COMMAND dpkg --print-architecture 10 | OUTPUT_VARIABLE TARGET_ARCH 11 | OUTPUT_STRIP_TRAILING_WHITESPACE 12 | ) 13 | endif() 14 | 15 | # set the Cpack generators (specific to types of packages to create) 16 | set(CPACK_GENERATOR DEB RPM) # RPM requires rpmbuild executable 17 | 18 | # assemble a debian package filename from known info 19 | include(InstallRequiredSystemLibraries) 20 | set(CPACK_PACKAGE_FILE_NAME "lib${LibTargetName}-${PINNACLE_DRIVER}_${${LibName}_VERSION_STRING}-${PKG_REV}_${TARGET_ARCH}") 21 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE") 22 | set(CPACK_PACKAGE_VERSION_MAJOR "${${LibName}_VERSION_MAJOR}") 23 | set(CPACK_PACKAGE_VERSION_MINOR "${${LibName}_VERSION_MINOR}") 24 | set(CPACK_PACKAGE_VERSION_PATCH "${${LibName}_VERSION_PATCH}") 25 | set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/pkgs") # for easy uploading to github releases 26 | 27 | ############################### 28 | # info specific debian packages 29 | ############################### 30 | set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) 31 | set(CPACK_DEBIAN_PACKAGE_SECTION libs) 32 | set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE) 33 | 34 | ############################### 35 | # info specific rpm (fedora) packages 36 | ############################### 37 | set(CPACK_RPM_FILE_NAME "lib${LibTargetName}-${PINNACLE_DRIVER}-${${LibName}_VERSION_STRING}-${PKG_REV}.${TARGET_ARCH}.rpm") 38 | set(CPACK_RPM_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) 39 | set(CPACK_RPM_PACKAGE_LICENSE "MIT") 40 | set(CPACK_RPM_PACKAGE_VENDOR "Humanity") 41 | 42 | # create a post-install & post-removal scripts to update linker 43 | set(POST_SCRIPTS 44 | ${CMAKE_BINARY_DIR}/DEBIAN/postrm 45 | ${CMAKE_BINARY_DIR}/DEBIAN/postinst 46 | ) 47 | foreach(script ${POST_SCRIPTS}) 48 | file(WRITE ${script} ldconfig) 49 | execute_process(COMMAND chmod +x ${script}) 50 | execute_process(COMMAND chmod 775 ${script}) 51 | endforeach() 52 | # declare scripts for deb pkgs 53 | list(JOIN POST_SCRIPTS ";" EXTRA_CTRL_FILES) 54 | set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${EXTRA_CTRL_FILES}) 55 | # declare scripts for rpm pkgs 56 | list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE) 57 | list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_INSTALL_SCRIPT_FILE) 58 | 59 | message(STATUS "ready to package: ${CPACK_PACKAGE_FILE_NAME}.deb") 60 | message(STATUS "ready to package: ${CPACK_RPM_FILE_NAME}") 61 | 62 | include(CPack) 63 | -------------------------------------------------------------------------------- /src/cmake/Cache.cmake: -------------------------------------------------------------------------------- 1 | option(ENABLE_CACHE "Enable cache if available" ON) 2 | if(NOT ENABLE_CACHE) 3 | return() 4 | endif() 5 | 6 | set(CACHE_OPTION "ccache" CACHE STRING "Compiler cache to be used") 7 | set(CACHE_OPTION_VALUES "ccache" "sccache") 8 | set_property(CACHE CACHE_OPTION PROPERTY STRINGS ${CACHE_OPTION_VALUES}) 9 | list( 10 | FIND 11 | CACHE_OPTION_VALUES 12 | ${CACHE_OPTION} 13 | CACHE_OPTION_INDEX 14 | ) 15 | 16 | if(${CACHE_OPTION_INDEX} EQUAL -1) 17 | message(STATUS 18 | "Using custom compiler cache system: '${CACHE_OPTION}', explicitly supported entries are ${CACHE_OPTION_VALUES}" 19 | ) 20 | endif() 21 | 22 | find_program(CACHE_BINARY ${CACHE_OPTION}) 23 | if(CACHE_BINARY) 24 | message(STATUS "${CACHE_OPTION} found and enabled") 25 | set(CMAKE_CXX_COMPILER_LAUNCHER ${CACHE_BINARY}) 26 | else() 27 | message(WARNING "${CACHE_OPTION} is enabled but was not found. Not using it") 28 | endif() 29 | -------------------------------------------------------------------------------- /src/cmake/CompilerWarnings.cmake: -------------------------------------------------------------------------------- 1 | # from here: 2 | # 3 | # https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md 4 | 5 | function(set_project_warnings project_name) 6 | option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" TRUE) 7 | 8 | set(MSVC_WARNINGS 9 | /W4 # Baseline reasonable warnings 10 | /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data 11 | /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 12 | /w14263 # 'function': member function does not override any base class virtual member function 13 | /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not 14 | # be destructed correctly 15 | /w14287 # 'operator': unsigned/negative constant mismatch 16 | /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside 17 | # the for-loop scope 18 | /w14296 # 'operator': expression is always 'boolean_value' 19 | /w14311 # 'variable': pointer truncation from 'type1' to 'type2' 20 | /w14545 # expression before comma evaluates to a function which is missing an argument list 21 | /w14546 # function call before comma missing argument list 22 | /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect 23 | /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? 24 | /w14555 # expression has no effect; expected expression with side- effect 25 | /w14619 # pragma warning: there is no warning number 'number' 26 | /w14640 # Enable warning on thread un-safe static member initialization 27 | /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. 28 | /w14905 # wide string literal cast to 'LPSTR' 29 | /w14906 # string literal cast to 'LPWSTR' 30 | /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied 31 | /permissive- # standards conformance mode for MSVC compiler. 32 | ) 33 | 34 | set(CLANG_WARNINGS 35 | -Wall 36 | -Wextra # reasonable and standard 37 | -Wshadow # warn the user if a variable declaration shadows one from a parent context 38 | -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps 39 | # catch hard to track down memory errors 40 | # -Wold-style-cast # warn for c-style casts 41 | -Wcast-align # warn for potential performance problem casts 42 | -Wunused # warn on anything being unused 43 | -Woverloaded-virtual # warn if you overload (not override) a virtual function 44 | -Wpedantic # warn if non-standard C++ is used 45 | -Wconversion # warn on type conversions that may lose data 46 | -Wsign-conversion # warn on sign conversions 47 | -Wnull-dereference # warn if a null dereference is detected 48 | -Wdouble-promotion # warn if float is implicit promoted to double 49 | -Wformat=2 # warn on security issues around functions that format output (ie printf) 50 | ) 51 | 52 | if(WARNINGS_AS_ERRORS) 53 | set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) 54 | set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) 55 | endif() 56 | 57 | set(GCC_WARNINGS 58 | ${CLANG_WARNINGS} 59 | -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist 60 | -Wduplicated-cond # warn if if / else chain has duplicated conditions 61 | -Wduplicated-branches # warn if if / else branches have duplicated code 62 | -Wlogical-op # warn about logical operations being used where bitwise were probably wanted 63 | -Wuseless-cast # warn if you perform a cast to the same type 64 | ) 65 | 66 | if(MSVC) 67 | set(PROJECT_WARNINGS ${MSVC_WARNINGS}) 68 | elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") 69 | set(PROJECT_WARNINGS ${CLANG_WARNINGS}) 70 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 71 | set(PROJECT_WARNINGS ${GCC_WARNINGS}) 72 | else() 73 | message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") 74 | endif() 75 | 76 | target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS}) 77 | 78 | endfunction() 79 | -------------------------------------------------------------------------------- /src/cmake/GetLibInfo.cmake: -------------------------------------------------------------------------------- 1 | # get lib info from the maintained library.properties required by the Arduino IDE 2 | file(STRINGS ${CMAKE_CURRENT_LIST_DIR}/../../library.properties LibInfo) 3 | foreach(line ${LibInfo}) 4 | string(FIND ${line} "=" label_delimiter) 5 | if(${label_delimiter} GREATER 0) 6 | math(EXPR label_delimiter "${label_delimiter} + 1") 7 | string(FIND ${line} "version" has_version) 8 | string(FIND ${line} "name" has_name) 9 | string(FIND ${line} "maintainer" has_maintainer) 10 | string(FIND ${line} "sentence" has_sentence) 11 | string(FIND ${line} "url" has_url) 12 | string(FIND ${line} "paragraph" has_paragraph) 13 | if(${has_version} EQUAL 0) 14 | string(SUBSTRING ${line} ${label_delimiter} "-1" VERSION) 15 | elseif(${has_name} EQUAL 0) 16 | string(SUBSTRING ${line} ${label_delimiter} "-1" LibName) 17 | elseif(${has_maintainer} EQUAL 0) 18 | string(SUBSTRING ${line} ${label_delimiter} "-1" CPACK_PACKAGE_CONTACT) 19 | elseif(${has_sentence} EQUAL 0) 20 | string(SUBSTRING ${line} ${label_delimiter} "-1" CPACK_PACKAGE_DESCRIPTION_SUMMARY) 21 | elseif(${has_url} EQUAL 0) 22 | string(SUBSTRING ${line} ${label_delimiter} "-1" CMAKE_PROJECT_HOMEPAGE_URL) 23 | elseif(${has_paragraph} EQUAL 0) 24 | string(SUBSTRING ${line} ${label_delimiter} "-1" CPACK_PACKAGE_DESCRIPTION) 25 | endif() 26 | endif() 27 | endforeach() 28 | 29 | # convert the LibName to lower case 30 | string(TOLOWER ${LibName} LibTargetName) 31 | 32 | #parse the version information into pieces. 33 | string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") 34 | string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") 35 | string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}") 36 | 37 | # this is the library version 38 | set(${LibName}_VERSION_MAJOR ${VERSION_MAJOR}) 39 | set(${LibName}_VERSION_MINOR ${VERSION_MINOR}) 40 | set(${LibName}_VERSION_PATCH ${VERSION_PATCH}) 41 | set(${LibName}_VERSION_STRING ${${LibName}_VERSION_MAJOR}.${${LibName}_VERSION_MINOR}.${${LibName}_VERSION_PATCH}) 42 | 43 | message(STATUS "${LibName} library version: ${${LibName}_VERSION_STRING}") 44 | -------------------------------------------------------------------------------- /src/cmake/PreventInSourceBuilds.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # This function will prevent in-source builds 3 | function(AssureOutOfSourceBuilds) 4 | # make sure the user doesn't play dirty with symlinks 5 | get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) 6 | get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) 7 | 8 | # disallow in-source builds 9 | if("${srcdir}" STREQUAL "${bindir}") 10 | message("######################################################") 11 | message("Warning: in-source builds are disabled") 12 | message("Please create a separate build directory and run cmake from there") 13 | message("######################################################") 14 | message(FATAL_ERROR "Quitting configuration") 15 | endif() 16 | endfunction() 17 | 18 | assureoutofsourcebuilds() 19 | -------------------------------------------------------------------------------- /src/cmake/Sanitizers.cmake: -------------------------------------------------------------------------------- 1 | function(enable_sanitizers project_name) 2 | 3 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") 4 | option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) 5 | 6 | if(ENABLE_COVERAGE) 7 | target_compile_options(${project_name} INTERFACE --coverage -O0 -g) 8 | target_link_libraries(${project_name} INTERFACE --coverage) 9 | endif() 10 | 11 | set(SANITIZERS "") 12 | 13 | option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" FALSE) 14 | if(ENABLE_SANITIZER_ADDRESS) 15 | list(APPEND SANITIZERS "address") 16 | endif() 17 | 18 | option(ENABLE_SANITIZER_LEAK "Enable leak sanitizer" FALSE) 19 | if(ENABLE_SANITIZER_LEAK) 20 | list(APPEND SANITIZERS "leak") 21 | endif() 22 | 23 | option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" FALSE) 24 | if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR) 25 | list(APPEND SANITIZERS "undefined") 26 | endif() 27 | 28 | option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE) 29 | if(ENABLE_SANITIZER_THREAD) 30 | if("address" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS) 31 | message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled") 32 | else() 33 | list(APPEND SANITIZERS "thread") 34 | endif() 35 | endif() 36 | 37 | option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" FALSE) 38 | if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") 39 | if("address" IN_LIST SANITIZERS OR "thread" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS) 40 | message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled") 41 | else() 42 | list(APPEND SANITIZERS "memory") 43 | endif() 44 | endif() 45 | 46 | list(JOIN SANITIZERS "," LIST_OF_SANITIZERS) 47 | 48 | endif() 49 | 50 | if(LIST_OF_SANITIZERS AND NOT "${LIST_OF_SANITIZERS}" STREQUAL "") 51 | target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) 52 | target_link_libraries(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) 53 | endif() 54 | 55 | endfunction() 56 | -------------------------------------------------------------------------------- /src/cmake/StandardProjectSettings.cmake: -------------------------------------------------------------------------------- 1 | # Set a default build type if none was specified 2 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 3 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) 4 | message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE}' as none was specified.") 5 | 6 | # Set the possible values of build type for cmake-gui, ccmake 7 | set_property( 8 | CACHE CMAKE_BUILD_TYPE 9 | PROPERTY STRINGS 10 | "Debug" 11 | "Release" 12 | "MinSizeRel" 13 | "RelWithDebInfo" 14 | ) 15 | endif() 16 | 17 | # Generate compile_commands.json to make it easier to work with clang based tools 18 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 19 | 20 | option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF) 21 | 22 | if(ENABLE_IPO) 23 | include(CheckIPOSupported) 24 | check_ipo_supported( 25 | RESULT result 26 | OUTPUT output 27 | ) 28 | if(result) 29 | set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) 30 | else() 31 | message(SEND_ERROR "IPO is not supported: ${output}") 32 | endif() 33 | endif() 34 | -------------------------------------------------------------------------------- /src/cmake/StaticAnalyzers.cmake: -------------------------------------------------------------------------------- 1 | option(ENABLE_CPPCHECK "Enable static analysis with cppcheck" OFF) 2 | option(ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF) 3 | option(ENABLE_INCLUDE_WHAT_YOU_USE "Enable static analysis with include-what-you-use" OFF) 4 | 5 | if(ENABLE_CPPCHECK) 6 | find_program(CPPCHECK cppcheck) 7 | if(CPPCHECK) 8 | set(CMAKE_CXX_CPPCHECK 9 | ${CPPCHECK} 10 | --suppress=missingInclude 11 | --enable=all 12 | --inline-suppr 13 | --inconclusive 14 | -i 15 | ${CMAKE_SOURCE_DIR}/imgui/lib 16 | ) 17 | else() 18 | message(SEND_ERROR "cppcheck requested but executable not found") 19 | endif() 20 | endif() 21 | 22 | if(ENABLE_CLANG_TIDY) 23 | find_program(CLANGTIDY clang-tidy) 24 | if(CLANGTIDY) 25 | set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option) 26 | else() 27 | message(SEND_ERROR "clang-tidy requested but executable not found") 28 | endif() 29 | endif() 30 | 31 | if(ENABLE_INCLUDE_WHAT_YOU_USE) 32 | find_program(INCLUDE_WHAT_YOU_USE include-what-you-use) 33 | if(INCLUDE_WHAT_YOU_USE) 34 | set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE}) 35 | else() 36 | message(SEND_ERROR "include-what-you-use requested but executable not found") 37 | endif() 38 | endif() 39 | -------------------------------------------------------------------------------- /src/cmake/auto_config_driver.cmake: -------------------------------------------------------------------------------- 1 | set(PINNACLE_DRIVER "linux_kernel" CACHE STRING "using folder src/utility/linux_kernel") 2 | 3 | # detect installed libraries despite what PINNACLE_DRIVER is set to 4 | # this is always done for cross-compiling purposes 5 | if(EXISTS /dev/spidev0.0) 6 | set(SPIDEV_EXISTS TRUE) 7 | else() 8 | set(SPIDEV_EXISTS FALSE) 9 | endif() 10 | 11 | 12 | if(NOT SPIDEV_EXISTS) 13 | message(STATUS "detected that SPIDEV is enabled: ${SPIDEV_EXISTS}") 14 | endif() 15 | 16 | message(STATUS "Using driver: ${PINNACLE_DRIVER}") 17 | -------------------------------------------------------------------------------- /src/cmake/detectCPU.cmake: -------------------------------------------------------------------------------- 1 | # try to get the CPU model using a Linux bash command 2 | if(NOT SOC) # if SOC variable not defined by user at CLI 3 | if(EXISTS "/sys/class/sunxi_info/sys_info") 4 | execute_process(COMMAND grep sunxi_platform /sys/class/sunxi_info/sys_info 5 | OUTPUT_VARIABLE CPU_MODEL 6 | OUTPUT_STRIP_TRAILING_WHITESPACE 7 | ) 8 | else() 9 | execute_process(COMMAND grep Hardware /proc/cpuinfo 10 | OUTPUT_VARIABLE CPU_MODEL 11 | OUTPUT_STRIP_TRAILING_WHITESPACE 12 | ) 13 | endif() 14 | 15 | string(FIND "${CPU_MODEL}" ":" cpu_is_described) 16 | if(${cpu_is_described} GREATER 0) # Hardware field does exist 17 | math(EXPR cpu_is_described "${cpu_is_described} + 1") 18 | string(SUBSTRING "${CPU_MODEL}" ${cpu_is_described} -1 SOC) 19 | string(STRIP "${SOC}" SOC) 20 | else() # Hardware field does not exist 21 | set(SOC "UNKNOWN") # use this string as a sentinel 22 | endif() 23 | message(STATUS "detected SoC: ${SOC}") 24 | else() 25 | message(STATUS "SOC set to ${SOC}") 26 | endif() 27 | 28 | string(FIND "${SOC}" "Generic AM33XX" is_AM33XX) 29 | 30 | #[[ detect machine hardware name 31 | This CPU_TYPE variable is not used anywhere. 32 | It remains as useful prompt info & to be consistent with old build system ]] 33 | execute_process(COMMAND uname -m 34 | OUTPUT_VARIABLE CPU_TYPE 35 | OUTPUT_STRIP_TRAILING_WHITESPACE 36 | ) 37 | message(STATUS "detected CPU type: ${CPU_TYPE}") 38 | 39 | # identify the compiler base name for customizing flags 40 | # THIS ONLY WORKS/TESTED FOR GNU COMPILERS 41 | if(NOT CMAKE_CROSSCOMPILING) # need to use /usr/lib/gcc soft symlink 42 | # NOTE the following command doesn't work with " | tail -1" appended 43 | execute_process(COMMAND ls /usr/lib/gcc 44 | OUTPUT_VARIABLE tool_name 45 | OUTPUT_STRIP_TRAILING_WHITESPACE 46 | ) 47 | 48 | # use only last entry if multiple entries are returned; this tactic is a possible point of error 49 | string(FIND "${tool_name}" "\n" last_list_delimiter REVERSE) 50 | if(last_list_delimiter GREATER -1) 51 | math(EXPR last_list_delimiter "${last_list_delimiter} + 1") 52 | string(SUBSTRING "${tool_name}" ${last_list_delimiter} -1 tool_name) 53 | endif() 54 | 55 | else() # we can use the compiler's name of the path set in the toolchain file 56 | string(REGEX REPLACE "^\/usr\/bin\/(.*)-gcc.*" "\\1" tool_name "${CMAKE_C_COMPILER}") 57 | endif() 58 | 59 | message(STATUS "tool name being used: ${tool_name}") 60 | 61 | # add compiler flags to optomize builds with arm-linux-gnueabihf-g* compilers 62 | if("${tool_name}" STREQUAL "arm-linux-gnueabihf") 63 | if("${SOC}" STREQUAL "BCM2835" OR "${SOC}" STREQUAL "BCM2708") 64 | add_compile_options(-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard) 65 | elseif("$SOC" STREQUAL "BCM2836" OR "${SOC}" STREQUAL "BCM2709") 66 | add_compile_options(-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard) 67 | elseif(${is_AM33XX} GREATER -1) 68 | add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) 69 | elseif("$SOC" STREQUAL "sun4i" OR "${SOC}" STREQUAL "Sun4iw1p1") # A10 70 | add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) 71 | elseif("$SOC" STREQUAL "sun5i" OR "${SOC}" STREQUAL "Sun4iw2p1") # A13 72 | add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) 73 | elseif("$SOC" STREQUAL "sun7i" OR "${SOC}" STREQUAL "Sun8iw2p1") # A20 74 | add_compile_options(-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard) 75 | elseif("$SOC" STREQUAL "sun8i" OR "${SOC}" STREQUAL "Sun8iw7p1") # H3 76 | add_compile_options(-march=armv8-a -mtune=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard) 77 | endif() 78 | endif() 79 | -------------------------------------------------------------------------------- /src/cmake/pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | # 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if(DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif() 10 | 11 | if(DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif() 15 | 16 | if(DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif() 20 | 21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 24 | 25 | if(NOT PICO_SDK_PATH) 26 | if(PICO_SDK_FETCH_FROM_GIT) 27 | include(FetchContent) 28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 29 | if(PICO_SDK_FETCH_FROM_GIT_PATH) 30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 31 | endif() 32 | FetchContent_Declare( 33 | pico_sdk 34 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 35 | GIT_TAG master 36 | ) 37 | if(NOT pico_sdk) 38 | message("Downloading Raspberry Pi Pico SDK") 39 | FetchContent_Populate(pico_sdk) 40 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 41 | endif() 42 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 43 | else () 44 | message(FATAL_ERROR 45 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 46 | ) 47 | endif() 48 | endif() 49 | 50 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 51 | if(NOT EXISTS ${PICO_SDK_PATH}) 52 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 53 | endif() 54 | 55 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 56 | if(NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 57 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 58 | endif() 59 | 60 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 61 | 62 | include(${PICO_SDK_INIT_CMAKE_FILE}) 63 | -------------------------------------------------------------------------------- /src/cmake/toolchains/arm64.cmake: -------------------------------------------------------------------------------- 1 | ###################### FOR CROSS-COMPILING using the aarch64-linux-gnu-g** compiler 2 | # invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` 3 | # this file is meant to be used generically, but will not work for all CMake projects 4 | # this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use 5 | 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR arm64) 8 | set(TARGET_ARCH arm64) # only used in cmake/createDebianPkg.cmake 9 | set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc) 10 | set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++) 11 | 12 | # CMAKE_SYSROOT can only be set in a toolchain file 13 | # set(CMAKE_SYSROOT /usr/aarch64-linux-gnu) # useful when a target machine's files are available 14 | 15 | # set the directory for searching installed headers 16 | # add_compile_options(-I /usr/aarch64-linux-gnu/include) # this may not be best practice 17 | 18 | #[[ 19 | # CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine 20 | set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) 21 | 22 | CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) 23 | if cross-compiling a dependent lib (like mraa - which is optional), then 24 | set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to CirquePinnacle lib's CMAKE_FIND_ROOT_PATH 25 | example using mraa: 26 | (for mraa/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/CirquePinnacle/src/cmake/toolchains/arm64.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/aarch64-linux-gnu 27 | (for CirquePinnacle/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm64.cmake 28 | ]] 29 | list(APPEND CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) 30 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called 31 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called 32 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called 33 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called 34 | -------------------------------------------------------------------------------- /src/cmake/toolchains/armhf.cmake: -------------------------------------------------------------------------------- 1 | ###################### FOR CROSS-COMPILING using the arm-linux-gnueabihf-g** compiler 2 | # invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` 3 | # this file is meant to be used generically, but will not work for all CMake projects 4 | # this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use 5 | 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR armhf) 8 | set(TARGET_ARCH armhf) # only used in cmake/CPackInfo.cmake 9 | set(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc) 10 | set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++) 11 | 12 | # CMAKE_SYSROOT can only be set in a toolchain file 13 | # set(CMAKE_SYSROOT /usr/arm-linux-gnueabihf) # useful when a target machine's files are available 14 | 15 | # set the directory for searching installed headers 16 | # add_compile_options(-I /usr/arm-linux-gnueabihf/include) # this may not be best practice 17 | 18 | #[[ 19 | # CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine 20 | set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) 21 | 22 | CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) 23 | if cross-compiling a dependent lib (like mraa - which is optional), then 24 | set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to CirquePinnacle lib's CMAKE_FIND_ROOT_PATH 25 | example using mraa: 26 | (for mraa/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/CirquePinnacle/src/cmake/toolchains/arm.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/arm-linux-gnueabihf 27 | (for CirquePinnacle/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm.cmake 28 | ]] 29 | list(APPEND CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf) 30 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called 31 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called 32 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called 33 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called 34 | -------------------------------------------------------------------------------- /src/cmake/toolchains/clang.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Linux) 2 | set(CMAKE_SYSTEM_PROCESSOR arm) 3 | 4 | set(triple arm-linux-gnueabihf) 5 | 6 | set(CMAKE_C_COMPILER clang) 7 | set(CMAKE_C_COMPILER_TARGET ${triple}) 8 | set(CMAKE_CXX_COMPILER clang++) 9 | set(CMAKE_CXX_COMPILER_TARGET ${triple}) 10 | -------------------------------------------------------------------------------- /src/cmake/toolchains/default.cmake: -------------------------------------------------------------------------------- 1 | # empty toolchain file to allow CI scripts to still use system default toolchains 2 | -------------------------------------------------------------------------------- /src/cmake/toolchains/i686.cmake: -------------------------------------------------------------------------------- 1 | ###################### FOR CROSS-COMPILING using the i686-linux-gnu-g** compiler 2 | # invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` 3 | # this file is meant to be used generically, but will not work for all CMake projects 4 | # this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use 5 | 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR i686) 8 | set(TARGET_ARCH i686) # only used in cmake/createDebianPkg.cmake 9 | set(CMAKE_C_COMPILER /usr/bin/i686-linux-gnu-gcc) 10 | set(CMAKE_CXX_COMPILER /usr/bin/i686-linux-gnu-g++) 11 | 12 | # CMAKE_SYSROOT can only be set in a toolchain file 13 | # set(CMAKE_SYSROOT /usr/i686-linux-gnu) # useful when a target machine's files are available 14 | 15 | # set the directory for searching installed headers 16 | # add_compile_options(-I /usr/i686-linux-gnu/include) # this may not be best practice 17 | 18 | #[[ 19 | # CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine 20 | set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) 21 | 22 | CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) 23 | if cross-compiling a dependent lib (like mraa - which is optional), then 24 | set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to CirquePinnacle lib's CMAKE_FIND_ROOT_PATH 25 | example using mraa: 26 | (for mraa/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/CirquePinnacle/src/cmake/toolchains/i686.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/i686-linux-gnu 27 | (for CirquePinnacle/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686.cmake 28 | ]] 29 | list(APPEND CMAKE_FIND_ROOT_PATH /usr/i686-linux-gnu) 30 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called 31 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called 32 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called 33 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called 34 | -------------------------------------------------------------------------------- /src/cmake/toolchains/x86_64.cmake: -------------------------------------------------------------------------------- 1 | ###################### FOR CROSS-COMPILING using the x86_64-linux-gnux32-g** compiler 2 | # invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` 3 | # this file is meant to be used generically, but will not work for all CMake projects 4 | # this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use 5 | 6 | set(CMAKE_SYSTEM_NAME Linux) 7 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 8 | set(TARGET_ARCH x86_64) # only used in cmake/createDebianPkg.cmake 9 | set(CMAKE_C_COMPILER /usr/bin/x86_64-linux-gnux32-gcc) 10 | set(CMAKE_CXX_COMPILER /usr/bin/x86_64-linux-gnux32-g++) 11 | 12 | # CMAKE_SYSROOT can only be set in a toolchain file 13 | # set(CMAKE_SYSROOT /usr/x86_64-linux-gnux32) # useful when a target machine's files are available 14 | 15 | # set the directory for searching installed headers 16 | # add_compile_options(-I /usr/x86_64-linux-gnux32/include) # this may not be best practice 17 | 18 | #[[ 19 | # CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine 20 | set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) 21 | 22 | CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) 23 | if cross-compiling a dependent lib (like mraa - which is optional), then 24 | set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to CirquePinnacle lib's CMAKE_FIND_ROOT_PATH 25 | example using mraa: 26 | (for mraa/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/CirquePinnacle/src/cmake/toolchains/x86_64.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/x86_64-linux-gnux32 27 | (for CirquePinnacle/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/x86_64.cmake 28 | ]] 29 | list(APPEND CMAKE_FIND_ROOT_PATH /usr/x86_64-linux-gnux32) 30 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called 31 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called 32 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called 33 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called 34 | -------------------------------------------------------------------------------- /src/utility/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # auto-generate utility driver sources and/or linked libs 2 | if("${PINNACLE_DRIVER}" STREQUAL "linux_kernel") # use linux_kernel 3 | if(NOT SPIDEV_EXISTS) 4 | message(WARNING "Detecting /dev/spidev0.0 failed - continuing anyway. Please make sure SPI is enabled.") 5 | endif() 6 | install(FILES 7 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/gpio.h 8 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/spi.h 9 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/i2c.h 10 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/time_keeping.h 11 | DESTINATION include/CirquePinnacle/utility/${PINNACLE_DRIVER} 12 | ) 13 | set(PINNACLE_DRIVER_SOURCES 14 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/spi.cpp 15 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/i2c.cpp 16 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/time_keeping.cpp 17 | ${CMAKE_CURRENT_LIST_DIR}/${PINNACLE_DRIVER}/gpio.cpp 18 | PARENT_SCOPE 19 | ) 20 | else() # No valid/supported driver selected nor detected... this is vital 21 | message(FATAL_ERROR "No valid/supported driver selected. 22 | Please specify 1 of the following supported drivers (ie `-D PINNACLE_DRIVER=linux_kernel`): 23 | \tlinux_kernel" 24 | ) 25 | endif() 26 | 27 | configure_file(${CMAKE_CURRENT_LIST_DIR}/includes.h.in ${CMAKE_CURRENT_LIST_DIR}/includes.h) 28 | -------------------------------------------------------------------------------- /src/utility/includes.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_INCLUDES_H_ 20 | #define CIRQUEPINNACLE_UTILITY_INCLUDES_H_ 21 | 22 | #include "@PINNACLE_DRIVER@/gpio.h" 23 | #include "@PINNACLE_DRIVER@/spi.h" 24 | #include "@PINNACLE_DRIVER@/i2c.h" 25 | #include "@PINNACLE_DRIVER@/time_keeping.h" 26 | 27 | /** 28 | * An alias for platform-specific representation of SPI bus objects 29 | * 30 | * @ingroup arduino-spi 31 | */ 32 | typedef cirque_pinnacle_arduino_wrappers::SPIClass pinnacle_spi_t; 33 | 34 | /** 35 | * An alias for platform-specific representation of I2C bus objects 36 | * 37 | * @ingroup arduino-i2c 38 | */ 39 | typedef cirque_pinnacle_arduino_wrappers::TwoWire pinnacle_i2c_t; 40 | 41 | #define PINNACLE_USE_ARDUINO_API using namespace cirque_pinnacle_arduino_wrappers; 42 | 43 | #endif // CIRQUEPINNACLE_UTILITY_INCLUDES_H_ 44 | -------------------------------------------------------------------------------- /src/utility/linux_kernel/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_LINUX_KERNEL_GPIO_H_ 20 | #define CIRQUEPINNACLE_UTILITY_LINUX_KERNEL_GPIO_H_ 21 | #ifndef ARDUINO 22 | 23 | #include // uintXX_t 24 | #include // std::exception, std::string 25 | #include "linux/gpio.h" // gpiochip_info 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | typedef unsigned int pinnacle_gpio_t; 32 | 33 | #ifndef PINNACLE_LINUX_GPIO_CHIP 34 | /** 35 | * The default GPIO chip to use. Defaults to `/dev/gpiochip0`. 36 | */ 37 | #define PINNACLE_LINUX_GPIO_CHIP "/dev/gpiochip0" 38 | #endif 39 | namespace cirque_pinnacle_arduino_wrappers { 40 | 41 | /** Specific exception for GPIO errors */ 42 | class GPIOException : public std::runtime_error 43 | { 44 | public: 45 | explicit GPIOException(const std::string& msg) 46 | : std::runtime_error(msg) 47 | { 48 | } 49 | }; 50 | 51 | /// A struct to manage the GPIO chip file descriptor. 52 | /// This struct's destructor should close any cached GPIO pin requests' file descriptors. 53 | struct GPIOChipCache 54 | { 55 | static int fd; 56 | 57 | /// Open the File Descriptor for the GPIO chip 58 | void openDevice(); 59 | 60 | /// Close the File Descriptor for the GPIO chip 61 | void closeDevice(); 62 | 63 | /// should be called automatically on program start. 64 | /// Here, we do some one-off configuration. 65 | GPIOChipCache(); 66 | 67 | /// Should be called automatically on program exit. 68 | /// What we need here is to make sure that the File Descriptors used to 69 | /// control GPIO pins are properly closed. 70 | ~GPIOChipCache(); 71 | }; 72 | 73 | class GPIOClass 74 | { 75 | 76 | public: 77 | GPIOClass(); 78 | 79 | static const bool DIRECTION_OUT = true; 80 | static const bool DIRECTION_IN = false; 81 | 82 | static const bool OUTPUT_HIGH = true; 83 | static const bool OUTPUT_LOW = false; 84 | 85 | /** 86 | * Similar to Arduino pinMode(pin, mode); 87 | * @param port 88 | * @param direction 89 | */ 90 | static void open(pinnacle_gpio_t port, bool direction); 91 | 92 | /** 93 | * Defined for completeness; not actually exposed in the Arduino API 94 | * @param port 95 | */ 96 | static void close(pinnacle_gpio_t port); 97 | 98 | /** 99 | * Similar to Arduino digitalRead(pin); 100 | * @param port 101 | */ 102 | static bool read(pinnacle_gpio_t port); 103 | 104 | /** 105 | * Similar to Arduino digitalWrite(pin, level); 106 | * @param port 107 | * @param value 108 | */ 109 | static void write(pinnacle_gpio_t port, bool value); 110 | 111 | virtual ~GPIOClass(); 112 | }; 113 | 114 | #define INPUT GPIOClass::DIRECTION_IN 115 | #define OUTPUT GPIOClass::DIRECTION_OUT 116 | #define HIGH GPIOClass::OUTPUT_HIGH 117 | #define LOW GPIOClass::OUTPUT_LOW 118 | #define digitalRead(pin) GPIOClass::read(pin) 119 | #define digitalWrite(pin, value) GPIOClass::write(pin, value) 120 | #define pinMode(pin, direction) GPIOClass::open(pin, direction) 121 | 122 | } // namespace cirque_pinnacle_arduino_wrappers 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif // !defined(ARDUINO) 129 | #endif // CIRQUEPINNACLE_UTILITY_LINUX_KERNEL_GPIO_H_ 130 | -------------------------------------------------------------------------------- /src/utility/linux_kernel/i2c.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef ARDUINO 20 | 21 | #include // free(), malloc() 22 | #include // size_t 23 | #include // uintXX_t 24 | #include // sprintf 25 | #include // close() 26 | #include // open() 27 | #include // ioctl() 28 | #include // errno 29 | #include // strerror() 30 | #include 31 | #include 32 | #include "i2c.h" 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | namespace cirque_pinnacle_arduino_wrappers { 39 | 40 | #ifndef PINNACLE_I2C_BUFFER_LENGTH 41 | #define PINNACLE_I2C_BUFFER_LENGTH 32 42 | #endif 43 | 44 | TwoWire::TwoWire() 45 | : xBuffIndex(0), xBuffLen(0), bus_fd(-1) 46 | { 47 | xBuff = (uint8_t*)malloc(PINNACLE_I2C_BUFFER_LENGTH); 48 | } 49 | 50 | void TwoWire::begin(uint8_t busNumber) 51 | { 52 | int file; 53 | char filename[13]; 54 | 55 | sprintf(filename, "/dev/i2c-%d", busNumber); 56 | file = open(filename, O_RDWR); 57 | if (file < 0) { 58 | std::string msg = "[TwoWire::begin] Can't open I2C bus; "; 59 | msg += strerror(errno); 60 | throw I2CException(msg); 61 | } 62 | bus_fd = file; 63 | } 64 | 65 | void TwoWire::end() 66 | { 67 | close(bus_fd); 68 | bus_fd = -1; 69 | } 70 | 71 | void TwoWire::beginTransmission(uint8_t address) 72 | { 73 | if (ioctl(bus_fd, I2C_SLAVE, address) < 0) { 74 | std::string msg = "[TwoWire::beginTransmission] Could not select I2C slave address; "; 75 | msg += strerror(errno); 76 | throw I2CException(msg); 77 | } 78 | xBuffIndex = 0; 79 | xBuffLen = 0; 80 | } 81 | 82 | uint8_t TwoWire::endTransmission(uint8_t sendStop) 83 | { 84 | (void)sendStop; // param not used in this implementation 85 | 86 | if (::write(bus_fd, xBuff, xBuffLen) != xBuffLen) { 87 | std::string msg = "[TwoWire::endTransmission] Could not write data to I2C bus; "; 88 | msg += strerror(errno); 89 | throw I2CException(msg); 90 | } 91 | return xBuffLen; 92 | } 93 | 94 | size_t TwoWire::write(uint8_t data) 95 | { 96 | if (xBuffIndex < PINNACLE_I2C_BUFFER_LENGTH) { 97 | xBuff[xBuffIndex++] = data; 98 | xBuffLen++; 99 | return 1; 100 | } 101 | return 0; 102 | } 103 | 104 | uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) 105 | { 106 | (void)sendStop; // param not used in this implementation 107 | 108 | if (quantity > PINNACLE_I2C_BUFFER_LENGTH) { 109 | quantity = PINNACLE_I2C_BUFFER_LENGTH; 110 | } 111 | 112 | xBuffIndex = 0; 113 | int retVal = ::read(bus_fd, xBuff, quantity); 114 | if (retVal < 0) { 115 | std::string msg = "[TwoWire::endTransmission] Could not read data from I2C bus; "; 116 | msg += strerror(errno); 117 | throw I2CException(msg); 118 | } 119 | xBuffLen = quantity; 120 | return xBuffLen; 121 | } 122 | 123 | int TwoWire::available() 124 | { 125 | if (xBuffIndex < xBuffLen) { 126 | return xBuffLen - xBuffIndex; 127 | } 128 | return 0; 129 | } 130 | 131 | int TwoWire::read() 132 | { 133 | if (xBuffIndex < xBuffLen) { 134 | return xBuff[xBuffIndex++]; 135 | } 136 | return -1; 137 | } 138 | 139 | TwoWire::~TwoWire() 140 | { 141 | free(xBuff); 142 | end(); 143 | } 144 | 145 | TwoWire Wire; 146 | 147 | } // namespace cirque_pinnacle_arduino_wrappers 148 | 149 | #ifdef __cplusplus 150 | } 151 | #endif 152 | 153 | #endif // !defined(ARDUINO) 154 | -------------------------------------------------------------------------------- /src/utility/linux_kernel/time_keeping.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef ARDUINO 20 | #include 21 | #include 22 | #include "time_keeping.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | namespace cirque_pinnacle_arduino_wrappers { 29 | 30 | void __msleep(int milliseconds) 31 | { 32 | struct timespec req; 33 | req.tv_sec = (time_t)milliseconds / 1000; 34 | req.tv_nsec = (milliseconds % 1000) * 1000000L; 35 | //nanosleep(&req, (struct timespec *)NULL); 36 | clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); 37 | } 38 | 39 | void __usleep(int microseconds) 40 | { 41 | struct timespec req; 42 | req.tv_sec = (time_t)microseconds / 1000000; 43 | req.tv_nsec = (microseconds % 1000000) * 1000; 44 | //nanosleep(&req, (struct timespec *)NULL); 45 | clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); 46 | } 47 | 48 | auto start = std::chrono::steady_clock::now(); 49 | 50 | uint32_t __millis() 51 | { 52 | auto end = std::chrono::steady_clock::now(); 53 | 54 | return std::chrono::duration_cast(end - start).count(); 55 | } 56 | 57 | } // namespace cirque_pinnacle_arduino_wrappers 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif // !defined(ARDUINO) 64 | -------------------------------------------------------------------------------- /src/utility/linux_kernel/time_keeping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_LINUX_KERNEL_TIME_KEEPING_H_ 20 | #define CIRQUEPINNACLE_UTILITY_LINUX_KERNEL_TIME_KEEPING_H_ 21 | #ifndef ARDUINO 22 | 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | namespace cirque_pinnacle_arduino_wrappers { 30 | 31 | void __msleep(int milliseconds); 32 | 33 | void __usleep(int microseconds); 34 | 35 | uint32_t __millis(); 36 | 37 | #define delay(ms) __msleep(ms) 38 | #define delayMicroseconds(us) __usleep(us) 39 | #define millis() __millis() 40 | 41 | } // namespace cirque_pinnacle_arduino_wrappers 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif // !defined(ARDUINO) 48 | #endif // CIRQUEPINNACLE_UTILITY_LINUX_KERNEL_TIME_KEEPING_H_ 49 | -------------------------------------------------------------------------------- /src/utility/rp2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## Include this file if you want to use the CirquePinnacle library 2 | ## in YOUR (Pico) project. 3 | ## See examples/pico_sdk/CMakeLists.txt to see how it could be done 4 | 5 | cmake_minimum_required(VERSION 3.12) 6 | 7 | set(CMAKE_C_STANDARD 11) 8 | set(CMAKE_CXX_STANDARD 17) 9 | 10 | option(PINNACLE_ANYMEAS_SUPPORT "Enable anymeas mode support" ON) 11 | option(PINNACLE_EXPERIMENTAL_ERA_2025_FIRMWARE 12 | "Allow experimental ERA functionality on trackpads with newer firmware. 13 | To use this feature, C++ inheritance shall be used 14 | because the ERA functions are private. 15 | Does not apply to the Python binding." 16 | OFF 17 | ) 18 | 19 | # Define the CirquePinnacle core library 20 | add_library(CirquePinnacle INTERFACE) 21 | 22 | if(NOT PINNACLE_ANYMEAS_SUPPORT) 23 | message(STATUS "Excluding code related to the Pinnacle's anymeas mode.") 24 | target_compile_definitions(CirquePinnacle INTERFACE PINNACLE_ANYMEAS_SUPPORT=0) 25 | endif() 26 | 27 | if (PINNACLE_EXPERIMENTAL_ERA_2025_FIRMWARE) 28 | message(STATUS "Allowing experimental ERA functionality on newer trackpads") 29 | target_compile_definitions(${LibTargetName} PUBLIC PINNACLE_EXPERIMENTAL_ERA_2025_FIRMWARE=1) 30 | endif() 31 | 32 | # generate the lib-specific includes.h for the Pico SDK 33 | set(PINNACLE_DRIVER "rp2") 34 | configure_file(${CMAKE_CURRENT_LIST_DIR}/../includes.h.in ${CMAKE_CURRENT_LIST_DIR}/../includes.h) 35 | 36 | target_sources(CirquePinnacle INTERFACE 37 | ${CMAKE_CURRENT_LIST_DIR}/../../CirquePinnacle.cpp 38 | ${CMAKE_CURRENT_LIST_DIR}/gpio.cpp 39 | ${CMAKE_CURRENT_LIST_DIR}/spi.cpp 40 | ${CMAKE_CURRENT_LIST_DIR}/i2c.cpp 41 | ${CMAKE_CURRENT_LIST_DIR}/time_keeping.h 42 | ) 43 | 44 | target_include_directories(CirquePinnacle INTERFACE 45 | ${CMAKE_CURRENT_LIST_DIR}/../../ 46 | ) 47 | -------------------------------------------------------------------------------- /src/utility/rp2/gpio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef ARDUINO 20 | #include "gpio.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | namespace cirque_pinnacle_arduino_wrappers { 27 | 28 | GPIOClass::GPIOClass() 29 | { 30 | } 31 | 32 | void GPIOClass::open(pinnacle_gpio_t port, bool direction) 33 | { 34 | gpio_init(port); 35 | gpio_set_dir(port, direction); 36 | } 37 | 38 | void GPIOClass::close(pinnacle_gpio_t port) 39 | { 40 | gpio_init(port); 41 | } 42 | 43 | bool GPIOClass::read(pinnacle_gpio_t port) 44 | { 45 | return gpio_get(port); 46 | } 47 | 48 | void GPIOClass::write(pinnacle_gpio_t port, bool value) 49 | { 50 | gpio_put(port, value); 51 | } 52 | 53 | GPIOClass::~GPIOClass() 54 | { 55 | } 56 | 57 | } // namespace cirque_pinnacle_arduino_wrappers 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif // !defined(ARDUINO) 64 | -------------------------------------------------------------------------------- /src/utility/rp2/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_RP2_GPIO_H_ 20 | #define CIRQUEPINNACLE_UTILITY_RP2_GPIO_H_ 21 | #ifndef ARDUINO 22 | 23 | #include "pico/stdlib.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | typedef uint8_t pinnacle_gpio_t; 30 | 31 | namespace cirque_pinnacle_arduino_wrappers { 32 | 33 | class GPIOClass 34 | { 35 | 36 | public: 37 | static const bool DIRECTION_OUT = true; 38 | static const bool DIRECTION_IN = false; 39 | 40 | static const bool OUTPUT_HIGH = true; 41 | static const bool OUTPUT_LOW = false; 42 | 43 | GPIOClass(); 44 | 45 | /** 46 | * Similar to Arduino pinMode(pin, mode); 47 | * @param port 48 | * @param direction 49 | */ 50 | static void open(pinnacle_gpio_t port, bool direction); 51 | 52 | /** 53 | * Defined for completeness; not actually exposed in the Arduino API 54 | * @param port 55 | */ 56 | static void close(pinnacle_gpio_t port); 57 | 58 | /** 59 | * Similar to Arduino digitalRead(pin); 60 | * @param port 61 | */ 62 | static bool read(pinnacle_gpio_t port); 63 | 64 | /** 65 | * Similar to Arduino digitalWrite(pin, level); 66 | * @param port 67 | * @param value 68 | */ 69 | static void write(pinnacle_gpio_t port, bool value); 70 | 71 | virtual ~GPIOClass(); 72 | }; 73 | 74 | #define INPUT GPIOClass::DIRECTION_IN 75 | #define OUTPUT GPIOClass::DIRECTION_OUT 76 | #define HIGH GPIOClass::OUTPUT_HIGH 77 | #define LOW GPIOClass::OUTPUT_LOW 78 | #define digitalRead(pin) GPIOClass::read(pin) 79 | #define digitalWrite(pin, value) GPIOClass::write(pin, value) 80 | #define pinMode(pin, direction) GPIOClass::open(pin, direction) 81 | 82 | } // namespace cirque_pinnacle_arduino_wrappers 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | 88 | #endif // !defined(ARDUINO) 89 | #endif // CIRQUEPINNACLE_UTILITY_RP2_GPIO_H_ 90 | -------------------------------------------------------------------------------- /src/utility/rp2/i2c.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef ARDUINO 20 | 21 | #include 22 | #include "i2c.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | namespace cirque_pinnacle_arduino_wrappers { 29 | 30 | #ifndef PINNACLE_I2C_BUFFER_LENGTH 31 | #define PINNACLE_I2C_BUFFER_LENGTH 32 32 | #endif 33 | 34 | TwoWire::TwoWire() 35 | : slaveAddress(0), xBuffIndex(0), xBuffLen(0) 36 | { 37 | xBuff = (uint8_t*)malloc(PINNACLE_I2C_BUFFER_LENGTH); 38 | } 39 | 40 | void TwoWire::begin(i2c_inst_t* hw_i2c, uint sda, uint scl) 41 | { 42 | hw_id = hw_i2c; 43 | i2c_init(hw_id, 100000); 44 | gpio_set_function(sda, GPIO_FUNC_I2C); 45 | gpio_set_function(scl, GPIO_FUNC_I2C); 46 | gpio_pull_up(sda); 47 | gpio_pull_up(scl); 48 | } 49 | 50 | void TwoWire::end() 51 | { 52 | i2c_deinit(hw_id); 53 | } 54 | 55 | void TwoWire::beginTransmission(uint8_t address) 56 | { 57 | slaveAddress = address; 58 | xBuffLen = 0; 59 | xBuffIndex = 0; 60 | } 61 | 62 | uint8_t TwoWire::endTransmission(uint8_t sendStop) 63 | { 64 | int result = i2c_write_blocking(hw_id, slaveAddress, xBuff, xBuffLen, !sendStop); 65 | if (result == PICO_ERROR_GENERIC) { 66 | // no I2C slave device present at specified address. 67 | return 0; 68 | } 69 | else if (result == PICO_ERROR_TIMEOUT) { 70 | // I2C read() operation timed out. 71 | return 0; 72 | } 73 | return (uint8_t)result; 74 | } 75 | 76 | size_t TwoWire::write(uint8_t data) 77 | { 78 | if (xBuffIndex < PINNACLE_I2C_BUFFER_LENGTH) { 79 | xBuff[xBuffIndex++] = data; 80 | xBuffLen++; 81 | return 1; 82 | } 83 | return 0; 84 | } 85 | 86 | uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) 87 | { 88 | if (quantity > PINNACLE_I2C_BUFFER_LENGTH) 89 | quantity = PINNACLE_I2C_BUFFER_LENGTH; 90 | 91 | int result = i2c_read_blocking(hw_id, address, xBuff, quantity, !sendStop); 92 | xBuffIndex = 0; 93 | xBuffLen = 0; 94 | if (result == PICO_ERROR_GENERIC) { 95 | // "no I2C slave device present at specified address. 96 | return 0; 97 | } 98 | else if (result == PICO_ERROR_TIMEOUT) { 99 | // "I2C read() operation timed out. 100 | return 0; 101 | } 102 | xBuffLen = (uint8_t)result; 103 | return (uint8_t)result; 104 | } 105 | 106 | int TwoWire::available() 107 | { 108 | if (xBuffIndex < xBuffLen) { 109 | return (xBuffLen - xBuffIndex); 110 | } 111 | return 0; 112 | } 113 | 114 | int TwoWire::read() 115 | { 116 | if (xBuffIndex < xBuffLen) { 117 | return xBuff[xBuffIndex++]; 118 | } 119 | return -1; 120 | } 121 | 122 | TwoWire::~TwoWire() 123 | { 124 | free(xBuff); 125 | 126 | i2c_deinit(hw_id); 127 | } 128 | 129 | TwoWire Wire; 130 | 131 | } // namespace cirque_pinnacle_arduino_wrappers 132 | 133 | #ifdef __cplusplus 134 | } 135 | #endif 136 | 137 | #endif // !defined(ARDUINO) 138 | -------------------------------------------------------------------------------- /src/utility/rp2/i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_RP2_I2C_H_ 20 | #define CIRQUEPINNACLE_UTILITY_RP2_I2C_H_ 21 | #ifndef ARDUINO 22 | 23 | #include 24 | #include "pico/stdlib.h" 25 | #include "hardware/i2c.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | namespace cirque_pinnacle_arduino_wrappers { 32 | 33 | #ifdef PICO_DEFAULT_I2C_INSTANCE 34 | #define PINNACLE_DEFAULT_I2C_BUS PICO_DEFAULT_I2C_INSTANCE() 35 | #else 36 | #define PINNACLE_DEFAULT_I2C_BUS i2c0 37 | #endif 38 | class TwoWire 39 | { 40 | 41 | public: 42 | /** Instantiate the object for use with the I2C bus. */ 43 | TwoWire(); 44 | 45 | /** Initialize the I2C bus' pins. */ 46 | void begin(i2c_inst_t* hw_i2c = PINNACLE_DEFAULT_I2C_BUS, uint sda = PICO_DEFAULT_I2C_SDA_PIN, uint scl = PICO_DEFAULT_I2C_SCL_PIN); 47 | 48 | /** De-initialize the I2C bus' pins. */ 49 | void end(); 50 | 51 | /** 52 | * Start a transaction over the bus. 53 | * @note This will reset the internal buffer used for write(). 54 | * @param address The slave device's I2C address. 55 | */ 56 | void beginTransmission(uint8_t address); 57 | 58 | /** 59 | * Terminate transactions on the bus. 60 | * 61 | * This function is used to send the bytes in the internal buffer (set with `write()`) over 62 | * the bus with an optional stop condition. 63 | * 64 | * @note This will also reset the internal buffer. 65 | * @param sendStop If set to a non-zero value, then a stop condition is sent over the bus. 66 | * @return The number of bytes sent over the bus. 67 | */ 68 | uint8_t endTransmission(uint8_t sendStop = false); 69 | 70 | /** 71 | * Write a single byte to the bus. 72 | * @note This must be called after `beginTransmission()`. After all bytes are ready to be sent, 73 | * use `endTransmission()` to send the internal buffer over the bus. 74 | * @returns The number of bytes written to the internal buffer. 75 | */ 76 | size_t write(uint8_t data); 77 | 78 | /** 79 | * Request a number of bytes to read from the specified I2C device's address. 80 | * @param address The slave device's I2C address. 81 | * To specify the register offset, use beginTransmission() and write() the register offset. 82 | * @param quantity The number of bytes to request. 83 | * @param sendStop If set to a non-zero value, then a stop condition is sent over the bus 84 | * after the transaction is completed. 85 | * @return The number of bytes read into the internal buffer. 86 | */ 87 | uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop); 88 | 89 | /** 90 | * Check for remaining bytes in the internal buffer. 91 | * @note This must be called after `requestFrom()` in order to capture bytes from the bus into 92 | * the internal buffer. 93 | * @return the number of bytes left in the buffer. A negative number (or zero) means 94 | * all data from buffer has been `read()`. 95 | */ 96 | int available(); 97 | 98 | /** 99 | * Read a byte from the internal buffer. 100 | * @returns The next single byte from the internal buffer. 101 | * Use `available()` to prevent out of bounds and/or segmentation fault errors. 102 | */ 103 | int read(); 104 | 105 | /** free up the allocated memory for internal buffer */ 106 | virtual ~TwoWire(); 107 | 108 | private: 109 | i2c_inst_t* hw_id; 110 | uint8_t slaveAddress; 111 | uint8_t* xBuff; 112 | uint8_t xBuffIndex; 113 | uint8_t xBuffLen; 114 | }; 115 | 116 | // pre-instantiated I2C bus object (to use as a convenient default) 117 | extern TwoWire Wire; 118 | 119 | } // namespace cirque_pinnacle_arduino_wrappers 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | 125 | #endif // !defined(ARDUINO) 126 | #endif // CIRQUEPINNACLE_UTILITY_RP2_I2C_H_ 127 | -------------------------------------------------------------------------------- /src/utility/rp2/spi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef ARDUINO 20 | 21 | #include "spi.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | namespace cirque_pinnacle_arduino_wrappers { 28 | 29 | #define PINNACLE_SPI_BYTE_SIZE 8 30 | 31 | SPIClass::SPIClass() 32 | { 33 | } 34 | 35 | void SPIClass::begin(spi_inst_t* hw_id, uint8_t _sck, uint8_t _tx, uint8_t _rx) 36 | { 37 | _hw_id = hw_id; 38 | gpio_set_function(_sck, GPIO_FUNC_SPI); 39 | gpio_set_function(_tx, GPIO_FUNC_SPI); 40 | gpio_set_function(_rx, GPIO_FUNC_SPI); 41 | spi_init(_hw_id, PINNACLE_SPI_SPEED); 42 | } 43 | 44 | void SPIClass::end() 45 | { 46 | spi_deinit(_hw_id); 47 | } 48 | 49 | void SPIClass::transfer(void* tx_buf, void* rx_buf, uint32_t len) 50 | { 51 | spi_write_read_blocking(_hw_id, (const uint8_t*)tx_buf, (uint8_t*)rx_buf, len); 52 | } 53 | 54 | void SPIClass::transfer(void* buf, uint32_t len) 55 | { 56 | spi_write_blocking(_hw_id, (const uint8_t*)buf, len); 57 | } 58 | 59 | uint8_t SPIClass::transfer(uint8_t tx) 60 | { 61 | uint8_t recv = 0; 62 | spi_write_read_blocking(_hw_id, &tx, &recv, 1); 63 | return recv; 64 | } 65 | 66 | void SPIClass::beginTransaction(SPISettings spiSettings) 67 | { 68 | spi_set_baudrate(_hw_id, spiSettings.clock); 69 | spi_set_format(_hw_id, PINNACLE_SPI_BYTE_SIZE, (spi_cpol_t)spiSettings.polarity, (spi_cpha_t)spiSettings.phase, (spi_order_t)spiSettings.bitOrder); 70 | } 71 | 72 | void SPIClass::endTransaction() 73 | { 74 | } 75 | 76 | SPIClass::~SPIClass() 77 | { 78 | end(); 79 | } 80 | 81 | SPIClass SPI; 82 | 83 | } // namespace cirque_pinnacle_arduino_wrappers 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif // !defined(ARDUINO) 90 | -------------------------------------------------------------------------------- /src/utility/rp2/time_keeping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_RP2_TIME_KEEPING_H_ 20 | #define CIRQUEPINNACLE_UTILITY_RP2_TIME_KEEPING_H_ 21 | #ifndef ARDUINO 22 | 23 | #include "pico/stdlib.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | namespace cirque_pinnacle_arduino_wrappers { 30 | 31 | #define delay(milisec) sleep_ms(milisec) 32 | #define delayMicroseconds(usec) sleep_us(usec) 33 | #define millis() to_ms_since_boot(get_absolute_time()) 34 | 35 | } // namespace cirque_pinnacle_arduino_wrappers 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif // !defined(ARDUINO) 42 | #endif // CIRQUEPINNACLE_UTILITY_RP2_TIME_KEEPING_H_ 43 | -------------------------------------------------------------------------------- /src/utility/template/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_TEMPLATE_GPIO_H 20 | #define CIRQUEPINNACLE_UTILITY_TEMPLATE_GPIO_H 21 | #ifndef ARDUINO 22 | 23 | #include 24 | 25 | /** 26 | * An alias for platform-specific representation of GPIO pin numbers 27 | * 28 | * @ingroup arduino-gpio 29 | */ 30 | typedef uint16_t pinnacle_gpio_t; 31 | 32 | namespace cirque_pinnacle_arduino_wrappers { 33 | 34 | /** 35 | * Specific exception for GPIO errors 36 | * 37 | * @ingroup arduino-gpio 38 | */ 39 | class GPIOException : public std::runtime_error 40 | { 41 | public: 42 | explicit GPIOException(const std::string& msg) 43 | : std::runtime_error(msg) 44 | { 45 | } 46 | }; 47 | 48 | /** 49 | * A class to wrap platform-specific implementation of GPIO pins in Arduino-like API. 50 | * 51 | * @ingroup arduino-gpio 52 | */ 53 | class GPIOClass 54 | { 55 | 56 | public: 57 | static const int DIRECTION_OUT = 1; 58 | static const int DIRECTION_IN = 0; 59 | 60 | static const int OUTPUT_HIGH = 1; 61 | static const int OUTPUT_LOW = 0; 62 | 63 | GPIOClass(); 64 | 65 | /** 66 | * Similar to Arduino ``pinMode(pin, mode)``. 67 | * 68 | * @param port The GPIO pin. 69 | * @param direction The direction of the signals (``INPUT`` or ``OUTPUT``). 70 | */ 71 | static void open(pinnacle_gpio_t port, int direction); 72 | 73 | /** 74 | * Defined for completeness; not actually exposed in the Arduino API 75 | * 76 | * @param port The GPIO pin. 77 | */ 78 | static void close(pinnacle_gpio_t port); 79 | 80 | /** 81 | * Similar to Arduino ``digitalRead(pin)``. 82 | * 83 | * @param port The GPIO pin. 84 | */ 85 | static int read(pinnacle_gpio_t port); 86 | 87 | /** 88 | * Similar to Arduino ``digitalWrite(pin, level)``. 89 | * 90 | * @param port The GPIO pin. 91 | * @param value The binary level of an output signal (``HIGH`` or ``LOW``). 92 | */ 93 | static void write(pinnacle_gpio_t port, int value); 94 | 95 | /* virtual ~GPIOClass(); */ 96 | 97 | private: 98 | }; 99 | 100 | #define INPUT GPIOClass::DIRECTION_IN 101 | #define OUTPUT GPIOClass::DIRECTION_OUT 102 | #define HIGH GPIOClass::OUTPUT_HIGH 103 | #define LOW GPIOClass::OUTPUT_LOW 104 | #define digitalRead(pin) GPIOClass::read(pin) 105 | #define digitalWrite(pin, value) GPIOClass::write(pin, value) 106 | #define pinMode(pin, direction) GPIOClass::open(pin, direction) 107 | 108 | } // namespace cirque_pinnacle_arduino_wrappers 109 | 110 | #endif // !defined(ARDUINO) 111 | #endif // CIRQUEPINNACLE_UTILITY_TEMPLATE_GPIO_H 112 | -------------------------------------------------------------------------------- /src/utility/template/time_keeping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Brendan Doherty (2bndy5) 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | * SOFTWARE. 18 | */ 19 | #ifndef CIRQUEPINNACLE_UTILITY_TEMPLATE_TIME_KEEPING_H_ 20 | #define CIRQUEPINNACLE_UTILITY_TEMPLATE_TIME_KEEPING_H_ 21 | #ifndef ARDUINO 22 | 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | namespace cirque_pinnacle_arduino_wrappers { 30 | 31 | void __msleep(int milliseconds); 32 | 33 | void __usleep(int microseconds); 34 | 35 | uint32_t __millis(); 36 | 37 | #define delay(ms) __msleep(ms) 38 | #define delayMicroseconds(us) __usleep(us) 39 | #define millis() __millis() 40 | 41 | } // namespace cirque_pinnacle_arduino_wrappers 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif // !defined(ARDUINO) 48 | #endif // CIRQUEPINNACLE_UTILITY_TEMPLATE_TIME_KEEPING_H_ 49 | --------------------------------------------------------------------------------